]> git.stg.codes - stg.git/commitdiff
Move projects back into subfolder.
authorMaksym Mamontov <madf@madf.info>
Sun, 17 Jan 2021 17:48:47 +0000 (19:48 +0200)
committerMaksym Mamontov <madf@madf.info>
Sun, 17 Jan 2021 17:48:47 +0000 (19:48 +0200)
578 files changed:
CMakeLists.txt
functest/test.sh
functest/test_admins.sh
functest/test_server_info.sh
functest/test_services.sh
projects/rscriptd/CMakeLists.txt [new file with mode: 0644]
projects/rscriptd/listener.cpp [new file with mode: 0644]
projects/rscriptd/listener.h [new file with mode: 0644]
projects/rscriptd/main.cpp [new file with mode: 0644]
projects/rscriptd/pidfile.cpp [new file with mode: 0644]
projects/rscriptd/pidfile.h [new file with mode: 0644]
projects/rscriptd/rscriptd.conf [new file with mode: 0644]
projects/sgauth/.gitignore [new file with mode: 0644]
projects/sgauth/CMakeLists.txt [new file with mode: 0644]
projects/sgauth/css.h.in [new file with mode: 0644]
projects/sgauth/main.cpp [new file with mode: 0644]
projects/sgauth/settings_impl.cpp [new file with mode: 0644]
projects/sgauth/settings_impl.h [new file with mode: 0644]
projects/sgauth/sgauth.conf [new file with mode: 0644]
projects/sgauth/sgauth.css [new file with mode: 0644]
projects/sgauth/web.cpp [new file with mode: 0644]
projects/sgauth/web.h [new file with mode: 0644]
projects/sgconf/CHANGES [new file with mode: 0644]
projects/sgconf/CMakeLists.txt [new file with mode: 0644]
projects/sgconf/README.txt [new file with mode: 0644]
projects/sgconf/TODO [new file with mode: 0644]
projects/sgconf/action.h [new file with mode: 0644]
projects/sgconf/actions.cpp [new file with mode: 0644]
projects/sgconf/actions.h [new file with mode: 0644]
projects/sgconf/admins.cpp [new file with mode: 0644]
projects/sgconf/admins.h [new file with mode: 0644]
projects/sgconf/api_action.cpp [new file with mode: 0644]
projects/sgconf/api_action.h [new file with mode: 0644]
projects/sgconf/config.h [new file with mode: 0644]
projects/sgconf/corps.cpp [new file with mode: 0644]
projects/sgconf/corps.h [new file with mode: 0644]
projects/sgconf/info.cpp [new file with mode: 0644]
projects/sgconf/info.h [new file with mode: 0644]
projects/sgconf/main.cpp [new file with mode: 0644]
projects/sgconf/options.cpp [new file with mode: 0644]
projects/sgconf/options.h [new file with mode: 0644]
projects/sgconf/parser_state.h [new file with mode: 0644]
projects/sgconf/services.cpp [new file with mode: 0644]
projects/sgconf/services.h [new file with mode: 0644]
projects/sgconf/tariffs.cpp [new file with mode: 0644]
projects/sgconf/tariffs.h [new file with mode: 0644]
projects/sgconf/users.cpp [new file with mode: 0644]
projects/sgconf/users.h [new file with mode: 0644]
projects/sgconf/utils.h [new file with mode: 0644]
projects/sgconf/xml.cpp [new file with mode: 0644]
projects/sgconf/xml.h [new file with mode: 0644]
projects/stargazer/BUGS [new file with mode: 0644]
projects/stargazer/CHANGES [new file with mode: 0644]
projects/stargazer/CMakeLists.txt [new file with mode: 0644]
projects/stargazer/README [new file with mode: 0644]
projects/stargazer/TODO [new file with mode: 0644]
projects/stargazer/actions.h [new file with mode: 0644]
projects/stargazer/actions.inl.h [new file with mode: 0644]
projects/stargazer/admins_impl.cpp [new file with mode: 0644]
projects/stargazer/admins_impl.h [new file with mode: 0644]
projects/stargazer/corps_impl.cpp [new file with mode: 0644]
projects/stargazer/corps_impl.h [new file with mode: 0644]
projects/stargazer/eventloop.cpp [new file with mode: 0644]
projects/stargazer/eventloop.h [new file with mode: 0644]
projects/stargazer/inst/freebsd/etc/stargazer/OnChange [new file with mode: 0755]
projects/stargazer/inst/freebsd/etc/stargazer/OnConnect [new file with mode: 0755]
projects/stargazer/inst/freebsd/etc/stargazer/OnDisconnect [new file with mode: 0755]
projects/stargazer/inst/freebsd/etc/stargazer/OnUserAdd [new file with mode: 0755]
projects/stargazer/inst/freebsd/etc/stargazer/OnUserDel [new file with mode: 0755]
projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_ao.conf [new file with mode: 0644]
projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_cap_bpf.conf [new file with mode: 0644]
projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_cap_divert.conf [new file with mode: 0644]
projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_cap_nf.conf [new file with mode: 0644]
projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_ia.conf [new file with mode: 0644]
projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_ping.conf [new file with mode: 0644]
projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_radius.conf [new file with mode: 0644]
projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_remote_script.conf [new file with mode: 0644]
projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_rpc.conf [new file with mode: 0644]
projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_sg.conf [new file with mode: 0644]
projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_smux.conf [new file with mode: 0644]
projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/store_files.conf [new file with mode: 0644]
projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/store_firebird.conf [new file with mode: 0644]
projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/store_mysql.conf [new file with mode: 0644]
projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/store_postgresql.conf [new file with mode: 0644]
projects/stargazer/inst/freebsd/etc/stargazer/conf-enabled.d/mod_ao.conf [new symlink]
projects/stargazer/inst/freebsd/etc/stargazer/conf-enabled.d/mod_cap_bpf.conf [new symlink]
projects/stargazer/inst/freebsd/etc/stargazer/conf-enabled.d/mod_ia.conf [new symlink]
projects/stargazer/inst/freebsd/etc/stargazer/conf-enabled.d/mod_ping.conf [new symlink]
projects/stargazer/inst/freebsd/etc/stargazer/conf-enabled.d/mod_sg.conf [new symlink]
projects/stargazer/inst/freebsd/etc/stargazer/conf-enabled.d/store_files.conf [new symlink]
projects/stargazer/inst/freebsd/etc/stargazer/rules [new file with mode: 0644]
projects/stargazer/inst/freebsd/etc/stargazer/stargazer.conf [new file with mode: 0644]
projects/stargazer/inst/linux/etc/init.d/stargazer.gentoo [new file with mode: 0755]
projects/stargazer/inst/linux/etc/init.d/stargazer.suse.9.3 [new file with mode: 0755]
projects/stargazer/inst/linux/etc/init.d/stargazer.ubuntu.7.10 [new file with mode: 0755]
projects/stargazer/inst/linux/etc/stargazer/OnChange [new file with mode: 0755]
projects/stargazer/inst/linux/etc/stargazer/OnConnect [new file with mode: 0755]
projects/stargazer/inst/linux/etc/stargazer/OnDisconnect [new file with mode: 0755]
projects/stargazer/inst/linux/etc/stargazer/OnUserAdd [new file with mode: 0755]
projects/stargazer/inst/linux/etc/stargazer/OnUserDel [new file with mode: 0755]
projects/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_ao.conf [new file with mode: 0644]
projects/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_cap_ether.conf [new file with mode: 0644]
projects/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_cap_ipq.conf [new file with mode: 0644]
projects/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_cap_nf.conf [new file with mode: 0644]
projects/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_ia.conf [new file with mode: 0644]
projects/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_ping.conf [new file with mode: 0644]
projects/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_radius.conf [new file with mode: 0644]
projects/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_remote_script.conf [new file with mode: 0644]
projects/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_rpc.conf [new file with mode: 0644]
projects/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_sg.conf [new file with mode: 0644]
projects/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_smux.conf [new file with mode: 0644]
projects/stargazer/inst/linux/etc/stargazer/conf-available.d/store_files.conf [new file with mode: 0644]
projects/stargazer/inst/linux/etc/stargazer/conf-available.d/store_firebird.conf [new file with mode: 0644]
projects/stargazer/inst/linux/etc/stargazer/conf-available.d/store_mysql.conf [new file with mode: 0644]
projects/stargazer/inst/linux/etc/stargazer/conf-available.d/store_postgresql.conf [new file with mode: 0644]
projects/stargazer/inst/linux/etc/stargazer/conf-enabled.d/mod_ao.conf [new symlink]
projects/stargazer/inst/linux/etc/stargazer/conf-enabled.d/mod_cap_ether.conf [new symlink]
projects/stargazer/inst/linux/etc/stargazer/conf-enabled.d/mod_ia.conf [new symlink]
projects/stargazer/inst/linux/etc/stargazer/conf-enabled.d/mod_ping.conf [new symlink]
projects/stargazer/inst/linux/etc/stargazer/conf-enabled.d/mod_sg.conf [new symlink]
projects/stargazer/inst/linux/etc/stargazer/conf-enabled.d/store_files.conf [new symlink]
projects/stargazer/inst/linux/etc/stargazer/rules [new file with mode: 0644]
projects/stargazer/inst/linux/etc/stargazer/stargazer.conf [new file with mode: 0644]
projects/stargazer/inst/var/00-alter-01.postgresql.sql [new file with mode: 0644]
projects/stargazer/inst/var/00-alter-01.sql [new file with mode: 0644]
projects/stargazer/inst/var/00-base-00.postgresql.sql [new file with mode: 0644]
projects/stargazer/inst/var/00-base-00.sql [new file with mode: 0644]
projects/stargazer/inst/var/00-mysql-01.sql [new file with mode: 0644]
projects/stargazer/inst/var/01-alter-02.mysql.sql [new file with mode: 0644]
projects/stargazer/inst/var/01-alter-02.postgresql.sql [new file with mode: 0644]
projects/stargazer/inst/var/01-alter-02.sql [new file with mode: 0644]
projects/stargazer/inst/var/02-alter-03.postgresql.sql [new file with mode: 0644]
projects/stargazer/inst/var/02-alter-03.sql [new file with mode: 0644]
projects/stargazer/inst/var/base.dia [new file with mode: 0644]
projects/stargazer/inst/var/stargazer/admins/admin.adm [new file with mode: 0644]
projects/stargazer/inst/var/stargazer/tariffs/tariff.tf [new file with mode: 0644]
projects/stargazer/inst/var/stargazer/users/test/conf [new file with mode: 0644]
projects/stargazer/inst/var/stargazer/users/test/stat [new file with mode: 0644]
projects/stargazer/main.cpp [new file with mode: 0644]
projects/stargazer/pidfile.cpp [new file with mode: 0644]
projects/stargazer/pidfile.h [new file with mode: 0644]
projects/stargazer/plugin_mgr.cpp [new file with mode: 0644]
projects/stargazer/plugin_mgr.h [new file with mode: 0644]
projects/stargazer/plugin_runner.cpp [new file with mode: 0644]
projects/stargazer/plugin_runner.h [new file with mode: 0644]
projects/stargazer/plugins/CMakeLists.txt [new file with mode: 0644]
projects/stargazer/plugins/authorization/ao/ao.cpp [new file with mode: 0644]
projects/stargazer/plugins/authorization/ao/ao.h [new file with mode: 0644]
projects/stargazer/plugins/authorization/inetaccess/inetaccess.cpp [new file with mode: 0644]
projects/stargazer/plugins/authorization/inetaccess/inetaccess.h [new file with mode: 0644]
projects/stargazer/plugins/capture/cap_nf/cap_nf.cpp [new file with mode: 0644]
projects/stargazer/plugins/capture/cap_nf/cap_nf.h [new file with mode: 0644]
projects/stargazer/plugins/capture/divert_freebsd/divert_cap.cpp [new file with mode: 0644]
projects/stargazer/plugins/capture/divert_freebsd/divert_cap.h [new file with mode: 0644]
projects/stargazer/plugins/capture/ether_freebsd/ether_cap.cpp [new file with mode: 0644]
projects/stargazer/plugins/capture/ether_freebsd/ether_cap.h [new file with mode: 0644]
projects/stargazer/plugins/capture/ether_linux/ether_cap.cpp [new file with mode: 0644]
projects/stargazer/plugins/capture/ether_linux/ether_cap.h [new file with mode: 0644]
projects/stargazer/plugins/capture/nfqueue/nfqueue.cpp [new file with mode: 0644]
projects/stargazer/plugins/capture/nfqueue/nfqueue.h [new file with mode: 0644]
projects/stargazer/plugins/capture/pcap/pcap_cap.cpp [new file with mode: 0644]
projects/stargazer/plugins/capture/pcap/pcap_cap.h [new file with mode: 0644]
projects/stargazer/plugins/configuration/rpcconfig/admins_methods.cpp [new file with mode: 0644]
projects/stargazer/plugins/configuration/rpcconfig/admins_methods.h [new file with mode: 0644]
projects/stargazer/plugins/configuration/rpcconfig/info_methods.cpp [new file with mode: 0644]
projects/stargazer/plugins/configuration/rpcconfig/info_methods.h [new file with mode: 0644]
projects/stargazer/plugins/configuration/rpcconfig/messages_methods.cpp [new file with mode: 0644]
projects/stargazer/plugins/configuration/rpcconfig/messages_methods.h [new file with mode: 0644]
projects/stargazer/plugins/configuration/rpcconfig/rpcconfig.cpp [new file with mode: 0644]
projects/stargazer/plugins/configuration/rpcconfig/rpcconfig.h [new file with mode: 0644]
projects/stargazer/plugins/configuration/rpcconfig/tariff_helper.cpp [new file with mode: 0644]
projects/stargazer/plugins/configuration/rpcconfig/tariff_helper.h [new file with mode: 0644]
projects/stargazer/plugins/configuration/rpcconfig/tariffs_methods.cpp [new file with mode: 0644]
projects/stargazer/plugins/configuration/rpcconfig/tariffs_methods.h [new file with mode: 0644]
projects/stargazer/plugins/configuration/rpcconfig/user_helper.cpp [new file with mode: 0644]
projects/stargazer/plugins/configuration/rpcconfig/user_helper.h [new file with mode: 0644]
projects/stargazer/plugins/configuration/rpcconfig/users_methods.cpp [new file with mode: 0644]
projects/stargazer/plugins/configuration/rpcconfig/users_methods.h [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig/configproto.cpp [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig/configproto.h [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig/conn.cpp [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig/conn.h [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig/dumphelpers.h [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig/parser.cpp [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig/parser.h [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig/parser_admins.cpp [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig/parser_admins.h [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig/parser_auth_by.cpp [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig/parser_auth_by.h [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig/parser_message.cpp [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig/parser_message.h [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig/parser_server_info.cpp [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig/parser_server_info.h [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig/parser_services.cpp [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig/parser_services.h [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig/parser_tariffs.cpp [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig/parser_tariffs.h [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig/parser_user_info.cpp [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig/parser_user_info.h [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig/parser_users.cpp [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig/parser_users.h [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig/stgconfig.cpp [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig/stgconfig.h [new file with mode: 0644]
projects/stargazer/plugins/other/ping/ping.cpp [new file with mode: 0644]
projects/stargazer/plugins/other/ping/ping.h [new file with mode: 0644]
projects/stargazer/plugins/other/rscript/nrmap_parser.cpp [new file with mode: 0644]
projects/stargazer/plugins/other/rscript/nrmap_parser.h [new file with mode: 0644]
projects/stargazer/plugins/other/rscript/rscript.cpp [new file with mode: 0644]
projects/stargazer/plugins/other/rscript/rscript.h [new file with mode: 0644]
projects/stargazer/plugins/other/rscript/send_functor.h [new file with mode: 0644]
projects/stargazer/plugins/other/rscript/ur_functor.h [new file with mode: 0644]
projects/stargazer/plugins/other/smux/STG-MIB.mib [new file with mode: 0644]
projects/stargazer/plugins/other/smux/TODO [new file with mode: 0644]
projects/stargazer/plugins/other/smux/handlers.cpp [new file with mode: 0644]
projects/stargazer/plugins/other/smux/pen.h [new file with mode: 0644]
projects/stargazer/plugins/other/smux/sensors.cpp [new file with mode: 0644]
projects/stargazer/plugins/other/smux/sensors.h [new file with mode: 0644]
projects/stargazer/plugins/other/smux/smux.cpp [new file with mode: 0644]
projects/stargazer/plugins/other/smux/smux.h [new file with mode: 0644]
projects/stargazer/plugins/other/smux/tables.cpp [new file with mode: 0644]
projects/stargazer/plugins/other/smux/tables.h [new file with mode: 0644]
projects/stargazer/plugins/other/smux/types.cpp [new file with mode: 0644]
projects/stargazer/plugins/other/smux/types.h [new file with mode: 0644]
projects/stargazer/plugins/other/smux/utils.cpp [new file with mode: 0644]
projects/stargazer/plugins/other/smux/utils.h [new file with mode: 0644]
projects/stargazer/plugins/other/smux/value2os.h [new file with mode: 0644]
projects/stargazer/plugins/store/files/file_store.cpp [new file with mode: 0644]
projects/stargazer/plugins/store/files/file_store.h [new file with mode: 0644]
projects/stargazer/plugins/store/firebird/firebird_store.cpp [new file with mode: 0644]
projects/stargazer/plugins/store/firebird/firebird_store.h [new file with mode: 0644]
projects/stargazer/plugins/store/firebird/firebird_store_admins.cpp [new file with mode: 0644]
projects/stargazer/plugins/store/firebird/firebird_store_corporations.cpp [new file with mode: 0644]
projects/stargazer/plugins/store/firebird/firebird_store_messages.cpp [new file with mode: 0644]
projects/stargazer/plugins/store/firebird/firebird_store_services.cpp [new file with mode: 0644]
projects/stargazer/plugins/store/firebird/firebird_store_tariffs.cpp [new file with mode: 0644]
projects/stargazer/plugins/store/firebird/firebird_store_users.cpp [new file with mode: 0644]
projects/stargazer/plugins/store/firebird/firebird_store_utils.cpp [new file with mode: 0644]
projects/stargazer/plugins/store/mysql/mysql_store.cpp [new file with mode: 0644]
projects/stargazer/plugins/store/mysql/mysql_store.h [new file with mode: 0644]
projects/stargazer/plugins/store/postgresql/postgresql_store.cpp [new file with mode: 0644]
projects/stargazer/plugins/store/postgresql/postgresql_store.h [new file with mode: 0644]
projects/stargazer/plugins/store/postgresql/postgresql_store_admins.cpp [new file with mode: 0644]
projects/stargazer/plugins/store/postgresql/postgresql_store_corporations.cpp [new file with mode: 0644]
projects/stargazer/plugins/store/postgresql/postgresql_store_messages.cpp [new file with mode: 0644]
projects/stargazer/plugins/store/postgresql/postgresql_store_services.cpp [new file with mode: 0644]
projects/stargazer/plugins/store/postgresql/postgresql_store_tariffs.cpp [new file with mode: 0644]
projects/stargazer/plugins/store/postgresql/postgresql_store_users.cpp [new file with mode: 0644]
projects/stargazer/plugins/store/postgresql/postgresql_store_utils.cpp [new file with mode: 0644]
projects/stargazer/plugins/store/postgresql/postgresql_store_utils.h [new file with mode: 0644]
projects/stargazer/scripts/clean_db [new file with mode: 0755]
projects/stargazer/scripts/monitor [new file with mode: 0755]
projects/stargazer/scripts/shaper/OnConnect [new file with mode: 0755]
projects/stargazer/scripts/shaper/OnDisconnect [new file with mode: 0755]
projects/stargazer/scripts/shaper/Readme.txt [new file with mode: 0644]
projects/stargazer/scripts/shaper/shaper.sh [new file with mode: 0755]
projects/stargazer/scripts/shaper/shaper.stop.sh [new file with mode: 0755]
projects/stargazer/scripts/shaper_vpn_radius/Readme [new file with mode: 0644]
projects/stargazer/scripts/shaper_vpn_radius/firewall/firewall [new file with mode: 0755]
projects/stargazer/scripts/shaper_vpn_radius/freeradius/clients.conf [new file with mode: 0644]
projects/stargazer/scripts/shaper_vpn_radius/freeradius/radiusd.conf [new file with mode: 0644]
projects/stargazer/scripts/shaper_vpn_radius/ppp/ip-down.d/stg [new file with mode: 0755]
projects/stargazer/scripts/shaper_vpn_radius/ppp/ip-up.d/stg [new file with mode: 0755]
projects/stargazer/scripts/shaper_vpn_radius/ppp/pptpd-options [new file with mode: 0644]
projects/stargazer/scripts/shaper_vpn_radius/pptpd.conf [new file with mode: 0644]
projects/stargazer/scripts/shaper_vpn_radius/radiusclient/servers [new file with mode: 0644]
projects/stargazer/scripts/shaper_vpn_radius/stargazer/OnChange [new file with mode: 0755]
projects/stargazer/scripts/shaper_vpn_radius/stargazer/OnConnect [new file with mode: 0755]
projects/stargazer/scripts/shaper_vpn_radius/stargazer/OnDisconnect [new file with mode: 0755]
projects/stargazer/scripts/shaper_vpn_radius/stargazer/OnUserAdd [new file with mode: 0755]
projects/stargazer/scripts/shaper_vpn_radius/stargazer/OnUserDel [new file with mode: 0755]
projects/stargazer/scripts/shaper_vpn_radius/stargazer/rules [new file with mode: 0644]
projects/stargazer/scripts/shaper_vpn_radius/stargazer/stargazer.conf [new file with mode: 0644]
projects/stargazer/services_impl.cpp [new file with mode: 0644]
projects/stargazer/services_impl.h [new file with mode: 0644]
projects/stargazer/settings_impl.cpp [new file with mode: 0644]
projects/stargazer/settings_impl.h [new file with mode: 0644]
projects/stargazer/stg_timer.cpp [new file with mode: 0644]
projects/stargazer/stg_timer.h [new file with mode: 0644]
projects/stargazer/store_loader.cpp [new file with mode: 0644]
projects/stargazer/store_loader.h [new file with mode: 0644]
projects/stargazer/tariff_impl.cpp [new file with mode: 0644]
projects/stargazer/tariff_impl.h [new file with mode: 0644]
projects/stargazer/tariffs_impl.cpp [new file with mode: 0644]
projects/stargazer/tariffs_impl.h [new file with mode: 0644]
projects/stargazer/traffcounter_impl.cpp [new file with mode: 0644]
projects/stargazer/traffcounter_impl.h [new file with mode: 0644]
projects/stargazer/user_impl.cpp [new file with mode: 0644]
projects/stargazer/user_impl.h [new file with mode: 0644]
projects/stargazer/user_property.cpp [new file with mode: 0644]
projects/stargazer/users_impl.cpp [new file with mode: 0644]
projects/stargazer/users_impl.h [new file with mode: 0644]
rscriptd/CMakeLists.txt [deleted file]
rscriptd/listener.cpp [deleted file]
rscriptd/listener.h [deleted file]
rscriptd/main.cpp [deleted file]
rscriptd/pidfile.cpp [deleted file]
rscriptd/pidfile.h [deleted file]
rscriptd/rscriptd.conf [deleted file]
sgauth/.gitignore [deleted file]
sgauth/CMakeLists.txt [deleted file]
sgauth/css.h.in [deleted file]
sgauth/main.cpp [deleted file]
sgauth/settings_impl.cpp [deleted file]
sgauth/settings_impl.h [deleted file]
sgauth/sgauth.conf [deleted file]
sgauth/sgauth.css [deleted file]
sgauth/web.cpp [deleted file]
sgauth/web.h [deleted file]
sgconf/CHANGES [deleted file]
sgconf/CMakeLists.txt [deleted file]
sgconf/README.txt [deleted file]
sgconf/TODO [deleted file]
sgconf/action.h [deleted file]
sgconf/actions.cpp [deleted file]
sgconf/actions.h [deleted file]
sgconf/admins.cpp [deleted file]
sgconf/admins.h [deleted file]
sgconf/api_action.cpp [deleted file]
sgconf/api_action.h [deleted file]
sgconf/config.h [deleted file]
sgconf/corps.cpp [deleted file]
sgconf/corps.h [deleted file]
sgconf/info.cpp [deleted file]
sgconf/info.h [deleted file]
sgconf/main.cpp [deleted file]
sgconf/options.cpp [deleted file]
sgconf/options.h [deleted file]
sgconf/parser_state.h [deleted file]
sgconf/services.cpp [deleted file]
sgconf/services.h [deleted file]
sgconf/tariffs.cpp [deleted file]
sgconf/tariffs.h [deleted file]
sgconf/users.cpp [deleted file]
sgconf/users.h [deleted file]
sgconf/utils.h [deleted file]
sgconf/xml.cpp [deleted file]
sgconf/xml.h [deleted file]
stargazer/BUGS [deleted file]
stargazer/CHANGES [deleted file]
stargazer/CMakeLists.txt [deleted file]
stargazer/README [deleted file]
stargazer/TODO [deleted file]
stargazer/actions.h [deleted file]
stargazer/actions.inl.h [deleted file]
stargazer/admins_impl.cpp [deleted file]
stargazer/admins_impl.h [deleted file]
stargazer/corps_impl.cpp [deleted file]
stargazer/corps_impl.h [deleted file]
stargazer/eventloop.cpp [deleted file]
stargazer/eventloop.h [deleted file]
stargazer/inst/freebsd/etc/stargazer/OnChange [deleted file]
stargazer/inst/freebsd/etc/stargazer/OnConnect [deleted file]
stargazer/inst/freebsd/etc/stargazer/OnDisconnect [deleted file]
stargazer/inst/freebsd/etc/stargazer/OnUserAdd [deleted file]
stargazer/inst/freebsd/etc/stargazer/OnUserDel [deleted file]
stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_ao.conf [deleted file]
stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_cap_bpf.conf [deleted file]
stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_cap_divert.conf [deleted file]
stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_cap_nf.conf [deleted file]
stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_ia.conf [deleted file]
stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_ping.conf [deleted file]
stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_radius.conf [deleted file]
stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_remote_script.conf [deleted file]
stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_rpc.conf [deleted file]
stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_sg.conf [deleted file]
stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_smux.conf [deleted file]
stargazer/inst/freebsd/etc/stargazer/conf-available.d/store_files.conf [deleted file]
stargazer/inst/freebsd/etc/stargazer/conf-available.d/store_firebird.conf [deleted file]
stargazer/inst/freebsd/etc/stargazer/conf-available.d/store_mysql.conf [deleted file]
stargazer/inst/freebsd/etc/stargazer/conf-available.d/store_postgresql.conf [deleted file]
stargazer/inst/freebsd/etc/stargazer/conf-enabled.d/mod_ao.conf [deleted symlink]
stargazer/inst/freebsd/etc/stargazer/conf-enabled.d/mod_cap_bpf.conf [deleted symlink]
stargazer/inst/freebsd/etc/stargazer/conf-enabled.d/mod_ia.conf [deleted symlink]
stargazer/inst/freebsd/etc/stargazer/conf-enabled.d/mod_ping.conf [deleted symlink]
stargazer/inst/freebsd/etc/stargazer/conf-enabled.d/mod_sg.conf [deleted symlink]
stargazer/inst/freebsd/etc/stargazer/conf-enabled.d/store_files.conf [deleted symlink]
stargazer/inst/freebsd/etc/stargazer/rules [deleted file]
stargazer/inst/freebsd/etc/stargazer/stargazer.conf [deleted file]
stargazer/inst/linux/etc/init.d/stargazer.gentoo [deleted file]
stargazer/inst/linux/etc/init.d/stargazer.suse.9.3 [deleted file]
stargazer/inst/linux/etc/init.d/stargazer.ubuntu.7.10 [deleted file]
stargazer/inst/linux/etc/stargazer/OnChange [deleted file]
stargazer/inst/linux/etc/stargazer/OnConnect [deleted file]
stargazer/inst/linux/etc/stargazer/OnDisconnect [deleted file]
stargazer/inst/linux/etc/stargazer/OnUserAdd [deleted file]
stargazer/inst/linux/etc/stargazer/OnUserDel [deleted file]
stargazer/inst/linux/etc/stargazer/conf-available.d/mod_ao.conf [deleted file]
stargazer/inst/linux/etc/stargazer/conf-available.d/mod_cap_ether.conf [deleted file]
stargazer/inst/linux/etc/stargazer/conf-available.d/mod_cap_ipq.conf [deleted file]
stargazer/inst/linux/etc/stargazer/conf-available.d/mod_cap_nf.conf [deleted file]
stargazer/inst/linux/etc/stargazer/conf-available.d/mod_ia.conf [deleted file]
stargazer/inst/linux/etc/stargazer/conf-available.d/mod_ping.conf [deleted file]
stargazer/inst/linux/etc/stargazer/conf-available.d/mod_radius.conf [deleted file]
stargazer/inst/linux/etc/stargazer/conf-available.d/mod_remote_script.conf [deleted file]
stargazer/inst/linux/etc/stargazer/conf-available.d/mod_rpc.conf [deleted file]
stargazer/inst/linux/etc/stargazer/conf-available.d/mod_sg.conf [deleted file]
stargazer/inst/linux/etc/stargazer/conf-available.d/mod_smux.conf [deleted file]
stargazer/inst/linux/etc/stargazer/conf-available.d/store_files.conf [deleted file]
stargazer/inst/linux/etc/stargazer/conf-available.d/store_firebird.conf [deleted file]
stargazer/inst/linux/etc/stargazer/conf-available.d/store_mysql.conf [deleted file]
stargazer/inst/linux/etc/stargazer/conf-available.d/store_postgresql.conf [deleted file]
stargazer/inst/linux/etc/stargazer/conf-enabled.d/mod_ao.conf [deleted symlink]
stargazer/inst/linux/etc/stargazer/conf-enabled.d/mod_cap_ether.conf [deleted symlink]
stargazer/inst/linux/etc/stargazer/conf-enabled.d/mod_ia.conf [deleted symlink]
stargazer/inst/linux/etc/stargazer/conf-enabled.d/mod_ping.conf [deleted symlink]
stargazer/inst/linux/etc/stargazer/conf-enabled.d/mod_sg.conf [deleted symlink]
stargazer/inst/linux/etc/stargazer/conf-enabled.d/store_files.conf [deleted symlink]
stargazer/inst/linux/etc/stargazer/rules [deleted file]
stargazer/inst/linux/etc/stargazer/stargazer.conf [deleted file]
stargazer/inst/var/00-alter-01.postgresql.sql [deleted file]
stargazer/inst/var/00-alter-01.sql [deleted file]
stargazer/inst/var/00-base-00.postgresql.sql [deleted file]
stargazer/inst/var/00-base-00.sql [deleted file]
stargazer/inst/var/00-mysql-01.sql [deleted file]
stargazer/inst/var/01-alter-02.mysql.sql [deleted file]
stargazer/inst/var/01-alter-02.postgresql.sql [deleted file]
stargazer/inst/var/01-alter-02.sql [deleted file]
stargazer/inst/var/02-alter-03.postgresql.sql [deleted file]
stargazer/inst/var/02-alter-03.sql [deleted file]
stargazer/inst/var/base.dia [deleted file]
stargazer/inst/var/stargazer/admins/admin.adm [deleted file]
stargazer/inst/var/stargazer/tariffs/tariff.tf [deleted file]
stargazer/inst/var/stargazer/users/test/conf [deleted file]
stargazer/inst/var/stargazer/users/test/stat [deleted file]
stargazer/main.cpp [deleted file]
stargazer/pidfile.cpp [deleted file]
stargazer/pidfile.h [deleted file]
stargazer/plugin_mgr.cpp [deleted file]
stargazer/plugin_mgr.h [deleted file]
stargazer/plugin_runner.cpp [deleted file]
stargazer/plugin_runner.h [deleted file]
stargazer/plugins/CMakeLists.txt [deleted file]
stargazer/plugins/authorization/ao/ao.cpp [deleted file]
stargazer/plugins/authorization/ao/ao.h [deleted file]
stargazer/plugins/authorization/inetaccess/inetaccess.cpp [deleted file]
stargazer/plugins/authorization/inetaccess/inetaccess.h [deleted file]
stargazer/plugins/capture/cap_nf/cap_nf.cpp [deleted file]
stargazer/plugins/capture/cap_nf/cap_nf.h [deleted file]
stargazer/plugins/capture/divert_freebsd/divert_cap.cpp [deleted file]
stargazer/plugins/capture/divert_freebsd/divert_cap.h [deleted file]
stargazer/plugins/capture/ether_freebsd/ether_cap.cpp [deleted file]
stargazer/plugins/capture/ether_freebsd/ether_cap.h [deleted file]
stargazer/plugins/capture/ether_linux/ether_cap.cpp [deleted file]
stargazer/plugins/capture/ether_linux/ether_cap.h [deleted file]
stargazer/plugins/capture/nfqueue/nfqueue.cpp [deleted file]
stargazer/plugins/capture/nfqueue/nfqueue.h [deleted file]
stargazer/plugins/capture/pcap/pcap_cap.cpp [deleted file]
stargazer/plugins/capture/pcap/pcap_cap.h [deleted file]
stargazer/plugins/configuration/rpcconfig/admins_methods.cpp [deleted file]
stargazer/plugins/configuration/rpcconfig/admins_methods.h [deleted file]
stargazer/plugins/configuration/rpcconfig/info_methods.cpp [deleted file]
stargazer/plugins/configuration/rpcconfig/info_methods.h [deleted file]
stargazer/plugins/configuration/rpcconfig/messages_methods.cpp [deleted file]
stargazer/plugins/configuration/rpcconfig/messages_methods.h [deleted file]
stargazer/plugins/configuration/rpcconfig/rpcconfig.cpp [deleted file]
stargazer/plugins/configuration/rpcconfig/rpcconfig.h [deleted file]
stargazer/plugins/configuration/rpcconfig/tariff_helper.cpp [deleted file]
stargazer/plugins/configuration/rpcconfig/tariff_helper.h [deleted file]
stargazer/plugins/configuration/rpcconfig/tariffs_methods.cpp [deleted file]
stargazer/plugins/configuration/rpcconfig/tariffs_methods.h [deleted file]
stargazer/plugins/configuration/rpcconfig/user_helper.cpp [deleted file]
stargazer/plugins/configuration/rpcconfig/user_helper.h [deleted file]
stargazer/plugins/configuration/rpcconfig/users_methods.cpp [deleted file]
stargazer/plugins/configuration/rpcconfig/users_methods.h [deleted file]
stargazer/plugins/configuration/sgconfig/configproto.cpp [deleted file]
stargazer/plugins/configuration/sgconfig/configproto.h [deleted file]
stargazer/plugins/configuration/sgconfig/conn.cpp [deleted file]
stargazer/plugins/configuration/sgconfig/conn.h [deleted file]
stargazer/plugins/configuration/sgconfig/dumphelpers.h [deleted file]
stargazer/plugins/configuration/sgconfig/parser.cpp [deleted file]
stargazer/plugins/configuration/sgconfig/parser.h [deleted file]
stargazer/plugins/configuration/sgconfig/parser_admins.cpp [deleted file]
stargazer/plugins/configuration/sgconfig/parser_admins.h [deleted file]
stargazer/plugins/configuration/sgconfig/parser_auth_by.cpp [deleted file]
stargazer/plugins/configuration/sgconfig/parser_auth_by.h [deleted file]
stargazer/plugins/configuration/sgconfig/parser_message.cpp [deleted file]
stargazer/plugins/configuration/sgconfig/parser_message.h [deleted file]
stargazer/plugins/configuration/sgconfig/parser_server_info.cpp [deleted file]
stargazer/plugins/configuration/sgconfig/parser_server_info.h [deleted file]
stargazer/plugins/configuration/sgconfig/parser_services.cpp [deleted file]
stargazer/plugins/configuration/sgconfig/parser_services.h [deleted file]
stargazer/plugins/configuration/sgconfig/parser_tariffs.cpp [deleted file]
stargazer/plugins/configuration/sgconfig/parser_tariffs.h [deleted file]
stargazer/plugins/configuration/sgconfig/parser_user_info.cpp [deleted file]
stargazer/plugins/configuration/sgconfig/parser_user_info.h [deleted file]
stargazer/plugins/configuration/sgconfig/parser_users.cpp [deleted file]
stargazer/plugins/configuration/sgconfig/parser_users.h [deleted file]
stargazer/plugins/configuration/sgconfig/stgconfig.cpp [deleted file]
stargazer/plugins/configuration/sgconfig/stgconfig.h [deleted file]
stargazer/plugins/other/ping/ping.cpp [deleted file]
stargazer/plugins/other/ping/ping.h [deleted file]
stargazer/plugins/other/rscript/nrmap_parser.cpp [deleted file]
stargazer/plugins/other/rscript/nrmap_parser.h [deleted file]
stargazer/plugins/other/rscript/rscript.cpp [deleted file]
stargazer/plugins/other/rscript/rscript.h [deleted file]
stargazer/plugins/other/rscript/send_functor.h [deleted file]
stargazer/plugins/other/rscript/ur_functor.h [deleted file]
stargazer/plugins/other/smux/STG-MIB.mib [deleted file]
stargazer/plugins/other/smux/TODO [deleted file]
stargazer/plugins/other/smux/handlers.cpp [deleted file]
stargazer/plugins/other/smux/pen.h [deleted file]
stargazer/plugins/other/smux/sensors.cpp [deleted file]
stargazer/plugins/other/smux/sensors.h [deleted file]
stargazer/plugins/other/smux/smux.cpp [deleted file]
stargazer/plugins/other/smux/smux.h [deleted file]
stargazer/plugins/other/smux/tables.cpp [deleted file]
stargazer/plugins/other/smux/tables.h [deleted file]
stargazer/plugins/other/smux/types.cpp [deleted file]
stargazer/plugins/other/smux/types.h [deleted file]
stargazer/plugins/other/smux/utils.cpp [deleted file]
stargazer/plugins/other/smux/utils.h [deleted file]
stargazer/plugins/other/smux/value2os.h [deleted file]
stargazer/plugins/store/files/file_store.cpp [deleted file]
stargazer/plugins/store/files/file_store.h [deleted file]
stargazer/plugins/store/firebird/firebird_store.cpp [deleted file]
stargazer/plugins/store/firebird/firebird_store.h [deleted file]
stargazer/plugins/store/firebird/firebird_store_admins.cpp [deleted file]
stargazer/plugins/store/firebird/firebird_store_corporations.cpp [deleted file]
stargazer/plugins/store/firebird/firebird_store_messages.cpp [deleted file]
stargazer/plugins/store/firebird/firebird_store_services.cpp [deleted file]
stargazer/plugins/store/firebird/firebird_store_tariffs.cpp [deleted file]
stargazer/plugins/store/firebird/firebird_store_users.cpp [deleted file]
stargazer/plugins/store/firebird/firebird_store_utils.cpp [deleted file]
stargazer/plugins/store/mysql/mysql_store.cpp [deleted file]
stargazer/plugins/store/mysql/mysql_store.h [deleted file]
stargazer/plugins/store/postgresql/postgresql_store.cpp [deleted file]
stargazer/plugins/store/postgresql/postgresql_store.h [deleted file]
stargazer/plugins/store/postgresql/postgresql_store_admins.cpp [deleted file]
stargazer/plugins/store/postgresql/postgresql_store_corporations.cpp [deleted file]
stargazer/plugins/store/postgresql/postgresql_store_messages.cpp [deleted file]
stargazer/plugins/store/postgresql/postgresql_store_services.cpp [deleted file]
stargazer/plugins/store/postgresql/postgresql_store_tariffs.cpp [deleted file]
stargazer/plugins/store/postgresql/postgresql_store_users.cpp [deleted file]
stargazer/plugins/store/postgresql/postgresql_store_utils.cpp [deleted file]
stargazer/plugins/store/postgresql/postgresql_store_utils.h [deleted file]
stargazer/scripts/clean_db [deleted file]
stargazer/scripts/monitor [deleted file]
stargazer/scripts/shaper/OnConnect [deleted file]
stargazer/scripts/shaper/OnDisconnect [deleted file]
stargazer/scripts/shaper/Readme.txt [deleted file]
stargazer/scripts/shaper/shaper.sh [deleted file]
stargazer/scripts/shaper/shaper.stop.sh [deleted file]
stargazer/scripts/shaper_vpn_radius/Readme [deleted file]
stargazer/scripts/shaper_vpn_radius/firewall/firewall [deleted file]
stargazer/scripts/shaper_vpn_radius/freeradius/clients.conf [deleted file]
stargazer/scripts/shaper_vpn_radius/freeradius/radiusd.conf [deleted file]
stargazer/scripts/shaper_vpn_radius/ppp/ip-down.d/stg [deleted file]
stargazer/scripts/shaper_vpn_radius/ppp/ip-up.d/stg [deleted file]
stargazer/scripts/shaper_vpn_radius/ppp/pptpd-options [deleted file]
stargazer/scripts/shaper_vpn_radius/pptpd.conf [deleted file]
stargazer/scripts/shaper_vpn_radius/radiusclient/servers [deleted file]
stargazer/scripts/shaper_vpn_radius/stargazer/OnChange [deleted file]
stargazer/scripts/shaper_vpn_radius/stargazer/OnConnect [deleted file]
stargazer/scripts/shaper_vpn_radius/stargazer/OnDisconnect [deleted file]
stargazer/scripts/shaper_vpn_radius/stargazer/OnUserAdd [deleted file]
stargazer/scripts/shaper_vpn_radius/stargazer/OnUserDel [deleted file]
stargazer/scripts/shaper_vpn_radius/stargazer/rules [deleted file]
stargazer/scripts/shaper_vpn_radius/stargazer/stargazer.conf [deleted file]
stargazer/services_impl.cpp [deleted file]
stargazer/services_impl.h [deleted file]
stargazer/settings_impl.cpp [deleted file]
stargazer/settings_impl.h [deleted file]
stargazer/stg_timer.cpp [deleted file]
stargazer/stg_timer.h [deleted file]
stargazer/store_loader.cpp [deleted file]
stargazer/store_loader.h [deleted file]
stargazer/tariff_impl.cpp [deleted file]
stargazer/tariff_impl.h [deleted file]
stargazer/tariffs_impl.cpp [deleted file]
stargazer/tariffs_impl.h [deleted file]
stargazer/traffcounter_impl.cpp [deleted file]
stargazer/traffcounter_impl.h [deleted file]
stargazer/user_impl.cpp [deleted file]
stargazer/user_impl.h [deleted file]
stargazer/user_property.cpp [deleted file]
stargazer/users_impl.cpp [deleted file]
stargazer/users_impl.h [deleted file]
tests/CMakeLists.txt

index 2ca566860ad2ffd4ad05e47289998406376423cb..30deed57d12ebaafdce18794ca8880faebfd7179 100644 (file)
@@ -143,25 +143,8 @@ endif ()
 include_directories ( include )
 
 add_subdirectory ( libs )
-
-if ( BUILD_RSCRIPTD )
-    add_subdirectory ( rscriptd )
-endif ( BUILD_RSCRIPTD )
-
-if ( BUILD_SGAUTH )
-    add_subdirectory ( sgauth )
-endif ( BUILD_SGAUTH )
-
-if ( BUILD_SGCONF )
-    add_subdirectory ( sgconf )
-endif ( BUILD_SGCONF )
-
-if ( BUILD_STG )
-    add_subdirectory ( stargazer )
-endif ( BUILD_STG )
+add_subdirectory ( projects )
 
 if ( BUILD_TESTS )
     add_subdirectory ( tests )
 endif ( BUILD_TESTS )
-
-add_custom_target (cppcheck COMMAND cppcheck --enable=all --std=c++14 ${CMAKE_SOURCE_DIR}/rlm_stg ${CMAKE_SOURCE_DIR}/rscriptd ${CMAKE_SOURCE_DIR}/sgauth ${CMAKE_SOURCE_DIR}/sgconf ${CMAKE_SOURCE_DIR}/sgconv ${CMAKE_SOURCE_DIR}/stargazer)
index 00728cc8adf31edfa65780a4f534aad93809824d..83ec1b99ebeacb583f460dd5c4a9a0e8f7843384 100755 (executable)
@@ -16,7 +16,7 @@ then
     exit -1
 fi
 
-STGPATH="$BASEPATH/stg/build/stargazer"
+STGPATH="$BASEPATH/stg/build/projects/stargazer"
 
 cp "stuff/stargazer-files.conf" "$STGPATH/stargazer.conf"
 cp "stuff/rules" "$STGPATH/"
index 3bedb37a46a7e17acc0ad0cb472550763a692d16..562d5e1d94af4c2ee535eaf973fe2be16e7d6294 100755 (executable)
@@ -4,7 +4,7 @@ source `dirname $0`/functions
 
 BASEPATH=$1
 
-SGCONFPATH="$BASEPATH/stg/build/sgconf"
+SGCONFPATH="$BASEPATH/stg/build/projects/sgconf"
 
 printf "Check initial admin list... "
 
index f41f470e9bbe46e5e15fe4246842a51ff94fae18..ac729b9fb03d41f4e09c27741afcfc9609f07653 100755 (executable)
@@ -4,7 +4,7 @@ source `dirname $0`/functions
 
 BASEPATH=$1
 
-SGCONFPATH="$BASEPATH/stg/build/sgconf"
+SGCONFPATH="$BASEPATH/stg/build/projects/sgconf"
 
 printf "Check server info... "
 
index aaca9d01da185d3158667e6feae36e52bdf4e0b0..97c3c7440a757ad4af9070962fd3c877129a8c78 100755 (executable)
@@ -4,7 +4,7 @@ source `dirname $0`/functions
 
 BASEPATH=$1
 
-SGCONFPATH="$BASEPATH/stg/build/sgconf"
+SGCONFPATH="$BASEPATH/stg/build/projects/sgconf"
 
 printf "Check initial service list... "
 
diff --git a/projects/rscriptd/CMakeLists.txt b/projects/rscriptd/CMakeLists.txt
new file mode 100644 (file)
index 0000000..9228b37
--- /dev/null
@@ -0,0 +1,10 @@
+set ( CPP_FILES main.cpp listener.cpp pidfile.cpp )
+
+set ( THREADS_PREFER_PTHREAD_FLAG ON )
+find_package ( Threads REQUIRED )
+
+add_executable ( rscriptd ${CPP_FILES} )
+
+target_link_libraries ( rscriptd scriptexecuter conffiles logger crypto common Threads::Threads )
+
+# TODO: install
diff --git a/projects/rscriptd/listener.cpp b/projects/rscriptd/listener.cpp
new file mode 100644 (file)
index 0000000..3d8fd48
--- /dev/null
@@ -0,0 +1,513 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#include <arpa/inet.h>
+#include <sys/uio.h> // readv
+#include <sys/types.h> // for historical versions of BSD
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <unistd.h>
+
+#include <csignal>
+#include <cerrno>
+#include <ctime>
+#include <cstring>
+#include <sstream>
+#include <algorithm>
+
+#include "stg/scriptexecuter.h"
+#include "stg/locker.h"
+#include "stg/common.h"
+#include "stg/const.h"
+#include "listener.h"
+
+void InitEncrypt(BLOWFISH_CTX * ctx, const std::string & password);
+void Decrypt(BLOWFISH_CTX * ctx, char * dst, const char * src, int len8);
+
+//-----------------------------------------------------------------------------
+LISTENER::LISTENER()
+    : WriteServLog(STG::Logger::get()),
+      port(0),
+      running(false),
+      receiverStopped(true),
+      processorStopped(true),
+      userTimeout(0),
+      listenSocket(0),
+      version("rscriptd listener v.1.2")
+{
+pthread_mutex_init(&mutex, NULL);
+}
+//-----------------------------------------------------------------------------
+void LISTENER::SetPassword(const std::string & p)
+{
+password = p;
+printfd(__FILE__, "Encryption initiated with password \'%s\'\n", password.c_str());
+InitEncrypt(&ctxS, password);
+}
+//-----------------------------------------------------------------------------
+bool LISTENER::Start()
+{
+printfd(__FILE__, "LISTENER::Start()\n");
+running = true;
+
+if (PrepareNet())
+    {
+    return true;
+    }
+
+if (receiverStopped)
+    {
+    if (pthread_create(&receiverThread, NULL, Run, this))
+        {
+        errorStr = "Cannot create thread.";
+        return true;
+        }
+    }
+
+if (processorStopped)
+    {
+    if (pthread_create(&processorThread, NULL, RunProcessor, this))
+        {
+        errorStr = "Cannot create thread.";
+        return true;
+        }
+    }
+
+errorStr = "";
+
+return false;
+}
+//-----------------------------------------------------------------------------
+bool LISTENER::Stop()
+{
+running = false;
+
+printfd(__FILE__, "LISTENER::Stop()\n");
+
+struct timespec ts = {0, 500000000};
+nanosleep(&ts, NULL);
+
+if (!processorStopped)
+    {
+    //5 seconds to thread stops itself
+    for (int i = 0; i < 25 && !processorStopped; i++)
+        {
+        struct timespec ts = {0, 200000000};
+        nanosleep(&ts, NULL);
+        }
+
+    //after 5 seconds waiting thread still running. now killing it
+    if (!processorStopped)
+        {
+        //TODO pthread_cancel()
+        if (pthread_kill(processorThread, SIGINT))
+            {
+            errorStr = "Cannot kill thread.";
+            return true;
+            }
+        printfd(__FILE__, "LISTENER killed Timeouter\n");
+        }
+    }
+
+if (!receiverStopped)
+    {
+    //5 seconds to thread stops itself
+    for (int i = 0; i < 25 && !receiverStopped; i++)
+        {
+        struct timespec ts = {0, 200000000};
+        nanosleep(&ts, NULL);
+        }
+
+    //after 5 seconds waiting thread still running. now killing it
+    if (!receiverStopped)
+        {
+        //TODO pthread_cancel()
+        if (pthread_kill(receiverThread, SIGINT))
+            {
+            errorStr = "Cannot kill thread.";
+            return true;
+            }
+        printfd(__FILE__, "LISTENER killed Run\n");
+        }
+    }
+
+pthread_join(receiverThread, NULL);
+pthread_join(processorThread, NULL);
+
+pthread_mutex_destroy(&mutex);
+
+FinalizeNet();
+
+std::for_each(users.begin(), users.end(), DisconnectUser(*this));
+
+printfd(__FILE__, "LISTENER::Stoped successfully.\n");
+
+return false;
+}
+//-----------------------------------------------------------------------------
+void * LISTENER::Run(void * d)
+{
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+LISTENER * listener = static_cast<LISTENER *>(d);
+
+listener->Runner();
+
+return NULL;
+}
+//-----------------------------------------------------------------------------
+void LISTENER::Runner()
+{
+receiverStopped = false;
+
+while (running)
+    {
+    RecvPacket();
+    }
+
+receiverStopped = true;
+}
+//-----------------------------------------------------------------------------
+void * LISTENER::RunProcessor(void * d)
+{
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+LISTENER * listener = static_cast<LISTENER *>(d);
+
+listener->ProcessorRunner();
+
+return NULL;
+}
+//-----------------------------------------------------------------------------
+void LISTENER::ProcessorRunner()
+{
+processorStopped = false;
+
+while (running)
+    {
+    struct timespec ts = {0, 500000000};
+    nanosleep(&ts, NULL);
+    if (!pending.empty())
+        ProcessPending();
+    ProcessTimeouts();
+    }
+
+processorStopped = true;
+}
+//-----------------------------------------------------------------------------
+bool LISTENER::PrepareNet()
+{
+listenSocket = socket(AF_INET, SOCK_DGRAM, 0);
+
+if (listenSocket < 0)
+    {
+    errorStr = "Cannot create socket.";
+    return true;
+    }
+
+struct sockaddr_in listenAddr;
+listenAddr.sin_family = AF_INET;
+listenAddr.sin_port = htons(port);
+listenAddr.sin_addr.s_addr = inet_addr("0.0.0.0");
+
+if (bind(listenSocket, (struct sockaddr*)&listenAddr, sizeof(listenAddr)) < 0)
+    {
+    errorStr = "LISTENER: Bind failed.";
+    return true;
+    }
+
+printfd(__FILE__, "LISTENER::PrepareNet() >>>> Start successfull.\n");
+
+return false;
+}
+//-----------------------------------------------------------------------------
+bool LISTENER::FinalizeNet()
+{
+close(listenSocket);
+
+return false;
+}
+//-----------------------------------------------------------------------------
+bool LISTENER::RecvPacket()
+{
+struct iovec iov[2];
+
+char buffer[RS_MAX_PACKET_LEN];
+RS::PACKET_HEADER packetHead;
+
+iov[0].iov_base = reinterpret_cast<char *>(&packetHead);
+iov[0].iov_len = sizeof(packetHead);
+iov[1].iov_base = buffer;
+iov[1].iov_len = sizeof(buffer) - sizeof(packetHead);
+
+size_t dataLen = 0;
+while (dataLen < sizeof(buffer))
+    {
+    if (!WaitPackets(listenSocket))
+        {
+        if (!running)
+            return false;
+        continue;
+        }
+    int portion = readv(listenSocket, iov, 2);
+    if (portion < 0)
+        {
+        return true;
+        }
+    dataLen += portion;
+    }
+
+if (CheckHeader(packetHead))
+    {
+    printfd(__FILE__, "Invalid packet or incorrect protocol version!\n");
+    return true;
+    }
+
+std::string userLogin((char *)packetHead.login);
+PendingData data;
+data.login = userLogin;
+data.ip = ntohl(packetHead.ip);
+data.id = ntohl(packetHead.id);
+
+if (packetHead.packetType == RS_ALIVE_PACKET)
+    {
+    data.type = PendingData::ALIVE;
+    }
+else if (packetHead.packetType == RS_CONNECT_PACKET)
+    {
+    data.type = PendingData::CONNECT;
+    if (GetParams(buffer, data))
+        {
+        return true;
+        }
+    }
+else if (packetHead.packetType == RS_DISCONNECT_PACKET)
+    {
+    data.type = PendingData::DISCONNECT;
+    if (GetParams(buffer, data))
+        {
+        return true;
+        }
+    }
+
+STG_LOCKER lock(&mutex);
+pending.push_back(data);
+
+return false;
+}
+//-----------------------------------------------------------------------------
+bool LISTENER::GetParams(char * buffer, UserData & data)
+{
+RS::PACKET_TAIL packetTail;
+
+Decrypt(&ctxS, (char *)&packetTail, buffer, sizeof(packetTail) / 8);
+
+if (strncmp((char *)packetTail.magic, RS_ID, RS_MAGIC_LEN))
+    {
+    printfd(__FILE__, "Invalid crypto magic\n");
+    return true;
+    }
+
+std::ostringstream params;
+params << "\"" << data.login << "\" "
+       << inet_ntostring(data.ip) << " "
+       << data.id << " "
+       << (char *)packetTail.params;
+
+data.params = params.str();
+
+return false;
+}
+//-----------------------------------------------------------------------------
+void LISTENER::ProcessPending()
+{
+std::list<PendingData>::iterator it(pending.begin());
+size_t count = 0;
+printfd(__FILE__, "Pending: %d\n", pending.size());
+while (it != pending.end() && count < 256)
+    {
+    std::vector<AliveData>::iterator uit(
+            std::lower_bound(
+                users.begin(),
+                users.end(),
+                it->login)
+            );
+    if (it->type == PendingData::CONNECT)
+        {
+        printfd(__FILE__, "Connect packet\n");
+        if (uit == users.end() || uit->login != it->login)
+            {
+            printfd(__FILE__, "Connect new user '%s'\n", it->login.c_str());
+            // Add new user
+            Connect(*it);
+            users.insert(uit, AliveData(static_cast<UserData>(*it)));
+            }
+        else if (uit->login == it->login)
+            {
+            printfd(__FILE__, "Update existing user '%s'\n", it->login.c_str());
+            // Update already existing user
+            time(&uit->lastAlive);
+            uit->params = it->params;
+            }
+        else
+            {
+            printfd(__FILE__, "Hmmm... Strange connect for '%s'\n", it->login.c_str());
+            }
+        }
+    else if (it->type == PendingData::ALIVE)
+        {
+        printfd(__FILE__, "Alive packet\n");
+        if (uit != users.end() && uit->login == it->login)
+            {
+            printfd(__FILE__, "Alive user '%s'\n", it->login.c_str());
+            // Update existing user
+            time(&uit->lastAlive);
+            }
+        else
+            {
+            printfd(__FILE__, "Alive user '%s' is not found\n", it->login.c_str());
+            }
+        }
+    else if (it->type == PendingData::DISCONNECT)
+        {
+        printfd(__FILE__, "Disconnect packet\n");
+        if (uit != users.end() && uit->login == it->login.c_str())
+            {
+            printfd(__FILE__, "Disconnect user '%s'\n", it->login.c_str());
+            // Disconnect existing user
+            uit->params = it->params;
+            Disconnect(*uit);
+            users.erase(uit);
+            }
+        else
+            {
+            printfd(__FILE__, "Cannot find user '%s' for disconnect\n", it->login.c_str());
+            }
+        }
+    else
+        {
+        printfd(__FILE__, "Unknown packet type\n");
+        }
+    ++it;
+    ++count;
+    }
+STG_LOCKER lock(&mutex);
+pending.erase(pending.begin(), it);
+}
+//-----------------------------------------------------------------------------
+void LISTENER::ProcessTimeouts()
+{
+const std::vector<AliveData>::iterator it(
+        std::stable_partition(
+            users.begin(),
+            users.end(),
+            IsNotTimedOut(userTimeout)
+        )
+    );
+
+if (it != users.end())
+    {
+    printfd(__FILE__, "Total users: %d, users to disconnect: %d\n", users.size(), std::distance(it, users.end()));
+
+    std::for_each(
+            it,
+            users.end(),
+            DisconnectUser(*this)
+        );
+
+    users.erase(it, users.end());
+    }
+}
+//-----------------------------------------------------------------------------
+bool LISTENER::Connect(const UserData & data) const
+{
+printfd(__FILE__, "Connect %s\n", data.login.c_str());
+if (access(scriptOnConnect.c_str(), X_OK) == 0)
+    {
+    if (ScriptExec((scriptOnConnect + " " + data.params).c_str()))
+        {
+        WriteServLog("Script %s cannot be executed for an unknown reason.", scriptOnConnect.c_str());
+        return true;
+        }
+    }
+else
+    {
+    WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
+    return true;
+    }
+return false;
+}
+//-----------------------------------------------------------------------------
+bool LISTENER::Disconnect(const UserData & data) const
+{
+printfd(__FILE__, "Disconnect %s\n", data.login.c_str());
+if (access(scriptOnDisconnect.c_str(), X_OK) == 0)
+    {
+    if (ScriptExec((scriptOnDisconnect + " " + data.params).c_str()))
+        {
+        WriteServLog("Script %s cannot be executed for an unknown reson.", scriptOnDisconnect.c_str());
+        return true;
+        }
+    }
+else
+    {
+    WriteServLog("Script %s cannot be executed. File not found.", scriptOnDisconnect.c_str());
+    return true;
+    }
+return false;
+}
+//-----------------------------------------------------------------------------
+bool LISTENER::CheckHeader(const RS::PACKET_HEADER & header) const
+{
+if (strncmp((char *)header.magic, RS_ID, RS_MAGIC_LEN))
+    {
+    return true;
+    }
+if (strncmp((char *)header.protoVer, "02", RS_PROTO_VER_LEN))
+    {
+    return true;
+    }
+return false;
+}
+//-----------------------------------------------------------------------------
+inline
+void InitEncrypt(BLOWFISH_CTX * ctx, const std::string & password)
+{
+unsigned char keyL[PASSWD_LEN];
+memset(keyL, 0, PASSWD_LEN);
+strncpy((char *)keyL, password.c_str(), PASSWD_LEN);
+Blowfish_Init(ctx, keyL, PASSWD_LEN);
+}
+//-----------------------------------------------------------------------------
+inline
+void Decrypt(BLOWFISH_CTX * ctx, char * dst, const char * src, int len8)
+{
+if (dst != src)
+    memcpy(dst, src, len8 * 8);
+
+for (int i = 0; i < len8; i++)
+    Blowfish_Decrypt(ctx, (uint32_t *)(dst + i * 8), (uint32_t *)(dst + i * 8 + 4));
+}
+//-----------------------------------------------------------------------------
diff --git a/projects/rscriptd/listener.h b/projects/rscriptd/listener.h
new file mode 100644 (file)
index 0000000..7fb71ee
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#include <pthread.h>
+
+#include <string>
+#include <vector>
+#include <list>
+#include <functional>
+#include <cstdint>
+
+#include "stg/blowfish.h"
+#include "stg/rs_packets.h"
+#include "stg/logger.h"
+
+struct UserData
+{
+    std::string params;
+    std::string login;
+    uint32_t    ip;
+    uint32_t    id;
+};
+
+struct PendingData : public UserData
+{
+    enum {CONNECT, ALIVE, DISCONNECT} type;
+};
+
+struct AliveData : public UserData
+{
+    explicit AliveData(const UserData & data)
+        : UserData(data),
+          lastAlive(time(NULL))
+    {};
+    bool operator<(const std::string & rvalue) const { return login < rvalue; };
+    time_t      lastAlive;
+};
+
+class IsNotTimedOut : public std::unary_function<const AliveData &, bool> {
+    public:
+        explicit IsNotTimedOut(double to) : timeout(to), now(time(NULL)) {}
+        bool operator()(const AliveData & data) const
+        {
+            return difftime(now, data.lastAlive) < timeout;
+        }
+    private:
+        double timeout;
+        time_t now;
+};
+
+class LISTENER
+{
+public:
+                        LISTENER();
+                        ~LISTENER(){};
+
+    void                SetPort(uint16_t p) { port = p; };
+    void                SetPassword(const std::string & p);
+    void                SetUserTimeout(int t) { userTimeout = t; };
+    void                SetScriptOnConnect(const std::string & script) { scriptOnConnect = script; };
+    void                SetScriptOnDisconnect(const std::string & script) { scriptOnDisconnect = script; };
+
+    bool                Start();
+    bool                Stop();
+    bool                IsRunning() const { return !receiverStopped && !processorStopped; };
+
+    const std::string & GetStrError() const { return errorStr; };
+    const std::string & GetVersion() const { return version; };
+
+private:
+    // Threading stuff
+    static void *       Run(void * self);
+    static void *       RunProcessor(void * self);
+    void                Runner();
+    void                ProcessorRunner();
+    // Networking stuff
+    bool                PrepareNet();
+    bool                FinalizeNet();
+    bool                RecvPacket();
+    // Parsing stuff
+    bool                CheckHeader(const RS::PACKET_HEADER & header) const;
+    bool                GetParams(char * buffer, UserData & data);
+    // Processing stuff
+    void                ProcessPending();
+    void                ProcessTimeouts();
+    bool                Disconnect(const UserData & data) const;
+    bool                Connect(const UserData & data) const;
+
+    BLOWFISH_CTX        ctxS;
+    STG::Logger&        WriteServLog;
+
+    mutable std::string errorStr;
+    std::string         scriptOnConnect;
+    std::string         scriptOnDisconnect;
+    std::string         password;
+    uint16_t            port;
+
+    bool                running;
+    bool                receiverStopped;
+    bool                processorStopped;
+    std::vector<AliveData> users;
+    std::list<PendingData> pending;
+    int                 userTimeout;
+
+    pthread_t           receiverThread;
+    pthread_t           processorThread;
+    pthread_mutex_t     mutex;
+
+    int                 listenSocket;
+
+    std::string         version;
+
+    friend class DisconnectUser;
+};
+
+class DisconnectUser : public std::unary_function<const UserData &, void> {
+    public:
+        explicit DisconnectUser(LISTENER & l) : listener(l) {};
+        void operator()(const UserData & data)
+        {
+            listener.Disconnect(data);
+        };
+    private:
+        LISTENER & listener;
+};
+//-----------------------------------------------------------------------------
diff --git a/projects/rscriptd/main.cpp b/projects/rscriptd/main.cpp
new file mode 100644 (file)
index 0000000..e7c54ee
--- /dev/null
@@ -0,0 +1,337 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+ /*
+ $Revision: 1.19 $
+ $Author: faust $
+ $Date: 2010/09/10 06:37:45 $
+ */
+
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <fcntl.h> // creat
+#include <unistd.h>
+
+#include <cstdlib>
+#include <cstdio>
+#include <csignal>
+#include <cerrno>
+#include <cstring> // strerror
+#include <set>
+
+#include "stg/common.h"
+#include "stg/logger.h"
+#include "stg/scriptexecuter.h"
+#include "stg/conffiles.h"
+#include "stg/version.h"
+#include "listener.h"
+#include "pidfile.h"
+
+#ifdef DEBUG
+# define MAIN_DEBUG  1
+# define NO_DAEMON    1
+#endif
+
+#define START_FILE "/._ST_ART_ED_"
+
+std::set<pid_t> executersPid;
+volatile time_t stgTime = time(NULL);
+
+//-----------------------------------------------------------------------------
+void KillExecuters()
+{
+std::set<pid_t>::iterator pid;
+pid = executersPid.begin();
+while (pid != executersPid.end())
+    {
+    printfd(__FILE__, "KillExecuters pid=%d\n", *pid);
+    kill(*pid, SIGUSR1);
+    ++pid;
+    }
+}
+//-----------------------------------------------------------------------------
+#if defined(LINUX) || defined(DARWIN)
+int StartScriptExecuter(char * procName, int msgKey, int * msgID)
+#else
+int StartScriptExecuter(char *, int msgKey, int * msgID)
+#endif
+{
+auto & WriteServLog = STG::Logger::get();
+
+if (*msgID == -11)   // If msgID == -11 - first call. Create queue
+    {
+    for (int i = 0; i < 2; i++)
+        {
+        *msgID = msgget(msgKey, IPC_CREAT | IPC_EXCL | 0600);
+
+        if (*msgID == -1)
+            {
+            *msgID = msgget(msgKey, 0);
+            if (*msgID == -1)
+                {
+                WriteServLog("Message queue not created.");
+                return -1;
+                }
+            else
+                {
+                msgctl(*msgID, IPC_RMID, NULL);
+                }
+            }
+        else
+            {
+            WriteServLog("Message queue created successfully. msgKey=%d msgID=%d", msgKey, *msgID);
+            break;
+            }
+        }
+    }
+
+pid_t executerPid = fork();
+
+switch (executerPid)
+    {
+    case -1:    // Failure
+        WriteServLog("Fork error!");
+        return -1;
+
+    case 0:     // Child
+        //close(0);
+        //close(1);
+        //close(2);
+        //setsid();
+#if defined(LINUX) || defined(DARWIN)
+        Executer(*msgID, executerPid, procName);
+#else
+        Executer(*msgID, executerPid);
+#endif
+        return 1;
+
+    default:    // Parent
+        if (executersPid.empty())
+#if defined(LINUX) || defined(DARWIN)
+            Executer(*msgID, executerPid, NULL);
+#else
+            Executer(*msgID, executerPid);
+#endif
+        executersPid.insert(executerPid);
+    }
+return 0;
+}
+//-----------------------------------------------------------------------------
+void StopScriptExecuter(int msgID)
+{
+auto & WriteServLog = STG::Logger::get();
+
+for (int i = 0; i < 5; ++i)
+    {
+    struct msqid_ds data;
+    if (msgctl(msgID, IPC_STAT, &data))
+        {
+        int e = errno;
+        printfd(__FILE__, "StopScriptExecuter() - msgctl for IPC_STAT failed: '%s'\n", strerror(e));
+        WriteServLog( "Failed to check queue emptiness: '%s'", strerror(e));
+        break;
+        }
+
+    WriteServLog("Messages in queue: %d", data.msg_qnum);
+
+    if (data.msg_qnum == 0)
+        break;
+
+    struct timespec ts = {1, 0};
+    nanosleep(&ts, NULL);
+    }
+
+if (msgctl(msgID, IPC_RMID, NULL))
+    {
+    int e = errno;
+    printfd(__FILE__, "StopScriptExecuter() - msgctl for IPC_STAT failed: '%s'\n", strerror(e));
+    WriteServLog("Failed to remove queue: '%s'", strerror(e));
+    }
+else
+    {
+    WriteServLog("Queue removed successfully.");
+    }
+
+KillExecuters();
+}
+//-----------------------------------------------------------------------------
+#ifdef NO_DAEMON
+int ForkAndWait(const std::string &)
+#else
+int ForkAndWait(const std::string & confDir)
+#endif
+{
+#ifndef NO_DAEMON
+pid_t childPid = fork();
+
+switch (childPid)
+    {
+    case -1:    // Failure
+        return -1;
+        break;
+
+    case 0:     // Child
+        //close(0);
+        close(1);
+        close(2);
+        setsid();
+        break;
+
+    default:    // Parent
+        exit(1);
+        break;
+    }
+#endif
+return 0;
+}
+//-----------------------------------------------------------------------------
+int main(int argc, char * argv[])
+{
+CONFIGFILE * cfg = NULL;
+LISTENER * listener = NULL;
+int msgID = -11;
+int execNum = 0;
+int execMsgKey = 0;
+
+std::string logFileName;
+std::string confDir;
+std::string password;
+std::string onConnect;
+std::string onDisconnect;
+int port;
+int userTimeout;
+
+if (getuid())
+    {
+    printf("You must be root. Exit.\n");
+    exit(1);
+    }
+
+if (argc == 2)
+    cfg = new CONFIGFILE(argv[1]);
+else
+    cfg = new CONFIGFILE("/etc/rscriptd/rscriptd.conf");
+
+if (cfg->Error())
+    {
+    auto & WriteServLog = STG::Logger::get();
+    WriteServLog.setFileName("/var/log/rscriptd.log");
+    WriteServLog("Error reading config file!");
+    delete cfg;
+    return EXIT_FAILURE;
+    }
+
+cfg->ReadString("LogFileName", &logFileName, "/var/log/rscriptd.log");
+cfg->ReadInt("ExecutersNum", &execNum, 1);
+cfg->ReadInt("ExecMsgKey", &execMsgKey, 5555);
+cfg->ReadString("ConfigDir", &confDir, "/etc/rscriptd");
+cfg->ReadString("Password", &password, "");
+cfg->ReadInt("Port", &port, 5555);
+cfg->ReadInt("UserTimeout", &userTimeout, 60);
+cfg->ReadString("ScriptOnConnect", &onConnect, "/etc/rscriptd/OnConnect");
+cfg->ReadString("ScriptOnDisconnect", &onDisconnect, "/etc/rscriptd/OnDisconnect");
+
+if (ForkAndWait(confDir) < 0)
+    {
+    auto & WriteServLog = STG::Logger::get();
+    WriteServLog("Fork error!");
+    delete cfg;
+    return EXIT_FAILURE;
+    }
+
+auto & WriteServLog = STG::Logger::get();
+PIDFile pidFile("/var/run/rscriptd.pid");
+WriteServLog.setFileName(logFileName);
+WriteServLog("rscriptd v. %s", SERVER_VERSION);
+
+for (int i = 0; i < execNum; i++)
+    {
+    int ret = StartScriptExecuter(argv[0], execMsgKey, &msgID);
+    if (ret < 0)
+        {
+        STG::Logger::get()("Start Script Executer error!");
+        delete cfg;
+        return EXIT_FAILURE;
+        }
+    if (ret == 1)
+        {
+        delete cfg;
+        return EXIT_SUCCESS;
+        }
+    }
+
+listener = new LISTENER();
+listener->SetPort(port);
+listener->SetPassword(password);
+listener->SetUserTimeout(userTimeout);
+listener->SetScriptOnConnect(onConnect);
+listener->SetScriptOnDisconnect(onDisconnect);
+
+listener->Start();
+
+WriteServLog("rscriptd started successfully.");
+WriteServLog("+++++++++++++++++++++++++++++++++++++++++++++");
+
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+while (true)
+    {
+    sigfillset(&signalSet);
+    int sig = 0;
+    printfd(__FILE__, "Before sigwait\n");
+    sigwait(&signalSet, &sig);
+    printfd(__FILE__, "After sigwait. Signal: %d\n", sig);
+    bool stop = false;
+    switch (sig)
+        {
+        case SIGTERM:
+            stop = true;
+            break;
+        case SIGINT:
+            stop = true;
+            break;
+        default:
+            WriteServLog("Ignore signel %d", sig);
+            break;
+        }
+    if (stop)
+        break;
+    }
+
+listener->Stop();
+
+WriteServLog("+++++++++++++++++++++++++++++++++++++++++++++");
+
+StopScriptExecuter(msgID);
+
+WriteServLog("rscriptd stopped successfully.");
+WriteServLog("---------------------------------------------");
+
+delete listener;
+delete cfg;
+return EXIT_SUCCESS;
+}
+//-----------------------------------------------------------------------------
diff --git a/projects/rscriptd/pidfile.cpp b/projects/rscriptd/pidfile.cpp
new file mode 100644 (file)
index 0000000..5f3f497
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+/*
+ $Revision: 1.1 $
+ $Date: 2010/02/11 12:32:25 $
+ $Author: faust $
+ */
+
+/*
+ *  An implementation of RAII pid-file writer
+ */
+
+#include <fstream>
+#include <unistd.h>
+
+#include "pidfile.h"
+
+PIDFile::PIDFile(const std::string & fn)
+    : fileName(fn)
+{
+if (fileName != "")
+    {
+    std::ofstream pf(fileName.c_str());
+    pf << getpid() << std::endl;
+    pf.close();
+    }
+}
+
+PIDFile::~PIDFile()
+{
+if (fileName != "")
+    {
+    unlink(fileName.c_str());
+    }
+}
diff --git a/projects/rscriptd/pidfile.h b/projects/rscriptd/pidfile.h
new file mode 100644 (file)
index 0000000..82ff003
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+/*
+ *  Header file for RAII pid-file writer
+ */
+
+/*
+ $Revision: 1.1 $
+ $Date: 2010/02/11 12:32:25 $
+ $Author: faust $
+ */
+
+#ifndef __PID_FILE_H__
+#define __PID_FILE_H__
+
+#include <string>
+
+class PIDFile {
+public:
+    explicit PIDFile(const std::string & fn);
+    ~PIDFile();
+private:
+    std::string fileName;
+};
+
+#endif
diff --git a/projects/rscriptd/rscriptd.conf b/projects/rscriptd/rscriptd.conf
new file mode 100644 (file)
index 0000000..45b7b5c
--- /dev/null
@@ -0,0 +1,68 @@
+################################################################################
+#                         Rscriptd Configuration file                          #
+################################################################################
+
+# LOG file name
+# Parameter: optional
+# Value: file path
+# Default: /var/log/rscriptd.log
+LogFileName = /var/log/rscriptd.log
+
+# Amount of rscriptd-exec processes.
+# These processes are responsible for the execution of scripts 
+# OnConnect and OnDisconnect.
+# Amount of processes means how many scripts can be executed simultaneously.
+# Recommend to leave 1 to avoid errors when executing scripts
+# Parameter: optional
+# Value: 1 ... 1024
+# Default: 1
+ExecutersNum = 1
+
+# Message queue identifier for the script executer.
+# It may be changed if there're a needs to run multiple copies of rscriptd.
+# Warning: If you do not understand it, do not touch this setting!
+# Parameter: optional
+# Value: 0 ... 2 ^ 32
+# Default: 5555
+# ExecMsgKey = 5555
+
+# The path to directory where config files are
+# Parameter: optional
+# Value: directory path
+# Default: /etc/rscriptd
+ConfigDir = /etc/rscriptd
+
+# Defines password for the encryption exchange between
+# Stargazer server and rscriptd.
+# Parameter: optional
+# Value: any
+# Default: 123456
+Password = 123456
+
+# Defines port number for communication between
+# Stargazer server and rscriptd.
+# Parameter: optional
+# Value: 1 ... 65535
+# Default: 9999
+Port = 9999
+
+# User timeout. If Stargazer does not respond during this time,
+# the user will be disconnected.
+# Parameter: optional
+# Values: 5 ... 600
+# Default: 60
+UserTimeout = 60
+
+# Defines file which runs when user gets access
+# Parameter: optional
+# Value: file path
+# Default: /etc/rscriptd/OnConnect
+ScriptOnConnect = /etc/rscriptd/OnConnect
+
+# Defines file which runs when user loses access
+# Parameter: optional
+# Value: file path
+# Default: /etc/rscriptd/OnDisconnect
+ScriptOnDisconnect = /etc/rscriptd/OnDisconnect
+
+################################################################################
diff --git a/projects/sgauth/.gitignore b/projects/sgauth/.gitignore
new file mode 100644 (file)
index 0000000..f4bcc89
--- /dev/null
@@ -0,0 +1,2 @@
+css.h
+sgauth
diff --git a/projects/sgauth/CMakeLists.txt b/projects/sgauth/CMakeLists.txt
new file mode 100644 (file)
index 0000000..2a87f3f
--- /dev/null
@@ -0,0 +1,18 @@
+set ( CPP_FILES main.cpp settings_impl.cpp web.cpp )
+
+set ( THREADS_PREFER_PTHREAD_FLAG ON )
+find_package ( Threads REQUIRED )
+find_package ( Intl REQUIRED )
+
+file ( READ sgauth.css CSS_DATA )
+configure_file ( css.h.in css.h ESCAPE_QUOTES @ONLY )
+
+set ( CMAKE_INCLUDE_CURRENT_DIR ON )
+
+include_directories ( ${Intl_INCLUDE_DIRS} )
+
+add_executable ( sgauth ${CPP_FILES} )
+
+target_link_libraries ( sgauth conffiles ia crypto common ${Intl_LIBRARIES} Threads::Threads )
+
+# TODO: install
diff --git a/projects/sgauth/css.h.in b/projects/sgauth/css.h.in
new file mode 100644 (file)
index 0000000..5a14125
--- /dev/null
@@ -0,0 +1,10 @@
+#pragma once
+
+namespace SGAuth
+{
+
+const auto css = R"EOR(
+@CSS_DATA@
+)EOR";
+
+}
diff --git a/projects/sgauth/main.cpp b/projects/sgauth/main.cpp
new file mode 100644 (file)
index 0000000..3256ae5
--- /dev/null
@@ -0,0 +1,278 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+ /*
+ $Revision: 1.13 $
+ $Date: 2010/04/14 09:01:29 $
+ $Author: faust $
+ */
+
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <csignal>
+#include <cstdio>
+#include <cstring>
+#include <iostream>
+#include <vector>
+
+#include "stg/ia.h"
+#include "stg/common.h"
+#include "web.h"
+#include "settings_impl.h"
+
+int mes;
+char infoText[256];
+char messageText[256];
+
+const int winKOI = 0;
+
+IA_CLIENT_PROT * clnp;
+WEB * web = NULL;
+
+time_t stgTime;
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void Usage()
+{
+printf("sgauth <path_to_config>\n");
+}
+//-----------------------------------------------------------------------------
+void SetDirName(const std::vector<std::string> & dn, void *)
+{
+for (int j = 0; j < DIR_NUM; j++)
+    {
+    if (winKOI)
+        {
+        std::string dir;
+        KOIToWin(dn[j], &dir);
+        if (web)
+            web->SetDirName(dir, j);
+        }
+    else
+        {
+        if (web)
+            web->SetDirName(dn[j], j);
+        }
+    }
+}
+//-----------------------------------------------------------------------------
+void StatUpdate(const LOADSTAT & ls, void *)
+{
+if (web)
+    web->UpdateStat(ls);
+}
+//-----------------------------------------------------------------------------
+void StatusChanged(int, void *)
+{
+}
+//-----------------------------------------------------------------------------
+void ShowMessage(const std::string & message, int i, int, int, void *)
+{
+if (web)
+    web->AddMessage(message, i);
+}
+//-----------------------------------------------------------------------------
+void ShowError(const std::string & message, int, void *)
+{
+if (web)
+     web->AddMessage(message, 0);
+}
+//-----------------------------------------------------------------------------
+void CatchUSR1(int)
+{
+if (clnp->GetAuthorized())
+    {
+    std::cout << "Connect" << std::endl;
+    clnp->Connect();
+    }
+}
+//-----------------------------------------------------------------------------
+void CatchUSR2(int)
+{
+std::cout << "Disconnect" << std::endl;
+clnp->Disconnect();
+}
+//-----------------------------------------------------------------------------
+void CatchTERM(int)
+{
+std::cout << "Terminated" << std::endl;
+clnp->Disconnect();
+sleep(2);
+exit(0);
+}
+//-----------------------------------------------------------------------------
+static void SetSignalHandlers()
+{
+struct sigaction newsa, oldsa;
+sigset_t sigmask;
+
+sigemptyset(&sigmask);
+sigaddset(&sigmask, SIGTERM);
+newsa.sa_handler = CatchTERM;
+newsa.sa_mask = sigmask;
+newsa.sa_flags = 0;
+sigaction(SIGTERM, &newsa, &oldsa);
+
+sigemptyset(&sigmask);
+sigaddset(&sigmask, SIGINT);
+newsa.sa_handler = CatchTERM;
+newsa.sa_mask = sigmask;
+newsa.sa_flags = 0;
+sigaction(SIGINT, &newsa, &oldsa);
+
+sigemptyset(&sigmask);
+sigaddset(&sigmask, SIGUSR1);
+newsa.sa_handler = CatchUSR1;
+newsa.sa_mask = sigmask;
+newsa.sa_flags = 0;
+sigaction(SIGUSR1, &newsa, &oldsa);
+
+sigemptyset(&sigmask);
+sigaddset(&sigmask, SIGUSR2);
+newsa.sa_handler = CatchUSR2;
+newsa.sa_mask = sigmask;
+newsa.sa_flags = 0;
+sigaction(SIGUSR2, &newsa, &oldsa);
+
+return;
+}
+//-----------------------------------------------------------------------------
+int main(int argc, char *argv[])
+{
+SETTINGS_IMPL settings;
+
+if (argc == 2)
+    {
+    settings.SetConfFile(argv[1]);
+    }
+else
+    {
+    // Usage
+    }
+
+if (settings.ReadSettings())
+    {
+    printf("ReadSettingsError\n");
+    printf("%s\n", settings.GetStrError().c_str());
+    exit(-1);
+    }
+settings.Print();
+
+if (settings.GetDaemon())
+    {
+    switch (fork())
+        {
+        case -1:
+            exit(1);
+            break;
+
+        case 0:
+            setsid();
+            break;
+
+        default:
+            exit(0);
+            break;
+        }
+    }
+
+clnp = new IA_CLIENT_PROT(settings.GetServerName(), settings.GetServerPort(), settings.GetLocalName(), settings.GetLocalPort());
+
+if (!settings.GetNoWeb())
+    {
+    web = new WEB();
+    web->SetRefreshPagePeriod(settings.GetRefreshPeriod());
+    web->SetListenAddr(settings.GetListenWebIP());
+    web->Start();
+    }
+
+clnp->SetLogin(settings.GetLogin());
+clnp->SetPassword(settings.GetPassword());
+
+clnp->SetStatusChangedCb(StatusChanged, NULL);
+clnp->SetInfoCb(ShowMessage, NULL);
+clnp->SetErrorCb(ShowError, NULL);
+clnp->SetDirNameCb(SetDirName, NULL);
+clnp->SetStatChangedCb(StatUpdate, NULL);
+clnp->SetReconnect(settings.GetReconnect());
+
+clnp->Start();
+
+SetSignalHandlers();
+
+#ifdef LINUX
+for (int i = 1; i < argc; i++)
+    memset(argv[i], 0, strlen(argv[i]));
+
+if(argc > 1)
+    strcpy(argv[1], "Connecting...");
+#endif
+
+#ifdef FREEBSD
+setproctitle("Connecting...");
+#endif
+clnp->Connect();
+
+while (1)
+    {
+    struct timespec ts = {0, 200000000};
+    nanosleep(&ts, NULL);
+
+    char state[20];
+
+    if (clnp->GetAuthorized())
+        {
+        if (settings.GetShowPid())
+            sprintf(state, "On %d", getpid());
+        else
+            strcpy(state, "Online");
+        }
+    else
+        {
+        if (settings.GetShowPid())
+            sprintf(state, "Off %d", getpid());
+        else
+            strcpy(state, "Offline");
+        }
+
+    #ifdef LINUX
+    for (int i = 1; i < argc; i++)
+        memset(argv[i], 0, strlen(argv[i]));
+    if(argc > 1)
+        strcpy(argv[1], state);
+    #endif
+
+    #ifdef FREEBSD
+    setproctitle(state);
+    #endif
+
+    #ifdef FREEBSD_5
+    setproctitle(state);
+    #endif
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
diff --git a/projects/sgauth/settings_impl.cpp b/projects/sgauth/settings_impl.cpp
new file mode 100644 (file)
index 0000000..1a7b8dc
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#include <iostream>
+#include <cstring>
+
+#include "stg/common.h"
+#include "stg/conffiles.h"
+#include "settings_impl.h"
+
+SETTINGS_IMPL::SETTINGS_IMPL()
+    : port(0),
+      localPort(0),
+      listenWebIP(0),
+      refreshPeriod(0),
+      daemon(false),
+      noWeb(false),
+      reconnect(false),
+      showPid(false),
+      confFile("/etc/sgauth.conf")
+{
+}
+//-----------------------------------------------------------------------------
+int SETTINGS_IMPL::ReadSettings()
+{
+CONFIGFILE cf(confFile);
+
+if (cf.Error())
+    {
+    strError = "Cannot read file '" + confFile + "'";
+    return -1;
+    }
+
+cf.ReadString("Login", &login, "/?--?--?*");
+if (login == "/?--?--?*")
+    {
+    strError = "Parameter 'Login' not found.";
+    return -1;
+    }
+
+cf.ReadString("Password", &password, "/?--?--?*");
+if (login == "/?--?--?*")
+    {
+    strError = "Parameter 'Password' not found.";
+    return -1;
+    }
+
+cf.ReadString("ServerName", &serverName, "?*?*?");
+if (serverName == "?*?*?")
+    {
+    strError = "Parameter 'ServerName' not found.";
+    return -1;
+    }
+
+std::string temp;
+cf.ReadString("ListenWebIP", &temp, "127.0.0.1");
+listenWebIP = inet_strington(temp);
+if (listenWebIP == 0)
+    {
+    strError = "Parameter 'ListenWebIP' is not valid.";
+    return -1;
+    }
+
+cf.ReadString("ServerPort", &temp, "5555");
+if (ParseIntInRange(temp, 1, 65535, &port))
+    {
+    strError = "Parameter 'ServerPort' is not valid.";
+    return -1;
+    }
+
+cf.ReadString("LocalName", &localName, "");
+
+cf.ReadString("LocalPort", &temp, "0");
+if (ParseIntInRange(temp, 0, 65535, &localPort))
+    {
+    strError = "Parameter 'LocalPort' is not valid.";
+    return -1;
+    }
+
+cf.ReadString("RefreshPeriod", &temp, "5");
+if (ParseIntInRange(temp, 1, 24*3600, &refreshPeriod))
+    {
+    strError = "Parameter 'RefreshPeriod' is not valid.";
+    return -1;
+    }
+
+cf.ReadString("Reconnect", &temp, "yes");
+if (ParseYesNo(temp, &reconnect))
+    {
+    strError = "Parameter 'Reconnect' is not valid.";
+    return -1;
+    }
+
+cf.ReadString("Daemon", &temp, "yes");
+if (ParseYesNo(temp, &daemon))
+    {
+    strError = "Parameter 'Daemon' is not valid.";
+    return -1;
+    }
+
+cf.ReadString("ShowPid", &temp, "no");
+if (ParseYesNo(temp, &showPid))
+    {
+    strError = "Parameter 'ShowPid' is not valid.";
+    return -1;
+    }
+
+cf.ReadString("DisableWeb", &temp, "no");
+if (ParseYesNo(temp, &noWeb))
+    {
+    strError = "Parameter 'DisableWeb' is not valid.";
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+void SETTINGS_IMPL::Print() const
+{
+std::cout << "Login = " << login << "\n"
+          << "Password = " << password << "\n"
+          << "Ip = " << serverName << "\n"
+          << "Port = " << port << "\n"
+          << "LocalPort = " << localPort << "\n"
+          << "ListenWebIP = " << inet_ntostring(listenWebIP) << "\n"
+          << "RefreshPeriod = " << refreshPeriod << "\n"
+          << "Daemon = " << daemon << "\n"
+          << "DisableWeb = " << noWeb << "\n"
+          << "Reconnect = " << reconnect << "\n"
+          << "ShowPid = " << showPid << std::endl;
+}
diff --git a/projects/sgauth/settings_impl.h b/projects/sgauth/settings_impl.h
new file mode 100644 (file)
index 0000000..c5305b8
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#ifndef SETTINGS_IMPL_H
+#define SETTINGS_IMPL_H
+
+#include <string>
+#include <cstdint>
+
+class SETTINGS_IMPL {
+public:
+                        SETTINGS_IMPL();
+                        ~SETTINGS_IMPL() {}
+    int                 Reload() { return 0; }
+    void                SetConfFile(const std::string & cf) { confFile = cf; }
+    int                 ReadSettings();
+
+    const std::string & GetStrError() const { return strError; }
+
+    const std::string & GetServerName() const { return serverName; }
+    uint16_t            GetServerPort() const { return port; }
+    const std::string & GetLocalName() const { return localName; }
+    uint16_t            GetLocalPort() const { return localPort; }
+
+    const std::string & GetLogin() const { return login; }
+    const std::string & GetPassword() const { return password; }
+
+    bool                GetDaemon() const { return daemon; }
+    bool                GetShowPid() const { return showPid; }
+    bool                GetNoWeb() const { return noWeb; }
+    bool                GetReconnect() const { return reconnect; }
+    int                 GetRefreshPeriod() const { return refreshPeriod; }
+    uint32_t            GetListenWebIP() const { return listenWebIP; }
+
+    void                Print() const;
+
+private:
+    std::string login;
+    std::string password;
+    std::string serverName;
+    int         port;
+    std::string localName;
+    int         localPort;
+    uint32_t    listenWebIP;
+    int         refreshPeriod;
+
+    bool        daemon;
+    bool        noWeb;
+    bool        reconnect;
+    bool        showPid;
+
+    std::string confFile;
+    std::string strError;
+};
+
+#endif
diff --git a/projects/sgauth/sgauth.conf b/projects/sgauth/sgauth.conf
new file mode 100644 (file)
index 0000000..bb5fca3
--- /dev/null
@@ -0,0 +1,78 @@
+################################################################################
+#                           Sgauth Configuration file                          #
+################################################################################
+
+# Stargazer server
+# Parameter: required
+# Values: IP address or DNS name
+# Default:
+ServerName = 192.168.1.2
+
+# Port on which Stargazer interacts with sgauth
+# Parameter: optional
+# Value: 1 ... 65535
+# Default: 5555
+ServerPort = 5555
+
+# User's login in Stargazer
+# Parameter: required
+# Value: any
+# Default:
+Login = test
+
+# Local host to bind
+# Parameter: optional
+# Values: IP address or DNS name
+# Default: 0.0.0.0
+LocalName = localhost
+
+# Port on which sgauth interacts with Stargazer
+# Parameter: optional
+# Value: 1 ... 65535
+# Default: 0
+LocalPort = 12345
+
+# User's password in Stargazer
+# Parameter: required
+# Value: any
+# Default:
+Password = 123456
+
+# Defines whether sgauth should try to reestablish connection to Stargazer
+# if it was lost
+# Parameter: optional
+# Value: yes, no
+# Default: yes
+Reconnect = yes
+
+# Defines whether sgauth should run as daemon
+# Parameter: optional
+# Value: yes, no
+# Default: yes
+Daemon = yes
+
+# Web-page refresh period in built-in webserver
+# Parameter: optional
+# Value: any numeric (minutes)
+# Default: 10
+RefreshPeriod = 10
+
+# Defines whether sgauth should use built-in webserver
+# Parameter: optional
+# Value: yes, no
+# Default: no
+DisableWeb = no
+
+# Defines address on which sgauth's built-in webserver will listen
+# Parameter: optional
+# Value: IP address or DNS name
+# Default: 127.0.0.1
+ListenWebIP = 127.0.0.1
+
+# Defines whether sgauth should show its process ID
+# Parameter: optional
+# Value: yes, no
+# Default: no
+ShowPid = no
+
+################################################################################
diff --git a/projects/sgauth/sgauth.css b/projects/sgauth/sgauth.css
new file mode 100644 (file)
index 0000000..f816dbf
--- /dev/null
@@ -0,0 +1,78 @@
+H3
+{
+color: black;
+}
+
+body
+{
+background-color: silver;
+}
+
+#TraffTable
+{
+background-color: white;
+}
+
+#TraffTableCaptionRow
+{
+background-color: silver;
+}
+
+#TraffTableCaptionCellC,
+#TraffTableUMCellC,
+#TraffTableDMCellC,
+#TraffTableUSCellC,
+#TraffTableDSCellC
+{
+background-color: silver;
+}
+
+#TraffTableDMRow,
+#TraffTableDSRow
+{
+background-color: #f2f0cc;
+}
+
+#TraffTableUMRow,
+#TraffTableUSRow
+{
+background-color: white;
+}
+
+#ConnectionStateOnline
+{
+color: green;
+font-size: 20px
+}
+
+#ConnectionStateOffline
+{
+color: red;
+font-size: 20px
+}
+
+p
+{
+padding: 2px;
+margin: 0px;
+}
+
+#MessagesTable
+{
+background-color: white;
+}
+
+#MessagesTableRowC
+{
+background-color: silver;
+}
+
+
+#MessagesTableRow0,
+#MessagesTableRow2,
+#MessagesTableRow4,
+#MessagesTableRow6,
+#MessagesTableRow8
+{
+background-color: #f2f0cc;
+}
diff --git a/projects/sgauth/web.cpp b/projects/sgauth/web.cpp
new file mode 100644 (file)
index 0000000..a162acc
--- /dev/null
@@ -0,0 +1,461 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+ /*
+ $Revision: 1.7 $
+ $Date: 2010/03/15 12:58:17 $
+ */
+
+#include <libintl.h>
+
+#include <csignal>
+#include <cstdio>
+#include <cstring>
+#include <ctime>
+
+#include "stg/common.h"
+#include "stg/ia.h"
+#include "web.h"
+
+extern WEB * web;
+extern IA_CLIENT_PROT * clnp;
+
+#define LISTEN_PORT (5580)
+
+#include "css.h"
+
+//---------------------------------------------------------------------------
+#ifndef WIN32
+void * RunWeb(void *)
+{
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+#else
+unsigned long WINAPI RunWeb(void *)
+{
+#endif
+while (1)
+    web->Run();
+return NULL;
+}
+//---------------------------------------------------------------------------
+WEB::WEB()
+    : res(0),
+      listenSocket(0),
+      outerSocket(0),
+      refreshPeriod(0),
+      listenWebAddr(0)
+{
+#ifdef WIN32
+res = WSAStartup(MAKEWORD(2,0), &wsaData);
+#endif
+
+for (int i = 0; i < DIR_NUM; i++)
+    dirName[i] = "-";
+
+refreshPeriod = 5;
+
+memset(&ls, 0, sizeof(ls));
+}
+//---------------------------------------------------------------------------
+void WEB::Start()
+{
+#ifdef WIN32
+unsigned long pt;
+CreateThread(
+    NULL,   // pointer to thread security attributes
+    16384,  // initial thread stack size, in bytes
+    RunWeb, // pointer to thread function
+    NULL,   // argument for new thread
+    0,      // CREATE_SUSPENDED, // creation flags
+    &pt     // pointer to returned thread identifier
+   );
+#else
+pthread_create(&thread, NULL, RunWeb, NULL);
+#endif
+}
+//---------------------------------------------------------------------------
+void WEB::PrepareNet()
+{
+listenSocket = socket(PF_INET, SOCK_STREAM, 0);
+
+struct sockaddr_in listenAddr;
+listenAddr.sin_family = AF_INET;
+listenAddr.sin_port = htons(LISTEN_PORT);
+listenAddr.sin_addr.s_addr = listenWebAddr;
+
+#ifndef WIN32
+int lng = 1;
+if (0 != setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR, &lng, 4))
+    {
+    printf("Setsockopt Fail\n");
+    printf(">>> Error %s\n", strerror(errno));
+    }
+#else
+//??? TODO
+#endif
+
+
+res = bind(listenSocket, (struct sockaddr*)&listenAddr, sizeof(listenAddr));
+
+if (res == -1)
+    {
+    printf("Bind failed.\n");
+    exit(0);
+    }
+
+res = listen(listenSocket, 0);
+if (res == -1)
+    {
+    printf("Listen failed.\n");
+    exit(0);
+    }
+}
+//---------------------------------------------------------------------------
+void WEB::SetRefreshPagePeriod(int p)
+{
+refreshPeriod = p;
+if (refreshPeriod <= 0 || refreshPeriod > 24*3600)
+    refreshPeriod = 5;
+}
+//---------------------------------------------------------------------------
+void WEB::SetListenAddr(uint32_t ip)
+{
+listenWebAddr = ip;
+}
+//---------------------------------------------------------------------------
+void WEB::Run()
+{
+PrepareNet();
+char recvBuffer[4096];
+while (1)
+    {
+    struct sockaddr_in outerAddr;
+
+    #ifndef WIN32
+    socklen_t outerAddrLen = sizeof(outerAddr);
+    #else
+    int outerAddrLen = sizeof(outerAddr);
+    #endif
+
+    outerSocket = accept(listenSocket, (struct sockaddr*)&outerAddr, &outerAddrLen);
+    if (outerSocket == -1)
+        {
+        printf(">>> Error %s\n", strerror(errno));
+        continue;
+        }
+    recv(outerSocket, recvBuffer, sizeof(recvBuffer), 0);
+
+    if (strncmp(recvBuffer, "GET /sgauth.css", strlen("GET /sgauth.css")) == 0)
+        {
+        SendCSS();
+        //printf("(1) recvBuffer=%s\n", recvBuffer);
+        }
+    else if (strncmp(recvBuffer, "GET /disconnect", strlen("GET /disconnect")) == 0)
+        {
+        clnp->Disconnect();
+        Redirect("/");
+        //printf("(2) recvBuffer=%s\n", recvBuffer);
+        }
+    else if (strncmp(recvBuffer, "GET /connect", strlen("GET /connect")) == 0)
+        {
+        clnp->Connect();
+        Redirect("/");
+        //printf("(3) recvBuffer=%s\n", recvBuffer);
+        }
+    else if (strncmp(recvBuffer, "GET /exit", strlen("GET /exit")) == 0)
+        {
+        Redirect("/");
+        clnp->Disconnect();
+        #ifdef WIN32
+        Sleep(1000);
+        #else
+        struct timespec ts = {1, 0};
+        nanosleep(&ts, NULL);
+        #endif
+        exit(0);
+        }
+    else
+       {
+       SendReply();
+       //printf("(4) recvBuffer=%s\n", recvBuffer);
+       }
+
+    #ifdef WIN32
+    closesocket(outerSocket);
+    #else
+    close(outerSocket);
+    #endif
+    }
+}
+//---------------------------------------------------------------------------
+int WEB::Redirect(const char * url)
+{
+const char * redirect =
+    "HTTP/1.0 200 OK\n"
+    "Content-Type: text/html\n"
+    "Connection: close"
+    "\n\n"
+    "<html>\n"
+    "<head>\n"
+    "<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0;%s\">\n"
+    "</head>\n"
+    "<body>\n"
+    "</body></html>\n\n";
+
+char buff[2000];
+sprintf(buff, redirect, url);
+send(outerSocket, buff, strlen(buff), 0);
+
+return 0;
+}
+//---------------------------------------------------------------------------
+int WEB::SendReply()
+{
+int j, rowNum;
+
+const char * replyHeader =
+    "HTTP/1.0 200 OK\n"
+    "Content-Type: text/html\n"
+    "Connection: close"
+    "\n\n"
+    "<html>\n"
+    "<head>\n"
+    "<META HTTP-EQUIV=\"Refresh\" CONTENT=\"%d\">\n"
+    "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=windows-1251\">\n"
+    "<title>sgauth</title>\n"
+    "<link rel=\"Stylesheet\" href=\"sgauth.css\">"
+    "</head>\n"
+    "<body>\n"
+    "<H3>Stargazer</H3><p>\n";
+
+const char * replyFooter = "</body></html>\n\n";
+
+char replyHeaderBuffer[2000];
+sprintf(replyHeaderBuffer, replyHeader, refreshPeriod);
+
+send(outerSocket, replyHeaderBuffer, strlen(replyHeaderBuffer), 0);
+
+char str[512];
+
+int st = clnp->GetAuthorized();
+
+sprintf(str, "<a href=\"connect\">%s</a><p>\n", gettext("Connect"));
+res = send(outerSocket, str, strlen(str), 0);
+
+sprintf(str, "<a href=\"disconnect\">%s</a><p>\n", gettext("Disconnect"));
+res = send(outerSocket, str, strlen(str), 0);
+
+sprintf(str, "<a href=\"/\">%s</a><p>\n", gettext("Refresh"));
+res = send(outerSocket, str, strlen(str), 0);
+
+sprintf(str, "<a href=\"exit\">%s</a><p>\n", gettext("Exit"));
+res = send(outerSocket, str, strlen(str), 0);
+
+sprintf(str, "<div id=\"%s\">%s</div><p>\n" , st ? "ConnectionStateOnline":"ConnectionStateOffline", st ? "Online":"Offline");
+res = send(outerSocket, str, strlen(str), 0);
+
+sprintf(str, "<div id=\"Cash\">%s: %.3f</div><p>\n" , gettext("Cash"), ls.cash / 1000.0);
+res = send(outerSocket, str, strlen(str), 0);
+
+sprintf(str, "<div id=\"Prepaid Traffic\">%s: %s</div><p>\n" ,
+        gettext("PrepaidTraffic"),
+        ls.freeMb[0] == 'C' ? ls.freeMb + 1 : ls.freeMb);
+res = send(outerSocket, str, strlen(str), 0);
+
+sprintf(str, "<TABLE id=\"TraffTable\">\n");
+res = send(outerSocket, str, strlen(str), 0);
+sprintf(str, "    <TR id=\"TraffTableCaptionRow\">\n");
+res = send(outerSocket, str, strlen(str), 0);
+sprintf(str, "       <TD id=\"TraffTableCaptionCellC\">&nbsp;</TD>\n");
+res = send(outerSocket, str, strlen(str), 0);
+
+rowNum = 0;
+for (j = 0; j < DIR_NUM; j++)
+    {
+    if (dirName[j][0] == 0)
+        continue;
+    std::string s;
+    KOIToWin(dirName[j], &s);// +++++++++ sigsegv ==========   TODO too long dir name crashes sgauth
+    sprintf(str, "       <TD id=\"TraffTableCaptionCell%d\">%s</TD>\n", rowNum++, s.c_str());
+    send(outerSocket, str, strlen(str), 0);
+    }
+
+sprintf(str,"    </TR>\n");
+send(outerSocket, str, strlen(str), 0);
+
+sprintf(str,"    <TR id=\"TraffTableUMRow\">\n");
+send(outerSocket, str, strlen(str), 0);
+
+sprintf(str,"        <TD id=\"TraffTableUMCellC\">%s</TD>\n", gettext("Month Upload"));
+send(outerSocket, str, strlen(str), 0);
+
+rowNum = 0;
+for (j = 0; j < DIR_NUM; j++)
+    {
+    if (dirName[j][0] == 0)
+        continue;
+    sprintf(str,"        <TD id=\"TraffTableUMCell%d\">%s</TD>\n", rowNum++, IntToKMG(ls.mu[j], ST_F));
+    res = send(outerSocket, str, strlen(str), 0);
+    }
+
+sprintf(str,"    </TR>\n");
+res = send(outerSocket, str, strlen(str), 0);
+sprintf(str,"    <TR id=\"TraffTableDMRow\">\n");
+res = send(outerSocket, str, strlen(str), 0);
+sprintf(str,"        <TD id=\"TraffTableDMCellC\">%s</TD>\n", gettext("Month Download"));
+res = send(outerSocket, str, strlen(str), 0);
+
+rowNum = 0;
+for (j = 0; j < DIR_NUM; j++)
+    {
+    if (dirName[j][0] == 0)
+        continue;
+    sprintf(str,"        <TD id=\"TraffTableDMCell%d\">%s</TD>\n", rowNum++, IntToKMG(ls.md[j], ST_F));
+    res = send(outerSocket, str, strlen(str), 0);
+    }
+sprintf(str,"    </TR>\n");
+res = send(outerSocket, str, strlen(str), 0);
+
+
+sprintf(str,"    <TR id=\"TraffTableUSRow\">\n");
+res = send(outerSocket, str, strlen(str), 0);
+sprintf(str,"        <TD id=\"TraffTableUSCellC\">%s</TD>\n", gettext("Session Upload"));
+res = send(outerSocket, str, strlen(str), 0);
+
+rowNum = 0;
+for (j = 0; j < DIR_NUM; j++)
+    {
+    if (dirName[j][0] == 0)
+        continue;
+    sprintf(str,"        <TD id=\"TraffTableUSCell%d\">%s</TD>\n", rowNum++, IntToKMG(ls.su[j], ST_F));
+    res = send(outerSocket, str, strlen(str), 0);
+    }
+
+sprintf(str,"    </TR>\n");
+res = send(outerSocket, str, strlen(str), 0);
+sprintf(str,"    <TR id=\"TraffTableDSRow\">\n");
+res = send(outerSocket, str, strlen(str), 0);
+sprintf(str,"        <TD id=\"TraffTableDSCellC\">%s</TD>\n", gettext("Session Download"));
+res = send(outerSocket, str, strlen(str), 0);
+
+for (j = 0; j < DIR_NUM; j++)
+    {
+    if (dirName[j][0] == 0)
+        continue;
+    sprintf(str,"        <TD id=\"TraffTableDSCell%d\">%s</TD>\n", j, IntToKMG(ls.sd[j], ST_F));
+    res = send(outerSocket, str, strlen(str), 0);
+    }
+
+sprintf(str,"    </TR>\n");
+res = send(outerSocket, str, strlen(str), 0);
+
+sprintf(str,"</TABLE>\n");
+res = send(outerSocket, str, strlen(str), 0);
+
+rowNum = 0;
+if (!messages.empty())
+    {
+    sprintf(str,"    <TABLE id=\"MessagesTable\">\n");
+    res = send(outerSocket, str, strlen(str), 0);
+
+    sprintf(str,"        <TR id=\"MessagesTableRowC\">\n");
+    send(outerSocket, str, strlen(str), 0);
+    sprintf(str,"            <TD>Date</TD>\n");
+    send(outerSocket, str, strlen(str), 0);
+    sprintf(str,"            <TD>Text</TD>\n");
+    send(outerSocket, str, strlen(str), 0);
+    sprintf(str,"        </TR>\n");
+    send(outerSocket, str, strlen(str), 0);
+
+    std::list<STG_MESSAGE>::reverse_iterator it;
+    it = messages.rbegin();
+    while (it != messages.rend())
+        {
+        sprintf(str,"        <TR id=\"MessagesTableRow%d\">\n", rowNum);
+        send(outerSocket, str, strlen(str), 0);
+        sprintf(str,"            <TD>%s</TD>\n", it->recvTime.c_str());
+        send(outerSocket, str, strlen(str), 0);
+        sprintf(str,"            <TD>%s</TD>\n", it->msg.c_str());
+        send(outerSocket, str, strlen(str), 0);
+        sprintf(str,"        </TR>\n");
+        send(outerSocket, str, strlen(str), 0);
+        ++it;
+        ++rowNum;
+        }
+
+    sprintf(str,"   </TABLE>\n");
+    res = send(outerSocket, str, strlen(str), 0);
+    }
+
+time_t t = time(NULL);
+sprintf(str,"Îáíîâëåíî: %s</b>" , ctime(&t));
+res = send(outerSocket, str, strlen(str), 0);
+
+send(outerSocket, replyFooter, strlen(replyFooter), 0);
+
+return 0;
+}
+//---------------------------------------------------------------------------
+int WEB::SendCSS()
+{
+const char * replyHeader =
+    "HTTP/1.0 200 OK\n"
+    "Content-Type: text/css\n"
+    "Connection: close\n\n";
+
+const char * replyFooter= "\n\n";
+
+send(outerSocket, replyHeader, strlen(replyHeader), 0);
+send(outerSocket, SGAuth::css, strlen(SGAuth::css), 0);
+send(outerSocket, replyFooter, strlen(replyFooter), 0);
+
+return 0;
+}
+//---------------------------------------------------------------------------
+void WEB::SetDirName(const std::string & dn, int n)
+{
+web->dirName[n] =  dn;
+}
+//---------------------------------------------------------------------------
+void WEB::AddMessage(const std::string & message, int type)
+{
+time_t t = time(NULL);
+STG_MESSAGE m;
+
+m.msg = message;
+m.type = type;
+m.recvTime = ctime(&t);
+
+messages.push_back(m);
+
+if (messages.size() > MAX_MESSAGES)
+    messages.pop_front();
+
+}
+//---------------------------------------------------------------------------
+void WEB::UpdateStat(const LOADSTAT & ls)
+{
+memcpy((void*)&(WEB::ls), &ls, sizeof(LOADSTAT));
+}
+//---------------------------------------------------------------------------
+
diff --git a/projects/sgauth/web.h b/projects/sgauth/web.h
new file mode 100644 (file)
index 0000000..a933230
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+ /*
+ $Revision: 1.3 $
+ $Date: 2007/12/17 08:39:08 $
+ */
+
+#ifndef WIN32
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#else
+#include <winsock2.h>
+#endif
+
+#include <string>
+#include <list>
+
+#include "stg/const.h"
+#include "stg/ia_packets.h"
+
+#define MAX_MESSAGES    (10)
+//-----------------------------------------------------------------------------
+struct STG_MESSAGE
+{
+std::string  msg;
+std::string  recvTime;
+int     type;
+};
+//-----------------------------------------------------------------------------
+class WEB
+{
+public:
+    WEB();
+    void Run();
+    void SetDirName(const std::string & dn, int n);
+    void SetRefreshPagePeriod(int p);
+    void SetListenAddr(uint32_t ip);
+    void AddMessage(const std::string & message, int type);
+    void UpdateStat(const LOADSTAT & ls);
+    void Start();
+private:
+    void PrepareNet();
+    int SendReply();
+    int SendCSS();
+    int Redirect(const char * url);
+
+    #ifdef WIN32
+    WSADATA wsaData;
+    #else
+    pthread_t thread;
+    #endif
+
+    std::string dirName[DIR_NUM];
+    int res;
+    int listenSocket;
+    int outerSocket;
+    int refreshPeriod;
+
+    uint32_t listenWebAddr;
+    LOADSTAT ls;
+
+    std::list<STG_MESSAGE> messages;
+};
+//-----------------------------------------------------------------------------
diff --git a/projects/sgconf/CHANGES b/projects/sgconf/CHANGES
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/projects/sgconf/CMakeLists.txt b/projects/sgconf/CMakeLists.txt
new file mode 100644 (file)
index 0000000..c2666b8
--- /dev/null
@@ -0,0 +1,12 @@
+find_package ( EXPAT REQUIRED )
+
+set ( CPP_FILES main.cpp options.cpp api_action.cpp actions.cpp admins.cpp tariffs.cpp users.cpp services.cpp corps.cpp info.cpp xml.cpp )
+
+set ( THREADS_PREFER_PTHREAD_FLAG ON )
+find_package ( Threads REQUIRED )
+
+add_executable ( sgconf ${CPP_FILES} )
+
+target_link_libraries ( sgconf srvconf crypto common EXPAT::EXPAT )
+
+# TODO: install
diff --git a/projects/sgconf/README.txt b/projects/sgconf/README.txt
new file mode 100644 (file)
index 0000000..bb2db5b
--- /dev/null
@@ -0,0 +1,4 @@
+Compiling:
+> ./build
+
+
diff --git a/projects/sgconf/TODO b/projects/sgconf/TODO
new file mode 100644 (file)
index 0000000..19b51f5
--- /dev/null
@@ -0,0 +1,2 @@
+1. No default value for server.
+2. No default value for port.
diff --git a/projects/sgconf/action.h b/projects/sgconf/action.h
new file mode 100644 (file)
index 0000000..940ea7f
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#ifndef __STG_SGCONF_ACTION_H__
+#define __STG_SGCONF_ACTION_H__
+
+#include <string>
+#include <map>
+#include <stdexcept>
+
+namespace SGCONF
+{
+
+class OPTION_BLOCK;
+struct PARSER_STATE;
+struct CONFIG;
+
+class ACTION
+{
+    public:
+        virtual ~ACTION() {}
+
+        virtual ACTION * Clone() const = 0;
+        virtual std::string ParamDescription() const = 0;
+        virtual std::string DefaultDescription() const = 0;
+        virtual OPTION_BLOCK & Suboptions() = 0;
+        virtual PARSER_STATE Parse(int argc, char ** argv, void * data = NULL) = 0;
+        virtual void ParseValue(const std::string &) {}
+
+        class ERROR : public std::runtime_error
+        {
+            public:
+                ERROR(const std::string & message)
+                    : std::runtime_error(message.c_str()) {}
+        };
+};
+
+} // namespace SGCONF
+
+#endif
diff --git a/projects/sgconf/actions.cpp b/projects/sgconf/actions.cpp
new file mode 100644 (file)
index 0000000..afa5162
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
diff --git a/projects/sgconf/actions.h b/projects/sgconf/actions.h
new file mode 100644 (file)
index 0000000..3181a10
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#pragma once
+
+#include "action.h"
+#include "options.h"
+#include "parser_state.h"
+
+#include "stg/common.h"
+#include "stg/optional.h"
+
+#include <string>
+
+#include <cassert>
+
+namespace SGCONF
+{
+
+typedef void (* FUNC0)();
+
+template <typename F>
+class FUNC0_ACTION : public ACTION
+{
+    public:
+        FUNC0_ACTION(const F & func) : m_func(func) {}
+
+        virtual ACTION * Clone() const { return new FUNC0_ACTION<F>(*this); }
+
+        virtual std::string ParamDescription() const { return ""; }
+        virtual std::string DefaultDescription() const { return ""; }
+        virtual OPTION_BLOCK & Suboptions() { return m_suboptions; }
+        virtual PARSER_STATE Parse(int argc, char ** argv, void * /*data*/)
+        {
+        m_func();
+        return PARSER_STATE(true, argc, argv);
+        }
+
+    private:
+        F m_func;
+        OPTION_BLOCK m_suboptions;
+};
+
+template <typename F>
+inline
+FUNC0_ACTION<F> * MakeFunc0Action(F func)
+{
+return new FUNC0_ACTION<F>(func);
+}
+
+template <typename T>
+class PARAM_ACTION : public ACTION
+{
+    public:
+        PARAM_ACTION(STG::Optional<T> & param,
+                     const T & defaultValue,
+                     const std::string & paramDescription)
+            : m_param(param),
+              m_defaltValue(defaultValue),
+              m_description(paramDescription),
+              m_hasDefault(true)
+        {}
+        PARAM_ACTION(STG::Optional<T> & param)
+            : m_param(param),
+              m_hasDefault(false)
+        {}
+        PARAM_ACTION(STG::Optional<T> & param,
+                     const std::string & paramDescription)
+            : m_param(param),
+              m_description(paramDescription),
+              m_hasDefault(false)
+        {}
+
+        virtual ACTION * Clone() const { return new PARAM_ACTION<T>(*this); }
+
+        virtual std::string ParamDescription() const { return m_description; }
+        virtual std::string DefaultDescription() const;
+        virtual OPTION_BLOCK & Suboptions() { return m_suboptions; }
+        virtual PARSER_STATE Parse(int argc, char ** argv, void * /*data*/);
+        virtual void ParseValue(const std::string & value);
+
+    private:
+        STG::Optional<T> & m_param;
+        T m_defaltValue;
+        std::string m_description;
+        bool m_hasDefault;
+        OPTION_BLOCK m_suboptions;
+};
+
+template <typename T>
+inline
+std::string PARAM_ACTION<T>::DefaultDescription() const
+{
+return m_hasDefault ? " (default: '" + std::to_string(m_defaltValue) + "')"
+                    : "";
+}
+
+template <>
+inline
+std::string PARAM_ACTION<std::string>::DefaultDescription() const
+{
+return m_hasDefault ? " (default: '" + m_defaltValue + "')"
+                    : "";
+}
+
+template <typename T>
+inline
+PARSER_STATE PARAM_ACTION<T>::Parse(int argc, char ** argv, void * /*data*/)
+{
+if (argc == 0 ||
+    argv == NULL ||
+    *argv == NULL)
+    throw ERROR("Missing argument.");
+T value;
+if (str2x(*argv, value))
+    throw ERROR(std::string("Bad argument: '") + *argv + "'");
+m_param = value;
+return PARSER_STATE(false, --argc, ++argv);
+}
+
+template <>
+inline
+PARSER_STATE PARAM_ACTION<bool>::Parse(int argc, char ** argv, void * /*data*/)
+{
+m_param = true;
+return PARSER_STATE(false, argc, argv);
+}
+
+template <typename T>
+inline
+void PARAM_ACTION<T>::ParseValue(const std::string & stringValue)
+{
+if (stringValue.empty())
+    throw ERROR("Missing value.");
+T value;
+if (str2x(stringValue, value))
+    throw ERROR(std::string("Bad value: '") + stringValue + "'");
+m_param = value;
+}
+
+template <>
+inline
+void PARAM_ACTION<std::string>::ParseValue(const std::string & stringValue)
+{
+m_param = stringValue;
+}
+
+template <>
+inline
+PARSER_STATE PARAM_ACTION<std::string>::Parse(int argc, char ** argv, void * /*data*/)
+{
+if (argc == 0 ||
+    argv == NULL ||
+    *argv == NULL)
+    throw ERROR("Missing argument.");
+m_param = *argv;
+return PARSER_STATE(false, --argc, ++argv);
+}
+
+template <typename T>
+inline
+PARAM_ACTION<T> * MakeParamAction(STG::Optional<T> & param,
+                                  const T & defaultValue,
+                                  const std::string & paramDescription)
+{
+return new PARAM_ACTION<T>(param, defaultValue, paramDescription);
+}
+
+template <typename T>
+inline
+PARAM_ACTION<T> * MakeParamAction(STG::Optional<T> & param)
+{
+return new PARAM_ACTION<T>(param);
+}
+
+template <typename T>
+inline
+PARAM_ACTION<T> * MakeParamAction(STG::Optional<T> & param,
+                                  const std::string & paramDescription)
+{
+return new PARAM_ACTION<T>(param, paramDescription);
+}
+
+class KV_ACTION : public ACTION
+{
+    public:
+        KV_ACTION(const std::string & name,
+                  const std::string & paramDescription)
+            : m_name(name),
+              m_description(paramDescription)
+        {}
+
+        virtual ACTION * Clone() const { return new KV_ACTION(*this); }
+
+        virtual std::string ParamDescription() const { return m_description; }
+        virtual std::string DefaultDescription() const { return ""; }
+        virtual OPTION_BLOCK & Suboptions() { return m_suboptions; }
+        virtual PARSER_STATE Parse(int argc, char ** argv, void * data);
+
+    private:
+        std::string m_name;
+        std::string m_description;
+        OPTION_BLOCK m_suboptions;
+};
+
+inline
+PARSER_STATE KV_ACTION::Parse(int argc, char ** argv, void * data)
+{
+if (argc == 0 ||
+    argv == NULL ||
+    *argv == NULL)
+    throw ERROR("Missing argument.");
+assert(data != NULL && "Expecting container pointer.");
+std::map<std::string, std::string> & kvs = *static_cast<std::map<std::string, std::string>*>(data);
+kvs[m_name] = *argv;
+return PARSER_STATE(false, --argc, ++argv);
+}
+
+inline
+KV_ACTION * MakeKVAction(const std::string & name,
+                         const std::string & paramDescription)
+{
+return new KV_ACTION(name, paramDescription);
+}
+
+} // namespace SGCONF
diff --git a/projects/sgconf/admins.cpp b/projects/sgconf/admins.cpp
new file mode 100644 (file)
index 0000000..ea79621
--- /dev/null
@@ -0,0 +1,205 @@
+#include "admins.h"
+
+#include "api_action.h"
+#include "options.h"
+#include "config.h"
+#include "utils.h"
+
+#include "stg/servconf.h"
+#include "stg/servconf_types.h"
+#include "stg/admin_conf.h"
+
+#include <iostream>
+#include <string>
+#include <map>
+#include <cstdint>
+#include <cassert>
+
+namespace
+{
+
+std::string Indent(size_t level, bool dash = false)
+{
+if (level == 0)
+    return "";
+return dash ? std::string(level * 4 - 2, ' ') + "- " : std::string(level * 4, ' ');
+}
+
+std::string PrivToString(const STG::Priv& priv)
+{
+return std::string("") +
+       (priv.corpChg ? "1" : "0") +
+       (priv.serviceChg ? "1" : "0") +
+       (priv.tariffChg ? "1" : "0") +
+       (priv.adminChg ? "1" : "0") +
+       (priv.userAddDel ? "1" : "0") +
+       (priv.userPasswd ? "1" : "0") +
+       (priv.userCash ? "1" : "0") +
+       (priv.userConf ? "1" : "0") +
+       (priv.userStat ? "1" : "0");
+}
+
+void PrintAdmin(const STG::GetAdmin::Info & info, size_t level = 0)
+{
+std::cout << Indent(level, true) << "login: " << info.login << "\n"
+          << Indent(level)       << "priviledges: " << PrivToString(info.priv) << "\n";
+}
+
+std::vector<SGCONF::API_ACTION::PARAM> GetAdminParams()
+{
+std::vector<SGCONF::API_ACTION::PARAM> params;
+params.push_back(SGCONF::API_ACTION::PARAM("password", "<password>", "password"));
+params.push_back(SGCONF::API_ACTION::PARAM("priv", "<priv>", "priviledges"));
+return params;
+}
+
+void ConvPriv(const std::string & value, STG::Optional<STG::Priv> & res)
+{
+if (value.length() != 9)
+    throw SGCONF::ACTION::ERROR("Priviledges value should be a 9-digits length binary number.");
+STG::Priv priv;
+priv.corpChg = (value[0] == '0' ? 0 : 1);
+priv.serviceChg = (value[1] == '0' ? 0 : 1);
+priv.tariffChg = (value[2] == '0' ? 0 : 1);
+priv.adminChg = (value[3] == '0' ? 0 : 1);
+priv.userAddDel = (value[4] == '0' ? 0 : 1);
+priv.userPasswd = (value[5] == '0' ? 0 : 1);
+priv.userCash = (value[6] == '0' ? 0 : 1);
+priv.userConf = (value[7] == '0' ? 0 : 1);
+priv.userStat = (value[8] == '0' ? 0 : 1);
+res = priv;
+}
+
+void SimpleCallback(bool result,
+                    const std::string & reason,
+                    void * /*data*/)
+{
+if (!result)
+    {
+    std::cerr << "Operation failed. Reason: '" << reason << "'." << std::endl;
+    return;
+    }
+std::cout << "Success.\n";
+}
+
+void GetAdminsCallback(bool result,
+                       const std::string & reason,
+                       const std::vector<STG::GetAdmin::Info> & info,
+                       void * /*data*/)
+{
+if (!result)
+    {
+    std::cerr << "Failed to get admin list. Reason: '" << reason << "'." << std::endl;
+    return;
+    }
+std::cout << "Admins:\n";
+for (size_t i = 0; i < info.size(); ++i)
+    PrintAdmin(info[i], 1);
+}
+
+void GetAdminCallback(bool result,
+                      const std::string & reason,
+                      const std::vector<STG::GetAdmin::Info> & info,
+                      void * data)
+{
+assert(data != NULL && "Expecting pointer to std::string with the admin's login.");
+const std::string & login = *static_cast<const std::string *>(data);
+if (!result)
+    {
+    std::cerr << "Failed to get admin. Reason: '" << reason << "'." << std::endl;
+    return;
+    }
+for (size_t i = 0; i < info.size(); ++i)
+    if (info[i].login == login)
+        PrintAdmin(info[i]);
+}
+
+
+bool GetAdminsFunction(const SGCONF::CONFIG & config,
+                       const std::string & /*arg*/,
+                       const std::map<std::string, std::string> & /*options*/)
+{
+STG::ServConf proto(config.server.data(),
+                    config.port.data(),
+                    config.localAddress.data(),
+                    config.localPort.data(),
+                    config.userName.data(),
+                    config.userPass.data());
+return proto.GetAdmins(GetAdminsCallback, NULL) == STG::st_ok;
+}
+
+bool GetAdminFunction(const SGCONF::CONFIG & config,
+                      const std::string & arg,
+                      const std::map<std::string, std::string> & /*options*/)
+{
+STG::ServConf proto(config.server.data(),
+                    config.port.data(),
+                    config.localAddress.data(),
+                    config.localPort.data(),
+                    config.userName.data(),
+                    config.userPass.data());
+// STG currently doesn't support <GetAdmin login="..."/>.
+// So get a list of admins and filter it. 'data' param holds a pointer to 'login'.
+std::string login(arg);
+return proto.GetAdmins(GetAdminCallback, &login) == STG::st_ok;
+}
+
+bool DelAdminFunction(const SGCONF::CONFIG & config,
+                      const std::string & arg,
+                      const std::map<std::string, std::string> & /*options*/)
+{
+STG::ServConf proto(config.server.data(),
+                    config.port.data(),
+                    config.localAddress.data(),
+                    config.localPort.data(),
+                    config.userName.data(),
+                    config.userPass.data());
+return proto.DelAdmin(arg, SimpleCallback, NULL) == STG::st_ok;
+}
+
+bool AddAdminFunction(const SGCONF::CONFIG & config,
+                      const std::string & arg,
+                      const std::map<std::string, std::string> & options)
+{
+STG::AdminConfOpt conf;
+conf.login = arg;
+SGCONF::MaybeSet(options, "priv", conf.priv, ConvPriv);
+SGCONF::MaybeSet(options, "password", conf.password);
+STG::ServConf proto(config.server.data(),
+                    config.port.data(),
+                    config.localAddress.data(),
+                    config.localPort.data(),
+                    config.userName.data(),
+                    config.userPass.data());
+return proto.AddAdmin(arg, conf, SimpleCallback, NULL) == STG::st_ok;
+}
+
+bool ChgAdminFunction(const SGCONF::CONFIG & config,
+                      const std::string & arg,
+                      const std::map<std::string, std::string> & options)
+{
+STG::AdminConfOpt conf;
+conf.login = arg;
+SGCONF::MaybeSet(options, "priv", conf.priv, ConvPriv);
+SGCONF::MaybeSet(options, "password", conf.password);
+STG::ServConf proto(config.server.data(),
+                    config.port.data(),
+                    config.localAddress.data(),
+                    config.localPort.data(),
+                    config.userName.data(),
+                    config.userPass.data());
+return proto.ChgAdmin(conf, SimpleCallback, NULL) == STG::st_ok;
+}
+
+} // namespace anonymous
+
+void SGCONF::AppendAdminsOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks)
+{
+std::vector<API_ACTION::PARAM> params(GetAdminParams());
+blocks.Add("Admin management options")
+      .Add("get-admins", SGCONF::MakeAPIAction(commands, GetAdminsFunction), "\tget admin list")
+      .Add("get-admin", SGCONF::MakeAPIAction(commands, "<login>", GetAdminFunction), "get admin")
+      .Add("add-admin", SGCONF::MakeAPIAction(commands, "<login>", params, AddAdminFunction), "add admin")
+      .Add("del-admin", SGCONF::MakeAPIAction(commands, "<login>", DelAdminFunction), "del admin")
+      .Add("chg-admin", SGCONF::MakeAPIAction(commands, "<login>", params, ChgAdminFunction), "change admin");
+}
diff --git a/projects/sgconf/admins.h b/projects/sgconf/admins.h
new file mode 100644 (file)
index 0000000..303d6d1
--- /dev/null
@@ -0,0 +1,11 @@
+#pragma once
+
+namespace SGCONF
+{
+
+class OPTION_BLOCKS;
+class COMMANDS;
+
+void AppendAdminsOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks);
+
+} // namespace SGCONF
diff --git a/projects/sgconf/api_action.cpp b/projects/sgconf/api_action.cpp
new file mode 100644 (file)
index 0000000..d5b1e8e
--- /dev/null
@@ -0,0 +1,40 @@
+#include "api_action.h"
+
+#include "actions.h"
+#include "parser_state.h"
+
+SGCONF::PARSER_STATE SGCONF::API_ACTION::Parse(int argc, char ** argv, void * /*data*/)
+{
+PARSER_STATE state(false, argc, argv);
+if (!m_argument.empty())
+    {
+    if (argc == 0 ||
+        argv == NULL ||
+        *argv == NULL)
+        throw ERROR("Missing argument.");
+    m_argument = *argv;
+    --state.argc;
+    ++state.argv;
+    }
+state = m_suboptions.Parse(state.argc, state.argv, &m_params);
+m_commands.Add(m_funPtr, m_argument, m_params);
+return state;
+}
+
+SGCONF::API_ACTION::API_ACTION(COMMANDS & commands,
+                               const std::string & paramDescription,
+                               bool needArgument,
+                               const std::vector<PARAM> & params,
+                               API_FUNCTION funPtr)
+    : m_commands(commands),
+      m_description(paramDescription),
+      m_argument(needArgument ? "1" : ""), // Hack
+      m_funPtr(funPtr)
+{
+std::vector<PARAM>::const_iterator it(params.begin());
+while (it != params.end())
+    {
+    m_suboptions.Add(it->name, MakeKVAction(it->name, it->shortDescr), it->longDescr);
+    ++it;
+    }
+}
diff --git a/projects/sgconf/api_action.h b/projects/sgconf/api_action.h
new file mode 100644 (file)
index 0000000..f27715c
--- /dev/null
@@ -0,0 +1,143 @@
+#ifndef __STG_SGCONF_API_ACTION_H__
+#define __STG_SGCONF_API_ACTION_H__
+
+#include "action.h"
+
+#include "options.h"
+
+#include <string>
+#include <map>
+#include <vector>
+
+namespace SGCONF
+{
+
+typedef bool (* API_FUNCTION) (const CONFIG &,
+                               const std::string &,
+                               const std::map<std::string, std::string> &);
+
+class COMMAND
+{
+    public:
+        COMMAND(API_FUNCTION funPtr,
+                const std::string & arg,
+                const std::map<std::string, std::string> & options)
+            : m_funPtr(funPtr),
+              m_arg(arg),
+              m_options(options)
+        {}
+        bool Execute(const SGCONF::CONFIG & config) const
+        {
+            return m_funPtr(config, m_arg, m_options);
+        }
+
+    private:
+        API_FUNCTION m_funPtr;
+        std::string m_arg;
+        std::map<std::string, std::string> m_options;
+};
+
+class COMMANDS
+{
+    public:
+        void Add(API_FUNCTION funPtr,
+                 const std::string & arg,
+                 const std::map<std::string, std::string> & options) { m_commands.push_back(COMMAND(funPtr, arg, options)); }
+        bool Execute(const SGCONF::CONFIG & config) const
+        {
+            std::vector<COMMAND>::const_iterator it(m_commands.begin());
+            bool res = true;
+            while (it != m_commands.end() && res)
+            {
+                res = res && it->Execute(config);
+                ++it;
+            }
+            return res;
+        }
+    private:
+        std::vector<COMMAND> m_commands;
+};
+
+class API_ACTION : public ACTION
+{
+    public:
+        struct PARAM
+        {
+            PARAM(const std::string & n,
+                  const std::string & s,
+                  const std::string & l)
+                : name(n),
+                  shortDescr(s),
+                  longDescr(l)
+            {}
+            std::string name;
+            std::string shortDescr;
+            std::string longDescr;
+        };
+
+        API_ACTION(COMMANDS & commands,
+                   const std::string & paramDescription,
+                   bool needArgument,
+                   const std::vector<PARAM> & params,
+                   API_FUNCTION funPtr);
+        API_ACTION(COMMANDS & commands,
+                   const std::string & paramDescription,
+                   bool needArgument,
+                   API_FUNCTION funPtr)
+            : m_commands(commands),
+              m_description(paramDescription),
+              m_argument(needArgument ? "1" : ""), // Hack
+              m_funPtr(funPtr)
+        {}
+
+        virtual ACTION * Clone() const { return new API_ACTION(*this); }
+
+        virtual std::string ParamDescription() const { return m_description; }
+        virtual std::string DefaultDescription() const { return ""; }
+        virtual OPTION_BLOCK & Suboptions() { return m_suboptions; }
+        virtual PARSER_STATE Parse(int argc, char ** argv, void * /*data*/);
+
+    private:
+        COMMANDS & m_commands;
+        std::string m_description;
+        std::string m_argument;
+        OPTION_BLOCK m_suboptions;
+        std::map<std::string, std::string> m_params;
+        API_FUNCTION m_funPtr;
+};
+
+inline
+ACTION * MakeAPIAction(COMMANDS & commands,
+                       const std::string & paramDescription,
+                       const std::vector<API_ACTION::PARAM> & params,
+                       API_FUNCTION funPtr)
+{
+return new API_ACTION(commands, paramDescription, true, params, funPtr);
+}
+
+inline
+ACTION * MakeAPIAction(COMMANDS & commands,
+                       const std::vector<API_ACTION::PARAM> & params,
+                       API_FUNCTION funPtr)
+{
+return new API_ACTION(commands, "", false, params, funPtr);
+}
+
+inline
+ACTION * MakeAPIAction(COMMANDS & commands,
+                       const std::string & paramDescription,
+                       API_FUNCTION funPtr)
+{
+return new API_ACTION(commands, paramDescription, true, funPtr);
+}
+
+inline
+ACTION * MakeAPIAction(COMMANDS & commands,
+                       API_FUNCTION funPtr)
+{
+return new API_ACTION(commands, "", false, funPtr);
+}
+
+}
+
+#endif
diff --git a/projects/sgconf/config.h b/projects/sgconf/config.h
new file mode 100644 (file)
index 0000000..f5313ef
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#pragma once
+
+#include "stg/common.h"
+#include "stg/optional.h"
+
+#include <string>
+#include <cstdint>
+
+namespace SGCONF
+{
+
+struct CONFIG
+{
+    STG::Optional<std::string> configFile;
+    STG::Optional<std::string> server;
+    STG::Optional<uint16_t> port;
+    STG::Optional<std::string> localAddress;
+    STG::Optional<uint16_t> localPort;
+    STG::Optional<std::string> userName;
+    STG::Optional<std::string> userPass;
+    STG::Optional<bool> showConfig;
+
+    CONFIG & operator=(const CONFIG & rhs)
+    {
+    if (!rhs.configFile.empty())
+        configFile = rhs.configFile;
+    if (!rhs.server.empty())
+        server = rhs.server;
+    if (!rhs.port.empty())
+        port = rhs.port;
+    if (!rhs.localAddress.empty())
+        localAddress = rhs.localAddress;
+    if (!rhs.localPort.empty())
+        localPort = rhs.localPort;
+    if (!rhs.userName.empty())
+        userName = rhs.userName;
+    if (!rhs.userPass.empty())
+        userPass = rhs.userPass;
+    if (!rhs.showConfig.empty())
+        showConfig = rhs.showConfig;
+    return *this;
+    }
+
+    std::string Serialize() const
+    {
+    std::string res;
+    if (!configFile.empty())
+        res += "configFile: '" + configFile.data() + "'\n";
+    if (!server.empty())
+        res += "server: '" + server.data() + "'\n";
+    if (!port.empty())
+        res += "port: " + std::to_string(port.data()) + "\n";
+    if (!localAddress.empty())
+        res += "local address: '" + localAddress.data() + "'\n";
+    if (!localPort.empty())
+        res += "local port: " + std::to_string(localPort.data()) + "\n";
+    if (!userName.empty())
+        res += "userName: '" + userName.data() + "'\n";
+    if (!userPass.empty())
+        res += "userPass: '" + userPass.data() + "\n";
+    return res;
+    }
+};
+
+} // namespace SGCONF
diff --git a/projects/sgconf/corps.cpp b/projects/sgconf/corps.cpp
new file mode 100644 (file)
index 0000000..586ddcd
--- /dev/null
@@ -0,0 +1,162 @@
+#include "corps.h"
+
+#include "api_action.h"
+#include "options.h"
+#include "config.h"
+#include "utils.h"
+
+#include "stg/servconf.h"
+#include "stg/servconf_types.h"
+#include "stg/corp_conf.h"
+#include "stg/common.h"
+
+#include <iostream>
+#include <string>
+#include <map>
+
+namespace
+{
+
+std::string Indent(size_t level, bool dash = false)
+{
+if (level == 0)
+    return "";
+return dash ? std::string(level * 4 - 2, ' ') + "- " : std::string(level * 4, ' ');
+}
+
+void PrintCorp(const STG::GetCorp::Info & info, size_t level = 0)
+{
+std::cout << Indent(level, true) << "name: " << info.name << "\n"
+          << Indent(level)       << "cash: " << info.cash << "\n";
+}
+
+std::vector<SGCONF::API_ACTION::PARAM> GetCorpParams()
+{
+std::vector<SGCONF::API_ACTION::PARAM> params;
+params.push_back(SGCONF::API_ACTION::PARAM("cash", "<cash>", "\tcorporation's cash"));
+return params;
+}
+
+void SimpleCallback(bool result,
+                    const std::string & reason,
+                    void * /*data*/)
+{
+if (!result)
+    {
+    std::cerr << "Operation failed. Reason: '" << reason << "'." << std::endl;
+    return;
+    }
+std::cout << "Success.\n";
+}
+
+void GetCorpsCallback(bool result,
+                      const std::string & reason,
+                      const std::vector<STG::GetCorp::Info> & info,
+                      void * /*data*/)
+{
+if (!result)
+    {
+    std::cerr << "Failed to get corp list. Reason: '" << reason << "'." << std::endl;
+    return;
+    }
+std::cout << "Corps:\n";
+for (size_t i = 0; i < info.size(); ++i)
+    PrintCorp(info[i], 1);
+}
+
+void GetCorpCallback(bool result,
+                     const std::string & reason,
+                     const STG::GetCorp::Info & info,
+                     void * /*data*/)
+{
+if (!result)
+    {
+    std::cerr << "Failed to get corp. Reason: '" << reason << "'." << std::endl;
+    return;
+    }
+PrintCorp(info);
+}
+
+bool GetCorpsFunction(const SGCONF::CONFIG & config,
+                      const std::string & /*arg*/,
+                      const std::map<std::string, std::string> & /*options*/)
+{
+STG::ServConf proto(config.server.data(),
+                    config.port.data(),
+                    config.localAddress.data(),
+                    config.localPort.data(),
+                    config.userName.data(),
+                    config.userPass.data());
+return proto.GetCorporations(GetCorpsCallback, NULL) == STG::st_ok;
+}
+
+bool GetCorpFunction(const SGCONF::CONFIG & config,
+                     const std::string & arg,
+                     const std::map<std::string, std::string> & /*options*/)
+{
+STG::ServConf proto(config.server.data(),
+                    config.port.data(),
+                    config.localAddress.data(),
+                    config.localPort.data(),
+                    config.userName.data(),
+                    config.userPass.data());
+return proto.GetCorp(arg, GetCorpCallback, NULL) == STG::st_ok;
+}
+
+bool DelCorpFunction(const SGCONF::CONFIG & config,
+                     const std::string & arg,
+                     const std::map<std::string, std::string> & /*options*/)
+{
+STG::ServConf proto(config.server.data(),
+                    config.port.data(),
+                    config.localAddress.data(),
+                    config.localPort.data(),
+                    config.userName.data(),
+                    config.userPass.data());
+return proto.DelCorp(arg, SimpleCallback, NULL) == STG::st_ok;
+}
+
+bool AddCorpFunction(const SGCONF::CONFIG & config,
+                     const std::string & arg,
+                     const std::map<std::string, std::string> & options)
+{
+STG::CorpConfOpt conf;
+conf.name = arg;
+SGCONF::MaybeSet(options, "cash", conf.cash);
+STG::ServConf proto(config.server.data(),
+                    config.port.data(),
+                    config.localAddress.data(),
+                    config.localPort.data(),
+                    config.userName.data(),
+                    config.userPass.data());
+return proto.AddCorp(arg, conf, SimpleCallback, NULL) == STG::st_ok;
+}
+
+bool ChgCorpFunction(const SGCONF::CONFIG & config,
+                     const std::string & arg,
+                     const std::map<std::string, std::string> & options)
+{
+STG::CorpConfOpt conf;
+conf.name = arg;
+SGCONF::MaybeSet(options, "cash", conf.cash);
+STG::ServConf proto(config.server.data(),
+                    config.port.data(),
+                    config.localAddress.data(),
+                    config.localPort.data(),
+                    config.userName.data(),
+                    config.userPass.data());
+return proto.ChgCorp(conf, SimpleCallback, NULL) == STG::st_ok;
+}
+
+} // namespace anonymous
+
+void SGCONF::AppendCorpsOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks)
+{
+std::vector<API_ACTION::PARAM> params(GetCorpParams());
+blocks.Add("Corporation management options")
+      .Add("get-corps", SGCONF::MakeAPIAction(commands, GetCorpsFunction), "\tget corporation list")
+      .Add("get-corp", SGCONF::MakeAPIAction(commands, "<name>", GetCorpFunction), "get corporation")
+      .Add("add-corp", SGCONF::MakeAPIAction(commands, "<name>", params, AddCorpFunction), "add corporation")
+      .Add("del-corp", SGCONF::MakeAPIAction(commands, "<name>", DelCorpFunction), "delete corporation")
+      .Add("chg-corp", SGCONF::MakeAPIAction(commands, "<name>", params, ChgCorpFunction), "change corporation");
+}
diff --git a/projects/sgconf/corps.h b/projects/sgconf/corps.h
new file mode 100644 (file)
index 0000000..550f453
--- /dev/null
@@ -0,0 +1,11 @@
+#pragma once
+
+namespace SGCONF
+{
+
+class OPTION_BLOCKS;
+class COMMANDS;
+
+void AppendCorpsOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks);
+
+} // namespace SGCONF
diff --git a/projects/sgconf/info.cpp b/projects/sgconf/info.cpp
new file mode 100644 (file)
index 0000000..421e438
--- /dev/null
@@ -0,0 +1,60 @@
+#include "info.h"
+
+#include "api_action.h"
+#include "options.h"
+#include "config.h"
+
+#include "stg/servconf.h"
+
+#include <iostream>
+#include <string>
+#include <map>
+
+#include <expat.h>
+
+namespace
+{
+
+void PrintInfo(const STG::ServerInfo::Info& info)
+{
+    std::cout << "Server version: '" << info.version << "'\n"
+              << "Number of tariffs: " << info.tariffNum << "\n"
+              << "Tariff subsystem version: " << info.tariffType << "\n"
+              << "Number of users: " << info.usersNum << "\n"
+              << "UName: '" << info.uname << "\n"
+              << "Number of directions: " << info.dirNum << "\n"
+              << "Dirs:\n";
+    for (size_t i = 0; i < info.dirName.size(); ++i)
+        std::cout << "\t - '" << info.dirName[i] << "'\n";
+}
+
+void InfoCallback(bool result, const std::string & reason, const STG::ServerInfo::Info & info, void * /*data*/)
+{
+if (!result)
+    {
+    std::cerr << "Failed to get server info. Reason: '" << reason << "'." << std::endl;
+    return;
+    }
+PrintInfo(info);
+}
+
+bool InfoFunction(const SGCONF::CONFIG & config,
+                  const std::string& /*arg*/,
+                  const std::map<std::string, std::string> & /*options*/)
+{
+STG::ServConf proto(config.server.data(),
+                    config.port.data(),
+                    config.localAddress.data(),
+                    config.localPort.data(),
+                    config.userName.data(),
+                    config.userPass.data());
+return proto.ServerInfo(InfoCallback, NULL) == STG::st_ok;
+}
+
+}
+
+void SGCONF::AppendServerInfoBlock(COMMANDS & commands, OPTION_BLOCKS & blocks)
+{
+blocks.Add("Server info")
+      .Add("server-info", SGCONF::MakeAPIAction(commands, InfoFunction), "\tget server info");
+}
diff --git a/projects/sgconf/info.h b/projects/sgconf/info.h
new file mode 100644 (file)
index 0000000..3eb47a4
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#pragma once
+
+namespace SGCONF
+{
+
+class OPTION_BLOCKS;
+class COMMANDS;
+
+void AppendServerInfoBlock(COMMANDS & commands, OPTION_BLOCKS & blocks);
+
+}
diff --git a/projects/sgconf/main.cpp b/projects/sgconf/main.cpp
new file mode 100644 (file)
index 0000000..9790819
--- /dev/null
@@ -0,0 +1,465 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#include "xml.h"
+#include "admins.h"
+#include "tariffs.h"
+#include "users.h"
+#include "services.h"
+#include "corps.h"
+#include "info.h"
+
+#include "api_action.h"
+#include "options.h"
+#include "actions.h"
+#include "config.h"
+
+#include <string>
+#include <iostream>
+
+#include <cstdlib> // getenv
+#include <cstring> // str*
+
+#include <unistd.h> // access
+#include <libgen.h> // basename
+
+namespace
+{
+
+template <typename T>
+struct nullary_function
+{
+typedef T result_type;
+};
+
+template <typename F>
+class binder0 : public nullary_function<typename F::result_type>
+{
+    public:
+        binder0(const F & func, const typename F::argument_type & arg)
+            : m_func(func), m_arg(arg) {}
+        typename F::result_type operator()() const { return m_func(m_arg); }
+    private:
+        F m_func;
+        typename F::argument_type m_arg;
+};
+
+template <typename F>
+inline
+binder0<F> bind0(const F & func, const typename F::argument_type & arg)
+{
+return binder0<F>(func, arg);
+}
+
+template <typename A, typename R>
+class FUNC1_ADAPTER : public std::unary_function<A, R>
+{
+    public:
+        FUNC1_ADAPTER(R (*func)(A)) : m_func(func) {}
+        const R operator()(A arg) const { return (m_func)(arg); }
+    private:
+        R (*m_func)(A);
+};
+
+template <typename C, typename A, typename R>
+class METHOD1_ADAPTER : public std::unary_function<A, R>
+{
+    public:
+        METHOD1_ADAPTER(R (C::* func)(A), C & obj) : m_func(func), m_obj(obj) {}
+        R operator()(A arg) { return (m_obj.*m_func)(arg); }
+    private:
+        R (C::* m_func)(A);
+        C & m_obj;
+};
+
+template <typename C, typename A, typename R>
+class CONST_METHOD1_ADAPTER : public std::unary_function<A, R>
+{
+    public:
+        CONST_METHOD1_ADAPTER(R (C::* func)(A) const, C & obj) : m_func(func), m_obj(obj) {}
+        R operator()(A arg) const { return (m_obj.*m_func)(arg); }
+    private:
+        R (C::* m_func)(A) const;
+        C & m_obj;
+};
+
+template <typename A, typename R>
+FUNC1_ADAPTER<A, R> Func1Adapt(R (func)(A))
+{
+return FUNC1_ADAPTER<A, R>(func);
+}
+
+template <typename C, typename A, typename R>
+METHOD1_ADAPTER<C, A, R> Method1Adapt(R (C::* func)(A), C & obj)
+{
+return METHOD1_ADAPTER<C, A, R>(func, obj);
+}
+
+template <typename C, typename A, typename R>
+CONST_METHOD1_ADAPTER<C, A, R> Method1Adapt(R (C::* func)(A) const, C & obj)
+{
+return CONST_METHOD1_ADAPTER<C, A, R>(func, obj);
+}
+
+void Version(const std::string & self)
+{
+std::cout << self << ", version: 2.0.0.\n";
+}
+
+void ReadUserConfigFile(SGCONF::OPTION_BLOCK & block)
+{
+std::vector<std::string> paths;
+const char * configHome = getenv("XDG_CONFIG_HOME");
+if (configHome == NULL)
+    {
+    const char * home = getenv("HOME");
+    if (home == NULL)
+        return;
+    paths.push_back(std::string(home) + "/.config/sgconf/sgconf.conf");
+    paths.push_back(std::string(home) + "/.sgconf/sgconf.conf");
+    }
+else
+    paths.push_back(std::string(configHome) + "/sgconf/sgconf.conf");
+for (std::vector<std::string>::const_iterator it = paths.begin(); it != paths.end(); ++it)
+    if (access(it->c_str(), R_OK) == 0)
+        {
+        block.ParseFile(*it);
+        return;
+        }
+}
+
+} // namespace anonymous
+
+namespace SGCONF
+{
+
+class CONFIG_ACTION : public ACTION
+{
+    public:
+        CONFIG_ACTION(SGCONF::CONFIG & config,
+                      const std::string & paramDescription)
+            : m_config(config),
+              m_description(paramDescription)
+        {}
+
+        virtual ACTION * Clone() const { return new CONFIG_ACTION(*this); }
+
+        virtual std::string ParamDescription() const { return m_description; }
+        virtual std::string DefaultDescription() const { return ""; }
+        virtual OPTION_BLOCK & Suboptions() { return m_suboptions; }
+        virtual PARSER_STATE Parse(int argc, char ** argv, void * /*data*/);
+
+    private:
+        SGCONF::CONFIG & m_config;
+        std::string m_description;
+        OPTION_BLOCK m_suboptions;
+
+        void ParseCredentials(const std::string & credentials);
+        void ParseHostAndPort(const std::string & hostAndPort);
+};
+
+
+PARSER_STATE CONFIG_ACTION::Parse(int argc, char ** argv, void * /*data*/)
+{
+if (argc == 0 ||
+    argv == NULL ||
+    *argv == NULL)
+    throw ERROR("Missing argument.");
+char * pos = strchr(*argv, '@');
+if (pos != NULL)
+    {
+    ParseCredentials(std::string(*argv, pos));
+    ParseHostAndPort(std::string(pos + 1));
+    }
+else
+    {
+    ParseHostAndPort(std::string(*argv));
+    }
+return PARSER_STATE(false, --argc, ++argv);
+}
+
+void CONFIG_ACTION::ParseCredentials(const std::string & credentials)
+{
+std::string::size_type pos = credentials.find_first_of(':');
+if (pos != std::string::npos)
+    {
+    m_config.userName = credentials.substr(0, pos);
+    m_config.userPass = credentials.substr(pos + 1);
+    }
+else
+    {
+    m_config.userName = credentials;
+    }
+}
+
+void CONFIG_ACTION::ParseHostAndPort(const std::string & hostAndPort)
+{
+std::string::size_type pos = hostAndPort.find_first_of(':');
+if (pos != std::string::npos)
+    {
+    m_config.server = hostAndPort.substr(0, pos);
+    uint16_t port = 0;
+    if (str2x(hostAndPort.substr(pos + 1), port))
+        throw ERROR("Invalid port value: '" + hostAndPort.substr(pos + 1) + "'");
+    m_config.port = port;
+    }
+else
+    {
+    m_config.server = hostAndPort;
+    }
+}
+
+inline
+CONFIG_ACTION * MakeParamAction(SGCONF::CONFIG & config,
+                                const std::string & paramDescription)
+{
+return new CONFIG_ACTION(config, paramDescription);
+}
+
+} // namespace SGCONF
+
+//-----------------------------------------------------------------------------
+int main(int argc, char **argv)
+{
+std::string self(basename(argv[0]));
+SGCONF::CONFIG config;
+SGCONF::COMMANDS commands;
+
+SGCONF::OPTION_BLOCKS blocks;
+blocks.Add("General options")
+      .Add("c", "config", SGCONF::MakeParamAction(config.configFile, std::string("~/.config/stg/sgconf.conf"), "<config file>"), "override default config file")
+      .Add("h", "help", SGCONF::MakeFunc0Action(bind0(Method1Adapt(&SGCONF::OPTION_BLOCKS::Help, blocks), 0)), "\t\tshow this help and exit")
+      //.Add("help-all", SGCONF::MakeFunc0Action(UsageAll), "\t\tshow full help and exit")
+      .Add("v", "version", SGCONF::MakeFunc0Action(bind0(Func1Adapt(Version), self)), "\t\tshow version information and exit");
+SGCONF::OPTION_BLOCK & block = blocks.Add("Connection options")
+      .Add("s", "server", SGCONF::MakeParamAction(config.server, std::string("localhost"), "<address>"), "\t\thost to connect")
+      .Add("p", "port", SGCONF::MakeParamAction(config.port, uint16_t(5555), "<port>"), "\t\tport to connect")
+      .Add("local-address", SGCONF::MakeParamAction(config.localAddress, std::string(""), "<address>"), "\tlocal address to bind")
+      .Add("local-port", SGCONF::MakeParamAction(config.localPort, uint16_t(0), "<port>"), "\t\tlocal port to bind")
+      .Add("u", "username", SGCONF::MakeParamAction(config.userName, std::string("admin"), "<username>"), "\tadministrative login")
+      .Add("w", "userpass", SGCONF::MakeParamAction(config.userPass, "<password>"), "\tpassword for the administrative login")
+      .Add("a", "address", SGCONF::MakeParamAction(config, "<connection string>"), "connection params as a single string in format: <login>:<password>@<host>:<port>");
+blocks.Add("Debug options")
+      .Add("show-config", SGCONF::MakeParamAction(config.showConfig), "\tshow config and exit");
+SGCONF::AppendXMLOptionBlock(commands, blocks);
+SGCONF::AppendServerInfoBlock(commands, blocks);
+SGCONF::AppendAdminsOptionBlock(commands, blocks);
+SGCONF::AppendTariffsOptionBlock(commands, blocks);
+SGCONF::AppendUsersOptionBlock(commands, blocks);
+SGCONF::AppendServicesOptionBlock(commands, blocks);
+SGCONF::AppendCorpsOptionBlock(commands, blocks);
+
+SGCONF::PARSER_STATE state(false, argc, argv);
+
+try
+{
+state = blocks.Parse(--argc, ++argv); // Skipping self name
+}
+catch (const SGCONF::OPTION::ERROR& ex)
+{
+std::cerr << ex.what() << "\n";
+return -1;
+}
+
+if (state.stop)
+    return 0;
+
+if (state.argc > 0)
+    {
+    std::cerr << "Unknown option: '" << *state.argv << "'\n";
+    return -1;
+    }
+
+try
+{
+SGCONF::CONFIG configOverride(config);
+
+if (config.configFile.empty())
+    {
+    const char * mainConfigFile = "/etc/sgconf/sgconf.conf";
+    if (access(mainConfigFile, R_OK) == 0)
+        block.ParseFile(mainConfigFile);
+    ReadUserConfigFile(block);
+    }
+else
+    {
+    block.ParseFile(config.configFile.data());
+    }
+
+config = configOverride;
+
+if (!config.showConfig.empty() && config.showConfig.data())
+    {
+    std::cout << config.Serialize() << std::endl;
+    return 0;
+    }
+return commands.Execute(config) ? 0 : -1;
+}
+catch (const std::exception& ex)
+{
+std::cerr << ex.what() << "\n";
+return -1;
+}
+}
+//-----------------------------------------------------------------------------
+
+namespace
+{
+
+/*void UsageTariffs(bool full)
+{
+std::cout << "Tariffs management options:\n"
+          << "\t--get-tariffs\t\t\t\tget a list of tariffs (subsequent options will define what to show)\n";
+if (full)
+    std::cout << "\t\t--name\t\t\t\tshow tariff's name\n"
+              << "\t\t--fee\t\t\t\tshow tariff's fee\n"
+              << "\t\t--free\t\t\t\tshow tariff's prepaid traffic in terms of cost\n"
+              << "\t\t--passive-cost\t\t\tshow tariff's cost of \"freeze\"\n"
+              << "\t\t--traff-type\t\t\tshow what type of traffix will be accounted by the tariff\n"
+              << "\t\t--dirs\t\t\t\tshow tarification rules for directions\n\n";
+std::cout << "\t--get-tariff\t\t\t\tget the information about tariff\n";
+if (full)
+    std::cout << "\t\t--name <name>\t\t\tname of the tariff to show\n"
+              << "\t\t--fee\t\t\t\tshow tariff's fee\n"
+              << "\t\t--free\t\t\t\tshow tariff's prepaid traffic in terms of cost\n"
+              << "\t\t--passive-cost\t\t\tshow tariff's cost of \"freeze\"\n"
+              << "\t\t--traff-type\t\t\tshow what type of traffix will be accounted by the tariff\n"
+              << "\t\t--dirs\t\t\t\tshow tarification rules for directions\n\n";
+std::cout << "\t--add-tariff\t\t\t\tadd a new tariff\n";
+if (full)
+    std::cout << "\t\t--name <name>\t\t\tname of the tariff to add\n"
+              << "\t\t--fee <fee>\t\t\tstariff's fee\n"
+              << "\t\t--free <free>\t\t\ttariff's prepaid traffic in terms of cost\n"
+              << "\t\t--passive-cost <cost>\t\ttariff's cost of \"freeze\"\n"
+              << "\t\t--traff-type <type>\t\twhat type of traffi will be accounted by the tariff\n"
+              << "\t\t--times <times>\t\t\tslash-separated list of \"day\" time-spans (in form \"hh:mm-hh:mm\") for each direction\n"
+              << "\t\t--prices-day-a <prices>\t\tslash-separated list of prices for \"day\" traffic before threshold for each direction\n"
+              << "\t\t--prices-night-a <prices>\tslash-separated list of prices for \"night\" traffic before threshold for each direction\n"
+              << "\t\t--prices-day-b <prices>\t\tslash-separated list of prices for \"day\" traffic after threshold for each direction\n"
+              << "\t\t--prices-night-b <prices>\tslash-separated list of prices for \"night\" traffic after threshold for each direction\n"
+              << "\t\t--single-prices <yes|no>\tslash-separated list of \"single price\" flags for each direction\n"
+              << "\t\t--no-discounts <yes|no>\t\tslash-separated list of \"no discount\" flags for each direction\n"
+              << "\t\t--thresholds <thresholds>\tslash-separated list of thresholds (in Mb) for each direction\n\n";
+std::cout << "\t--del-tariff\t\t\t\tdelete an existing tariff\n";
+if (full)
+    std::cout << "\t\t--name <name>\t\t\tname of the tariff to delete\n\n";
+std::cout << "\t--chg-tariff\t\t\t\tchange an existing tariff\n";
+if (full)
+    std::cout << "\t\t--name <name>\t\t\tname of the tariff to change\n"
+              << "\t\t--fee <fee>\t\t\tstariff's fee\n"
+              << "\t\t--free <free>\t\t\ttariff's prepaid traffic in terms of cost\n"
+              << "\t\t--passive-cost <cost>\t\ttariff's cost of \"freeze\"\n"
+              << "\t\t--traff-type <type>\t\twhat type of traffix will be accounted by the tariff\n"
+              << "\t\t--dir <N>\t\t\tnumber of direction data to change\n"
+              << "\t\t\t--time <time>\t\t\"day\" time-span (in form \"hh:mm-hh:mm\")\n"
+              << "\t\t\t--price-day-a <price>\tprice for \"day\" traffic before threshold\n"
+              << "\t\t\t--price-night-a <price>\tprice for \"night\" traffic before threshold\n"
+              << "\t\t\t--price-day-b <price>\tprice for \"day\" traffic after threshold\n"
+              << "\t\t\t--price-night-b <price>\tprice for \"night\" traffic after threshold\n"
+              << "\t\t\t--single-price <yes|no>\t\"single price\" flag\n"
+              << "\t\t\t--no-discount <yes|no>\t\"no discount\" flag\n"
+              << "\t\t\t--threshold <threshold>\tthreshold (in Mb)\n\n";
+}
+//-----------------------------------------------------------------------------
+void UsageUsers(bool full)
+{
+std::cout << "Users management options:\n"
+          << "\t--get-users\t\t\t\tget a list of users (subsequent options will define what to show)\n";
+if (full)
+    std::cout << "\n\n";
+std::cout << "\t--get-user\t\t\t\tget the information about user\n";
+if (full)
+    std::cout << "\n\n";
+std::cout << "\t--add-user\t\t\t\tadd a new user\n";
+if (full)
+    std::cout << "\n\n";
+std::cout << "\t--del-user\t\t\t\tdelete an existing user\n";
+if (full)
+    std::cout << "\n\n";
+std::cout << "\t--chg-user\t\t\t\tchange an existing user\n";
+if (full)
+    std::cout << "\n\n";
+std::cout << "\t--check-user\t\t\t\tcheck credentials is valid\n";
+if (full)
+    std::cout << "\n\n";
+std::cout << "\t--send-message\t\t\t\tsend a message to a user\n";
+if (full)
+    std::cout << "\n\n";
+}
+//-----------------------------------------------------------------------------
+void UsageServices(bool full)
+{
+std::cout << "Services management options:\n"
+          << "\t--get-services\t\t\t\tget a list of services (subsequent options will define what to show)\n";
+if (full)
+    std::cout << "\t\t--name\t\t\t\tshow service's name\n"
+              << "\t\t--comment\t\t\tshow a comment to the service\n"
+              << "\t\t--cost\t\t\t\tshow service's cost\n"
+              << "\t\t--pay-day\t\t\tshow service's pay day\n\n";
+std::cout << "\t--get-service\t\t\t\tget the information about service\n";
+if (full)
+    std::cout << "\t\t--name <name>\t\t\tname of the service to show\n"
+              << "\t\t--comment\t\t\tshow a comment to the service\n"
+              << "\t\t--cost\t\t\t\tshow service's cost\n"
+              << "\t\t--pay-day\t\t\tshow service's pay day\n\n";
+std::cout << "\t--add-service\t\t\t\tadd a new service\n";
+if (full)
+    std::cout << "\t\t--name <name>\t\t\tname of the service to add\n"
+              << "\t\t--comment <comment>\t\ta comment to the service\n"
+              << "\t\t--cost <cost>\t\t\tservice's cost\n"
+              << "\t\t--pay-day <day>\t\t\tservice's pay day\n\n";
+std::cout << "\t--del-service\t\t\t\tdelete an existing service\n";
+if (full)
+    std::cout << "\t\t--name <name>\t\t\tname of the service to delete\n\n";
+std::cout << "\t--chg-service\t\t\t\tchange an existing service\n";
+if (full)
+    std::cout << "\t\t--name <name>\t\t\tname of the service to change\n"
+              << "\t\t--comment <comment>\t\ta comment to the service\n"
+              << "\t\t--cost <cost>\t\t\tservice's cost\n"
+              << "\t\t--pay-day <day>\t\t\tservice's pay day\n\n";
+}
+//-----------------------------------------------------------------------------
+void UsageCorporations(bool full)
+{
+std::cout << "Corporations management options:\n"
+          << "\t--get-corporations\t\t\tget a list of corporations (subsequent options will define what to show)\n";
+if (full)
+    std::cout << "\t\t--name\t\t\t\tshow corporation's name\n"
+              << "\t\t--cash\t\t\t\tshow corporation's cash\n\n";
+std::cout << "\t--get-corp\t\t\t\tget the information about corporation\n";
+if (full)
+    std::cout << "\t\t--name <name>\t\t\tname of the corporation to show\n"
+              << "\t\t--cash\t\t\t\tshow corporation's cash\n\n";
+std::cout << "\t--add-corp\t\t\t\tadd a new corporation\n";
+if (full)
+    std::cout << "\t\t--name <name>\t\t\tname of the corporation to add\n"
+              << "\t\t--cash <cash>\t\t\tinitial corporation's cash (default: \"0\")\n\n";
+std::cout << "\t--del-corp\t\t\t\tdelete an existing corporation\n";
+if (full)
+    std::cout << "\t\t--name <name>\t\t\tname of the corporation to delete\n\n";
+std::cout << "\t--chg-corp\t\t\t\tchange an existing corporation\n";
+if (full)
+    std::cout << "\t\t--name <name>\t\t\tname of the corporation to change\n"
+              << "\t\t--add-cash <amount>[:<message>]\tadd cash to the corporation's account and optional comment message\n"
+              << "\t\t--set-cash <cash>[:<message>]\tnew corporation's cash and optional comment message\n\n";
+}*/
+
+} // namespace anonymous
diff --git a/projects/sgconf/options.cpp b/projects/sgconf/options.cpp
new file mode 100644 (file)
index 0000000..e431bcb
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#include "options.h"
+
+#include "action.h"
+#include "parser_state.h"
+
+#include "stg/common.h"
+
+#include <fstream>
+#include <sstream>
+#include <iostream>
+#include <functional>
+#include <algorithm>
+
+#include <unistd.h>
+
+namespace
+{
+
+template <class C>
+void ReadConfigFile(const std::string & filePath, void (C::* callback)(const std::string&, const std::string&), C * obj)
+{
+std::ifstream stream(filePath.c_str());
+std::string line;
+size_t num = 0;
+while (std::getline(stream, line))
+    {
+    ++num;
+    line = Trim(line);
+    std::string::size_type pos = line.find_first_of('#');
+    if (pos != std::string::npos)
+        line = line.substr(0, pos);
+    if (line.empty())
+        continue;
+    pos = line.find_first_of('=');
+    if (pos == std::string::npos)
+        {
+        std::ostringstream error;
+        error << "Bad file format, missing '=' in '" << filePath << ":" << num << "'.";
+        throw std::runtime_error(error.str().c_str());
+        }
+    (obj->*callback)(Trim(line.substr(0, pos)), Trim(line.substr(pos + 1, line.length() - pos - 1)));
+    }
+}
+
+} // namespace anonymous
+
+using SGCONF::OPTION;
+using SGCONF::OPTION_BLOCK;
+using SGCONF::OPTION_BLOCKS;
+using SGCONF::ACTION;
+using SGCONF::PARSER_STATE;
+
+OPTION::OPTION(const std::string & shortName,
+               const std::string & longName,
+               ACTION * action,
+               const std::string & description)
+    : m_shortName(shortName),
+      m_longName(longName),
+      m_action(action),
+      m_description(description)
+{
+}
+
+OPTION::OPTION(const std::string & longName,
+               ACTION * action,
+               const std::string & description)
+    : m_longName(longName),
+      m_action(action),
+      m_description(description)
+{
+}
+
+OPTION::OPTION(const OPTION & rhs)
+    : m_shortName(rhs.m_shortName),
+      m_longName(rhs.m_longName),
+      m_action(rhs.m_action->Clone()),
+      m_description(rhs.m_description)
+{
+}
+
+OPTION::~OPTION()
+{
+delete m_action;
+}
+
+OPTION & OPTION::operator=(const OPTION & rhs)
+{
+m_shortName = rhs.m_shortName;
+m_longName = rhs.m_longName;
+m_action = rhs.m_action->Clone();
+m_description = rhs.m_description;
+return *this;
+}
+
+void OPTION::Help(size_t level) const
+{
+if (!m_action)
+    throw ERROR("Option is not defined.");
+std::string indent(level, '\t');
+std::cout << indent;
+if (!m_shortName.empty())
+    std::cout << "-" << m_shortName << ", ";
+std::cout << "--" << m_longName << " " << m_action->ParamDescription()
+          << "\t" << m_description << m_action->DefaultDescription() << "\n";
+m_action->Suboptions().Help(level);
+}
+
+bool OPTION::Check(const char * arg) const
+{
+if (arg == NULL)
+    return false;
+
+if (*arg++ != '-')
+    return false;
+
+if (*arg == '-')
+{
+    return m_longName == arg + 1;
+}
+
+return m_shortName == arg;
+}
+
+PARSER_STATE OPTION::Parse(int argc, char ** argv, void * data)
+{
+if (!m_action)
+    throw ERROR("Option is not defined.");
+try
+    {
+    return m_action->Parse(argc, argv, data);
+    }
+catch (const ACTION::ERROR & ex)
+    {
+    if (m_longName.empty())
+        throw ERROR("-" + m_shortName + ": " + ex.what());
+    else
+        throw m_shortName.empty() ? ERROR("--" + m_longName + ": " + ex.what())
+                                  : ERROR("--" + m_longName + ", -" + m_shortName + ": " + ex.what());
+    }
+}
+
+void OPTION::ParseValue(const std::string & value)
+{
+if (!m_action)
+    throw ERROR("Option is not defined.");
+try
+    {
+    return m_action->ParseValue(value);
+    }
+catch (const ACTION::ERROR & ex)
+    {
+    throw ERROR(m_longName + ": " + ex.what());
+    }
+}
+
+OPTION_BLOCK & OPTION_BLOCK::Add(const std::string & shortName,
+                                 const std::string & longName,
+                                 ACTION * action,
+                                 const std::string & description)
+{
+m_options.push_back(OPTION(shortName, longName, action, description));
+return *this;
+}
+
+OPTION_BLOCK & OPTION_BLOCK::Add(const std::string & longName,
+                                 ACTION * action,
+                                 const std::string & description)
+{
+m_options.push_back(OPTION(longName, action, description));
+return *this;
+}
+
+void OPTION_BLOCK::Help(size_t level) const
+{
+if (m_options.empty())
+    return;
+if (!m_description.empty())
+    std::cout << m_description << ":\n";
+std::for_each(m_options.begin(),
+              m_options.end(),
+              [&level](const auto& opt){ opt.Help(level + 1); });
+}
+
+PARSER_STATE OPTION_BLOCK::Parse(int argc, char ** argv, void * data)
+{
+PARSER_STATE state(false, argc, argv);
+if (state.argc == 0)
+    return state;
+while (state.argc > 0 && !state.stop)
+    {
+    const auto it = std::find_if(m_options.begin(), m_options.end(), [&state](const auto& opt){ return opt.Check(*state.argv); });
+    if (it != m_options.end())
+        state = it->Parse(--state.argc, ++state.argv, data);
+    else
+        break;
+    }
+return state;
+}
+
+void OPTION_BLOCK::ParseFile(const std::string & filePath)
+{
+if (access(filePath.c_str(), R_OK))
+    throw ERROR("File '" + filePath + "' does not exists.");
+ReadConfigFile(filePath, &OPTION_BLOCK::OptionCallback, this);
+}
+
+void OPTION_BLOCK::OptionCallback(const std::string & key, const std::string & value)
+{
+for (std::vector<OPTION>::iterator it = m_options.begin(); it != m_options.end(); ++it)
+    if (it->Name() == key)
+        it->ParseValue(value);
+}
+
+void OPTION_BLOCKS::Help(size_t level) const
+{
+std::list<OPTION_BLOCK>::const_iterator it(m_blocks.begin());
+while (it != m_blocks.end())
+    {
+    it->Help(level);
+    std::cout << "\n";
+    ++it;
+    }
+}
+
+PARSER_STATE OPTION_BLOCKS::Parse(int argc, char ** argv)
+{
+PARSER_STATE state(false, argc, argv);
+std::list<OPTION_BLOCK>::iterator it(m_blocks.begin());
+while (state.argc > 0 && !state.stop && it != m_blocks.end())
+    {
+    state = it->Parse(state.argc, state.argv);
+    ++it;
+    }
+return state;
+}
diff --git a/projects/sgconf/options.h b/projects/sgconf/options.h
new file mode 100644 (file)
index 0000000..c00707b
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#ifndef __STG_SGCONF_OPTIONS_H__
+#define __STG_SGCONF_OPTIONS_H__
+
+#include <string>
+#include <vector>
+#include <list>
+#include <utility>
+#include <stdexcept>
+#include <cstddef> // size_t
+
+namespace SGCONF
+{
+
+class ACTION;
+struct PARSER_STATE;
+
+class OPTION
+{
+    public:
+        OPTION(const std::string & shortName,
+               const std::string & longName,
+               ACTION * action,
+               const std::string & description);
+        OPTION(const std::string & longName,
+               ACTION * action,
+               const std::string & description);
+        OPTION(const OPTION & rhs);
+        ~OPTION();
+
+        OPTION & operator=(const OPTION & rhs);
+
+        void Help(size_t level = 0) const;
+        PARSER_STATE Parse(int argc, char ** argv, void * data);
+        void ParseValue(const std::string & value);
+        bool Check(const char * arg) const;
+        const std::string & Name() const { return m_longName; }
+
+        class ERROR : public std::runtime_error
+        {
+            public:
+                ERROR(const std::string & message)
+                    : std::runtime_error(message.c_str()) {}
+        };
+
+    private:
+        std::string m_shortName;
+        std::string m_longName;
+        ACTION * m_action;
+        std::string m_description;
+};
+
+class OPTION_BLOCK
+{
+    public:
+        OPTION_BLOCK() {}
+        OPTION_BLOCK(const std::string & description)
+            : m_description(description) {}
+        OPTION_BLOCK & Add(const std::string & shortName,
+                           const std::string & longName,
+                           ACTION * action,
+                           const std::string & description);
+        OPTION_BLOCK & Add(const std::string & longName,
+                           ACTION * action,
+                           const std::string & description);
+
+        void Help(size_t level) const;
+
+        PARSER_STATE Parse(int argc, char ** argv, void * data = NULL);
+        void ParseFile(const std::string & filePath);
+
+        class ERROR : public std::runtime_error
+        {
+            public:
+                ERROR(const std::string & message)
+                    : std::runtime_error(message.c_str()) {}
+        };
+
+    private:
+        std::vector<OPTION> m_options;
+        std::string m_description;
+
+        void OptionCallback(const std::string & key, const std::string & value);
+};
+
+class OPTION_BLOCKS
+{
+    public:
+        OPTION_BLOCK & Add(const std::string & description)
+        { m_blocks.push_back(OPTION_BLOCK(description)); return m_blocks.back(); }
+        void Add(const OPTION_BLOCK & block) { m_blocks.push_back(block); }
+        void Help(size_t level) const;
+        PARSER_STATE Parse(int argc, char ** argv);
+
+    private:
+        std::list<OPTION_BLOCK> m_blocks;
+};
+
+} // namespace SGCONF
+
+#endif
diff --git a/projects/sgconf/parser_state.h b/projects/sgconf/parser_state.h
new file mode 100644 (file)
index 0000000..22ad794
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#ifndef __STG_SGCONF_PARSER_STATE_H__
+#define __STG_SGCONF_PARSER_STATE_H__
+
+namespace SGCONF
+{
+
+struct PARSER_STATE
+{
+    PARSER_STATE(bool s, int c, char ** v) : stop(s), argc(c), argv(v) {}
+    bool stop;
+    int argc;
+    char ** argv;
+};
+
+}
+
+#endif
diff --git a/projects/sgconf/services.cpp b/projects/sgconf/services.cpp
new file mode 100644 (file)
index 0000000..ede820a
--- /dev/null
@@ -0,0 +1,170 @@
+#include "services.h"
+
+#include "api_action.h"
+#include "options.h"
+#include "config.h"
+#include "utils.h"
+
+#include "stg/servconf.h"
+#include "stg/servconf_types.h"
+#include "stg/service_conf.h"
+#include "stg/common.h"
+
+#include <iostream>
+#include <string>
+#include <map>
+
+namespace
+{
+
+std::string Indent(size_t level, bool dash = false)
+{
+if (level == 0)
+    return "";
+return dash ? std::string(level * 4 - 2, ' ') + "- " : std::string(level * 4, ' ');
+}
+
+void PrintService(const STG::GetService::Info & info, size_t level = 0)
+{
+std::cout << Indent(level, true) << "name: " << info.name << "\n"
+          << Indent(level)       << "cost: " << info.cost << "\n"
+          << Indent(level)       << "payment day: " << static_cast<unsigned>(info.payDay) << "\n"
+          << Indent(level)       << "comment: " << info.comment << "\n";
+}
+
+std::vector<SGCONF::API_ACTION::PARAM> GetServiceParams()
+{
+std::vector<SGCONF::API_ACTION::PARAM> params;
+params.push_back(SGCONF::API_ACTION::PARAM("cost", "<cost>", "\tcost of the service"));
+params.push_back(SGCONF::API_ACTION::PARAM("pay-day", "<month day>", "payment day"));
+params.push_back(SGCONF::API_ACTION::PARAM("comment", "<text>", "comment"));
+return params;
+}
+
+void SimpleCallback(bool result,
+                    const std::string & reason,
+                    void * /*data*/)
+{
+if (!result)
+    {
+    std::cerr << "Operation failed. Reason: '" << reason << "'." << std::endl;
+    return;
+    }
+std::cout << "Success.\n";
+}
+
+void GetServicesCallback(bool result,
+                         const std::string & reason,
+                         const std::vector<STG::GetService::Info> & info,
+                         void * /*data*/)
+{
+if (!result)
+    {
+    std::cerr << "Failed to get service list. Reason: '" << reason << "'." << std::endl;
+    return;
+    }
+std::cout << "Services:\n";
+for (size_t i = 0; i < info.size(); ++i)
+    PrintService(info[i], 1);
+}
+
+void GetServiceCallback(bool result,
+                        const std::string & reason,
+                        const STG::GetService::Info & info,
+                        void * /*data*/)
+{
+if (!result)
+    {
+    std::cerr << "Failed to get service. Reason: '" << reason << "'." << std::endl;
+    return;
+    }
+PrintService(info);
+}
+
+bool GetServicesFunction(const SGCONF::CONFIG & config,
+                         const std::string & /*arg*/,
+                         const std::map<std::string, std::string> & /*options*/)
+{
+STG::ServConf proto(config.server.data(),
+                    config.port.data(),
+                    config.localAddress.data(),
+                    config.localPort.data(),
+                    config.userName.data(),
+                    config.userPass.data());
+return proto.GetServices(GetServicesCallback, NULL) == STG::st_ok;
+}
+
+bool GetServiceFunction(const SGCONF::CONFIG & config,
+                        const std::string & arg,
+                        const std::map<std::string, std::string> & /*options*/)
+{
+STG::ServConf proto(config.server.data(),
+                    config.port.data(),
+                    config.localAddress.data(),
+                    config.localPort.data(),
+                    config.userName.data(),
+                    config.userPass.data());
+return proto.GetService(arg, GetServiceCallback, NULL) == STG::st_ok;
+}
+
+bool DelServiceFunction(const SGCONF::CONFIG & config,
+                        const std::string & arg,
+                        const std::map<std::string, std::string> & /*options*/)
+{
+STG::ServConf proto(config.server.data(),
+                    config.port.data(),
+                    config.localAddress.data(),
+                    config.localPort.data(),
+                    config.userName.data(),
+                    config.userPass.data());
+return proto.DelService(arg, SimpleCallback, NULL) == STG::st_ok;
+}
+
+bool AddServiceFunction(const SGCONF::CONFIG & config,
+                        const std::string & arg,
+                        const std::map<std::string, std::string> & options)
+{
+STG::ServiceConfOpt conf;
+conf.name = arg;
+SGCONF::MaybeSet(options, "cost", conf.cost);
+SGCONF::MaybeSet(options, "pay-day", conf.payDay);
+SGCONF::MaybeSet(options, "comment", conf.comment);
+STG::ServConf proto(config.server.data(),
+                    config.port.data(),
+                    config.localAddress.data(),
+                    config.localPort.data(),
+                    config.userName.data(),
+                    config.userPass.data());
+return proto.AddService(arg, conf, SimpleCallback, NULL) == STG::st_ok;
+}
+
+bool ChgServiceFunction(const SGCONF::CONFIG & config,
+                        const std::string & arg,
+                        const std::map<std::string, std::string> & options)
+{
+STG::ServiceConfOpt conf;
+conf.name = arg;
+SGCONF::MaybeSet(options, "cost", conf.cost);
+SGCONF::MaybeSet(options, "pay-day", conf.payDay);
+SGCONF::MaybeSet(options, "comment", conf.comment);
+STG::ServConf proto(config.server.data(),
+                    config.port.data(),
+                    config.localAddress.data(),
+                    config.localPort.data(),
+                    config.userName.data(),
+                    config.userPass.data());
+return proto.ChgService(conf, SimpleCallback, NULL) == STG::st_ok;
+}
+
+} // namespace anonymous
+
+void SGCONF::AppendServicesOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks)
+{
+std::vector<API_ACTION::PARAM> params(GetServiceParams());
+blocks.Add("Service management options")
+      .Add("get-services", SGCONF::MakeAPIAction(commands, GetServicesFunction), "\tget service list")
+      .Add("get-service", SGCONF::MakeAPIAction(commands, "<name>", GetServiceFunction), "get service")
+      .Add("add-service", SGCONF::MakeAPIAction(commands, "<name>", params, AddServiceFunction), "add service")
+      .Add("del-service", SGCONF::MakeAPIAction(commands, "<name>", DelServiceFunction), "delete service")
+      .Add("chg-service", SGCONF::MakeAPIAction(commands, "<name>", params, ChgServiceFunction), "change service");
+}
diff --git a/projects/sgconf/services.h b/projects/sgconf/services.h
new file mode 100644 (file)
index 0000000..4eee2c6
--- /dev/null
@@ -0,0 +1,11 @@
+#pragma once
+
+namespace SGCONF
+{
+
+class OPTION_BLOCKS;
+class COMMANDS;
+
+void AppendServicesOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks);
+
+} // namespace SGCONF
diff --git a/projects/sgconf/tariffs.cpp b/projects/sgconf/tariffs.cpp
new file mode 100644 (file)
index 0000000..6c5ab3b
--- /dev/null
@@ -0,0 +1,449 @@
+#include "tariffs.h"
+
+#include "api_action.h"
+#include "options.h"
+#include "config.h"
+#include "utils.h"
+
+#include "stg/servconf.h"
+#include "stg/servconf_types.h"
+#include "stg/tariff_conf.h"
+#include "stg/common.h"
+
+#include <iostream>
+#include <algorithm>
+#include <sstream>
+#include <string>
+#include <map>
+#include <cstdint>
+#include <cassert>
+
+namespace
+{
+
+std::string Indent(size_t level, bool dash = false)
+{
+if (level == 0)
+    return "";
+return dash ? std::string(level * 4 - 2, ' ') + "- " : std::string(level * 4, ' ');
+}
+
+std::string ChangePolicyToString(STG::Tariff::ChangePolicy changePolicy)
+{
+switch (changePolicy)
+    {
+    case STG::Tariff::ALLOW: return "allow";
+    case STG::Tariff::TO_CHEAP: return "to_cheap";
+    case STG::Tariff::TO_EXPENSIVE: return "to_expensive";
+    case STG::Tariff::DENY: return "deny";
+    }
+return "unknown";
+}
+
+std::string PeriodToString(STG::Tariff::Period period)
+{
+switch (period)
+    {
+    case STG::Tariff::DAY:
+        return "daily";
+    case STG::Tariff::MONTH:
+        return "monthly";
+    }
+return "unknown";
+}
+
+std::string TraffTypeToString(STG::Tariff::TraffType traffType)
+{
+switch (traffType)
+    {
+    case STG::Tariff::TRAFF_UP:
+        return "upload";
+    case STG::Tariff::TRAFF_DOWN:
+        return "download";
+    case STG::Tariff::TRAFF_UP_DOWN:
+        return "upload + download";
+    case STG::Tariff::TRAFF_MAX:
+        return "max(upload, download)";
+    }
+return "unknown";
+}
+
+void ConvPeriod(const std::string & value, STG::Optional<STG::Tariff::Period> & res)
+{
+std::string lowered = ToLower(value);
+if (lowered == "daily")
+    res = STG::Tariff::DAY;
+else if (lowered == "monthly")
+    res = STG::Tariff::MONTH;
+else
+    throw SGCONF::ACTION::ERROR("Period should be 'daily' or 'monthly'. Got: '" + value + "'");
+}
+
+void ConvChangePolicy(const std::string & value, STG::Optional<STG::Tariff::ChangePolicy> & res)
+{
+std::string lowered = ToLower(value);
+if (lowered == "allow")
+    res = STG::Tariff::ALLOW;
+else if (lowered == "to_cheap")
+    res = STG::Tariff::TO_CHEAP;
+else if (lowered == "to_expensive")
+    res = STG::Tariff::TO_EXPENSIVE;
+else if (lowered == "deny")
+    res = STG::Tariff::DENY;
+else
+    throw SGCONF::ACTION::ERROR("Change policy should be 'allow', 'to_cheap', 'to_expensive' or 'deny'. Got: '" + value + "'");
+}
+
+void ConvChangePolicyTimeout(const std::string & value, STG::Optional<time_t> & res)
+{
+struct tm brokenTime;
+if (stg_strptime(value.c_str(), "%Y-%m-%d %H:%M:%S", &brokenTime) == NULL)
+    throw SGCONF::ACTION::ERROR("Credit expiration should be in format 'YYYY-MM-DD HH:MM:SS'. Got: '" + value + "'");
+res = stg_timegm(&brokenTime);
+}
+
+void ConvTraffType(const std::string & value, STG::Optional<STG::Tariff::TraffType> & res)
+{
+std::string lowered = ToLower(value);
+lowered.erase(std::remove(lowered.begin(), lowered.end(), ' '), lowered.end());
+if (lowered == "upload")
+    res = STG::Tariff::TRAFF_UP;
+else if (lowered == "download")
+    res = STG::Tariff::TRAFF_DOWN;
+else if (lowered == "upload+download")
+    res = STG::Tariff::TRAFF_UP_DOWN;
+else if (lowered.substr(0, 3) == "max")
+    res = STG::Tariff::TRAFF_MAX;
+else
+    throw SGCONF::ACTION::ERROR("Traff type should be 'upload', 'download', 'upload + download' or 'max'. Got: '" + value + "'");
+}
+
+STG::DirPriceDataOpt ConvTimeSpan(const std::string & value)
+{
+size_t dashPos = value.find_first_of('-');
+if (dashPos == std::string::npos)
+    throw SGCONF::ACTION::ERROR("Time span should be in format 'hh:mm-hh:mm'. Got: '" + value + "'");
+size_t fromColon = value.find_first_of(':');
+if (fromColon == std::string::npos || fromColon > dashPos)
+    throw SGCONF::ACTION::ERROR("Time span should be in format 'hh:mm-hh:mm'. Got: '" + value + "'");
+size_t toColon = value.find_first_of(':', dashPos);
+if (toColon == std::string::npos)
+    throw SGCONF::ACTION::ERROR("Time span should be in format 'hh:mm-hh:mm'. Got: '" + value + "'");
+STG::DirPriceDataOpt res;
+res.hDay = FromString<int>(value.substr(0, fromColon));
+if (res.hDay.data() < 0 || res.hDay.data() > 23)
+    throw SGCONF::ACTION::ERROR("Invalid 'from' hours. Got: '" + value.substr(0, fromColon) + "'");
+res.mDay = FromString<int>(value.substr(fromColon + 1, dashPos - fromColon - 1));
+if (res.mDay.data() < 0 || res.mDay.data() > 59)
+    throw SGCONF::ACTION::ERROR("Invalid 'from' minutes. Got: '" + value.substr(fromColon + 1, dashPos - fromColon - 1) + "'");
+res.hNight = FromString<int>(value.substr(dashPos + 1, toColon - dashPos - 1));
+if (res.hNight.data() < 0 || res.hNight.data() > 23)
+    throw SGCONF::ACTION::ERROR("Invalid 'to' hours. Got: '" + value.substr(dashPos + 1, toColon - dashPos - 1) + "'");
+res.mNight = FromString<int>(value.substr(toColon + 1, value.length() - toColon));
+if (res.mNight.data() < 0 || res.mNight.data() > 59)
+    throw SGCONF::ACTION::ERROR("Invalid 'to' minutes. Got: '" + value.substr(toColon + 1, value.length() - toColon) + "'");
+return res;
+}
+
+void splice(std::vector<STG::DirPriceDataOpt> & lhs, const std::vector<STG::DirPriceDataOpt> & rhs)
+{
+for (size_t i = 0; i < lhs.size() && i < rhs.size(); ++i)
+    lhs[i].splice(rhs[i]);
+}
+
+void ConvTimes(std::string value, std::vector<STG::DirPriceDataOpt> & res)
+{
+value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
+splice(res, Split<std::vector<STG::DirPriceDataOpt> >(value, ',', ConvTimeSpan));
+}
+
+struct ConvPrice : public std::unary_function<std::string, STG::DirPriceDataOpt>
+{
+    typedef STG::Optional<double> (STG::DirPriceDataOpt::* MemPtr);
+    ConvPrice(MemPtr before, MemPtr after)
+        : m_before(before), m_after(after)
+    {}
+
+    STG::DirPriceDataOpt operator()(const std::string & value)
+    {
+        STG::DirPriceDataOpt res;
+    size_t slashPos = value.find_first_of('/');
+    if (slashPos == std::string::npos)
+        {
+        double price = 0;
+        if (str2x(value, price) < 0)
+            throw SGCONF::ACTION::ERROR("Price should be a floating point number. Got: '" + value + "'");
+        (res.*m_before) = (res.*m_after) = price;
+        res.noDiscount = true;
+        }
+    else
+        {
+        double price = 0;
+        if (str2x(value.substr(0, slashPos), price) < 0)
+            throw SGCONF::ACTION::ERROR("Price should be a floating point number. Got: '" + value.substr(0, slashPos) + "'");
+        (res.*m_before) = price;
+        if (str2x(value.substr(slashPos + 1, value.length() - slashPos), price) < 0)
+            throw SGCONF::ACTION::ERROR("Price should be a floating point number. Got: '" + value.substr(slashPos + 1, value.length() - slashPos) + "'");
+        (res.*m_after) = price;
+        res.noDiscount = false;
+        }
+    return res;
+    }
+
+    MemPtr m_before;
+    MemPtr m_after;
+};
+
+void ConvDayPrices(std::string value, std::vector<STG::DirPriceDataOpt> & res)
+{
+value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
+splice(res, Split<std::vector<STG::DirPriceDataOpt> >(value, ',', ConvPrice(&STG::DirPriceDataOpt::priceDayA, &STG::DirPriceDataOpt::priceDayB)));
+}
+
+void ConvNightPrices(std::string value, std::vector<STG::DirPriceDataOpt> & res)
+{
+value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
+splice(res, Split<std::vector<STG::DirPriceDataOpt> >(value, ',', ConvPrice(&STG::DirPriceDataOpt::priceNightA, &STG::DirPriceDataOpt::priceNightB)));
+}
+
+STG::DirPriceDataOpt ConvThreshold(std::string value)
+{
+    STG::DirPriceDataOpt res;
+double threshold = 0;
+if (str2x(value, threshold) < 0)
+    throw SGCONF::ACTION::ERROR("Threshold should be a floating point value. Got: '" + value + "'");
+res.threshold = threshold;
+return res;
+}
+
+void ConvThresholds(std::string value, std::vector<STG::DirPriceDataOpt> & res)
+{
+value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
+splice(res, Split<std::vector<STG::DirPriceDataOpt> >(value, ',', ConvThreshold));
+}
+
+std::string TimeToString(int h, int m)
+{
+std::ostringstream stream;
+stream << (h < 10 ? "0" : "") << h << ":"
+       << (m < 10 ? "0" : "") << m;
+return stream.str();
+}
+
+void PrintDirPriceData(size_t dir, const STG::DirPriceData & data, size_t level)
+{
+std::string night = TimeToString(data.hNight, data.mNight);
+std::string day = TimeToString(data.hDay, data.mDay);
+std::cout << Indent(level, true) << "dir: " << dir << "\n"
+          << Indent(level)       << "'" << night << "' - '" << day << "': " << data.priceDayA << "/" << data.priceDayB << "\n"
+          << Indent(level)       << "'" << day << "' - '" << night << "': " << data.priceNightA << "/" << data.priceNightB << "\n"
+          << Indent(level)       << "threshold: " << data.threshold << "\n"
+          << Indent(level)       << "single price: " << (data.singlePrice ? "yes" : "no") << "\n"
+          << Indent(level)       << "discount: " << (data.noDiscount ? "no" : "yes") << "\n"; // Attention!
+}
+
+void PrintTariffConf(const STG::TariffConf & conf, size_t level)
+{
+std::cout << Indent(level, true) << "name: " << conf.name << "\n"
+          << Indent(level)       << "fee: " << conf.fee << "\n"
+          << Indent(level)       << "free mb: " << conf.free << "\n"
+          << Indent(level)       << "passive cost: " << conf.passiveCost << "\n"
+          << Indent(level)       << "traff type: " << TraffTypeToString(conf.traffType) << "\n"
+          << Indent(level)       << "period: " << PeriodToString(conf.period) << "\n"
+          << Indent(level)       << "change policy: " << ChangePolicyToString(conf.changePolicy) << "\n"
+          << Indent(level)       << "change policy timeout: " << formatTime(conf.changePolicyTimeout) << "\n";
+}
+
+void PrintTariff(const STG::GetTariff::Info & info, size_t level = 0)
+{
+PrintTariffConf(info.tariffConf, level);
+std::cout << Indent(level) << "dir prices:\n";
+for (size_t i = 0; i < info.dirPrice.size(); ++i)
+    PrintDirPriceData(i, info.dirPrice[i], level + 1);
+}
+
+std::vector<SGCONF::API_ACTION::PARAM> GetTariffParams()
+{
+std::vector<SGCONF::API_ACTION::PARAM> params;
+params.push_back(SGCONF::API_ACTION::PARAM("fee", "<fee>", "\t\ttariff fee"));
+params.push_back(SGCONF::API_ACTION::PARAM("free", "<free mb>", "\tprepaid traffic"));
+params.push_back(SGCONF::API_ACTION::PARAM("passive-cost", "<cost>", "\tpassive cost"));
+params.push_back(SGCONF::API_ACTION::PARAM("traff-type", "<type>", "\ttraffic type (up, down, up+down, max)"));
+params.push_back(SGCONF::API_ACTION::PARAM("period", "<period>", "\ttarification period (daily, monthly)"));
+params.push_back(SGCONF::API_ACTION::PARAM("change-policy", "<policy>", "tariff change policy (allow, to_cheap, to_expensive, deny)"));
+params.push_back(SGCONF::API_ACTION::PARAM("change-policy-timeout", "<yyyy-mm-dd hh:mm:ss>", "tariff change policy timeout"));
+params.push_back(SGCONF::API_ACTION::PARAM("times", "<hh:mm-hh:mm, ...>", "coma-separated day time-spans for each direction"));
+params.push_back(SGCONF::API_ACTION::PARAM("day-prices", "<price/price, ...>", "coma-separated day prices for each direction"));
+params.push_back(SGCONF::API_ACTION::PARAM("night-prices", "<price/price, ...>", "coma-separated night prices for each direction"));
+params.push_back(SGCONF::API_ACTION::PARAM("thresholds", "<threshold, ...>", "coma-separated thresholds for each direction"));
+return params;
+}
+
+void SimpleCallback(bool result,
+                    const std::string & reason,
+                    void * /*data*/)
+{
+if (!result)
+    {
+    std::cerr << "Operation failed. Reason: '" << reason << "'." << std::endl;
+    return;
+    }
+std::cout << "Success.\n";
+}
+
+void GetTariffsCallback(bool result,
+                        const std::string & reason,
+                        const std::vector<STG::GetTariff::Info> & info,
+                        void * /*data*/)
+{
+if (!result)
+    {
+    std::cerr << "Failed to get tariff list. Reason: '" << reason << "'." << std::endl;
+    return;
+    }
+std::cout << "Tariffs:\n";
+for (size_t i = 0; i < info.size(); ++i)
+    PrintTariff(info[i], 1);
+}
+
+void GetTariffCallback(bool result,
+                       const std::string & reason,
+                       const std::vector<STG::GetTariff::Info> & info,
+                       void * data)
+{
+assert(data != NULL && "Expecting pointer to std::string with the tariff's name.");
+const std::string & name = *static_cast<const std::string *>(data);
+if (!result)
+    {
+    std::cerr << "Failed to get tariff. Reason: '" << reason << "'." << std::endl;
+    return;
+    }
+for (size_t i = 0; i < info.size(); ++i)
+    if (info[i].tariffConf.name == name)
+        PrintTariff(info[i]);
+}
+
+bool GetTariffsFunction(const SGCONF::CONFIG & config,
+                        const std::string & /*arg*/,
+                        const std::map<std::string, std::string> & /*options*/)
+{
+STG::ServConf proto(config.server.data(),
+                    config.port.data(),
+                    config.localAddress.data(),
+                    config.localPort.data(),
+                    config.userName.data(),
+                    config.userPass.data());
+return proto.GetTariffs(GetTariffsCallback, NULL) == STG::st_ok;
+}
+
+bool GetTariffFunction(const SGCONF::CONFIG & config,
+                       const std::string & arg,
+                       const std::map<std::string, std::string> & /*options*/)
+{
+STG::ServConf proto(config.server.data(),
+                    config.port.data(),
+                    config.localAddress.data(),
+                    config.localPort.data(),
+                    config.userName.data(),
+                    config.userPass.data());
+// STG currently doesn't support <GetTariff name="..."/>.
+// So get a list of tariffs and filter it. 'data' param holds a pointer to 'name'.
+std::string name(arg);
+return proto.GetTariffs(GetTariffCallback, &name) == STG::st_ok;
+}
+
+bool DelTariffFunction(const SGCONF::CONFIG & config,
+                       const std::string & arg,
+                       const std::map<std::string, std::string> & /*options*/)
+{
+STG::ServConf proto(config.server.data(),
+                    config.port.data(),
+                    config.localAddress.data(),
+                    config.localPort.data(),
+                    config.userName.data(),
+                    config.userPass.data());
+return proto.DelTariff(arg, SimpleCallback, NULL) == STG::st_ok;
+}
+
+bool AddTariffFunction(const SGCONF::CONFIG & config,
+                       const std::string & arg,
+                       const std::map<std::string, std::string> & options)
+{
+STG::TariffDataOpt conf;
+conf.tariffConf.name = arg;
+SGCONF::MaybeSet(options, "fee", conf.tariffConf.fee);
+SGCONF::MaybeSet(options, "free", conf.tariffConf.free);
+SGCONF::MaybeSet(options, "passive-cost", conf.tariffConf.passiveCost);
+SGCONF::MaybeSet(options, "traff-type", conf.tariffConf.traffType, ConvTraffType);
+SGCONF::MaybeSet(options, "period", conf.tariffConf.period, ConvPeriod);
+SGCONF::MaybeSet(options, "change-policy", conf.tariffConf.changePolicy, ConvChangePolicy);
+SGCONF::MaybeSet(options, "change-policy-timeout", conf.tariffConf.changePolicyTimeout, ConvChangePolicyTimeout);
+SGCONF::MaybeSet(options, "times", conf.dirPrice, ConvTimes);
+SGCONF::MaybeSet(options, "day-prices", conf.dirPrice, ConvDayPrices);
+SGCONF::MaybeSet(options, "night-prices", conf.dirPrice, ConvNightPrices);
+SGCONF::MaybeSet(options, "thresholds", conf.dirPrice, ConvThresholds);
+for (size_t i = 0; i < conf.dirPrice.size(); ++i)
+    {
+    if (!conf.dirPrice[i].priceDayA.empty() &&
+        !conf.dirPrice[i].priceNightA.empty() &&
+        !conf.dirPrice[i].priceDayB.empty() &&
+        !conf.dirPrice[i].priceNightB.empty())
+        conf.dirPrice[i].singlePrice = conf.dirPrice[i].priceDayA.data() == conf.dirPrice[i].priceNightA.data() &&
+                                       conf.dirPrice[i].priceDayB.data() == conf.dirPrice[i].priceNightB.data();
+    }
+STG::ServConf proto(config.server.data(),
+                    config.port.data(),
+                    config.localAddress.data(),
+                    config.localPort.data(),
+                    config.userName.data(),
+                    config.userPass.data());
+return proto.AddTariff(arg, conf, SimpleCallback, NULL) == STG::st_ok;
+}
+
+bool ChgTariffFunction(const SGCONF::CONFIG & config,
+                       const std::string & arg,
+                       const std::map<std::string, std::string> & options)
+{
+STG::TariffDataOpt conf;
+conf.tariffConf.name = arg;
+SGCONF::MaybeSet(options, "fee", conf.tariffConf.fee);
+SGCONF::MaybeSet(options, "free", conf.tariffConf.free);
+SGCONF::MaybeSet(options, "passive-cost", conf.tariffConf.passiveCost);
+SGCONF::MaybeSet(options, "traff-type", conf.tariffConf.traffType, ConvTraffType);
+SGCONF::MaybeSet(options, "period", conf.tariffConf.period, ConvPeriod);
+SGCONF::MaybeSet(options, "change-policy", conf.tariffConf.changePolicy, ConvChangePolicy);
+SGCONF::MaybeSet(options, "change-policy-timeout", conf.tariffConf.changePolicyTimeout, ConvChangePolicyTimeout);
+SGCONF::MaybeSet(options, "times", conf.dirPrice, ConvTimes);
+SGCONF::MaybeSet(options, "day-prices", conf.dirPrice, ConvDayPrices);
+SGCONF::MaybeSet(options, "night-prices", conf.dirPrice, ConvNightPrices);
+SGCONF::MaybeSet(options, "thresholds", conf.dirPrice, ConvThresholds);
+for (size_t i = 0; i < conf.dirPrice.size(); ++i)
+    {
+    if (!conf.dirPrice[i].priceDayA.empty() &&
+        !conf.dirPrice[i].priceNightA.empty() &&
+        !conf.dirPrice[i].priceDayB.empty() &&
+        !conf.dirPrice[i].priceNightB.empty())
+        conf.dirPrice[i].singlePrice = conf.dirPrice[i].priceDayA.data() == conf.dirPrice[i].priceNightA.data() &&
+                                       conf.dirPrice[i].priceDayB.data() == conf.dirPrice[i].priceNightB.data();
+    }
+STG::ServConf proto(config.server.data(),
+                    config.port.data(),
+                    config.localAddress.data(),
+                    config.localPort.data(),
+                    config.userName.data(),
+                    config.userPass.data());
+return proto.ChgTariff(conf, SimpleCallback, NULL) == STG::st_ok;
+}
+
+} // namespace anonymous
+
+void SGCONF::AppendTariffsOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks)
+{
+std::vector<API_ACTION::PARAM> params(GetTariffParams());
+blocks.Add("Tariff management options")
+      .Add("get-tariffs", SGCONF::MakeAPIAction(commands, GetTariffsFunction), "\tget tariff list")
+      .Add("get-tariff", SGCONF::MakeAPIAction(commands, "<name>", GetTariffFunction), "get tariff")
+      .Add("add-tariff", SGCONF::MakeAPIAction(commands, "<name>", params, AddTariffFunction), "add tariff")
+      .Add("del-tariff", SGCONF::MakeAPIAction(commands, "<name>", DelTariffFunction), "delete tariff")
+      .Add("chg-tariff", SGCONF::MakeAPIAction(commands, "<name>", params, ChgTariffFunction), "change tariff");
+}
diff --git a/projects/sgconf/tariffs.h b/projects/sgconf/tariffs.h
new file mode 100644 (file)
index 0000000..b6b896d
--- /dev/null
@@ -0,0 +1,11 @@
+#pragma once
+
+namespace SGCONF
+{
+
+class OPTION_BLOCKS;
+class COMMANDS;
+
+void AppendTariffsOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks);
+
+} // namespace SGCONF
diff --git a/projects/sgconf/users.cpp b/projects/sgconf/users.cpp
new file mode 100644 (file)
index 0000000..3bf5caa
--- /dev/null
@@ -0,0 +1,469 @@
+#include "users.h"
+
+#include "api_action.h"
+#include "options.h"
+#include "config.h"
+#include "utils.h"
+
+#include "stg/servconf.h"
+#include "stg/servconf_types.h"
+#include "stg/user_conf.h"
+#include "stg/user_stat.h"
+#include "stg/user_ips.h"
+#include "stg/common.h"
+
+#include <iostream>
+#include <algorithm>
+#include <string>
+#include <map>
+
+namespace
+{
+
+std::string Indent(size_t level, bool dash = false)
+{
+if (level == 0)
+    return "";
+return dash ? std::string(level * 4 - 2, ' ') + "- " : std::string(level * 4, ' ');
+}
+
+void PrintUser(const STG::GetUser::Info & info, size_t level = 0)
+{
+std::cout << Indent(level, true) << "login: " << info.login << "\n"
+          << Indent(level)       << "password: " << info.password << "\n"
+          << Indent(level)       << "cash: " << info.cash << "\n"
+          << Indent(level)       << "credit: " << info.credit << "\n"
+          << Indent(level)       << "credit expire: " << TimeToString(info.creditExpire) << "\n"
+          << Indent(level)       << "last cash add: " << info.lastCashAdd << "\n"
+          << Indent(level)       << "last cash add time: " << TimeToString(info.lastCashAddTime) << "\n"
+          << Indent(level)       << "prepaid traffic: " << info.prepaidTraff << "\n"
+          << Indent(level)       << "disabled: " << (info.disabled ? "t" : "f") << "\n"
+          << Indent(level)       << "passive: " << (info.passive ? "t" : "f") << "\n"
+          << Indent(level)       << "disabled detail stat: " << (info.disableDetailStat ? "t" : "f") << "\n"
+          << Indent(level)       << "connected: " << (info.connected ? "t" : "f") << "\n"
+          << Indent(level)       << "always on-line: " << (info.alwaysOnline ? "t" : "f") << "\n"
+          << Indent(level)       << "IP: " << inet_ntostring(info.ip) << "\n"
+          << Indent(level)       << "IPs: " << info.ips << "\n"
+          << Indent(level)       << "tariff: " << info.tariff << "\n"
+          << Indent(level)       << "group: " << info.group << "\n"
+          << Indent(level)       << "note: " << info.note << "\n"
+          << Indent(level)       << "email: " << info.email << "\n"
+          << Indent(level)       << "name: " << info.name << "\n"
+          << Indent(level)       << "address: " << info.address << "\n"
+          << Indent(level)       << "phone: " << info.phone << "\n"
+          << Indent(level)       << "corporation: " << info.corp << "\n"
+          << Indent(level)       << "last ping time: " << TimeToString(info.pingTime) << "\n"
+          << Indent(level)       << "last activity time: " << TimeToString(info.lastActivityTime) << "\n"
+          << Indent(level)       << "traffic:\n";
+for (size_t i = 0; i < DIR_NUM; ++i)
+    {
+    std::cout << Indent(level + 1, true) << "dir: " << i << "\n"
+              << Indent(level + 1)       << "session upload: " << info.stat.su[i] << "\n"
+              << Indent(level + 1)       << "session download: " << info.stat.sd[i] << "\n"
+              << Indent(level + 1)       << "month upload: " << info.stat.mu[i] << "\n"
+              << Indent(level + 1)       << "month download: " << info.stat.md[i] << "\n";
+    }
+std::cout << Indent(level)       << "user data:\n";
+for (size_t i = 0; i < USERDATA_NUM; ++i)
+    std::cout << Indent(level + 1, true) << "user data " << i << ": " << info.userData[i] << "\n";
+if (!info.services.empty())
+    {
+    std::cout << Indent(level) << "services:\n";
+    for (size_t i = 0; i < info.services.size(); ++i)
+        std::cout << Indent(level + 1, true) << info.services[i] << "\n";
+    }
+if (!info.authBy.empty())
+    {
+    std::cout << Indent(level) << "auth by:\n";
+    for (size_t i = 0; i < info.authBy.size(); ++i)
+        std::cout << Indent(level + 1, true) << info.authBy[i] << "\n";
+    }
+}
+
+std::vector<SGCONF::API_ACTION::PARAM> GetUserParams()
+{
+std::vector<SGCONF::API_ACTION::PARAM> params;
+params.push_back(SGCONF::API_ACTION::PARAM("password", "<password>", "\tuser's password"));
+params.push_back(SGCONF::API_ACTION::PARAM("cash-add", "<cash[:message]>", "cash to add (with optional comment)"));
+params.push_back(SGCONF::API_ACTION::PARAM("cash-set", "<cash[:message]>", "cash to set (with optional comment)"));
+params.push_back(SGCONF::API_ACTION::PARAM("credit", "<amount>", "\tuser's credit"));
+params.push_back(SGCONF::API_ACTION::PARAM("credit-expire", "<date>", "\tcredit expiration"));
+params.push_back(SGCONF::API_ACTION::PARAM("free", "<free mb>", "\tprepaid traffic"));
+params.push_back(SGCONF::API_ACTION::PARAM("disabled", "<flag>", "\tdisable user (y|n)"));
+params.push_back(SGCONF::API_ACTION::PARAM("passive", "<flag>", "\tmake user passive (y|n)"));
+params.push_back(SGCONF::API_ACTION::PARAM("disable-detail-stat", "<flag>", "disable detail stat (y|n)"));
+params.push_back(SGCONF::API_ACTION::PARAM("always-online", "<flag>", "\tmake user always online (y|n)"));
+params.push_back(SGCONF::API_ACTION::PARAM("ips", "<ips>", "\t\tcoma-separated list of ips"));
+params.push_back(SGCONF::API_ACTION::PARAM("tariff", "<tariff name>", "\tcurrent tariff"));
+params.push_back(SGCONF::API_ACTION::PARAM("next-tariff", "<tariff name>", "tariff starting from the next month"));
+params.push_back(SGCONF::API_ACTION::PARAM("group", "<group>", "\t\tuser's group"));
+params.push_back(SGCONF::API_ACTION::PARAM("note", "<note>", "\t\tuser's note"));
+params.push_back(SGCONF::API_ACTION::PARAM("email", "<email>", "\t\tuser's email"));
+params.push_back(SGCONF::API_ACTION::PARAM("name", "<real name>", "\tuser's real name"));
+params.push_back(SGCONF::API_ACTION::PARAM("address", "<address>", "\tuser's postal address"));
+params.push_back(SGCONF::API_ACTION::PARAM("phone", "<phone>", "\t\tuser's phone number"));
+params.push_back(SGCONF::API_ACTION::PARAM("corp", "<corp name>", "\tcorporation name"));
+params.push_back(SGCONF::API_ACTION::PARAM("session-traffic", "<up/dn, ...>", "coma-separated session upload and download"));
+params.push_back(SGCONF::API_ACTION::PARAM("month-traffic", "<up/dn, ...>", "coma-separated month upload and download"));
+params.push_back(SGCONF::API_ACTION::PARAM("user-data", "<value, ...>", "coma-separated user data values"));
+return params;
+}
+
+std::vector<SGCONF::API_ACTION::PARAM> GetCheckParams()
+{
+std::vector<SGCONF::API_ACTION::PARAM> params;
+params.push_back(SGCONF::API_ACTION::PARAM("password", "<password>", "\tuser's password"));
+return params;
+}
+
+std::vector<SGCONF::API_ACTION::PARAM> GetMessageParams()
+{
+std::vector<SGCONF::API_ACTION::PARAM> params;
+params.push_back(SGCONF::API_ACTION::PARAM("logins", "<login, ...>", "\tlist of logins to send a message"));
+params.push_back(SGCONF::API_ACTION::PARAM("text", "<text>", "\t\tmessage text"));
+return params;
+}
+
+void ConvBool(const std::string & value, STG::Optional<int> & res)
+{
+res = !value.empty() && value[0] == 'y';
+}
+
+void Splice(std::vector<STG::Optional<std::string> > & lhs, const std::vector<STG::Optional<std::string> > & rhs)
+{
+for (size_t i = 0; i < lhs.size() && i < rhs.size(); ++i)
+    lhs[i].splice(rhs[i]);
+}
+
+STG::Optional<std::string> ConvString(const std::string & value)
+{
+return STG::Optional<std::string>(value);
+}
+
+void ConvStringList(std::string value, std::vector<STG::Optional<std::string> > & res)
+{
+Splice(res, Split<std::vector<STG::Optional<std::string> > >(value, ',', ConvString));
+}
+
+void ConvServices(std::string value, STG::Optional<std::vector<std::string> > & res)
+{
+value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
+res = Split<std::vector<std::string> >(value, ',');
+}
+
+void ConvCreditExpire(const std::string & value, STG::Optional<time_t> & res)
+{
+struct tm brokenTime;
+if (stg_strptime(value.c_str(), "%Y-%m-%d %H:%M:%S", &brokenTime) == NULL)
+    throw SGCONF::ACTION::ERROR("Credit expiration should be in format 'YYYY-MM-DD HH:MM:SS'. Got: '" + value + "'");
+res = stg_timegm(&brokenTime);
+}
+
+void ConvIPs(const std::string & value, STG::Optional<STG::UserIPs> & res)
+{
+res = STG::UserIPs::parse(value);
+}
+
+struct TRAFF
+{
+    uint64_t up;
+    uint64_t down;
+};
+
+TRAFF ConvTraff(const std::string & value)
+{
+TRAFF res;
+size_t slashPos = value.find_first_of('/');
+if (slashPos == std::string::npos)
+    throw SGCONF::ACTION::ERROR("Traffic record should be in format 'upload/download'. Got: '" + value + "'");
+
+if (str2x(value.substr(0, slashPos), res.up) < 0)
+    throw SGCONF::ACTION::ERROR("Traffic value should be an integer. Got: '" + value.substr(0, slashPos) + "'");
+if (str2x(value.substr(slashPos + 1, value.length() - slashPos), res.down) < 0)
+    throw SGCONF::ACTION::ERROR("Traffic value should be an integer. Got: '" + value.substr(slashPos + 1, value.length() - slashPos) + "'");
+return res;
+}
+
+void ConvSessionTraff(std::string value, STG::UserStatOpt & res)
+{
+value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
+std::vector<TRAFF> traff(Split<std::vector<TRAFF> >(value, ',', ConvTraff));
+if (traff.size() != DIR_NUM)
+    throw SGCONF::ACTION::ERROR("There should be prcisely " + std::to_string(DIR_NUM) + " records of session traffic.");
+for (size_t i = 0; i < DIR_NUM; ++i)
+    {
+    res.sessionUp[i] = traff[i].up;
+    res.sessionDown[i] = traff[i].down;
+    }
+}
+
+void ConvMonthTraff(std::string value, STG::UserStatOpt & res)
+{
+value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
+std::vector<TRAFF> traff(Split<std::vector<TRAFF> >(value, ',', ConvTraff));
+if (traff.size() != DIR_NUM)
+    throw SGCONF::ACTION::ERROR("There should be prcisely " + std::to_string(DIR_NUM) + " records of month traffic.");
+for (size_t i = 0; i < DIR_NUM; ++i)
+    {
+    res.monthUp[i] = traff[i].up;
+    res.monthDown[i] = traff[i].down;
+    }
+}
+
+void ConvCashInfo(const std::string & value, STG::Optional<STG::CashInfo> & res)
+{
+STG::CashInfo info;
+size_t pos = value.find_first_of(':');
+if (pos == std::string::npos)
+    {
+    if (str2x(value, info.first) < 0)
+        throw SGCONF::ACTION::ERROR("Cash should be a double value. Got: '" + value + "'");
+    }
+else
+    {
+    if (str2x(value.substr(0, pos), info.first) < 0)
+        throw SGCONF::ACTION::ERROR("Cash should be a double value. Got: '" + value + "'");
+    info.second = value.substr(pos + 1);
+    }
+res = info;
+}
+
+void SimpleCallback(bool result,
+                    const std::string & reason,
+                    void * /*data*/)
+{
+if (!result)
+    {
+    std::cerr << "Operation failed. Reason: '" << reason << "'." << std::endl;
+    return;
+    }
+std::cout << "Success.\n";
+}
+
+void GetUsersCallback(bool result,
+                      const std::string & reason,
+                      const std::vector<STG::GetUser::Info> & info,
+                      void * /*data*/)
+{
+if (!result)
+    {
+    std::cerr << "Failed to get user list. Reason: '" << reason << "'." << std::endl;
+    return;
+    }
+std::cout << "Users:\n";
+for (size_t i = 0; i < info.size(); ++i)
+    PrintUser(info[i], 1);
+}
+
+void GetUserCallback(bool result,
+                     const std::string & reason,
+                     const STG::GetUser::Info & info,
+                     void * /*data*/)
+{
+if (!result)
+    {
+    std::cerr << "Failed to get user. Reason: '" << reason << "'." << std::endl;
+    return;
+    }
+PrintUser(info);
+}
+
+void AuthByCallback(bool result,
+                    const std::string & reason,
+                    const std::vector<std::string> & info,
+                    void * /*data*/)
+{
+if (!result)
+    {
+    std::cerr << "Failed to get authorizer list. Reason: '" << reason << "'." << std::endl;
+    return;
+    }
+std::cout << "Authorized by:\n";
+for (size_t i = 0; i < info.size(); ++i)
+    std::cout << Indent(1, true) << info[i] << "\n";
+}
+
+bool GetUsersFunction(const SGCONF::CONFIG & config,
+                      const std::string & /*arg*/,
+                      const std::map<std::string, std::string> & /*options*/)
+{
+STG::ServConf proto(config.server.data(),
+                    config.port.data(),
+                    config.localAddress.data(),
+                    config.localPort.data(),
+                    config.userName.data(),
+                    config.userPass.data());
+return proto.GetUsers(GetUsersCallback, NULL) == STG::st_ok;
+}
+
+bool GetUserFunction(const SGCONF::CONFIG & config,
+                     const std::string & arg,
+                     const std::map<std::string, std::string> & /*options*/)
+{
+STG::ServConf proto(config.server.data(),
+                    config.port.data(),
+                    config.localAddress.data(),
+                    config.localPort.data(),
+                    config.userName.data(),
+                    config.userPass.data());
+return proto.GetUser(arg, GetUserCallback, NULL) == STG::st_ok;
+}
+
+bool DelUserFunction(const SGCONF::CONFIG & config,
+                     const std::string & arg,
+                     const std::map<std::string, std::string> & /*options*/)
+{
+STG::ServConf proto(config.server.data(),
+                    config.port.data(),
+                    config.localAddress.data(),
+                    config.localPort.data(),
+                    config.userName.data(),
+                    config.userPass.data());
+return proto.DelUser(arg, SimpleCallback, NULL) == STG::st_ok;
+}
+
+bool AddUserFunction(const SGCONF::CONFIG & config,
+                     const std::string & arg,
+                     const std::map<std::string, std::string> & options)
+{
+STG::UserConfOpt conf;
+SGCONF::MaybeSet(options, "password", conf.password);
+SGCONF::MaybeSet(options, "passive", conf.passive, ConvBool);
+SGCONF::MaybeSet(options, "disabled", conf.disabled, ConvBool);
+SGCONF::MaybeSet(options, "disable-detail-stat", conf.disabledDetailStat, ConvBool);
+SGCONF::MaybeSet(options, "always-online", conf.alwaysOnline, ConvBool);
+SGCONF::MaybeSet(options, "tariff", conf.tariffName);
+SGCONF::MaybeSet(options, "address", conf.address);
+SGCONF::MaybeSet(options, "phone", conf.phone);
+SGCONF::MaybeSet(options, "email", conf.email);
+SGCONF::MaybeSet(options, "note", conf.note);
+SGCONF::MaybeSet(options, "name", conf.realName);
+SGCONF::MaybeSet(options, "corp", conf.corp);
+SGCONF::MaybeSet(options, "services", conf.services, ConvServices);
+SGCONF::MaybeSet(options, "group", conf.group);
+SGCONF::MaybeSet(options, "credit", conf.credit);
+SGCONF::MaybeSet(options, "next-tariff", conf.nextTariff);
+SGCONF::MaybeSet(options, "user-data", conf.userdata, ConvStringList);
+SGCONF::MaybeSet(options, "credit-expire", conf.creditExpire, ConvCreditExpire);
+SGCONF::MaybeSet(options, "ips", conf.ips, ConvIPs);
+STG::UserStatOpt stat;
+SGCONF::MaybeSet(options, "cash-set", stat.cashSet, ConvCashInfo);
+SGCONF::MaybeSet(options, "free", stat.freeMb);
+SGCONF::MaybeSet(options, "session-traffic", stat, ConvSessionTraff);
+SGCONF::MaybeSet(options, "month-traffic", stat, ConvMonthTraff);
+STG::ServConf proto(config.server.data(),
+                    config.port.data(),
+                    config.localAddress.data(),
+                    config.localPort.data(),
+                    config.userName.data(),
+                    config.userPass.data());
+return proto.AddUser(arg, conf, stat, SimpleCallback, NULL) == STG::st_ok;
+}
+
+bool ChgUserFunction(const SGCONF::CONFIG & config,
+                     const std::string & arg,
+                     const std::map<std::string, std::string> & options)
+{
+STG::UserConfOpt conf;
+SGCONF::MaybeSet(options, "password", conf.password);
+SGCONF::MaybeSet(options, "passive", conf.passive, ConvBool);
+SGCONF::MaybeSet(options, "disabled", conf.disabled, ConvBool);
+SGCONF::MaybeSet(options, "disable-detail-stat", conf.disabledDetailStat, ConvBool);
+SGCONF::MaybeSet(options, "always-online", conf.alwaysOnline, ConvBool);
+SGCONF::MaybeSet(options, "tariff", conf.tariffName);
+SGCONF::MaybeSet(options, "address", conf.address);
+SGCONF::MaybeSet(options, "phone", conf.phone);
+SGCONF::MaybeSet(options, "email", conf.email);
+SGCONF::MaybeSet(options, "note", conf.note);
+SGCONF::MaybeSet(options, "name", conf.realName);
+SGCONF::MaybeSet(options, "corp", conf.corp);
+SGCONF::MaybeSet(options, "services", conf.services, ConvServices);
+SGCONF::MaybeSet(options, "group", conf.group);
+SGCONF::MaybeSet(options, "credit", conf.credit);
+SGCONF::MaybeSet(options, "next-tariff", conf.nextTariff);
+SGCONF::MaybeSet(options, "user-data", conf.userdata, ConvStringList);
+SGCONF::MaybeSet(options, "credit-expire", conf.creditExpire, ConvCreditExpire);
+SGCONF::MaybeSet(options, "ips", conf.ips, ConvIPs);
+STG::UserStatOpt stat;
+SGCONF::MaybeSet(options, "cash-add", stat.cashAdd, ConvCashInfo);
+SGCONF::MaybeSet(options, "cash-set", stat.cashSet, ConvCashInfo);
+SGCONF::MaybeSet(options, "free", stat.freeMb);
+SGCONF::MaybeSet(options, "session-traffic", stat, ConvSessionTraff);
+SGCONF::MaybeSet(options, "month-traffic", stat, ConvMonthTraff);
+STG::ServConf proto(config.server.data(),
+                    config.port.data(),
+                    config.localAddress.data(),
+                    config.localPort.data(),
+                    config.userName.data(),
+                    config.userPass.data());
+return proto.ChgUser(arg, conf, stat, SimpleCallback, NULL) == STG::st_ok;
+}
+
+bool CheckUserFunction(const SGCONF::CONFIG & config,
+                       const std::string & arg,
+                       const std::map<std::string, std::string> & options)
+{
+std::map<std::string, std::string>::const_iterator it(options.find("password"));
+if (it == options.end())
+    throw SGCONF::ACTION::ERROR("Password is not specified.");
+STG::ServConf proto(config.server.data(),
+                    config.port.data(),
+                    config.localAddress.data(),
+                    config.localPort.data(),
+                    config.userName.data(),
+                    config.userPass.data());
+return proto.CheckUser(arg, it->second, SimpleCallback, NULL) == STG::st_ok;
+}
+
+bool SendMessageFunction(const SGCONF::CONFIG & config,
+                         const std::string & /*arg*/,
+                         const std::map<std::string, std::string> & options)
+{
+std::map<std::string, std::string>::const_iterator it(options.find("logins"));
+if (it == options.end())
+    throw SGCONF::ACTION::ERROR("Logins are not specified.");
+std::string logins = it->second;
+for (size_t i = 0; i < logins.length(); ++i)
+    if (logins[i] == ',')
+        logins[i] = ':';
+it = options.find("text");
+if (it == options.end())
+    throw SGCONF::ACTION::ERROR("Message text is not specified.");
+std::string text = it->second;
+STG::ServConf proto(config.server.data(),
+                    config.port.data(),
+                    config.localAddress.data(),
+                    config.localPort.data(),
+                    config.userName.data(),
+                    config.userPass.data());
+return proto.SendMessage(logins, text, SimpleCallback, NULL) == STG::st_ok;
+}
+
+bool AuthByFunction(const SGCONF::CONFIG & config,
+                    const std::string & arg,
+                    const std::map<std::string, std::string> & /*options*/)
+{
+STG::ServConf proto(config.server.data(),
+                    config.port.data(),
+                    config.localAddress.data(),
+                    config.localPort.data(),
+                    config.userName.data(),
+                    config.userPass.data());
+return proto.AuthBy(arg, AuthByCallback, NULL) == STG::st_ok;
+}
+
+} // namespace anonymous
+
+void SGCONF::AppendUsersOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks)
+{
+std::vector<API_ACTION::PARAM> params(GetUserParams());
+blocks.Add("User management options")
+      .Add("get-users", SGCONF::MakeAPIAction(commands, GetUsersFunction), "\tget user list")
+      .Add("get-user", SGCONF::MakeAPIAction(commands, "<login>", GetUserFunction), "get user")
+      .Add("add-user", SGCONF::MakeAPIAction(commands, "<login>", params, AddUserFunction), "add user")
+      .Add("del-user", SGCONF::MakeAPIAction(commands, "<login>", DelUserFunction), "delete user")
+      .Add("chg-user", SGCONF::MakeAPIAction(commands, "<login>", params, ChgUserFunction), "change user")
+      .Add("check-user", SGCONF::MakeAPIAction(commands, "<login>", GetCheckParams(), CheckUserFunction), "check user existance and credentials")
+      .Add("send-message", SGCONF::MakeAPIAction(commands, GetMessageParams(), SendMessageFunction), "send message")
+      .Add("auth-by", SGCONF::MakeAPIAction(commands, "<login>", AuthByFunction), "a list of authorizers user authorized by");
+}
diff --git a/projects/sgconf/users.h b/projects/sgconf/users.h
new file mode 100644 (file)
index 0000000..01bc6db
--- /dev/null
@@ -0,0 +1,11 @@
+#pragma once
+
+namespace SGCONF
+{
+
+class OPTION_BLOCKS;
+class COMMANDS;
+
+void AppendUsersOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks);
+
+}
diff --git a/projects/sgconf/utils.h b/projects/sgconf/utils.h
new file mode 100644 (file)
index 0000000..6168cbf
--- /dev/null
@@ -0,0 +1,45 @@
+#pragma once
+
+#include "stg/common.h"
+#include "stg/optional.h"
+
+#include <string>
+#include <map>
+
+namespace SGCONF
+{
+
+template <typename T>
+inline
+void MaybeSet(const std::map<std::string, std::string> & options, const std::string & name, STG::Optional<T> & res)
+{
+std::map<std::string, std::string>::const_iterator it(options.find(name));
+if (it == options.end())
+    return;
+T value;
+if (str2x(it->second, value) < 0)
+    return;
+res = value;
+}
+
+template <typename T, typename F>
+inline
+void MaybeSet(const std::map<std::string, std::string> & options, const std::string & name, T & res, F conv)
+{
+std::map<std::string, std::string>::const_iterator it(options.find(name));
+if (it == options.end())
+    return;
+conv(it->second, res);
+}
+
+template <>
+inline
+void MaybeSet<std::string>(const std::map<std::string, std::string> & options, const std::string & name, STG::Optional<std::string> & res)
+{
+std::map<std::string, std::string>::const_iterator it(options.find(name));
+if (it == options.end())
+    return;
+res = it->second;
+}
+
+} // namespace SGCONF
diff --git a/projects/sgconf/xml.cpp b/projects/sgconf/xml.cpp
new file mode 100644 (file)
index 0000000..61587a1
--- /dev/null
@@ -0,0 +1,105 @@
+#include "xml.h"
+
+#include "api_action.h"
+#include "options.h"
+#include "config.h"
+
+#include "stg/servconf.h"
+
+#include <iostream>
+#include <string>
+#include <map>
+
+#include <expat.h>
+
+namespace
+{
+
+struct ParserState
+{
+size_t level;
+};
+
+std::string Indent(size_t level)
+{
+return std::string(level * 4, ' ');
+}
+
+std::string PrintAttr(const char ** attr)
+{
+std::string res;
+if (attr == NULL)
+    return res;
+while (*attr)
+    {
+    if (*(attr + 1) == NULL)
+        return res;
+    res += std::string(" ") + *attr + "=\"" + *(attr + 1) + "\"";
+    ++attr; ++attr;
+    }
+return res;
+}
+
+void Start(void * data, const char * el, const char ** attr)
+{
+ParserState * state = static_cast<ParserState *>(data);
+if (el != NULL)
+    std::cout << Indent(state->level) << "<" << el << PrintAttr(attr) << ">\n";
+++state->level;
+}
+
+void End(void * data, const char * el)
+{
+ParserState * state = static_cast<ParserState *>(data);
+--state->level;
+if (el != NULL)
+    std::cout << Indent(state->level) << "</" << el << ">\n";
+}
+
+void PrintXML(const std::string& xml)
+{
+ParserState state = { 0 };
+
+XML_Parser parser = XML_ParserCreate(NULL);
+XML_ParserReset(parser, NULL);
+XML_SetElementHandler(parser, Start, End);
+XML_SetUserData(parser, &state);
+
+if (XML_Parse(parser, xml.c_str(), xml.length(), true) == XML_STATUS_ERROR)
+    std::cerr << "XML parse error at line " << XML_GetCurrentLineNumber(parser)
+              << ": '" << XML_ErrorString(XML_GetErrorCode(parser)) << "'"
+              << std::endl;
+
+XML_ParserFree(parser);
+}
+
+void RawXMLCallback(bool result, const std::string & reason, const std::string & response, void * /*data*/)
+{
+if (!result)
+    {
+    std::cerr << "Failed to get raw XML response. Reason: '" << reason << "'." << std::endl;
+    return;
+    }
+PrintXML(response);
+}
+
+bool RawXMLFunction(const SGCONF::CONFIG & config,
+                    const std::string & arg,
+                    const std::map<std::string, std::string> & /*options*/)
+{
+STG::ServConf proto(config.server.data(),
+                    config.port.data(),
+                    config.localAddress.data(),
+                    config.localPort.data(),
+                    config.userName.data(),
+                    config.userPass.data());
+return proto.RawXML(arg, RawXMLCallback, NULL) == STG::st_ok;
+}
+
+}
+
+void SGCONF::AppendXMLOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks)
+{
+blocks.Add("Raw XML")
+      .Add("r", "raw", SGCONF::MakeAPIAction(commands, "<xml>", RawXMLFunction), "\tmake raw XML request");
+}
diff --git a/projects/sgconf/xml.h b/projects/sgconf/xml.h
new file mode 100644 (file)
index 0000000..d00d441
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#pragma once
+
+namespace SGCONF
+{
+
+class OPTION_BLOCKS;
+class COMMANDS;
+
+void AppendXMLOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks);
+
+}
diff --git a/projects/stargazer/BUGS b/projects/stargazer/BUGS
new file mode 100644 (file)
index 0000000..139597f
--- /dev/null
@@ -0,0 +1,2 @@
+
+
diff --git a/projects/stargazer/CHANGES b/projects/stargazer/CHANGES
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/projects/stargazer/CMakeLists.txt b/projects/stargazer/CMakeLists.txt
new file mode 100644 (file)
index 0000000..073c716
--- /dev/null
@@ -0,0 +1,28 @@
+set ( CPP_FILES main.cpp
+                admins_impl.cpp
+                users_impl.cpp
+                tariffs_impl.cpp
+                corps_impl.cpp
+                services_impl.cpp
+                user_impl.cpp
+                tariff_impl.cpp
+                eventloop.cpp
+                pidfile.cpp
+                plugin_runner.cpp
+                plugin_mgr.cpp
+                settings_impl.cpp
+                stg_timer.cpp
+                store_loader.cpp
+                traffcounter_impl.cpp
+                user_property.cpp )
+
+set ( THREADS_PREFER_PTHREAD_FLAG ON )
+find_package ( Threads REQUIRED )
+
+add_executable ( stargazer ${CPP_FILES} )
+
+target_link_libraries ( stargazer scriptexecuter dotconfpp logger common Threads::Threads ${CMAKE_DL_LIBS} )
+
+add_subdirectory ( plugins )
+
+# TODO: install
diff --git a/projects/stargazer/README b/projects/stargazer/README
new file mode 100644 (file)
index 0000000..21ede00
--- /dev/null
@@ -0,0 +1,6 @@
+Инсталяция и запуск.
+1. > ./build
+2. > make install
+3. Правка конфигурационных файлов
+4. > stargazer
+
diff --git a/projects/stargazer/TODO b/projects/stargazer/TODO
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/projects/stargazer/actions.h b/projects/stargazer/actions.h
new file mode 100644 (file)
index 0000000..eea72b7
--- /dev/null
@@ -0,0 +1,90 @@
+#ifndef __ACTIONS_H__
+#define __ACTIONS_H__
+
+// Usage:
+//
+// ACTIONS_LIST actionsList;
+// CLASS myClass;
+// DATA1 myData1;
+// DATA2 myData2;
+//
+// actionsList.Enqueue(myClass, &CLASS::myMethod1, myData1);
+// actionsList.Enqueue(myClass, &CLASS::myMethod2, myData2);
+//
+// actionsList.InvokeAll();
+
+#include <pthread.h>
+#include <vector>
+#include <functional>
+
+// Generalized actor type - a method of some class with one argument
+template <class ACTIVE_CLASS, typename DATA_TYPE>
+struct ACTOR
+{
+typedef void (ACTIVE_CLASS::*TYPE)(DATA_TYPE);
+};
+
+// Abstract base action class for polymorphic action invocation
+class BASE_ACTION
+{
+public:
+    virtual ~BASE_ACTION() {}
+    virtual void Invoke() = 0;
+};
+
+// Concrete generalized action type - an actor with it's data and owner
+template <class ACTIVE_CLASS, typename DATA_TYPE>
+class ACTION : public BASE_ACTION,
+               public std::unary_function<ACTIVE_CLASS &, void>
+{
+public:
+    ACTION(ACTIVE_CLASS & ac,
+           typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE a,
+           DATA_TYPE d)
+        : activeClass(ac), actor(a), data(d) {}
+    void Invoke();
+private:
+    ACTION(const ACTION<ACTIVE_CLASS, DATA_TYPE> & rvalue);
+    ACTION<ACTIVE_CLASS, DATA_TYPE> & operator=(const ACTION<ACTIVE_CLASS, DATA_TYPE> & rvalue);
+
+    ACTIVE_CLASS & activeClass;
+    typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE actor;
+    DATA_TYPE data;
+};
+
+// A list of an actions
+// All methods are thread-safe
+class ACTIONS_LIST : private std::vector<BASE_ACTION *>
+{
+public:
+    // Just a typedef for parent class
+    typedef std::vector<BASE_ACTION *> parent;
+
+    // Initialize mutex
+    ACTIONS_LIST();
+    // Delete actions and destroy mutex
+    virtual ~ACTIONS_LIST();
+
+    parent::iterator begin();
+    parent::iterator end();
+    parent::const_iterator begin() const;
+    parent::const_iterator end() const;
+
+    bool empty() const;
+    size_t size() const;
+    void swap(ACTIONS_LIST & list);
+
+    // Add an action to list
+    template <class ACTIVE_CLASS, typename DATA_TYPE>
+    void Enqueue(ACTIVE_CLASS & ac,
+                 typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE a,
+                 DATA_TYPE d);
+    // Invoke all actions in the list
+    void InvokeAll();
+private:
+    mutable pthread_mutex_t mutex;
+};
+
+#include "actions.inl.h"
+
+#endif
diff --git a/projects/stargazer/actions.inl.h b/projects/stargazer/actions.inl.h
new file mode 100644 (file)
index 0000000..1b713f1
--- /dev/null
@@ -0,0 +1,110 @@
+#ifndef __ACTIONS_INL_H__
+#define __ACTIONS_INL_H__
+
+#include <algorithm>
+
+#include "stg/locker.h"
+
+// Polymorphick action invocation
+template <class ACTIVE_CLASS, typename DATA_TYPE>
+inline
+void ACTION<ACTIVE_CLASS, DATA_TYPE>::Invoke()
+{
+(activeClass.*actor)(data);
+}
+
+inline
+ACTIONS_LIST::ACTIONS_LIST()
+    : mutex()
+{
+pthread_mutex_init(&mutex, NULL);
+}
+
+// Delete all actions before deleting list
+inline
+ACTIONS_LIST::~ACTIONS_LIST()
+{
+
+    {
+    STG_LOCKER lock(&mutex);
+
+    parent::iterator it(parent::begin());
+    while (it != parent::end())
+        {
+        delete *it++;
+        }
+    }
+
+pthread_mutex_destroy(&mutex);
+}
+
+inline
+ACTIONS_LIST::parent::iterator ACTIONS_LIST::begin()
+{
+STG_LOCKER lock(&mutex);
+return parent::begin();
+}
+
+inline
+ACTIONS_LIST::parent::iterator ACTIONS_LIST::end()
+{
+STG_LOCKER lock(&mutex);
+return parent::end();
+}
+
+inline
+ACTIONS_LIST::parent::const_iterator ACTIONS_LIST::begin() const
+{
+STG_LOCKER lock(&mutex);
+return parent::begin();
+}
+
+inline
+ACTIONS_LIST::parent::const_iterator ACTIONS_LIST::end() const
+{
+STG_LOCKER lock(&mutex);
+return parent::end();
+}
+
+inline
+bool ACTIONS_LIST::empty() const
+{
+STG_LOCKER lock(&mutex);
+return parent::empty();
+}
+
+inline
+size_t ACTIONS_LIST::size() const
+{
+STG_LOCKER lock(&mutex);
+return parent::size();
+}
+
+inline
+void ACTIONS_LIST::swap(ACTIONS_LIST & list)
+{
+STG_LOCKER lock(&mutex);
+parent::swap(list);
+}
+
+template <class ACTIVE_CLASS, typename DATA_TYPE>
+inline
+void ACTIONS_LIST::Enqueue(ACTIVE_CLASS & ac,
+                           typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE a,
+                           DATA_TYPE d)
+{
+STG_LOCKER lock(&mutex);
+push_back(new ACTION<ACTIVE_CLASS, DATA_TYPE>(ac, a, d));
+}
+
+inline
+void ACTIONS_LIST::InvokeAll()
+{
+STG_LOCKER lock(&mutex);
+std::for_each(
+        parent::begin(),
+        parent::end(),
+        [](auto action){ action->Invoke(); });
+}
+
+#endif
diff --git a/projects/stargazer/admins_impl.cpp b/projects/stargazer/admins_impl.cpp
new file mode 100644 (file)
index 0000000..1e59736
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Date: 27.10.2002
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+#include "admins_impl.h"
+
+#include "stg/common.h"
+
+using STG::AdminsImpl;
+
+//-----------------------------------------------------------------------------
+AdminsImpl::AdminsImpl(Store& st)
+    : m_stg(Priv(0xFFFF), "@stargazer", ""),
+      m_noAdmin(Priv(0xFFFF), "NO-ADMIN", ""),
+      m_store(st),
+      WriteServLog(Logger::get())
+{
+    read();
+}
+//-----------------------------------------------------------------------------
+int AdminsImpl::add(const std::string& login, const Admin& admin)
+{
+    if (!admin.priv().adminChg)
+    {
+        const std::string s = admin.logStr() + " Add administrator \'" + login + "\'. Access denied.";
+        m_strError = "Access denied.";
+        WriteServLog(s.c_str());
+        return -1;
+    }
+
+    std::lock_guard<std::mutex> lock(m_mutex);
+    const auto it = find(login);
+
+    if (it != m_data.end())
+    {
+        m_strError = "Administrator \'" + login + "\' cannot not be added. Administrator already exists.";
+        WriteServLog("%s %s", admin.logStr().c_str(), m_strError.c_str());
+        return -1;
+    }
+
+    m_data.push_back(Admin(Priv(0), login, {}));
+
+    if (m_store.AddAdmin(login) == 0)
+    {
+        WriteServLog("%s Administrator \'%s\' added.",
+                     admin.logStr().c_str(), login.c_str());
+        return 0;
+    }
+
+    m_strError = "Administrator \'" + login + "\' was not added. Error: " + m_store.GetStrError();
+    WriteServLog("%s %s", admin.logStr().c_str(), m_strError.c_str());
+
+    return -1;
+}
+//-----------------------------------------------------------------------------
+int AdminsImpl::del(const std::string& login, const Admin& admin)
+{
+    if (!admin.priv().adminChg)
+    {
+        const std::string s = admin.logStr() + " Delete administrator \'" + login + "\'. Access denied.";
+        m_strError = "Access denied.";
+        WriteServLog(s.c_str());
+        return -1;
+    }
+
+    std::lock_guard<std::mutex> lock(m_mutex);
+    const auto it = find(login);
+
+    if (it == m_data.end())
+    {
+        m_strError = "Administrator \'" + login + "\' cannot be deleted. Administrator does not exist.";
+        WriteServLog("%s %s", admin.logStr().c_str(), m_strError.c_str());
+        return -1;
+    }
+
+    m_data.erase(it);
+    if (m_store.DelAdmin(login) < 0)
+    {
+        m_strError = "Administrator \'" + login + "\' was not deleted. Error: " + m_store.GetStrError();
+        WriteServLog("%s %s", admin.logStr().c_str(), m_strError.c_str());
+
+        return -1;
+    }
+
+    WriteServLog("%s Administrator \'%s\' deleted.", admin.logStr().c_str(), login.c_str());
+    return 0;
+}
+//-----------------------------------------------------------------------------
+int AdminsImpl::change(const AdminConf& ac, const Admin& admin)
+{
+    if (!admin.priv().adminChg)
+    {
+        const std::string s = admin.logStr() + " Change administrator \'" + ac.login + "\'. Access denied.";
+        m_strError = "Access denied.";
+        WriteServLog(s.c_str());
+        return -1;
+    }
+
+    std::lock_guard<std::mutex> lock(m_mutex);
+    const auto it = find(ac.login);
+
+    if (it == m_data.end())
+    {
+        m_strError = "Administrator \'" + ac.login + "\' cannot be changed " + ". Administrator does not exist.";
+        WriteServLog("%s %s", admin.logStr().c_str(), m_strError.c_str());
+        return -1;
+    }
+
+    *it = ac;
+    if (m_store.SaveAdmin(ac))
+    {
+        WriteServLog("Cannot write admin %s.", ac.login.c_str());
+        WriteServLog("%s", m_store.GetStrError().c_str());
+        return -1;
+    }
+
+    WriteServLog("%s Administrator \'%s\' changed.",
+                 admin.logStr().c_str(), ac.login.c_str());
+
+    return 0;
+}
+//-----------------------------------------------------------------------------
+void AdminsImpl::read()
+{
+    std::vector<std::string> logins;
+    if (m_store.GetAdminsList(&logins) < 0)
+    {
+        WriteServLog(m_store.GetStrError().c_str());
+        return;
+    }
+
+    std::vector<Admin> admins;
+    for (const auto& login : logins)
+    {
+        AdminConf ac(Priv(0), login, "");
+
+        if (m_store.RestoreAdmin(&ac, login))
+        {
+            WriteServLog(m_store.GetStrError().c_str());
+            return;
+        }
+
+        m_data.push_back(Admin(ac));
+    }
+
+    std::lock_guard<std::mutex> lock(m_mutex);
+    m_data.swap(admins);
+}
+//-----------------------------------------------------------------------------
+bool AdminsImpl::find(const std::string& login, Admin** admin)
+{
+    std::lock_guard<std::mutex> lock(m_mutex);
+    if (m_data.empty())
+    {
+        printfd(__FILE__, "No admin in system!\n");
+        if (admin != nullptr)
+            *admin = &m_noAdmin;
+        return false;
+    }
+
+    auto it = find(login);
+
+    if (it != m_data.end())
+    {
+        if (admin != nullptr)
+            *admin = &(*it);
+        return false;
+    }
+
+    return true;
+}
+//-----------------------------------------------------------------------------
+bool AdminsImpl::exists(const std::string& login) const
+{
+    std::lock_guard<std::mutex> lock(m_mutex);
+    if (m_data.empty())
+    {
+        printfd(__FILE__, "No admin in system!\n");
+        return true;
+    }
+
+    return find(login) != m_data.end();
+}
+//-----------------------------------------------------------------------------
+bool AdminsImpl::correct(const std::string& login, const std::string& password, Admin** admin)
+{
+    std::lock_guard<std::mutex> lock(m_mutex);
+    if (m_data.empty())
+    {
+        printfd(__FILE__, "No admin in system!\n");
+        return true;
+    }
+
+    const auto it = find(login);
+
+    if (it == m_data.end() || it->password() != password)
+        return false;
+
+    if (admin != nullptr)
+        *admin = &(*it);
+
+    return true;
+}
diff --git a/projects/stargazer/admins_impl.h b/projects/stargazer/admins_impl.h
new file mode 100644 (file)
index 0000000..9c443a7
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Date: 27.10.2002
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+#pragma once
+
+#include "stg/admins.h"
+#include "stg/admin.h"
+#include "stg/store.h"
+#include "stg/logger.h"
+
+#include <vector>
+#include <string>
+#include <algorithm>
+#include <mutex>
+
+namespace STG
+{
+
+class AdminsImpl : public Admins
+{
+    public:
+        explicit AdminsImpl(Store& st);
+
+        AdminsImpl(const AdminsImpl&) = delete;
+        AdminsImpl& operator=(const AdminsImpl&) = delete;
+
+        int          add(const std::string& login, const Admin& admin) override;
+        int          del(const std::string& login, const Admin& admin) override;
+        int          change(const AdminConf& ac, const Admin& admin) override;
+        const Admin& sysAdmin() const override { return m_stg; }
+        const Admin& noAdmin() const override { return m_noAdmin; }
+        bool         find(const std::string& login, Admin** admin) override;
+        bool         exists(const std::string& login) const override;
+        bool         correct(const std::string& login,
+                             const std::string& password,
+                             Admin** admin) override;
+
+        const std::string& strError() const override { return m_strError; }
+
+        size_t       count() const override { return m_data.size(); }
+
+        void fmap(std::function<void (const Admin&)> callback) const
+        {
+            for (const auto& admin : m_data)
+                callback(admin);
+        }
+
+    private:
+        void         read();
+        auto         find(const std::string& login) { return std::find(m_data.begin(), m_data.end(), Admin(Priv(0), login, "")); }
+        auto         find(const std::string& login) const { return std::find(m_data.begin(), m_data.end(), Admin(Priv(0), login, "")); }
+
+        Admin              m_stg;
+        Admin              m_noAdmin;
+        std::vector<Admin> m_data;
+        Store&             m_store;
+        Logger&            WriteServLog;
+        mutable std::mutex m_mutex;
+        std::string        m_strError;
+};
+
+}
diff --git a/projects/stargazer/corps_impl.cpp b/projects/stargazer/corps_impl.cpp
new file mode 100644 (file)
index 0000000..b41b455
--- /dev/null
@@ -0,0 +1,258 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#include "corps_impl.h"
+
+#include "stg/admin.h"
+#include "stg/admin_conf.h"
+#include "stg/store.h"
+#include "stg/common.h"
+
+#include <algorithm>
+#include <cassert>
+
+using STG::CorporationsImpl;
+
+//-----------------------------------------------------------------------------
+CorporationsImpl::CorporationsImpl(Store * st)
+    : store(st),
+      WriteServLog(Logger::get()),
+      handle(0)
+{
+Read();
+}
+//-----------------------------------------------------------------------------
+int CorporationsImpl::Add(const CorpConf & corp, const Admin * admin)
+{
+std::lock_guard<std::mutex> lock(mutex);
+const auto& priv = admin->priv();
+
+if (!priv.corpChg)
+    {
+    std::string s = admin->logStr() + " Add corporation \'" + corp.name + "\'. Access denied.";
+    strError = "Access denied.";
+    WriteServLog(s.c_str());
+    return -1;
+    }
+
+crp_iter si(find(data.begin(), data.end(), corp));
+
+if (si != data.end())
+    {
+    strError = "Corporation \'" + corp.name + "\' cannot not be added. Corporation already exist.";
+    WriteServLog("%s %s", admin->logStr().c_str(), strError.c_str());
+
+    return -1;
+    }
+
+data.push_back(corp);
+
+if (store->AddCorp(corp.name) == 0)
+    {
+    WriteServLog("%s Corporation \'%s\' added.",
+                 admin->logStr().c_str(), corp.name.c_str());
+    return 0;
+    }
+
+strError = "Corporation \'" + corp.name + "\' was not added. Error: " + store->GetStrError();
+WriteServLog("%s %s", admin->logStr().c_str(), strError.c_str());
+
+return -1;
+}
+//-----------------------------------------------------------------------------
+int CorporationsImpl::Del(const std::string & name, const Admin * admin)
+{
+std::lock_guard<std::mutex> lock(mutex);
+const auto& priv = admin->priv();
+
+if (!priv.corpChg)
+    {
+    std::string s = admin->logStr() + " Delete corporation \'" + name + "\'. Access denied.";
+    strError = "Access denied.";
+    WriteServLog(s.c_str());
+    return -1;
+    }
+
+crp_iter si(find(data.begin(), data.end(), CorpConf(name)));
+
+if (si == data.end())
+    {
+    strError = "Corporation \'" + name + "\' cannot be deleted. Corporation does not exist.";
+    WriteServLog("%s %s", admin->logStr().c_str(), strError.c_str());
+    return -1;
+    }
+
+std::map<int, const_crp_iter>::iterator csi;
+csi = searchDescriptors.begin();
+while (csi != searchDescriptors.end())
+    {
+    if (csi->second == si)
+        (csi->second)++;
+    ++csi;
+    }
+
+data.erase(si);
+if (store->DelCorp(name) < 0)
+    {
+    strError = "Corporation \'" + name + "\' was not deleted. Error: " + store->GetStrError();
+    WriteServLog("%s %s", admin->logStr().c_str(), strError.c_str());
+
+    return -1;
+    }
+
+WriteServLog("%s Corporation \'%s\' deleted.", admin->logStr().c_str(), name.c_str());
+return 0;
+}
+//-----------------------------------------------------------------------------
+int CorporationsImpl::Change(const CorpConf & corp, const Admin * admin)
+{
+std::lock_guard<std::mutex> lock(mutex);
+const auto& priv = admin->priv();
+
+if (!priv.corpChg)
+    {
+    std::string s = admin->logStr() + " Change corporation \'" + corp.name + "\'. Access denied.";
+    strError = "Access denied.";
+    WriteServLog(s.c_str());
+    return -1;
+    }
+
+crp_iter si(find(data.begin(), data.end(), corp));
+
+if (si == data.end())
+    {
+    strError = "Corporation \'" + corp.name + "\' cannot be changed " + ". Corporation does not exist.";
+    WriteServLog("%s %s", admin->logStr().c_str(), strError.c_str());
+    return -1;
+    }
+
+*si = corp;
+if (store->SaveCorp(corp))
+    {
+    WriteServLog("Cannot write corporation %s.", corp.name.c_str());
+    WriteServLog("%s", store->GetStrError().c_str());
+    return -1;
+    }
+
+WriteServLog("%s Corporation \'%s\' changed.",
+             admin->logStr().c_str(), corp.name.c_str());
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+bool CorporationsImpl::Read()
+{
+std::lock_guard<std::mutex> lock(mutex);
+std::vector<std::string> corpsList;
+if (store->GetCorpsList(&corpsList) < 0)
+    {
+    WriteServLog(store->GetStrError().c_str());
+    return true;
+    }
+
+for (size_t i = 0; i < corpsList.size(); i++)
+    {
+    CorpConf corp;
+
+    if (store->RestoreCorp(&corp, corpsList[i]))
+        {
+        WriteServLog(store->GetStrError().c_str());
+        return true;
+        }
+
+    data.push_back(corp);
+    }
+return false;
+}
+//-----------------------------------------------------------------------------
+bool CorporationsImpl::Find(const std::string & name, CorpConf * corp)
+{
+assert(corp != NULL && "Pointer to corporation is not null");
+
+std::lock_guard<std::mutex> lock(mutex);
+if (data.empty())
+    return false;
+
+crp_iter si(find(data.begin(), data.end(), CorpConf(name)));
+
+if (si != data.end())
+    {
+    *corp = *si;
+    return false;
+    }
+
+return true;
+}
+//-----------------------------------------------------------------------------
+bool CorporationsImpl::Exists(const std::string & name) const
+{
+std::lock_guard<std::mutex> lock(mutex);
+if (data.empty())
+    {
+    printfd(__FILE__, "no corporations in system!\n");
+    return true;
+    }
+
+const_crp_iter si(find(data.begin(), data.end(), CorpConf(name)));
+
+if (si != data.end())
+    return true;
+
+return false;
+}
+//-----------------------------------------------------------------------------
+int CorporationsImpl::OpenSearch() const
+{
+std::lock_guard<std::mutex> lock(mutex);
+handle++;
+searchDescriptors[handle] = data.begin();
+return handle;
+}
+//-----------------------------------------------------------------------------
+int CorporationsImpl::SearchNext(int h, CorpConf * corp) const
+{
+std::lock_guard<std::mutex> lock(mutex);
+if (searchDescriptors.find(h) == searchDescriptors.end())
+    {
+    WriteServLog("CORPORATIONS. Incorrect search handle.");
+    return -1;
+    }
+
+if (searchDescriptors[h] == data.end())
+    return -1;
+
+*corp = *searchDescriptors[h]++;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int CorporationsImpl::CloseSearch(int h) const
+{
+std::lock_guard<std::mutex> lock(mutex);
+if (searchDescriptors.find(h) != searchDescriptors.end())
+    {
+    searchDescriptors.erase(searchDescriptors.find(h));
+    return 0;
+    }
+
+WriteServLog("CORPORATIONS. Incorrect search handle.");
+return -1;
+}
+//-----------------------------------------------------------------------------
diff --git a/projects/stargazer/corps_impl.h b/projects/stargazer/corps_impl.h
new file mode 100644 (file)
index 0000000..43bcb5d
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#pragma once
+
+#include "stg/corporations.h"
+#include "stg/corp_conf.h"
+#include "stg/locker.h"
+#include "stg/logger.h"
+
+#include <vector>
+#include <map>
+#include <string>
+#include <mutex>
+
+namespace STG
+{
+
+struct Admin;
+struct Store;
+
+class CorporationsImpl : public Corporations {
+public:
+    explicit CorporationsImpl(Store* st);
+
+    int Add(const CorpConf& corp, const Admin* admin) override;
+    int Del(const std::string& name, const Admin* admin) override;
+    int Change(const CorpConf& corp, const Admin* admin) override;
+    bool Find(const std::string& name, CorpConf* corp) override;
+    bool Exists(const std::string& name) const override;
+    const std::string& GetStrError() const override { return strError; }
+
+    size_t Count() const override { return data.size(); }
+
+    int OpenSearch() const override;
+    int SearchNext(int, CorpConf* corp) const override;
+    int CloseSearch(int) const override;
+
+private:
+    typedef std::vector<CorpConf>::iterator       crp_iter;
+    typedef std::vector<CorpConf>::const_iterator const_crp_iter;
+
+    bool Read();
+
+    std::vector<CorpConf> data;
+    Store* store;
+    Logger& WriteServLog;
+    mutable std::map<int, const_crp_iter> searchDescriptors;
+    mutable unsigned int handle;
+    mutable std::mutex mutex;
+    std::string strError;
+};
+
+}
diff --git a/projects/stargazer/eventloop.cpp b/projects/stargazer/eventloop.cpp
new file mode 100644 (file)
index 0000000..36a77e9
--- /dev/null
@@ -0,0 +1,119 @@
+#include <csignal>
+#include <cerrno>
+#include <cstring>
+
+#include "stg/locker.h"
+#include "stg/common.h"
+#include "eventloop.h"
+
+EVENT_LOOP::EVENT_LOOP()
+    : ACTIONS_LIST(),
+      _running(false),
+      _stopped(true),
+      _tid(),
+      _mutex(),
+      _condition()
+{
+pthread_mutex_init(&_mutex, NULL);
+pthread_cond_init(&_condition, NULL);
+}
+
+EVENT_LOOP::~EVENT_LOOP()
+{
+pthread_cond_destroy(&_condition);
+pthread_mutex_destroy(&_mutex);
+}
+
+bool EVENT_LOOP::Start()
+{
+_running = true;
+if (pthread_create(&_tid, NULL, Run, this))
+    {
+    printfd(__FILE__, "EVENT_LOOP::Start - Failed to create thread: '%s'\n", strerror(errno));
+    return true;
+    }
+return false;
+}
+
+bool EVENT_LOOP::Stop()
+{
+_running = false;
+// Wake up thread
+pthread_cond_signal(&_condition);
+// Wait until thread exit
+pthread_join(_tid, NULL);
+return false;
+}
+
+void * EVENT_LOOP::Run(void * self)
+{
+EVENT_LOOP * ev = static_cast<EVENT_LOOP *>(self);
+ev->Runner();
+return NULL;
+}
+
+void EVENT_LOOP::Runner()
+{
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+_stopped = false;
+printfd(__FILE__, "EVENT_LOOP::Runner - Before start\n");
+while (_running)
+    {
+        {
+        STG_LOCKER lock(&_mutex);
+        // Check for any actions...
+        if (empty())
+            {
+            // ... and sleep until new actions added
+            printfd(__FILE__, "EVENT_LOOP::Runner - Sleeping until new actions arrived\n");
+            pthread_cond_wait(&_condition, &_mutex);
+            }
+        // Check for running after wake up
+        if (!_running)
+            {
+            // Don't process any actions if stopping
+            break;
+            }
+        }
+    // Create new empty actions list
+    ACTIONS_LIST local;
+    // Fast swap with current
+    swap(local);
+    // Invoke all current actions
+    printfd(__FILE__, "EVENT_LOOP::Runner - Invoke %d actions\n", local.size());
+    local.InvokeAll();
+    }
+printfd(__FILE__, "EVENT_LOOP::Runner - Before stop\n");
+_stopped = true;
+}
+
+namespace {
+
+pthread_mutex_t singletonMutex;
+
+}
+
+EVENT_LOOP & EVENT_LOOP_SINGLETON::GetInstance()
+{
+// Double-checking technique
+if (!_instance)
+    {
+    STG_LOCKER lock(&singletonMutex);
+    if (!_instance)
+        {
+        CreateInstance();
+        }
+    }
+return *_instance;
+}
+
+void EVENT_LOOP_SINGLETON::CreateInstance()
+{
+static EVENT_LOOP loop;
+_instance = &loop;
+}
+
+EVENT_LOOP * EVENT_LOOP_SINGLETON::_instance = NULL;
diff --git a/projects/stargazer/eventloop.h b/projects/stargazer/eventloop.h
new file mode 100644 (file)
index 0000000..0e79814
--- /dev/null
@@ -0,0 +1,63 @@
+#ifndef __EVENT_LOOP_H__
+#define __EVENT_LOOP_H__
+
+#include <pthread.h>
+
+#include "stg/noncopyable.h"
+#include "actions.h"
+
+class EVENT_LOOP : private NONCOPYABLE,
+                   private ACTIONS_LIST
+{
+    public:
+        bool Start();
+        bool Stop();
+        bool IsRunning() const { return _running; }
+
+        template <class ACTIVE_CLASS, typename DATA_TYPE>
+        void Enqueue(ACTIVE_CLASS & ac,
+                     typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE a,
+                     DATA_TYPE d);
+
+    private:
+        bool _running;
+        bool _stopped;
+        pthread_t _tid;
+        pthread_mutex_t _mutex;
+        pthread_cond_t _condition;
+
+        EVENT_LOOP();
+        virtual ~EVENT_LOOP();
+
+        static void * Run(void *);
+        void Runner();
+
+        friend class EVENT_LOOP_SINGLETON;
+};
+
+class EVENT_LOOP_SINGLETON : private NONCOPYABLE
+{
+    public:
+        static EVENT_LOOP & GetInstance();
+
+    private:
+        static EVENT_LOOP * _instance;
+        static void CreateInstance();
+
+        EVENT_LOOP_SINGLETON() {}
+        ~EVENT_LOOP_SINGLETON() {}
+};
+
+template <class ACTIVE_CLASS, typename DATA_TYPE>
+void EVENT_LOOP::Enqueue(ACTIVE_CLASS & ac,
+                         typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE a,
+                         DATA_TYPE d)
+{
+STG_LOCKER lock(&_mutex);
+// Add new action
+ACTIONS_LIST::Enqueue(ac, a, d);
+// Signal about new action
+pthread_cond_signal(&_condition);
+}
+
+#endif
diff --git a/projects/stargazer/inst/freebsd/etc/stargazer/OnChange b/projects/stargazer/inst/freebsd/etc/stargazer/OnChange
new file mode 100755 (executable)
index 0000000..8cb1096
--- /dev/null
@@ -0,0 +1,8 @@
+#! /bin/sh
+
+login=$1
+param=$2
+oldValue=$3
+newValue=$4
+
+#echo "User: '$login'. Parameter $param changed from '$oldValue' to '$newValue'" >> /var/stargazer/users.chg.log
\ No newline at end of file
diff --git a/projects/stargazer/inst/freebsd/etc/stargazer/OnConnect b/projects/stargazer/inst/freebsd/etc/stargazer/OnConnect
new file mode 100755 (executable)
index 0000000..912ed7d
--- /dev/null
@@ -0,0 +1,24 @@
+#! /bin/sh
+
+#Этот скрипт вызывается в момент, когда пользователь
+#успешно прошел авторизацию на сервере. Задача скрипта - перестроить 
+#файрвол так, что бы пользователь получил доступ в интернет
+
+# Login
+LOGIN=$1
+
+#user IP
+IP=$2
+
+#cash
+CASH=$3
+
+#user ID
+ID=$4
+
+#Selected dirs to connect
+DIRS=$5
+
+
+#echo "C `date +%Y.%m.%d-%H.%M.%S` $IP $CASH" >> /var/stargazer/users/$LOGIN/connect.log
+
diff --git a/projects/stargazer/inst/freebsd/etc/stargazer/OnDisconnect b/projects/stargazer/inst/freebsd/etc/stargazer/OnDisconnect
new file mode 100755 (executable)
index 0000000..6169ddc
--- /dev/null
@@ -0,0 +1,24 @@
+#! /bin/sh
+
+# Этот скрипт вызывается в момент, когда пользователь
+# желает отключится от интернета или вышел таймаут у пользователя
+# и сервер сам отключает пользователя
+# Задача скрипта подобна задаче скрипта OnConnect - перестроить 
+# файрвол так, что бы пользователю закрыть доступ в интернет
+
+# Login
+LOGIN=$1
+
+#user IP
+IP=$2
+
+#cash
+CASH=$3
+
+#user ID
+ID=$4
+
+#Selected dirs to disconnect
+DIRS=$5
+
+#echo "D `date +%Y.%m.%d-%H.%M.%S` $IP $CASH" >> /var/stargazer/users/$LOGIN/connect.log
diff --git a/projects/stargazer/inst/freebsd/etc/stargazer/OnUserAdd b/projects/stargazer/inst/freebsd/etc/stargazer/OnUserAdd
new file mode 100755 (executable)
index 0000000..22d321c
--- /dev/null
@@ -0,0 +1,14 @@
+#! /bin/sh
+
+# Использование (неиспользование) этого скрипта дело вкуса.
+# Он не выполняет критических функций. Его задача автматизировать
+# действия характерные при добавлении пользователя сети, например добавлекние 
+# пользователю почты
+
+# Login
+login=$1
+
+#echo "added user $login" >> /var/stargazer/add_del.log
+
+
+
diff --git a/projects/stargazer/inst/freebsd/etc/stargazer/OnUserDel b/projects/stargazer/inst/freebsd/etc/stargazer/OnUserDel
new file mode 100755 (executable)
index 0000000..248e5b3
--- /dev/null
@@ -0,0 +1,7 @@
+#! /bin/sh
+
+# Login
+login=$1
+
+#echo "deleted user $login" >> /var/stargazer/add_del.log
+
diff --git a/projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_ao.conf b/projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_ao.conf
new file mode 100644 (file)
index 0000000..62c0dc7
--- /dev/null
@@ -0,0 +1,3 @@
+# Enable the authorization module Always Online "mod_auth_ao.so"
+<Module auth_ao>
+</Module>
\ No newline at end of file
diff --git a/projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_cap_bpf.conf b/projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_cap_bpf.conf
new file mode 100644 (file)
index 0000000..4a6c626
--- /dev/null
@@ -0,0 +1,7 @@
+# Enable the traffic capture module "mod_cap_ipq.so" using Berkeley Packet Filter
+<Module cap_bpf>
+   # Define interface(s) for traffic capture
+   iface = rl0
+   iface = rl1
+   iface = dc0
+</Module>
\ No newline at end of file
diff --git a/projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_cap_divert.conf b/projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_cap_divert.conf
new file mode 100644 (file)
index 0000000..acd15e0
--- /dev/null
@@ -0,0 +1,14 @@
+# Enable the traffic capture module "mod_cap_divert.so" using Divert-sockets
+<Module cap_divert>
+   # Port for traffic
+   # Parameter: optional
+   # Value: 1 ... 65535
+   # Default: 15701
+   Port = 15701
+
+   # Disable packet forwarding
+   # Parameter: optional
+   # Value: yes, no
+   # Default: no
+   DisableForwarding = no
+</Module>
diff --git a/projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_cap_nf.conf b/projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_cap_nf.conf
new file mode 100644 (file)
index 0000000..948674c
--- /dev/null
@@ -0,0 +1,16 @@
+# Enable the traffic capture module "mod_cap_ipq.so" using NetFlow protocol
+<Module cap_nf>
+    # Port for TCP connections
+    # Note: Parameters TCPPort and UDPPort can be equal
+    # Parameter: optional
+    # Value: 1 ... 65535
+    # Default: 9996
+    #TCPPort = 9996
+
+    # Port for UDP connections
+    # Note: Parameters TCPPort and UDPPort can be equal
+    # Parameter: optional
+    # Value: 1 ... 65535
+    # Default: 9996
+    UDPPort = 9996
+</Module>
diff --git a/projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_ia.conf b/projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_ia.conf
new file mode 100644 (file)
index 0000000..df170dd
--- /dev/null
@@ -0,0 +1,44 @@
+# Enable the authorization module InetAccess "mod_auth_ia.so"
+<Module auth_ia>
+    # Port on which the server interacts with authorizator
+    # Parameter: required
+    # Value: 1 ... 65535
+    # Default: 5555
+    Port = 5555
+
+    # The time interval between sending an alive query to the user
+    # and updating statistics
+    # Parameter: required
+    # Values: 5 ... 600 (seconds)
+    # Default: 60
+    UserDelay = 60
+
+    # User timeout. If authorizer does not respond during this time,
+    # the user will be disconnected
+    # Parameter: required
+    # Values: 5 ... 600
+    # Default: 60
+    UserTimeout = 65
+
+    # Define which information will be transmitted from the server to InetAccess
+    # as a residue of prepaid traffic
+    # FreeMb = 0 — amount of free megabytes in terms of cost of zero direction
+    # FreeMb = 1 — amount of free megabytes in terms of cost of the first direction
+    # FreeMb = 1 — amount of free megabytes in terms of cost of the first direction
+    # FreeMb = 2 — amount of free megabytes in terms of cost of the second direction
+    # ........................
+    # FreeMb = 9 — amount of free megabytes in terms of cost of the ninth direction
+    # FreeMb = cash - amount of money for which the user can download for free
+    # FreeMb = none - no transfer
+    # Default: cash
+    # Parameter: required
+    # Values: different, see above
+    # Default: cash
+    FreeMb = cash
+
+    # Enable protocol errors logging
+    # Parameter: optional
+    # Values: yes, no
+    # Default: no
+    # LogProtocolErrors = no
+</Module>
diff --git a/projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_ping.conf b/projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_ping.conf
new file mode 100644 (file)
index 0000000..7402219
--- /dev/null
@@ -0,0 +1,8 @@
+# Enable the module that pings users "mod_ping.so"
+<Module ping>
+    # The time interval between pings
+    # Parameter: required
+    # Value: 10 ... 3600 (seconds)
+    # Default: 15
+    PingDelay = 15
+</Module>
\ No newline at end of file
diff --git a/projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_radius.conf b/projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_radius.conf
new file mode 100644 (file)
index 0000000..edc94d5
--- /dev/null
@@ -0,0 +1,34 @@
+# Enable the interaction module for FreeRADIUS "mod_radius.so"
+<Module radius>
+    # FreeRADIUS password
+    # Parameter: required
+    # Values: any, supported by software
+    # Default: 123456
+    Password = 123456
+
+    # FreeRADIUS server
+    # Parameter: required
+    # Values: IP address or DNS name
+    # Default: 127.0.0.1
+    ServerIP = 127.0.0.1
+
+    # FreeRADIUS port
+    # Parameter: required
+    # Value: 1 ... 65535
+    # Default: 6666
+    Port = 6666
+
+    # List of services for which will be carried out FreeRADIUS authentication 
+    # Note: Parameter can be blank
+    # Parameter: required
+    # Value: any, supported by software
+    # Default: Login-User
+    AuthServices = Login-User
+
+    # List of services for which will be carried out FreeRADIUS Accounting
+    # Note: Parameter can be blank
+    # Parameter: required
+    # Value: any, supported by software
+    # Default: Framed-User
+    AcctServices = Framed-User
+</Module>
\ No newline at end of file
diff --git a/projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_remote_script.conf b/projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_remote_script.conf
new file mode 100644 (file)
index 0000000..a71350c
--- /dev/null
@@ -0,0 +1,42 @@
+# Enable the module for remote execution of scripts OnConnect and OnDisconnect "mod_remote_script.so"
+<Module remote_script>
+    # The time interval between sending confirmations that the user is online
+    # Parametr: required
+    # Values: 10 ... 600 (seconds)
+    # Default: 60
+    SendPeriod = 15
+
+    # Define mapping between subnet(s) and remote server(s)
+    # File format: <subnet> <Router1> <Router2> ...
+    # Example:
+    # 192.168.1.0/24 192.168.1.7 192.168.1.8
+    # 192.168.2.0/24 192.168.2.5 192.168.2.6 192.168.2.7
+    # 192.168.3.0/24 192.168.3.5
+    # 192.168.4.0/24 192.168.4.5
+    # Parametr: required
+    # Values: file path
+    # Default: subnets
+    SubnetFile = subnets
+
+    # The password to encrypt packets between the stg-server and remote server
+    # Parameter: required
+    # Values: any
+    # Default: 123456
+    Password = 123456
+
+    # Define which user parameters are transferred to a remote server in addition to
+    # other parameters that transfered by default (ID, IP, Login, Cash, Dirs).
+    # Note: Parameter can be blank. 
+    # Parameter: required  
+    # Values: Cash, FreeMb, Passive, Disabled, AlwaysOnline, TariffName, 
+    # NextTariff, Address, Note, Group, Email, RealName, Credit, EnabledDirs, 
+    # Userdata0...Userdata9
+    # Default: Cash Tariff EnabledDirs
+    UserParams = Cash Tariff EnabledDirs
+
+    # Port on which the server interacts with remote server
+    # Parameter: required
+    # Value: 1...65535
+    # Default: 9999
+    Port = 9999
+</Module>
diff --git a/projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_rpc.conf b/projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_rpc.conf
new file mode 100644 (file)
index 0000000..b05695a
--- /dev/null
@@ -0,0 +1,14 @@
+# Enable the configuration module ConfRPC "mod_conf_rpc.so"
+<Module conf_rpc>
+    # Port on which the server interacts with configurator
+    # Parameter: required
+    # Value: 1...65535
+    # Default:
+    Port = 8080
+
+    # Session timeout in seconds
+    # Parameter: required
+    # Value: positive integer
+    # Default: 1800
+    CookieTimeout = 1800
+</Module>
diff --git a/projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_sg.conf b/projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_sg.conf
new file mode 100644 (file)
index 0000000..610a312
--- /dev/null
@@ -0,0 +1,8 @@
+# Enable the configuration module SgConfig "mod_conf_sg.so"
+<Module conf_sg>
+    # Port on which the server interacts with configurator
+    # Parameter: required
+    # Value: 1...65535
+    # Default: 5555
+    Port = 5555
+</Module>
\ No newline at end of file
diff --git a/projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_smux.conf b/projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_smux.conf
new file mode 100644 (file)
index 0000000..84ce24b
--- /dev/null
@@ -0,0 +1,19 @@
+# Enables SMUX-peer for SNMPd.
+<Module smux>
+    # IP-address of a server to connect to
+    # Parameter: required
+    # Value: X.X.X.X
+    # Default: 127.0.0.1
+    Server = 127.0.0.1
+
+    # Port number on a server to connect to
+    # Parameter: required
+    # Value: 1 ... 65535
+    # Default: 199
+    Port = 199
+
+    # Password for authentication on a server
+    # Parameter: required
+    # Value: any text
+    Password =
+</Module>
diff --git a/projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/store_files.conf b/projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/store_files.conf
new file mode 100644 (file)
index 0000000..f7e0f23
--- /dev/null
@@ -0,0 +1,30 @@
+# Enables plain file backend.
+<StoreModule store_files>
+
+    # Working server directory, provides data on tariffs, users, administrators.
+    # Parameter: required
+    # Value: directory path
+    WorkDir = /var/stargazer
+
+    # Owner, group and permissions of the files of user statistics (stat)
+    # Parameter: required
+    # Values: any, supported by OS
+    ConfOwner = root
+    ConfGroup = root
+    ConfMode = 640
+
+    # Owner, group and permissions on user configuration files (conf)
+    # Parameter: required
+    # Values: any, supported by OS
+    StatOwner = root
+    StatGroup = root
+    StatMode = 640
+
+    # Owner, group and permissions for user log files (log)
+    # Parameter: required
+    # Values: any, supported by OS
+    UserLogOwner = root
+    UserLogGroup = root
+    UserLogMode = 640
+
+</StoreModule>
diff --git a/projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/store_firebird.conf b/projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/store_firebird.conf
new file mode 100644 (file)
index 0000000..39e4ad3
--- /dev/null
@@ -0,0 +1,38 @@
+# Enables Firebird backend.
+<StoreModule store_firebird>
+    # Database server address
+    # Parameter: optional
+    # Value: IP address or DNS name
+    # Default: localhost
+    # Server = localhost
+
+    # Path to the database on the server or its alias
+    # Parameter: optional
+    # Value: file path
+    # Default: /var/stg/stargazer.fdb
+    # Database = /var/stg/stargazer.fdb
+
+    # Database username
+    # Parameter: optional
+    # Value: any, supported by database
+    # Default: stg
+    # User = stg
+
+    # Database password
+    # Parameter: optional
+    # Value: any, supported by database
+    # Default: 123456
+    # Password = 123456
+
+    # The transaction isolation level
+    # Parameter: optional
+    # Values: concurrency, dirtyread, readcommitted, consistency
+    # Defalt: concurrency
+    # IsolationLevel = concurrency
+
+    # Responding to lock (optional, defaults to wait):
+    # Parameter: optional
+    # Values: wait, nowait
+    # Defalt: wait
+    # LockResolution = wait
+</StoreModule>
diff --git a/projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/store_mysql.conf b/projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/store_mysql.conf
new file mode 100644 (file)
index 0000000..a5b2126
--- /dev/null
@@ -0,0 +1,26 @@
+# Enables MySQL backend.
+<StoreModule store_mysql>
+    # Database server address
+    # Parameter: required
+    # Value: IP address or DNS name
+    # Default: localhost
+    Server = localhost
+
+    # Database name
+    # Parameter: required
+    # Value: any, supported by database
+    # Default: stg
+    Database = stg
+
+    # Database username
+    # Parameter: required
+    # Value: any, supported by database
+    # Default: stg
+    User = stg
+
+    # Database password
+    # Parameter: required
+    # Value: any, supported by database
+    # Default: 123456
+    Password = 123456
+</StoreModule>
diff --git a/projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/store_postgresql.conf b/projects/stargazer/inst/freebsd/etc/stargazer/conf-available.d/store_postgresql.conf
new file mode 100644 (file)
index 0000000..8a52c75
--- /dev/null
@@ -0,0 +1,32 @@
+# Enables PostgreSQL backend.
+<StoreModule store_postgresql>
+    # Database server address
+    # Parameter: optional
+    # Value: IP address or DNS name
+    # Default: localhost
+    # Server = localhost
+
+    # Database name
+    # Parameter: optional
+    # Value: any, supported by database
+    # Default: stargazer
+    # Database = stargazer
+
+    # Database username
+    # Parameter: optional
+    # Value: any, supported by database
+    # Default: stg
+    # User = stg
+
+    # Database password
+    # Parameter: optional
+    # Value: any, supported by database
+    # Default: 123456
+    # Password = 123456
+
+    # Number of tries to reconnect
+    # Parameter: optional
+    # Value: positive integer
+    # Default: 3
+    # Retries = 3
+</StoreModule>
diff --git a/projects/stargazer/inst/freebsd/etc/stargazer/conf-enabled.d/mod_ao.conf b/projects/stargazer/inst/freebsd/etc/stargazer/conf-enabled.d/mod_ao.conf
new file mode 120000 (symlink)
index 0000000..fe7a6f5
--- /dev/null
@@ -0,0 +1 @@
+../conf-available.d/mod_ao.conf
\ No newline at end of file
diff --git a/projects/stargazer/inst/freebsd/etc/stargazer/conf-enabled.d/mod_cap_bpf.conf b/projects/stargazer/inst/freebsd/etc/stargazer/conf-enabled.d/mod_cap_bpf.conf
new file mode 120000 (symlink)
index 0000000..d9ec552
--- /dev/null
@@ -0,0 +1 @@
+../conf-available.d/mod_cap_bpf.conf
\ No newline at end of file
diff --git a/projects/stargazer/inst/freebsd/etc/stargazer/conf-enabled.d/mod_ia.conf b/projects/stargazer/inst/freebsd/etc/stargazer/conf-enabled.d/mod_ia.conf
new file mode 120000 (symlink)
index 0000000..3dea06d
--- /dev/null
@@ -0,0 +1 @@
+../conf-available.d/mod_ia.conf
\ No newline at end of file
diff --git a/projects/stargazer/inst/freebsd/etc/stargazer/conf-enabled.d/mod_ping.conf b/projects/stargazer/inst/freebsd/etc/stargazer/conf-enabled.d/mod_ping.conf
new file mode 120000 (symlink)
index 0000000..0d6db18
--- /dev/null
@@ -0,0 +1 @@
+../conf-available.d/mod_ping.conf
\ No newline at end of file
diff --git a/projects/stargazer/inst/freebsd/etc/stargazer/conf-enabled.d/mod_sg.conf b/projects/stargazer/inst/freebsd/etc/stargazer/conf-enabled.d/mod_sg.conf
new file mode 120000 (symlink)
index 0000000..7ab2476
--- /dev/null
@@ -0,0 +1 @@
+../conf-available.d/mod_sg.conf
\ No newline at end of file
diff --git a/projects/stargazer/inst/freebsd/etc/stargazer/conf-enabled.d/store_files.conf b/projects/stargazer/inst/freebsd/etc/stargazer/conf-enabled.d/store_files.conf
new file mode 120000 (symlink)
index 0000000..cb4e4da
--- /dev/null
@@ -0,0 +1 @@
+../conf-available.d/store_files.conf
\ No newline at end of file
diff --git a/projects/stargazer/inst/freebsd/etc/stargazer/rules b/projects/stargazer/inst/freebsd/etc/stargazer/rules
new file mode 100644 (file)
index 0000000..1042010
--- /dev/null
@@ -0,0 +1,3 @@
+ALL     192.168.0.0/16  DIR1
+ALL     10.0.0.0/8      DIR2
+ALL     0.0.0.0/0       DIR0
\ No newline at end of file
diff --git a/projects/stargazer/inst/freebsd/etc/stargazer/stargazer.conf b/projects/stargazer/inst/freebsd/etc/stargazer/stargazer.conf
new file mode 100644 (file)
index 0000000..bb8ee7c
--- /dev/null
@@ -0,0 +1,231 @@
+################################################################################
+#                        Stargazer Configuration file                          #
+################################################################################
+
+# LOG file name
+# Parameter: required
+# Value: file path
+# Default: /var/log/stargazer.log
+LogFile = /var/log/stargazer.log
+
+# PID file name
+# Parameter: optional
+# Value: file path
+# Default: /var/run/stargazer.pid
+PIDFile = /var/run/stargazer.pid
+
+# Traffic classification rules
+# Parameter: required
+# Value: file path
+# Default: /etc/stargazer/rules
+Rules = /etc/stargazer/rules
+
+# The time interval between writing detailed user's statistics into the database
+# Note: With a large number of users this value should be increased,
+# since writting into the database can take a long time.
+# Parameter: required
+# Values: 1 (hourly), 1/2 (every half hour), 1/4 (every 15 m), 1/6 (every 10 m)
+# Default: 1/2
+DetailStatWritePeriod = 1/2
+
+# The time interval between writing summary user's statistics into the database
+# Parameter: optional
+# Value: 1 ... 1440 (minutes)
+# Default: 10
+StatWritePeriod = 10
+
+# Day of charging fee
+# Note: 0 - The last day of the month
+# Parameter: required
+# Value: 0 ... 31
+# Default: 1
+DayFee = 1
+
+# When set to 'no' Stargazer will continue reading database after error and show all of them.
+# Parameter: optional
+# Values: yes, no
+# Default: yes
+# StopOnError = yes
+
+# Fee charged at the last (yes) or first (no) day of tariffication period.
+# Defines how the fee will be charged in the transition to the new tariff.
+# User has tariff A with fee 100. Changing it to tariff B with fee 200
+# will result in charging user's account at 100 if DayFeeIsLastDay = yes 
+# and at 200, if DayFeeIsLastDay = no
+# Parameter: required
+# Values: yes, no
+# Default: no
+DayFeeIsLastDay = no
+
+# Day of changing delayed tariffs and resetting summary user's statistics.
+# Defines the edge of the tariffication period.
+# Parameter: required
+# Value: 0 ... 31. 0 - The last day of the month
+# Default: 1
+DayResetTraff = 1
+
+# Defines whether to charge fee daily (yes) or monthly (no)
+# Parameter: required
+# Values: yes, no
+# Default: no
+SpreadFee = no
+
+# Defines whether the user can access the internet if it has no cash,
+# but remained prepaid traffic
+# Parameter: required
+# Values: yes, no
+# Default: no
+FreeMbAllowInet = no
+
+# Defines what will be written in the traffic cost in detail_stat.
+# If user still has the prepaid traffic and WriteFreeMbTraffCost = no,
+# then the traffic cost willn't be written in detail_stat.
+# If user doestn't have prepaid traffic and WriteFreeMbTraffCost = no, 
+# then the traffic cost will be written in detail_stat.
+# When WriteFreeMbTraffCost = yes the traffic cost will be recorded in any case.
+# Parameter: required
+# Values: yes, no
+# Default: yes
+WriteFreeMbTraffCost = yes
+
+# Charge a full monthly fee even if user was "frozen" a part 
+# of the tariffication period
+# Parameter: optional
+# Values: yes, no
+# Default: no
+FullFee = no
+
+# Allow user to see and use a full cash (yes) or hide a part of it (no) 
+# for the next fee charge
+# Parameter: optional
+# Values: yes, no
+# Default: yes
+# ShowFeeInCash=yes
+
+# The names of directions. Direction without names will not appear in
+# authorizer and configurator.
+# Note: Names consisting of several words should be quoted
+# Parameter: optional
+# Values:
+<DirNames>
+    DirName0 = Internet
+    DirName1 =
+    DirName2 =
+    DirName3 =
+    DirName4 =
+    DirName5 =
+    DirName6 =
+    DirName7 =
+    DirName8 =
+    DirName9 =
+</DirNames>
+
+# Amount of stg-exec processes.
+# These processes are responsible for the execution of scripts OnConnect, 
+# OnDisconnect, etc. 
+# Amount of processes means how many scripts can be executed simultaneously.
+# Recommend to leave 1 to avoid errors when executing scripts
+# Parameter: optional
+# Value: 1 ... 1024
+# Default: 1
+ExecutersNum = 1
+
+# Message queue identifier for the script executer.
+# It may be changed if there're a needs to run multiple copies of stargazer.
+# Warning: If you do not understand it, do not touch this setting!
+# Parameter: optional
+# Value: 0 ... 2 ^ 32
+# Default: 5555
+# ExecMsgKey = 5555
+
+# The path to directory with server modules
+# Parameter: required
+# Value: directory path
+# Default: /usr/lib/stg
+ModulesPath = /usr/lib/stg
+
+# Directory where the "monitor" files are located.
+# A blank files will be created in this directory. The modification time of such
+# files will be changed about once a minute. If server crashes or some of server 
+# component hang, the files will stop refreshing, and on this basis we can define
+# the failure of the server and if necessary restart. 
+# If option is omitted or blank, the monitoring is not performed.
+# Parameter: optional
+# Value: file path
+# Default: /var/stargazer/monitor
+#MonitorDir=/var/stargazer/monitor
+
+# Defines message maximum lifetime
+# Note: 0 - unlimited
+# Parameter: optional
+# Value: any numeric
+# Default: 0 (day)
+# MessagesTimeout = 0
+
+# Defines fee charging rules.
+# 0 - classic rules, allow fee charge even cash is negative;
+# 1 - disallow fee charge if cash value is negative;
+# 2 - disallow fee charge if there is not enought cash (cash < fee).
+# Parameter: optional
+# Value: 0 ... 2
+# Default: 0 (classic)
+# FeeChargeType = 0
+
+# Enable or disable reconnect on tariff change
+# Parameter: optional
+# Values: yes, no
+# Default: no
+# ReconnectOnTariffChange = no
+
+# Definest set of parameters passed to OnConnect and OnDisconnect scripts
+# This set is added to the end of the default param list, which are, respectively:
+# login, ip, cash, id, dirs
+# Valid parameter names: "cash", "upload", "download", "lastCashAdd", "passiveTime",
+# "lastCashAddTime", "freeMb", "lastActivityTime", "password", "passive", "disabled",
+# "disabledDetailStat", "alwaysOnline", "tariffName", "nextTariff", "address",
+# "note", "group", "email", "phone", "realName", "credit", "creditExpire", "ips",
+# "userdata0" ... "userdata9".
+# Parameter: optional
+# Values: parameter names, case insensitive
+# Default:
+# ScriptParams =
+
+# Enable or disable writing session log
+# Parameter: optional
+# Values: yes, no
+# Default: no (session log is enabled)
+# DisableSessionLog = no
+
+# Filter for logging parameter changes
+# Defines which parameters will be logged to parameter log in database. Allows
+# to specify multiuple parameter names or asterisk (*), which means "log all params".
+# Valid parameter names: "cash", "upload", "download", "lastCashAdd", "passiveTime",
+# "lastCashAddTime", "freeMb", "lastActivityTime", "password", "passive", "disabled",
+# "disabledDetailStat", "alwaysOnline", "tariffName", "nextTariff", "address",
+# "note", "group", "email", "phone", "realName", "credit", "creditExpire", "ips",
+# "userdata0" ... "userdata9".
+# Parameter: optional
+# Values: parameter names, case insensitive, or "*"
+# Default: *
+# FilterParamsLog = *
+
+################################################################################
+# Store module
+# Configure the module that works with the database server
+
+# Warning: Only one store module could be used at the same time!
+
+<IncludeFile "conf-enabled.d/store_*.conf">
+</IncludeFile>
+
+
+################################################################################
+# Other modules
+
+<Modules>
+
+    <IncludeFile "conf-enabled.d/mod_*.conf">
+    </IncludeFile>
+
+</Modules>
+################################################################################
diff --git a/projects/stargazer/inst/linux/etc/init.d/stargazer.gentoo b/projects/stargazer/inst/linux/etc/init.d/stargazer.gentoo
new file mode 100755 (executable)
index 0000000..daa0fd6
--- /dev/null
@@ -0,0 +1,33 @@
+#!/sbin/runscript
+
+extra_commands="reload"
+
+DAEMON=/usr/sbin/stargazer
+STARGAZER_OPTS=""
+PIDFILE=/var/run/stargazer.pid
+
+depend() {
+       need net
+       use postgresql firebird mysql
+       provide stargazer
+}
+
+start() {
+       ebegin "Starting stargazer"
+       start-stop-daemon --start --quiet --pidfile ${PIDFILE} --exec ${DAEMON} -- ${STARGAZER_OPTS}
+       eend $?
+}
+
+stop() {
+       ebegin "Stopping stargazer"
+       start-stop-daemon --stop --quiet --pidfile ${PIDFILE} --retry=INT/120/KILL/5
+       rm -f ${PIDFILE}
+       eend $?
+}
+
+reload() {
+       ebegin "Reloading stargazer rules"
+       start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE
+       return 0
+       eend $?
+}
diff --git a/projects/stargazer/inst/linux/etc/init.d/stargazer.suse.9.3 b/projects/stargazer/inst/linux/etc/init.d/stargazer.suse.9.3
new file mode 100755 (executable)
index 0000000..49a50da
--- /dev/null
@@ -0,0 +1,70 @@
+#!/bin/bash
+#
+# processname: stargazer
+# config: /etc/stargazer/stargazer.conf
+# pidfile: /var/run/stargazer.pid
+
+# Source function library.
+. /etc/init.d/functions
+
+# Source networking configuration.
+. /etc/sysconfig/network
+
+# Source stargazer configureation.
+DAEMON=yes
+QUEUE=1h
+
+# Check that networking is up.
+[ ${NETWORKING} = "no" ] && exit 0
+
+[ -f /sbin/stargazer ] || exit 0
+
+RETVAL=0
+prog="stargazer"
+
+start() {
+       # Start daemons.
+
+       echo -n $"Starting $prog: "
+       /etc/stargazer/first 2> /dev/null
+       daemon /sbin/stargazer
+       RETVAL=$?
+       /etc/stargazer/last 2> /dev/null
+       echo
+       [ $RETVAL -eq 0 ] && touch /var/lock/subsys/stargazer
+       return $RETVAL
+}
+
+stop() {
+       # Stop daemons.
+       echo -n $"Shutting down $prog: "
+       killproc stargazer
+       RETVAL=$?
+       echo
+       [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/stargazer
+       return $RETVAL
+}
+
+# See how we were called.
+case "$1" in
+  start)
+       start
+       ;;
+  stop)
+       stop
+       ;;
+  restart|reload)
+       stop
+       start
+       RETVAL=$?
+       ;;
+  status)
+       status stargazer
+       RETVAL=$?
+       ;;
+  *)
+       echo $"Usage: $0 {start|stop|restart|status}"
+       exit 1
+esac
+
+exit $RETVAL
diff --git a/projects/stargazer/inst/linux/etc/init.d/stargazer.ubuntu.7.10 b/projects/stargazer/inst/linux/etc/init.d/stargazer.ubuntu.7.10
new file mode 100755 (executable)
index 0000000..a5ed971
--- /dev/null
@@ -0,0 +1,152 @@
+#! /bin/sh
+### BEGIN INIT INFO
+# Provides:          stargazer
+# Required-Start:    $local_fs $remote_fs
+# Required-Stop:     $local_fs $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      S 0 1 6
+# Short-Description: Stargazer initscript
+# Description:       This file should be used to start and stop stargazer daemon
+### END INIT INFO
+
+# Author: Boris Mikhailenko <stg34@stg.dp.ua>
+
+# Do NOT "set -e"
+
+# PATH should only include /usr/* if it runs after the mountnfs.sh script
+PATH=/usr/sbin:/usr/bin:/sbin:/bin
+DESC="Billing system"
+NAME=stargazer
+DAEMON=/usr/sbin/$NAME
+DAEMON_ARGS=""
+PIDFILE=/var/run/$NAME.pid
+SCRIPTNAME=/etc/init.d/$NAME
+
+# Exit if the package is not installed
+[ -x "$DAEMON" ] || exit 0
+
+# Read configuration variable file if it is present
+[ -r /etc/default/$NAME ] && . /etc/default/$NAME
+
+# Load the VERBOSE setting and other rcS variables
+[ -f /etc/default/rcS ] && . /etc/default/rcS
+
+# Define LSB log_* functions.
+# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
+. /lib/lsb/init-functions
+
+#
+# Function that starts the daemon/service
+#
+do_start()
+{
+       # Return
+       #   0 if daemon has been started
+       #   1 if daemon was already running
+       #   2 if daemon could not be started
+       start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
+               || return 1
+               
+       # ps x | grep $DAEMON | grep -v grep | cut -f1 -d" " > $PIDFILE
+               
+       start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
+               $DAEMON_ARGS \
+               || return 2
+       
+       # ps x | grep $DAEMON | grep -v grep | cut -f1 -d" " > $PIDFILE
+       # Add code here, if necessary, that waits for the process to be ready
+       # to handle requests from services started subsequently which depend
+       # on this one.  As a last resort, sleep for some time.
+}
+
+#
+# Function that stops the daemon/service
+#
+do_stop()
+{
+       # Return
+       #   0 if daemon has been stopped
+       #   1 if daemon was already stopped
+       #   2 if daemon could not be stopped
+       #   other if a failure occurred
+       start-stop-daemon --stop --quiet --retry=INT/60/KILL/5 --pidfile $PIDFILE --name $NAME
+       RETVAL="$?"
+       [ "$RETVAL" = 2 ] && return 2
+       # Wait for children to finish too if this is a daemon that forks
+       # and if the daemon is only ever run from this initscript.
+       # If the above conditions are not satisfied then add some other code
+       # that waits for the process to drop all resources that could be
+       # needed by services started subsequently.  A last resort is to
+       # sleep for some time.
+       start-stop-daemon --stop --quiet --oknodo --retry=0/60/KILL/5 --exec $DAEMON
+       [ "$?" = 2 ] && return 2
+       # Many daemons don't delete their pidfiles when they exit.
+       rm -f $PIDFILE
+       return "$RETVAL"
+}
+
+#
+# Function that sends a SIGHUP to the daemon/service
+#
+do_reload() {
+       # If the daemon can reload its configuration without
+       # restarting (for example, when it is sent a SIGHUP),
+       # then implement that here.
+       start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
+       return 0
+}
+
+case "$1" in
+  start)
+       [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
+       do_start
+       case "$?" in
+               0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+               2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+       esac
+       ;;
+  stop)
+       [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
+       do_stop
+       case "$?" in
+               0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+               2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+       esac
+       ;;
+  reload)
+       # If do_reload() is not implemented then leave this commented out
+       # and leave 'force-reload' as an alias for 'restart'.
+       log_daemon_msg "Reloading $DESC" "$NAME"
+       do_reload
+       log_end_msg $?
+       ;;
+  restart)
+       #
+       # If the "reload" option is implemented then remove the
+       # 'force-reload' alias
+       #
+       log_daemon_msg "Restarting $DESC" "$NAME"
+       do_stop
+       case "$?" in
+         0|1)
+               do_start
+               case "$?" in
+                       0) log_end_msg 0 ;;
+                       1) log_end_msg 1 ;; # Old process is still running
+                       *) log_end_msg 1 ;; # Failed to start
+               esac
+               ;;
+         *)
+               # Failed to stop
+               log_end_msg 1
+               ;;
+       esac
+       ;;
+  *)
+       #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
+       echo "Usage: $SCRIPTNAME {start|stop|restart|reload}" >&2
+       exit 3
+       ;;
+esac
+
+:
diff --git a/projects/stargazer/inst/linux/etc/stargazer/OnChange b/projects/stargazer/inst/linux/etc/stargazer/OnChange
new file mode 100755 (executable)
index 0000000..c1ad6a6
--- /dev/null
@@ -0,0 +1,20 @@
+#! /bin/sh
+
+# About: This script is called when user account is changed.
+# Common Task: Notify about various events.
+# Priority: optional
+
+# User login
+LOGIN=$1
+
+# User parameter
+PARAMETER=$2
+
+# User parameter old value
+OLDVALUE=$3
+
+# User parameter new value
+NEWVALUE=$4
+
+# Usage examples:
+#echo "User: '$LOGIN'. Parameter $PARAMETER changed from '$OLDVALUE' to '$NEWVALUE'" >> /var/stargazer/user.change.log
\ No newline at end of file
diff --git a/projects/stargazer/inst/linux/etc/stargazer/OnConnect b/projects/stargazer/inst/linux/etc/stargazer/OnConnect
new file mode 100755 (executable)
index 0000000..cb1f64f
--- /dev/null
@@ -0,0 +1,23 @@
+#! /bin/sh
+
+# About: This script is called when the user successfully authenticated on the server.
+# Common Task: Rebuild firewall to allow user to access the Internet.
+# Priority: required
+
+# User login
+LOGIN=$1
+
+# User IP
+IP=$2
+
+# User cash
+CASH=$3
+
+# User ID
+ID=$4
+
+# Selected DIRs (from rules file) to connect
+DIRS=$5
+
+# Usage examples:
+#echo "Connected `date +%Y.%m.%d-%H.%M.%S` $IP $CASH" >> /var/stargazer/users/$LOGIN/connect.log
\ No newline at end of file
diff --git a/projects/stargazer/inst/linux/etc/stargazer/OnDisconnect b/projects/stargazer/inst/linux/etc/stargazer/OnDisconnect
new file mode 100755 (executable)
index 0000000..64a6c51
--- /dev/null
@@ -0,0 +1,23 @@
+#! /bin/sh
+
+# About: This script is called when the user wants to disconnect or authorization timeout has passed.
+# Common task: Rebuild firewall to disallow user to access the Internet.
+# Priority: required
+
+# User login
+LOGIN=$1
+
+# User IP
+IP=$2
+
+# User cash
+CASH=$3
+
+# User ID
+ID=$4
+
+# Selected DIRs (from rules file) to disconnect
+DIRS=$5
+
+# Usage examples:
+#echo "Disconnected `date +%Y.%m.%d-%H.%M.%S` $IP $CASH" >> /var/stargazer/users/$LOGIN/connect.log
diff --git a/projects/stargazer/inst/linux/etc/stargazer/OnUserAdd b/projects/stargazer/inst/linux/etc/stargazer/OnUserAdd
new file mode 100755 (executable)
index 0000000..2dcc056
--- /dev/null
@@ -0,0 +1,12 @@
+#! /bin/sh
+
+# About: This script is called when the user is added to the Stargazer.
+# Common task: Automate typical actions on adding user to the network,
+#              such as creating email or IM account.
+# Priority: optional
+
+# User login
+LOGIN=$1
+
+# Usage examples:
+#echo "Added user $login" >> /var/stargazer/add_del.log
\ No newline at end of file
diff --git a/projects/stargazer/inst/linux/etc/stargazer/OnUserDel b/projects/stargazer/inst/linux/etc/stargazer/OnUserDel
new file mode 100755 (executable)
index 0000000..a72da15
--- /dev/null
@@ -0,0 +1,13 @@
+#! /bin/sh
+
+# About: This script is called when the user is removed from the Stargazer.
+# Common task: Automate typical actions on removing user from the network,
+#              such as removing email or IM account.
+# Priority: optional
+
+# User login
+LOGIN=$1
+
+# Usage examples:
+#echo "Deleted user $LOGIN" >> /var/stargazer/add_del.log
+
diff --git a/projects/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_ao.conf b/projects/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_ao.conf
new file mode 100644 (file)
index 0000000..62c0dc7
--- /dev/null
@@ -0,0 +1,3 @@
+# Enable the authorization module Always Online "mod_auth_ao.so"
+<Module auth_ao>
+</Module>
\ No newline at end of file
diff --git a/projects/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_cap_ether.conf b/projects/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_cap_ether.conf
new file mode 100644 (file)
index 0000000..677ed5a
--- /dev/null
@@ -0,0 +1,3 @@
+# Enable the traffic capture module "mod_cap_ether.so" using Packet-sockets
+<Module cap_ether>
+</Module>
\ No newline at end of file
diff --git a/projects/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_cap_ipq.conf b/projects/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_cap_ipq.conf
new file mode 100644 (file)
index 0000000..6b4b3c0
--- /dev/null
@@ -0,0 +1,3 @@
+# Enable the traffic capture module "mod_cap_ipq.so" using mechanism of IP Queueing
+<Module cap_ipq>
+</Module>
\ No newline at end of file
diff --git a/projects/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_cap_nf.conf b/projects/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_cap_nf.conf
new file mode 100644 (file)
index 0000000..948674c
--- /dev/null
@@ -0,0 +1,16 @@
+# Enable the traffic capture module "mod_cap_ipq.so" using NetFlow protocol
+<Module cap_nf>
+    # Port for TCP connections
+    # Note: Parameters TCPPort and UDPPort can be equal
+    # Parameter: optional
+    # Value: 1 ... 65535
+    # Default: 9996
+    #TCPPort = 9996
+
+    # Port for UDP connections
+    # Note: Parameters TCPPort and UDPPort can be equal
+    # Parameter: optional
+    # Value: 1 ... 65535
+    # Default: 9996
+    UDPPort = 9996
+</Module>
diff --git a/projects/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_ia.conf b/projects/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_ia.conf
new file mode 100644 (file)
index 0000000..df170dd
--- /dev/null
@@ -0,0 +1,44 @@
+# Enable the authorization module InetAccess "mod_auth_ia.so"
+<Module auth_ia>
+    # Port on which the server interacts with authorizator
+    # Parameter: required
+    # Value: 1 ... 65535
+    # Default: 5555
+    Port = 5555
+
+    # The time interval between sending an alive query to the user
+    # and updating statistics
+    # Parameter: required
+    # Values: 5 ... 600 (seconds)
+    # Default: 60
+    UserDelay = 60
+
+    # User timeout. If authorizer does not respond during this time,
+    # the user will be disconnected
+    # Parameter: required
+    # Values: 5 ... 600
+    # Default: 60
+    UserTimeout = 65
+
+    # Define which information will be transmitted from the server to InetAccess
+    # as a residue of prepaid traffic
+    # FreeMb = 0 — amount of free megabytes in terms of cost of zero direction
+    # FreeMb = 1 — amount of free megabytes in terms of cost of the first direction
+    # FreeMb = 1 — amount of free megabytes in terms of cost of the first direction
+    # FreeMb = 2 — amount of free megabytes in terms of cost of the second direction
+    # ........................
+    # FreeMb = 9 — amount of free megabytes in terms of cost of the ninth direction
+    # FreeMb = cash - amount of money for which the user can download for free
+    # FreeMb = none - no transfer
+    # Default: cash
+    # Parameter: required
+    # Values: different, see above
+    # Default: cash
+    FreeMb = cash
+
+    # Enable protocol errors logging
+    # Parameter: optional
+    # Values: yes, no
+    # Default: no
+    # LogProtocolErrors = no
+</Module>
diff --git a/projects/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_ping.conf b/projects/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_ping.conf
new file mode 100644 (file)
index 0000000..7402219
--- /dev/null
@@ -0,0 +1,8 @@
+# Enable the module that pings users "mod_ping.so"
+<Module ping>
+    # The time interval between pings
+    # Parameter: required
+    # Value: 10 ... 3600 (seconds)
+    # Default: 15
+    PingDelay = 15
+</Module>
\ No newline at end of file
diff --git a/projects/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_radius.conf b/projects/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_radius.conf
new file mode 100644 (file)
index 0000000..edc94d5
--- /dev/null
@@ -0,0 +1,34 @@
+# Enable the interaction module for FreeRADIUS "mod_radius.so"
+<Module radius>
+    # FreeRADIUS password
+    # Parameter: required
+    # Values: any, supported by software
+    # Default: 123456
+    Password = 123456
+
+    # FreeRADIUS server
+    # Parameter: required
+    # Values: IP address or DNS name
+    # Default: 127.0.0.1
+    ServerIP = 127.0.0.1
+
+    # FreeRADIUS port
+    # Parameter: required
+    # Value: 1 ... 65535
+    # Default: 6666
+    Port = 6666
+
+    # List of services for which will be carried out FreeRADIUS authentication 
+    # Note: Parameter can be blank
+    # Parameter: required
+    # Value: any, supported by software
+    # Default: Login-User
+    AuthServices = Login-User
+
+    # List of services for which will be carried out FreeRADIUS Accounting
+    # Note: Parameter can be blank
+    # Parameter: required
+    # Value: any, supported by software
+    # Default: Framed-User
+    AcctServices = Framed-User
+</Module>
\ No newline at end of file
diff --git a/projects/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_remote_script.conf b/projects/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_remote_script.conf
new file mode 100644 (file)
index 0000000..a71350c
--- /dev/null
@@ -0,0 +1,42 @@
+# Enable the module for remote execution of scripts OnConnect and OnDisconnect "mod_remote_script.so"
+<Module remote_script>
+    # The time interval between sending confirmations that the user is online
+    # Parametr: required
+    # Values: 10 ... 600 (seconds)
+    # Default: 60
+    SendPeriod = 15
+
+    # Define mapping between subnet(s) and remote server(s)
+    # File format: <subnet> <Router1> <Router2> ...
+    # Example:
+    # 192.168.1.0/24 192.168.1.7 192.168.1.8
+    # 192.168.2.0/24 192.168.2.5 192.168.2.6 192.168.2.7
+    # 192.168.3.0/24 192.168.3.5
+    # 192.168.4.0/24 192.168.4.5
+    # Parametr: required
+    # Values: file path
+    # Default: subnets
+    SubnetFile = subnets
+
+    # The password to encrypt packets between the stg-server and remote server
+    # Parameter: required
+    # Values: any
+    # Default: 123456
+    Password = 123456
+
+    # Define which user parameters are transferred to a remote server in addition to
+    # other parameters that transfered by default (ID, IP, Login, Cash, Dirs).
+    # Note: Parameter can be blank. 
+    # Parameter: required  
+    # Values: Cash, FreeMb, Passive, Disabled, AlwaysOnline, TariffName, 
+    # NextTariff, Address, Note, Group, Email, RealName, Credit, EnabledDirs, 
+    # Userdata0...Userdata9
+    # Default: Cash Tariff EnabledDirs
+    UserParams = Cash Tariff EnabledDirs
+
+    # Port on which the server interacts with remote server
+    # Parameter: required
+    # Value: 1...65535
+    # Default: 9999
+    Port = 9999
+</Module>
diff --git a/projects/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_rpc.conf b/projects/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_rpc.conf
new file mode 100644 (file)
index 0000000..b05695a
--- /dev/null
@@ -0,0 +1,14 @@
+# Enable the configuration module ConfRPC "mod_conf_rpc.so"
+<Module conf_rpc>
+    # Port on which the server interacts with configurator
+    # Parameter: required
+    # Value: 1...65535
+    # Default:
+    Port = 8080
+
+    # Session timeout in seconds
+    # Parameter: required
+    # Value: positive integer
+    # Default: 1800
+    CookieTimeout = 1800
+</Module>
diff --git a/projects/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_sg.conf b/projects/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_sg.conf
new file mode 100644 (file)
index 0000000..610a312
--- /dev/null
@@ -0,0 +1,8 @@
+# Enable the configuration module SgConfig "mod_conf_sg.so"
+<Module conf_sg>
+    # Port on which the server interacts with configurator
+    # Parameter: required
+    # Value: 1...65535
+    # Default: 5555
+    Port = 5555
+</Module>
\ No newline at end of file
diff --git a/projects/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_smux.conf b/projects/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_smux.conf
new file mode 100644 (file)
index 0000000..84ce24b
--- /dev/null
@@ -0,0 +1,19 @@
+# Enables SMUX-peer for SNMPd.
+<Module smux>
+    # IP-address of a server to connect to
+    # Parameter: required
+    # Value: X.X.X.X
+    # Default: 127.0.0.1
+    Server = 127.0.0.1
+
+    # Port number on a server to connect to
+    # Parameter: required
+    # Value: 1 ... 65535
+    # Default: 199
+    Port = 199
+
+    # Password for authentication on a server
+    # Parameter: required
+    # Value: any text
+    Password =
+</Module>
diff --git a/projects/stargazer/inst/linux/etc/stargazer/conf-available.d/store_files.conf b/projects/stargazer/inst/linux/etc/stargazer/conf-available.d/store_files.conf
new file mode 100644 (file)
index 0000000..f7e0f23
--- /dev/null
@@ -0,0 +1,30 @@
+# Enables plain file backend.
+<StoreModule store_files>
+
+    # Working server directory, provides data on tariffs, users, administrators.
+    # Parameter: required
+    # Value: directory path
+    WorkDir = /var/stargazer
+
+    # Owner, group and permissions of the files of user statistics (stat)
+    # Parameter: required
+    # Values: any, supported by OS
+    ConfOwner = root
+    ConfGroup = root
+    ConfMode = 640
+
+    # Owner, group and permissions on user configuration files (conf)
+    # Parameter: required
+    # Values: any, supported by OS
+    StatOwner = root
+    StatGroup = root
+    StatMode = 640
+
+    # Owner, group and permissions for user log files (log)
+    # Parameter: required
+    # Values: any, supported by OS
+    UserLogOwner = root
+    UserLogGroup = root
+    UserLogMode = 640
+
+</StoreModule>
diff --git a/projects/stargazer/inst/linux/etc/stargazer/conf-available.d/store_firebird.conf b/projects/stargazer/inst/linux/etc/stargazer/conf-available.d/store_firebird.conf
new file mode 100644 (file)
index 0000000..39e4ad3
--- /dev/null
@@ -0,0 +1,38 @@
+# Enables Firebird backend.
+<StoreModule store_firebird>
+    # Database server address
+    # Parameter: optional
+    # Value: IP address or DNS name
+    # Default: localhost
+    # Server = localhost
+
+    # Path to the database on the server or its alias
+    # Parameter: optional
+    # Value: file path
+    # Default: /var/stg/stargazer.fdb
+    # Database = /var/stg/stargazer.fdb
+
+    # Database username
+    # Parameter: optional
+    # Value: any, supported by database
+    # Default: stg
+    # User = stg
+
+    # Database password
+    # Parameter: optional
+    # Value: any, supported by database
+    # Default: 123456
+    # Password = 123456
+
+    # The transaction isolation level
+    # Parameter: optional
+    # Values: concurrency, dirtyread, readcommitted, consistency
+    # Defalt: concurrency
+    # IsolationLevel = concurrency
+
+    # Responding to lock (optional, defaults to wait):
+    # Parameter: optional
+    # Values: wait, nowait
+    # Defalt: wait
+    # LockResolution = wait
+</StoreModule>
diff --git a/projects/stargazer/inst/linux/etc/stargazer/conf-available.d/store_mysql.conf b/projects/stargazer/inst/linux/etc/stargazer/conf-available.d/store_mysql.conf
new file mode 100644 (file)
index 0000000..a5b2126
--- /dev/null
@@ -0,0 +1,26 @@
+# Enables MySQL backend.
+<StoreModule store_mysql>
+    # Database server address
+    # Parameter: required
+    # Value: IP address or DNS name
+    # Default: localhost
+    Server = localhost
+
+    # Database name
+    # Parameter: required
+    # Value: any, supported by database
+    # Default: stg
+    Database = stg
+
+    # Database username
+    # Parameter: required
+    # Value: any, supported by database
+    # Default: stg
+    User = stg
+
+    # Database password
+    # Parameter: required
+    # Value: any, supported by database
+    # Default: 123456
+    Password = 123456
+</StoreModule>
diff --git a/projects/stargazer/inst/linux/etc/stargazer/conf-available.d/store_postgresql.conf b/projects/stargazer/inst/linux/etc/stargazer/conf-available.d/store_postgresql.conf
new file mode 100644 (file)
index 0000000..8a52c75
--- /dev/null
@@ -0,0 +1,32 @@
+# Enables PostgreSQL backend.
+<StoreModule store_postgresql>
+    # Database server address
+    # Parameter: optional
+    # Value: IP address or DNS name
+    # Default: localhost
+    # Server = localhost
+
+    # Database name
+    # Parameter: optional
+    # Value: any, supported by database
+    # Default: stargazer
+    # Database = stargazer
+
+    # Database username
+    # Parameter: optional
+    # Value: any, supported by database
+    # Default: stg
+    # User = stg
+
+    # Database password
+    # Parameter: optional
+    # Value: any, supported by database
+    # Default: 123456
+    # Password = 123456
+
+    # Number of tries to reconnect
+    # Parameter: optional
+    # Value: positive integer
+    # Default: 3
+    # Retries = 3
+</StoreModule>
diff --git a/projects/stargazer/inst/linux/etc/stargazer/conf-enabled.d/mod_ao.conf b/projects/stargazer/inst/linux/etc/stargazer/conf-enabled.d/mod_ao.conf
new file mode 120000 (symlink)
index 0000000..fe7a6f5
--- /dev/null
@@ -0,0 +1 @@
+../conf-available.d/mod_ao.conf
\ No newline at end of file
diff --git a/projects/stargazer/inst/linux/etc/stargazer/conf-enabled.d/mod_cap_ether.conf b/projects/stargazer/inst/linux/etc/stargazer/conf-enabled.d/mod_cap_ether.conf
new file mode 120000 (symlink)
index 0000000..b929151
--- /dev/null
@@ -0,0 +1 @@
+../conf-available.d/mod_cap_ether.conf
\ No newline at end of file
diff --git a/projects/stargazer/inst/linux/etc/stargazer/conf-enabled.d/mod_ia.conf b/projects/stargazer/inst/linux/etc/stargazer/conf-enabled.d/mod_ia.conf
new file mode 120000 (symlink)
index 0000000..3dea06d
--- /dev/null
@@ -0,0 +1 @@
+../conf-available.d/mod_ia.conf
\ No newline at end of file
diff --git a/projects/stargazer/inst/linux/etc/stargazer/conf-enabled.d/mod_ping.conf b/projects/stargazer/inst/linux/etc/stargazer/conf-enabled.d/mod_ping.conf
new file mode 120000 (symlink)
index 0000000..0d6db18
--- /dev/null
@@ -0,0 +1 @@
+../conf-available.d/mod_ping.conf
\ No newline at end of file
diff --git a/projects/stargazer/inst/linux/etc/stargazer/conf-enabled.d/mod_sg.conf b/projects/stargazer/inst/linux/etc/stargazer/conf-enabled.d/mod_sg.conf
new file mode 120000 (symlink)
index 0000000..7ab2476
--- /dev/null
@@ -0,0 +1 @@
+../conf-available.d/mod_sg.conf
\ No newline at end of file
diff --git a/projects/stargazer/inst/linux/etc/stargazer/conf-enabled.d/store_files.conf b/projects/stargazer/inst/linux/etc/stargazer/conf-enabled.d/store_files.conf
new file mode 120000 (symlink)
index 0000000..cb4e4da
--- /dev/null
@@ -0,0 +1 @@
+../conf-available.d/store_files.conf
\ No newline at end of file
diff --git a/projects/stargazer/inst/linux/etc/stargazer/rules b/projects/stargazer/inst/linux/etc/stargazer/rules
new file mode 100644 (file)
index 0000000..1042010
--- /dev/null
@@ -0,0 +1,3 @@
+ALL     192.168.0.0/16  DIR1
+ALL     10.0.0.0/8      DIR2
+ALL     0.0.0.0/0       DIR0
\ No newline at end of file
diff --git a/projects/stargazer/inst/linux/etc/stargazer/stargazer.conf b/projects/stargazer/inst/linux/etc/stargazer/stargazer.conf
new file mode 100644 (file)
index 0000000..bb8ee7c
--- /dev/null
@@ -0,0 +1,231 @@
+################################################################################
+#                        Stargazer Configuration file                          #
+################################################################################
+
+# LOG file name
+# Parameter: required
+# Value: file path
+# Default: /var/log/stargazer.log
+LogFile = /var/log/stargazer.log
+
+# PID file name
+# Parameter: optional
+# Value: file path
+# Default: /var/run/stargazer.pid
+PIDFile = /var/run/stargazer.pid
+
+# Traffic classification rules
+# Parameter: required
+# Value: file path
+# Default: /etc/stargazer/rules
+Rules = /etc/stargazer/rules
+
+# The time interval between writing detailed user's statistics into the database
+# Note: With a large number of users this value should be increased,
+# since writting into the database can take a long time.
+# Parameter: required
+# Values: 1 (hourly), 1/2 (every half hour), 1/4 (every 15 m), 1/6 (every 10 m)
+# Default: 1/2
+DetailStatWritePeriod = 1/2
+
+# The time interval between writing summary user's statistics into the database
+# Parameter: optional
+# Value: 1 ... 1440 (minutes)
+# Default: 10
+StatWritePeriod = 10
+
+# Day of charging fee
+# Note: 0 - The last day of the month
+# Parameter: required
+# Value: 0 ... 31
+# Default: 1
+DayFee = 1
+
+# When set to 'no' Stargazer will continue reading database after error and show all of them.
+# Parameter: optional
+# Values: yes, no
+# Default: yes
+# StopOnError = yes
+
+# Fee charged at the last (yes) or first (no) day of tariffication period.
+# Defines how the fee will be charged in the transition to the new tariff.
+# User has tariff A with fee 100. Changing it to tariff B with fee 200
+# will result in charging user's account at 100 if DayFeeIsLastDay = yes 
+# and at 200, if DayFeeIsLastDay = no
+# Parameter: required
+# Values: yes, no
+# Default: no
+DayFeeIsLastDay = no
+
+# Day of changing delayed tariffs and resetting summary user's statistics.
+# Defines the edge of the tariffication period.
+# Parameter: required
+# Value: 0 ... 31. 0 - The last day of the month
+# Default: 1
+DayResetTraff = 1
+
+# Defines whether to charge fee daily (yes) or monthly (no)
+# Parameter: required
+# Values: yes, no
+# Default: no
+SpreadFee = no
+
+# Defines whether the user can access the internet if it has no cash,
+# but remained prepaid traffic
+# Parameter: required
+# Values: yes, no
+# Default: no
+FreeMbAllowInet = no
+
+# Defines what will be written in the traffic cost in detail_stat.
+# If user still has the prepaid traffic and WriteFreeMbTraffCost = no,
+# then the traffic cost willn't be written in detail_stat.
+# If user doestn't have prepaid traffic and WriteFreeMbTraffCost = no, 
+# then the traffic cost will be written in detail_stat.
+# When WriteFreeMbTraffCost = yes the traffic cost will be recorded in any case.
+# Parameter: required
+# Values: yes, no
+# Default: yes
+WriteFreeMbTraffCost = yes
+
+# Charge a full monthly fee even if user was "frozen" a part 
+# of the tariffication period
+# Parameter: optional
+# Values: yes, no
+# Default: no
+FullFee = no
+
+# Allow user to see and use a full cash (yes) or hide a part of it (no) 
+# for the next fee charge
+# Parameter: optional
+# Values: yes, no
+# Default: yes
+# ShowFeeInCash=yes
+
+# The names of directions. Direction without names will not appear in
+# authorizer and configurator.
+# Note: Names consisting of several words should be quoted
+# Parameter: optional
+# Values:
+<DirNames>
+    DirName0 = Internet
+    DirName1 =
+    DirName2 =
+    DirName3 =
+    DirName4 =
+    DirName5 =
+    DirName6 =
+    DirName7 =
+    DirName8 =
+    DirName9 =
+</DirNames>
+
+# Amount of stg-exec processes.
+# These processes are responsible for the execution of scripts OnConnect, 
+# OnDisconnect, etc. 
+# Amount of processes means how many scripts can be executed simultaneously.
+# Recommend to leave 1 to avoid errors when executing scripts
+# Parameter: optional
+# Value: 1 ... 1024
+# Default: 1
+ExecutersNum = 1
+
+# Message queue identifier for the script executer.
+# It may be changed if there're a needs to run multiple copies of stargazer.
+# Warning: If you do not understand it, do not touch this setting!
+# Parameter: optional
+# Value: 0 ... 2 ^ 32
+# Default: 5555
+# ExecMsgKey = 5555
+
+# The path to directory with server modules
+# Parameter: required
+# Value: directory path
+# Default: /usr/lib/stg
+ModulesPath = /usr/lib/stg
+
+# Directory where the "monitor" files are located.
+# A blank files will be created in this directory. The modification time of such
+# files will be changed about once a minute. If server crashes or some of server 
+# component hang, the files will stop refreshing, and on this basis we can define
+# the failure of the server and if necessary restart. 
+# If option is omitted or blank, the monitoring is not performed.
+# Parameter: optional
+# Value: file path
+# Default: /var/stargazer/monitor
+#MonitorDir=/var/stargazer/monitor
+
+# Defines message maximum lifetime
+# Note: 0 - unlimited
+# Parameter: optional
+# Value: any numeric
+# Default: 0 (day)
+# MessagesTimeout = 0
+
+# Defines fee charging rules.
+# 0 - classic rules, allow fee charge even cash is negative;
+# 1 - disallow fee charge if cash value is negative;
+# 2 - disallow fee charge if there is not enought cash (cash < fee).
+# Parameter: optional
+# Value: 0 ... 2
+# Default: 0 (classic)
+# FeeChargeType = 0
+
+# Enable or disable reconnect on tariff change
+# Parameter: optional
+# Values: yes, no
+# Default: no
+# ReconnectOnTariffChange = no
+
+# Definest set of parameters passed to OnConnect and OnDisconnect scripts
+# This set is added to the end of the default param list, which are, respectively:
+# login, ip, cash, id, dirs
+# Valid parameter names: "cash", "upload", "download", "lastCashAdd", "passiveTime",
+# "lastCashAddTime", "freeMb", "lastActivityTime", "password", "passive", "disabled",
+# "disabledDetailStat", "alwaysOnline", "tariffName", "nextTariff", "address",
+# "note", "group", "email", "phone", "realName", "credit", "creditExpire", "ips",
+# "userdata0" ... "userdata9".
+# Parameter: optional
+# Values: parameter names, case insensitive
+# Default:
+# ScriptParams =
+
+# Enable or disable writing session log
+# Parameter: optional
+# Values: yes, no
+# Default: no (session log is enabled)
+# DisableSessionLog = no
+
+# Filter for logging parameter changes
+# Defines which parameters will be logged to parameter log in database. Allows
+# to specify multiuple parameter names or asterisk (*), which means "log all params".
+# Valid parameter names: "cash", "upload", "download", "lastCashAdd", "passiveTime",
+# "lastCashAddTime", "freeMb", "lastActivityTime", "password", "passive", "disabled",
+# "disabledDetailStat", "alwaysOnline", "tariffName", "nextTariff", "address",
+# "note", "group", "email", "phone", "realName", "credit", "creditExpire", "ips",
+# "userdata0" ... "userdata9".
+# Parameter: optional
+# Values: parameter names, case insensitive, or "*"
+# Default: *
+# FilterParamsLog = *
+
+################################################################################
+# Store module
+# Configure the module that works with the database server
+
+# Warning: Only one store module could be used at the same time!
+
+<IncludeFile "conf-enabled.d/store_*.conf">
+</IncludeFile>
+
+
+################################################################################
+# Other modules
+
+<Modules>
+
+    <IncludeFile "conf-enabled.d/mod_*.conf">
+    </IncludeFile>
+
+</Modules>
+################################################################################
diff --git a/projects/stargazer/inst/var/00-alter-01.postgresql.sql b/projects/stargazer/inst/var/00-alter-01.postgresql.sql
new file mode 100644 (file)
index 0000000..7fd8111
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ *  DB migration from v00 to v01 (postgres)
+ */
+
+ALTER TABLE tb_sessions_log ADD free_mb dm_money;
+ALTER TABLE tb_sessions_log ADD reason TEXT;
+
+DROP FUNCTION sp_add_session_log_entry ( dm_name, timestamp without time zone, dm_session_event_type, inet, dm_money);
+
+CREATE FUNCTION sp_add_session_log_entry(_login dm_name,
+                                         _event_time TIMESTAMP,
+                                         _event_type dm_session_event_type,
+                                         _ip INET,
+                                         _cash dm_money,
+                                         _free_mb dm_money,
+                                         _reason TEXT)
+RETURNS INTEGER
+AS $$
+DECLARE
+    _pk_user INTEGER;
+    _pk_session_log INTEGER;
+BEGIN
+    SELECT pk_user INTO _pk_user
+        FROM tb_users
+        WHERE name = _login;
+    IF _pk_user IS NULL THEN
+        RAISE EXCEPTION 'User % not found', _login;
+        RETURN -1;
+    END IF;
+    
+    INSERT INTO tb_sessions_log
+        (fk_user,
+         event_time,
+         event_type,
+         ip,
+         cash,
+         free_mb,
+         reason)
+    VALUES
+        (_pk_user,
+         _event_time,
+         _event_type,
+         _ip,
+         _cash,
+         _free_mb,
+         _reason);
+
+    SELECT CURRVAL('tb_sessions_log_pk_session_log_seq') INTO _pk_session_log;
+
+    RETURN _pk_session_log;
+END;
+$$ LANGUAGE plpgsql;
+
+UPDATE tb_info SET version = 6;
diff --git a/projects/stargazer/inst/var/00-alter-01.sql b/projects/stargazer/inst/var/00-alter-01.sql
new file mode 100644 (file)
index 0000000..f76ae5f
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ *  DB migration from v00 to v01 (firebird)
+ */
+
+alter table tb_users add disabled_detail_stat dm_bool;
+
+drop procedure sp_add_user;
+
+set term !! ;
+create procedure sp_add_user(name varchar(32), dirs integer)                             
+as  
+declare variable pk_user integer;
+declare variable pk_stat integer;                                                        
+begin                                                                                    
+    pk_user = gen_id(gn_pk_user, 1);                                                     
+    insert into tb_users(pk_user, fk_tariff, fk_tariff_change, fk_corporation, address, always_online, credit, credit_expire, disabled, disabled_detail_stat, email, grp, note, passive, passwd, phone, name, real_name) values (:pk_user, NULL, NULL, NULL, '', 0, 0, 'now', 0, 0, '', '_', '', 0, '', '', :name, '');
+    pk_stat = gen_id(gn_pk_stat, 1);                                                     
+    insert into tb_stats values (:pk_stat, :pk_user, 0, 0, 'now', 0, 'now', 0, 'now');   
+    while (dirs > 0) do
+    begin
+        insert into tb_stats_traffic (fk_stat, dir_num, upload, download) values (:pk_stat, :dirs - 1, 0, 0);
+        dirs = dirs - 1;
+    end
+end!!
+set term ; !!
diff --git a/projects/stargazer/inst/var/00-base-00.postgresql.sql b/projects/stargazer/inst/var/00-base-00.postgresql.sql
new file mode 100644 (file)
index 0000000..6b48d75
--- /dev/null
@@ -0,0 +1,644 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *****************************************************************************
+ *
+ * Скрипт генерации структуры базы для хранения данных Stargazer-a
+ *
+ * Примечание.
+ *      * dm_permission_flag. Представляет собой битовую маску - rw.
+ *          r - чтение, w - изменение параметра.
+ *          0 - дествие запрещено, 1 - действие разрешено
+ *
+ *      * dm_traff_type. Число определяющее тип подсчета трафика:
+ *          0 - up - считается по upload
+ *          1 - down - считается по download
+ *          2 - max - считается по максимальному среди upload/download
+ *          3 - up+down - считается по сумме upload и download
+ *
+ *      * dm_session_event_type. Указывает тип записи в логе о сессии.
+ *        'c' - connect, 'd' - disconnect.
+ *
+ *****************************************************************************
+ */
+
+/*
+ *  $Revision: 1.12 $
+ *  $Date: 2009/08/20 14:58:43 $
+ */
+
+
+/*
+ *****************************************************************************
+ * -= Создание типов и доменов =-
+ *****************************************************************************
+ */
+
+CREATE DOMAIN dm_name AS VARCHAR(32) NOT NULL;
+CREATE DOMAIN dm_password AS VARCHAR(64) NOT NULL;
+CREATE DOMAIN dm_permission_flag AS SMALLINT NOT NULL
+    CHECK ( value BETWEEN 0 AND 3 );
+CREATE DOMAIN dm_money AS NUMERIC(12, 4) NOT NULL DEFAULT 0;
+CREATE DOMAIN dm_traff_type AS SMALLINT NOT NULL
+    CHECK ( value BETWEEN 0 AND 3 );
+CREATE DOMAIN dm_day AS SMALLINT NOT NULL
+    CHECK ( value BETWEEN 0 AND 31 )
+    DEFAULT 0;
+CREATE DOMAIN dm_session_event_type AS CHAR(1) NOT NULL
+    CHECK ( value = 'c' OR value = 'd' );
+
+/*
+ *****************************************************************************
+ * -= Создание таблиц =-
+ *****************************************************************************
+ */
+
+CREATE TABLE tb_info
+(
+    version INTEGER NOT NULL
+);
+
+CREATE TABLE tb_admins
+(
+    pk_admin SERIAL PRIMARY KEY,
+    login dm_name UNIQUE,
+    passwd dm_password NOT NULL,
+    chg_conf dm_permission_flag,
+    chg_password dm_permission_flag,
+    chg_stat dm_permission_flag,
+    chg_cash dm_permission_flag,
+    usr_add_del dm_permission_flag,
+    chg_tariff dm_permission_flag,
+    chg_admin dm_permission_flag,
+    chg_service dm_permission_flag,
+    chg_corporation dm_permission_flag
+);
+
+CREATE TABLE tb_tariffs
+(
+    pk_tariff SERIAL PRIMARY KEY,
+    name dm_name UNIQUE,
+    fee dm_money,
+    free dm_money,
+    passive_cost dm_money,
+    traff_type dm_traff_type
+);
+
+CREATE TABLE tb_tariffs_params
+(
+    pk_tariff_param SERIAL PRIMARY KEY,
+    fk_tariff INTEGER NOT NULL,
+    dir_num SMALLINT NOT NULL,
+    price_day_a dm_money,
+    price_day_b dm_money,
+    price_night_a dm_money,
+    price_night_b dm_money,
+    threshold INTEGER NOT NULL,
+    time_day_begins TIME NOT NULL,
+    time_day_ends TIME NOT NULL,
+
+    FOREIGN KEY (fk_tariff)
+        REFERENCES tb_tariffs (pk_tariff)
+        ON DELETE CASCADE
+);
+
+CREATE TABLE tb_corporations
+(
+    pk_corporation SERIAL PRIMARY KEY,
+    name dm_name UNIQUE,
+    cash dm_money
+);
+
+CREATE TABLE tb_users
+(
+    pk_user SERIAL PRIMARY KEY,
+    fk_tariff INTEGER,
+    fk_tariff_change INTEGER,
+    fk_corporation INTEGER,
+    address VARCHAR(256) NOT NULL,
+    always_online BOOLEAN NOT NULL,
+    credit dm_money,
+    credit_expire TIMESTAMP NOT NULL,
+    disabled BOOLEAN NOT NULL,
+    disabled_detail_stat BOOLEAN NOT NULL,
+    email VARCHAR(256) NOT NULL,
+    grp dm_name,
+    note TEXT NOT NULL,
+    passive BOOLEAN NOT NULL,
+    passwd dm_password,
+    phone VARCHAR(256) NOT NULL,
+    name dm_name UNIQUE,
+    real_name VARCHAR(256) NOT NULL,
+    cash dm_money,
+    free_mb dm_money,
+    last_activity_time TIMESTAMP NOT NULL,
+    last_cash_add dm_money,
+    last_cash_add_time TIMESTAMP NOT NULL,
+    passive_time INTEGER NOT NULL,
+
+    FOREIGN KEY (fk_tariff)
+        REFERENCES tb_tariffs (pk_tariff)
+        ON DELETE CASCADE,
+    FOREIGN KEY (fk_tariff_change)
+        REFERENCES tb_tariffs (pk_tariff)
+        ON DELETE CASCADE,
+    FOREIGN KEY (fk_corporation)
+        REFERENCES tb_corporations (pk_corporation)
+        ON DELETE CASCADE
+);
+
+CREATE TABLE tb_detail_stats
+(
+    pk_detail_stat BIGSERIAL PRIMARY KEY,
+    fk_user INTEGER NOT NULL,
+    dir_num SMALLINT NOT NULL,
+    ip INET NOT NULL,
+    download BIGINT NOT NULL,
+    upload BIGINT NOT NULL,
+    cost dm_money,
+    from_time TIMESTAMP NOT NULL,
+    till_time TIMESTAMP NOT NULL,
+
+    FOREIGN KEY (fk_user)
+        REFERENCES tb_users (pk_user)
+        ON DELETE CASCADE
+);
+
+CREATE TABLE tb_services
+(
+    pk_service SERIAL PRIMARY KEY,
+    name dm_name UNIQUE,
+    comment TEXT NOT NULL,
+    cost dm_money,
+    pay_day dm_day
+);
+
+CREATE TABLE tb_users_services
+(
+    pk_user_service SERIAL PRIMARY KEY,
+    fk_user INTEGER NOT NULL,
+    fk_service INTEGER NOT NULL,
+
+    FOREIGN KEY (fk_user)
+        REFERENCES tb_users (pk_user)
+        ON DELETE CASCADE,
+    FOREIGN KEY (fk_service)
+        REFERENCES tb_services (pk_service)
+);
+
+CREATE TABLE tb_messages
+(
+    pk_message SERIAL PRIMARY KEY,
+    fk_user INTEGER NOT NULL,
+    ver SMALLINT NOT NULL,
+    msg_type SMALLINT NOT NULL,
+    last_send_time TIMESTAMP NOT NULL,
+    creation_time TIMESTAMP NOT NULL,
+    show_time INTEGER NOT NULL,
+    repeat SMALLINT NOT NULL,
+    repeat_period INTEGER NOT NULL,
+    msg_text TEXT NOT NULL,
+
+    FOREIGN KEY (fk_user)
+        REFERENCES tb_users (pk_user)
+        ON DELETE CASCADE
+);
+
+CREATE TABLE tb_stats_traffic
+(
+    pk_stat_traffic BIGSERIAL PRIMARY KEY,
+    fk_user INTEGER NOT NULL,
+    stats_date DATE NOT NULL,
+    dir_num SMALLINT NOT NULL,
+    download BIGINT NOT NULL,
+    upload BIGINT NOT NULL,
+
+    FOREIGN KEY (fk_user)
+        REFERENCES tb_users (pk_user)
+        ON DELETE CASCADE,
+    UNIQUE (fk_user, stats_date, dir_num)
+);
+
+CREATE TABLE tb_users_data
+(
+    pk_user_data SERIAL PRIMARY KEY,
+    fk_user INTEGER NOT NULL,
+    num SMALLINT NOT NULL,
+    data VARCHAR(256) NOT NULL,
+
+    FOREIGN KEY (fk_user)
+        REFERENCES tb_users (pk_user)
+        ON DELETE CASCADE
+);
+
+CREATE TABLE tb_allowed_ip
+(
+    pk_allowed_ip SERIAL PRIMARY KEY,
+    fk_user INTEGER NOT NULL,
+    ip INET NOT NULL,
+
+    FOREIGN KEY (fk_user)
+        REFERENCES tb_users (pk_user)
+        ON DELETE CASCADE
+);
+
+CREATE TABLE tb_sessions_log
+(
+    pk_session_log SERIAL PRIMARY KEY,
+    fk_user INTEGER NOT NULL,
+    event_time TIMESTAMP NOT NULL,
+    event_type dm_session_event_type,
+    ip INET NOT NULL,
+    cash dm_money,
+
+    FOREIGN KEY (fk_user)
+        REFERENCES tb_users (pk_user)
+        ON DELETE CASCADE
+);
+
+CREATE TABLE tb_sessions_data
+(
+    pk_session_data SERIAL PRIMARY KEY,
+    fk_session_log INTEGER NOT NULL,
+    dir_num SMALLINT NOT NULL,
+    session_upload BIGINT NOT NULL,
+    session_download BIGINT NOT NULL,
+    month_upload BIGINT NOT NULL,
+    month_download BIGINT NOT NULL,
+
+    FOREIGN KEY (fk_session_log)
+        REFERENCES tb_sessions_log (pk_session_log)
+        ON DELETE CASCADE
+);
+
+CREATE TABLE tb_parameters
+(
+    pk_parameter SERIAL PRIMARY KEY,
+    name dm_name UNIQUE
+);
+
+CREATE TABLE tb_params_log
+(
+    pk_param_log SERIAL PRIMARY KEY,
+    fk_user INTEGER NOT NULL,
+    fk_parameter INTEGER NOT NULL,
+    fk_admin INTEGER NOT NULL,
+    ip INET NOT NULL,
+    event_time TIMESTAMP NOT NULL,
+    from_val VARCHAR(256),
+    to_val VARCHAR(256),
+    comment TEXT,
+
+    FOREIGN KEY (fk_user)
+        REFERENCES tb_users (pk_user)
+        ON DELETE CASCADE,
+    FOREIGN KEY (fk_parameter)
+        REFERENCES tb_parameters (pk_parameter),
+    FOREIGN KEY (fk_admin)
+        REFERENCES tb_admins (pk_admin)
+        ON DELETE CASCADE
+);
+
+/*
+ *****************************************************************************
+ * -= Создание хранимых процедур =-
+ *****************************************************************************
+ */
+
+CREATE FUNCTION sp_add_message(_login dm_name,
+                               _ver SMALLINT,
+                               _msg_type SMALLINT,
+                               _last_send_time TIMESTAMP,
+                               _creation_time TIMESTAMP,
+                               _show_time INTEGER,
+                               _repeat SMALLINT,
+                               _repeat_period INTEGER,
+                               _msg_text TEXT)
+RETURNS INTEGER
+AS $$
+DECLARE
+    _pk_user INTEGER;
+BEGIN
+    SELECT pk_user INTO _pk_user
+        FROM tb_users
+        WHERE name = _login;
+    IF _pk_user IS NULL THEN
+        RAISE EXCEPTION 'User % not found', _login;
+        RETURN -1;
+    END IF;
+    INSERT INTO tb_messages
+        (fk_user,
+         ver,
+         msg_type,
+         last_send_time,
+         creation_time,
+         show_time,
+         repeat,
+         repeat_period,
+         msg_text)
+    VALUES
+        (_pk_user,
+         _ver,
+         _msg_type,
+         _last_send_time,
+         _creation_time,
+         _show_time,
+         _repeat,
+         _repeat_period,
+         _msg_text);
+    RETURN CURRVAL('tb_messages_pk_message_seq');
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE FUNCTION sp_add_tariff(_name dm_name, _dirs INTEGER)
+RETURNS INTEGER
+AS $$
+DECLARE
+    pk_tariff INTEGER;
+BEGIN
+    INSERT INTO tb_tariffs
+        (name,
+         fee,
+         free,
+         passive_cost,
+         traff_type)
+    VALUES
+        (_name,
+         0, 0, 0, 0);
+    SELECT CURRVAL('tb_tariffs_pk_tariff_seq') INTO pk_tariff;
+    FOR i IN 1.._dirs LOOP
+        INSERT INTO tb_tariffs_params
+            (fk_tariff,
+             dir_num,
+             price_day_a,
+             price_day_b,
+             price_night_a,
+             price_night_b,
+             threshold,
+             time_day_begins,
+             time_day_ends)
+        VALUES
+            (pk_tariff,
+             i - 1,
+             0, 0, 0, 0, 0,
+             CAST('1970-01-01 00:00:00+00' AS TIMESTAMP),
+             CAST('1970-01-01 00:00:00+00' AS TIMESTAMP));
+    END LOOP;
+    RETURN pk_tariff;
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE FUNCTION sp_add_user(_name dm_name)
+RETURNS INTEGER
+AS $$
+DECLARE
+    pk_user INTEGER;
+BEGIN
+    INSERT INTO tb_users
+        (fk_tariff,
+         fk_tariff_change,
+         fk_corporation,
+         address,
+         always_online,
+         credit,
+         credit_expire,
+         disabled,
+         disabled_detail_stat,
+         email,
+         grp,
+         note,
+         passive,
+         passwd,
+         phone,
+         name,
+         real_name,
+         cash,
+         free_mb,
+         last_activity_time,
+         last_cash_add,
+         last_cash_add_time,
+         passive_time)
+    VALUES
+        (NULL, NULL, NULL, '', FALSE, 0, CAST('now' AS TIMESTAMP),
+         FALSE, FALSE, '', '', '', FALSE, '', '', _name, '', 0, 0,
+         CAST('now' AS TIMESTAMP), 0, CAST('now' AS TIMESTAMP), 0);
+    SELECT CURRVAL('tb_users_pk_user_seq') INTO pk_user;
+    RETURN pk_user;
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE FUNCTION sp_add_stats_traffic (_login dm_name,
+                                      _stats_date DATE,
+                                      _dir_num SMALLINT,
+                                      _upload BIGINT,
+                                      _download BIGINT)
+RETURNS INTEGER
+AS $$
+DECLARE
+    _pk_user INTEGER;
+BEGIN
+    SELECT pk_user INTO _pk_user
+        FROM tb_users
+        WHERE name = _login;
+
+    IF _pk_user IS NULL THEN
+        RAISE EXCEPTION 'User % not found', _login;
+        RETURN -1;
+    END IF;
+
+    UPDATE tb_stats_traffic SET
+        upload = _upload,
+        download = _download
+    WHERE fk_user = _pk_user AND
+          dir_num = _dir_num AND
+          stats_date = _stats_date;
+
+    IF NOT FOUND THEN
+        INSERT INTO tb_stats_traffic
+            (fk_user,
+             dir_num,
+             stats_date,
+             upload,
+             download)
+        VALUES
+            (_pk_user,
+             _dir_num,
+             _stats_date,
+             _upload,
+             _download);
+    END IF;
+
+    RETURN 1;
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE FUNCTION sp_set_user_data (_pk_user INTEGER,
+                                  _num SMALLINT,
+                                  _data VARCHAR(256))
+RETURNS INTEGER
+AS $$
+BEGIN
+    UPDATE tb_users_data SET
+        data = _data
+    WHERE fk_user = _pk_user AND num = _num;
+
+    IF NOT FOUND THEN
+        INSERT INTO tb_users_data
+            (fk_user,
+             num,
+             data)
+        VALUES
+            (_pk_user,
+             _num,
+             _data);
+    END IF;
+
+    RETURN 1;
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE FUNCTION sp_add_param_log_entry(_login dm_name,
+                                       _admin_login dm_name,
+                                       _ip INET,
+                                       _param_name dm_name,
+                                       _event_time TIMESTAMP,
+                                       _from VARCHAR(256),
+                                       _to VARCHAR(256),
+                                       _comment TEXT)
+RETURNS INTEGER
+AS $$
+DECLARE
+    _pk_user INTEGER;
+    _pk_admin INTEGER;
+    _pk_param INTEGER;
+BEGIN
+    SELECT pk_user INTO _pk_user
+        FROM tb_users
+        WHERE name = _login;
+    IF _pk_user IS NULL THEN
+        RAISE EXCEPTION 'User % not found', _login;
+        RETURN -1;
+    END IF;
+
+    SELECT pk_admin INTO _pk_admin
+        FROM tb_admins
+        WHERE login = _admin_login;
+    IF _pk_admin IS NULL THEN
+        RAISE EXCEPTION 'Admin % not found', _admin_login;
+        RETURN -1;
+    END IF;
+
+    SELECT pk_parameter INTO _pk_param
+        FROM tb_parameters
+        WHERE name = _param_name;
+
+    IF NOT FOUND THEN
+        INSERT INTO tb_parameters (name) VALUES (_param_name);
+        SELECT CURRVAL('tb_parameters_pk_parameter_seq') INTO _pk_param;
+    END IF;
+
+    INSERT INTO tb_params_log
+        (fk_user,
+         fk_parameter,
+         fk_admin,
+         ip,
+         event_time,
+         from_val,
+         to_val,
+         comment)
+    VALUES
+        (_pk_user,
+         _pk_param,
+         _pk_admin,
+         _ip,
+         _event_time,
+         _from,
+         _to,
+         _comment);
+
+    RETURN 1;
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE FUNCTION sp_add_session_log_entry(_login dm_name,
+                                         _event_time TIMESTAMP,
+                                         _event_type dm_session_event_type,
+                                         _ip INET,
+                                         _cash dm_money)
+RETURNS INTEGER
+AS $$
+DECLARE
+    _pk_user INTEGER;
+    _pk_session_log INTEGER;
+BEGIN
+    SELECT pk_user INTO _pk_user
+        FROM tb_users
+        WHERE name = _login;
+    IF _pk_user IS NULL THEN
+        RAISE EXCEPTION 'User % not found', _login;
+        RETURN -1;
+    END IF;
+    
+    INSERT INTO tb_sessions_log
+        (fk_user,
+         event_time,
+         event_type,
+         ip,
+         cash)
+    VALUES
+        (_pk_user,
+         _event_time,
+         _event_type,
+         _ip,
+         _cash);
+
+    SELECT CURRVAL('tb_sessions_log_pk_session_log_seq') INTO _pk_session_log;
+
+    RETURN _pk_session_log;
+END;
+$$ LANGUAGE plpgsql;
+
+/*
+ *****************************************************************************
+ * -= Создание администратора =-
+ *
+ * Двоичные права доступа пока не поддерживаются, по этому используются флаги
+ *****************************************************************************
+ */
+INSERT INTO tb_admins
+    (login, passwd,
+     chg_conf, chg_password, chg_stat,
+     chg_cash, usr_add_del, chg_tariff,
+     chg_admin, chg_service, chg_corporation)
+VALUES
+    ('admin',
+     'geahonjehjfofnhammefahbbbfbmpkmkmmefahbbbfbmpkmkmmefahbbbfbmpkmk',
+     1, 1, 1, 1, 1, 1, 1, 1, 1);
+INSERT INTO tb_admins
+    (login, passwd,
+     chg_conf, chg_password, chg_stat,
+     chg_cash, usr_add_del, chg_tariff,
+     chg_admin, chg_service, chg_corporation)
+VALUES
+    ('@stargazer',
+     '',
+     0, 0, 0, 0, 0, 0, 0, 0, 0);
+
+INSERT INTO tb_info
+    (version)
+VALUES
+    (5);
diff --git a/projects/stargazer/inst/var/00-base-00.sql b/projects/stargazer/inst/var/00-base-00.sql
new file mode 100644 (file)
index 0000000..a452d81
--- /dev/null
@@ -0,0 +1,677 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *****************************************************************************
+ *
+ * Скрипт генерации структуры базы для хранения данных Stargazer-a
+ *
+ * $Id: 00-base-00.sql,v 1.7 2010/01/06 14:41:13 faust Exp $
+ *
+ * Примечание.
+ *      * dm_permission_flag. Представляет собой битовую маску - rw.
+ *          r - чтение, w - изменение параметра.
+ *          0 - дествие запрещено, 1 - действие разрешено
+ *
+ *      * dm_traff_type. Число определяющее тип подсчета трафика:
+ *          0 - up - считается по upload
+ *          1 - down - считается по download
+ *          2 - max - считается по максимальному среди upload/download
+ *          3 - up+down - считается по сумме upload и download
+ *
+ *      * dm_ip. IP адресс в виде четырех байтового целого числа со знаком.
+ *        Выполнять приведение к знаковуму целому при занесении IP в БД!!!
+ *
+ *      * dm_period. Задает периодичность показа сообщения пользователю.
+ *        Период задается целым числом (int16). Если значение равно 0 то
+ *        сообщение показывается только при подключении пользователя.
+ *        Также этот домен определяет промежуток времени в течении которого
+ *        сообщение показывается пользователю.
+ *
+ *      * dm_session_event_type. Указывает тип записи в логе о сессии.
+ *        'c' - connect, 'd' - disconnect.
+ *
+ *****************************************************************************
+ */
+
+/*
+ * CONNECT 'localhost:/var/stg/stargazer.fdb' USER 'stg' PASSWORD '123456';
+ * DROP DATABASE;
+ *
+ * CREATE DATABASE 'localhost:/var/stg/stargazer.fdb' USER 'stg' PASSWORD '123456' DEFAULT CHARACTER SET UTF8;
+ */
+
+
+/*
+ *****************************************************************************
+ * -= Создание ДОМЕНОВ =-
+ *****************************************************************************
+ */
+
+CREATE DOMAIN dm_id AS INTEGER NOT NULL;
+CREATE DOMAIN dm_null_id AS INTEGER;
+CREATE DOMAIN dm_login AS VARCHAR(32) NOT NULL;
+CREATE DOMAIN dm_tariff_name AS VARCHAR(32) NOT NULL;
+CREATE DOMAIN dm_group_name AS VARCHAR(32);
+CREATE DOMAIN dm_corporation_name AS VARCHAR(32);
+CREATE DOMAIN dm_parameter_name AS VARCHAR(32);
+
+CREATE DOMAIN dm_password AS VARCHAR(64) NOT NULL;
+/* bitmask - rw => Read, Write */
+CREATE DOMAIN dm_permission_flag AS SMALLINT NOT NULL
+    CHECK ( VALUE BETWEEN 0 AND 3 );
+CREATE DOMAIN dm_money AS NUMERIC(10,6) NOT NULL;
+/* (0, 1, 2, 3) => (up, down, max, up+down) */
+CREATE DOMAIN dm_traff_type AS SMALLINT NOT NULL
+    CHECK ( VALUE BETWEEN 0 AND 3 );
+CREATE DOMAIN dm_dir_num AS SMALLINT NOT NULL;
+CREATE DOMAIN dm_num AS SMALLINT NOT NULL;
+CREATE DOMAIN dm_traffic_mb AS INTEGER NOT NULL;
+CREATE DOMAIN dm_traffic_byte AS BIGINT NOT NULL;
+CREATE DOMAIN dm_time AS TIME NOT NULL;
+CREATE DOMAIN dm_moment AS TIMESTAMP NOT NULL;
+CREATE DOMAIN dm_credit_moment AS TIMESTAMP;
+CREATE DOMAIN dm_ip AS INTEGER NOT NULL;
+CREATE DOMAIN dm_mask AS INTEGER NOT NULL;
+CREATE DOMAIN dm_user_address AS VARCHAR(256) DEFAULT '';
+CREATE DOMAIN dm_bool AS CHAR(1) NOT NULL
+    CHECK ( VALUE IN ('0', '1', 't', 'f', 'T', 'F') );
+CREATE DOMAIN dm_email AS VARCHAR(256) DEFAULT '';
+CREATE DOMAIN dm_note AS VARCHAR(256) DEFAULT '';
+CREATE DOMAIN dm_phone AS VARCHAR(256) DEFAULT '';
+CREATE DOMAIN dm_user_name AS VARCHAR(256) DEFAULT '';
+CREATE DOMAIN dm_service_comment AS VARCHAR(256) DEFAULT '';
+CREATE DOMAIN dm_service_name AS VARCHAR(32) DEFAULT '';
+
+CREATE DOMAIN dm_pay_day AS SMALLINT NOT NULL
+    CHECK ( VALUE BETWEEN 0 AND 31 );
+CREATE DOMAIN dm_period AS INTEGER NOT NULL;
+CREATE DOMAIN dm_counter AS SMALLINT NOT NULL;
+
+CREATE DOMAIN dm_message_ver AS INTEGER NOT NULL;
+CREATE DOMAIN dm_message_type AS INTEGER NOT NULL;
+
+CREATE DOMAIN dm_message AS VARCHAR(256) NOT NULL;
+CREATE DOMAIN dm_user_data AS VARCHAR(256) NOT NULL;
+CREATE DOMAIN dm_session_event_type AS CHAR(1) NOT NULL
+    CHECK ( VALUE IN ('c', 'd') );
+CREATE DOMAIN dm_char_value AS VARCHAR(64) NOT NULL;
+CREATE DOMAIN dm_date AS DATE NOT NULL;
+
+
+
+/*
+ *****************************************************************************
+ * -= Создание ТАБЛИЦ =-
+ *****************************************************************************
+ */
+
+CREATE TABLE tb_admins
+(
+    pk_admin dm_id PRIMARY KEY,
+    login dm_login UNIQUE,
+    passwd dm_password,
+    chg_conf dm_permission_flag,
+    chg_password dm_permission_flag,
+    chg_stat dm_permission_flag,
+    chg_cash dm_permission_flag,
+    usr_add_del dm_permission_flag,
+    chg_tariff dm_permission_flag,
+    chg_admin dm_permission_flag,
+    chg_service dm_permission_flag,
+    chg_corporation dm_permission_flag
+);
+
+CREATE TABLE tb_tariffs
+(
+    pk_tariff dm_id PRIMARY KEY,
+    name dm_tariff_name UNIQUE,
+    fee dm_money,
+    free dm_money,
+    passive_cost dm_money,
+    traff_type dm_traff_type
+);
+
+CREATE TABLE tb_tariffs_params
+(
+    pk_tariff_param dm_id PRIMARY KEY,
+    fk_tariff dm_id,
+    dir_num dm_dir_num,
+    price_day_a dm_money,
+    price_day_b dm_money,
+    price_night_a dm_money,
+    price_night_b dm_money,
+    threshold dm_traffic_mb,
+    time_day_begins dm_time,
+    time_day_ends dm_time,
+
+    FOREIGN KEY (fk_tariff) REFERENCES tb_tariffs (pk_tariff)
+);
+
+CREATE TABLE tb_corporations
+(
+    pk_corporation dm_id PRIMARY KEY,
+    name dm_corporation_name UNIQUE,
+    cash dm_money
+);
+
+CREATE TABLE tb_users
+(
+    pk_user dm_id PRIMARY KEY,
+    fk_tariff dm_null_id,
+    fk_tariff_change dm_null_id,
+    fk_corporation dm_null_id,
+    address dm_user_address,
+    always_online dm_bool,
+    credit dm_money,
+    credit_expire dm_credit_moment,
+    disabled dm_bool,
+    disabled_detail_stat dm_bool,
+    email dm_email,
+    grp dm_group_name,
+    note dm_note,
+    passive dm_bool,
+    passwd dm_password,
+    phone dm_phone,
+    name dm_login UNIQUE,
+    real_name dm_user_name,
+
+    FOREIGN KEY (fk_tariff) REFERENCES tb_tariffs (pk_tariff),
+    FOREIGN KEY (fk_tariff_change) REFERENCES tb_tariffs (pk_tariff),
+    FOREIGN KEY (fk_corporation) REFERENCES tb_corporations (pk_corporation)
+);
+
+CREATE TABLE tb_detail_stats
+(
+    pk_detail_stat dm_id PRIMARY KEY,
+    fk_user dm_id,
+    dir_num dm_dir_num,
+    ip dm_ip,
+    download dm_traffic_byte,
+    upload dm_traffic_byte,
+    cost dm_money,
+    from_time dm_moment,
+    till_time dm_moment,
+
+    FOREIGN KEY (fk_user) REFERENCES tb_users (pk_user)
+);
+
+CREATE TABLE tb_services
+(
+    pk_service dm_id PRIMARY KEY,
+    name dm_service_name UNIQUE,
+    comment dm_service_comment,
+    cost dm_money,
+    pay_day dm_pay_day
+);
+
+CREATE TABLE tb_users_services
+(
+    pk_user_service dm_id PRIMARY KEY,
+    fk_user dm_id,
+    fk_service dm_id,
+
+    FOREIGN KEY (fk_user) REFERENCES tb_users (pk_user),
+    FOREIGN KEY (fk_service) REFERENCES tb_services (pk_service)
+);
+
+CREATE TABLE tb_messages
+(
+    pk_message dm_id PRIMARY KEY,
+    fk_user dm_id,
+    ver dm_message_ver,
+    msg_type dm_message_type,
+    last_send_time dm_period,
+    creation_time dm_period,
+    show_time dm_period,
+    repeat dm_counter,
+    repeat_period dm_period,
+    msg_text dm_message,
+
+    FOREIGN KEY (fk_user) REFERENCES tb_users (pk_user)
+);
+
+CREATE TABLE tb_stats
+(
+    pk_stat dm_id PRIMARY KEY,
+    fk_user dm_id,
+    cash dm_money,
+    free_mb dm_money,
+    last_activity_time dm_moment,
+    last_cash_add dm_money,
+    last_cash_add_time dm_moment,
+    passive_time dm_period,
+    stats_date dm_date,
+
+    FOREIGN KEY (fk_user) REFERENCES tb_users (pk_user)
+);
+
+CREATE TABLE tb_stats_traffic
+(
+    pk_stat_traffic dm_id PRIMARY KEY,
+    fk_stat dm_id,
+    dir_num dm_dir_num,
+    download dm_traffic_byte,
+    upload dm_traffic_byte,
+
+    FOREIGN KEY (fk_stat) REFERENCES tb_stats (pk_stat)
+);
+
+CREATE TABLE tb_users_data
+(
+    pk_user_data dm_id PRIMARY KEY,
+    fk_user dm_id,
+    num dm_num,
+    data dm_user_data,
+
+    FOREIGN KEY (fk_user) REFERENCES tb_users (pk_user)
+);
+
+CREATE TABLE tb_allowed_ip
+(
+    pk_allowed_ip dm_id PRIMARY KEY,
+    fk_user dm_id,
+    ip dm_ip,
+    mask dm_mask,
+
+    FOREIGN KEY (fk_user) REFERENCES tb_users (pk_user)
+);
+
+CREATE TABLE tb_sessions_log
+(
+    pk_session_log dm_id PRIMARY KEY,
+    fk_user dm_id,
+    event_time dm_moment,
+    event_type dm_session_event_type,
+    ip dm_ip,
+
+    FOREIGN KEY (fk_user) REFERENCES tb_users (pk_user)
+);
+
+CREATE TABLE tb_sessions_data
+(
+    pk_session_data dm_id PRIMARY KEY,
+    fk_session_log dm_id,
+    dir_num dm_dir_num,
+    session_upload dm_traffic_byte,
+    session_download dm_traffic_byte,
+    month_upload dm_traffic_byte,
+    month_download dm_traffic_byte,
+
+    FOREIGN KEY (fk_session_log) REFERENCES tb_sessions_log (pk_session_log)
+);
+
+CREATE TABLE tb_parameters
+(
+    pk_parameter dm_id PRIMARY KEY,
+    name dm_parameter_name UNIQUE
+);
+
+CREATE TABLE tb_params_log
+(
+    pk_param_log dm_id PRIMARY KEY,
+    fk_user dm_id,
+    fk_parameter dm_id,
+    event_time dm_moment,
+    from_val dm_char_value,
+    to_val dm_char_value,
+    comment dm_service_comment,
+
+    FOREIGN KEY (fk_user) REFERENCES tb_users (pk_user),
+    FOREIGN KEY (fk_parameter) REFERENCES tb_parameters (pk_parameter)
+);
+
+
+/*
+ *****************************************************************************
+ * -= Создание ИНДЕКСОВ =-
+ *****************************************************************************
+ */
+
+
+
+/*
+ *****************************************************************************
+ * -= Создание ГЕНЕРАТОРОВ =-
+ *****************************************************************************
+ */
+
+CREATE  GENERATOR gn_pk_admin;
+SET     GENERATOR gn_pk_admin           TO 0;
+CREATE  GENERATOR gn_pk_tariff;
+SET     GENERATOR gn_pk_tariff          TO 0;
+CREATE  GENERATOR gn_pk_tariff_param;
+SET     GENERATOR gn_pk_tariff_param    TO 0;
+CREATE  GENERATOR gn_pk_corporation;
+SET     GENERATOR gn_pk_corporation     TO 0;
+CREATE  GENERATOR gn_pk_user;
+SET     GENERATOR gn_pk_user            TO 0;
+CREATE  GENERATOR gn_pk_detail_stat;
+SET     GENERATOR gn_pk_detail_stat     TO 0;
+CREATE  GENERATOR gn_pk_service;
+SET     GENERATOR gn_pk_service         TO 0;
+CREATE  GENERATOR gn_pk_user_service;
+SET     GENERATOR gn_pk_user_service    TO 0;
+CREATE  GENERATOR gn_pk_message;
+SET     GENERATOR gn_pk_message         TO 0;
+CREATE  GENERATOR gn_pk_stat;
+SET     GENERATOR gn_pk_stat            TO 0;
+CREATE  GENERATOR gn_pk_stat_traffic;
+SET     GENERATOR gn_pk_stat_traffic    TO 0;
+CREATE  GENERATOR gn_pk_user_data;
+SET     GENERATOR gn_pk_user_data       TO 0;
+CREATE  GENERATOR gn_pk_allowed_ip;
+SET     GENERATOR gn_pk_allowed_ip      TO 0;
+CREATE  GENERATOR gn_pk_session;
+SET     GENERATOR gn_pk_session         TO 0;
+CREATE  GENERATOR gn_pk_session_log;
+SET     GENERATOR gn_pk_session_log     TO 0;
+CREATE  GENERATOR gn_pk_session_data;
+SET     GENERATOR gn_pk_session_data    TO 0;
+CREATE  GENERATOR gn_pk_parameter;
+SET     GENERATOR gn_pk_parameter       TO 0;
+CREATE  GENERATOR gn_pk_param_log;
+SET     GENERATOR gn_pk_param_log       TO 0;
+
+
+/*
+ *****************************************************************************
+ * -= Создание ТРИГГЕРОВ =-
+ *****************************************************************************
+ */
+
+SET TERM !! ;
+CREATE TRIGGER tr_admin_bi FOR tb_admins
+ACTIVE BEFORE INSERT POSITION 0
+AS
+BEGIN
+    IF (new.pk_admin IS NULL)
+    THEN new.pk_admin = GEN_ID(gn_pk_admin, 1);
+END !!
+SET TERM ; !!
+
+set term !! ;
+create trigger tr_tariff_param_bi for tb_tariffs_params active
+before insert position 0
+as
+begin
+    if (new.pk_tariff_param is null)
+    then new.pk_tariff_param = gen_id(gn_pk_tariff_param, 1);
+end !!
+set term ; !!
+
+set term !! ;
+create trigger tr_corporation_bi for tb_corporations active
+before insert position 0
+as
+begin
+    if (new.pk_corporation is null)
+    then new.pk_corporation = gen_id(gn_pk_corporation, 1);
+end !!
+set term ; !!
+
+set term !! ;
+create trigger tr_detail_stat_bi for tb_detail_stats active
+before insert position 0
+as
+begin
+    if (new.pk_detail_stat is null)
+    then new.pk_detail_stat = gen_id(gn_pk_detail_stat, 1);
+end !!
+set term ; !!
+
+set term !! ;
+create trigger tr_service_bi for tb_services active
+before insert position 0
+as
+begin
+    if (new.pk_service is null)
+    then new.pk_service = gen_id(gn_pk_service, 1);
+end !!
+set term ; !!
+
+set term !! ;
+create trigger tr_user_service_bi for tb_users_services active
+before insert position 0
+as
+begin
+    if (new.pk_user_service is null)
+    then new.pk_user_service = gen_id(gn_pk_user_service, 1);
+end !!
+set term ; !!
+
+set term !! ;
+create trigger tr_stat_traffic_bi for tb_stats_traffic active
+before insert position 0
+as
+begin
+    if (new.pk_stat_traffic is null)
+    then new.pk_stat_traffic = gen_id(gn_pk_stat_traffic, 1);
+end !!
+set term ; !!
+
+set term !! ;
+create trigger tr_user_data_bi for tb_users_data active
+before insert position 0
+as
+begin
+    if (new.pk_user_data is null)
+    then new.pk_user_data = gen_id(gn_pk_user_data, 1);
+end !!
+set term ; !!
+
+set term !! ;
+create trigger tr_allowed_ip_bi for tb_allowed_ip active
+before insert position 0
+as
+begin
+    if (new.pk_allowed_ip is null)
+    then new.pk_allowed_ip = gen_id(gn_pk_allowed_ip, 1);
+end !!
+set term ; !!
+
+set term !! ;
+create trigger tr_session_data_bi for tb_sessions_data active
+before insert position 0
+as
+begin
+    if (new.pk_session_data is null)
+    then new.pk_session_data = gen_id(gn_pk_session_data, 1);
+end !!
+set term ; !!
+
+set term !! ;
+create trigger tr_parameter_bi for tb_parameters active
+before insert position 0
+as
+begin
+    if (new.pk_parameter is null)
+    then new.pk_parameter = gen_id(gn_pk_parameter, 1);
+end !!
+set term ; !!
+
+set term !! ;
+create trigger tr_param_log_bi for tb_params_log active
+before insert position 0
+as
+begin
+    if (new.pk_param_log is null)
+    then new.pk_param_log = gen_id(gn_pk_param_log, 1);
+end !!
+set term ; !!
+
+/*
+ *****************************************************************************
+ * -= Создание stored procedure =-
+ *****************************************************************************
+ */
+
+/*
+ * Add a message returning it's ID
+ */
+set term !! ;
+create procedure sp_add_message(pk_message integer, login varchar(32), ver integer, msg_type integer, last_send_time integer, creation_time integer, show_time integer, repeat integer, repeat_period integer, msg_text varchar(256))
+returns(res integer)
+as  
+begin
+    if (:pk_message is null) then
+    begin
+       pk_message = gen_id(gn_pk_message, 1);
+       insert into tb_messages values (:pk_message,
+                                       (select pk_user from tb_users where name = :login),
+                                       :ver,
+                                       :msg_type,
+                                       :last_send_time,
+                                       :creation_time, 
+                                       :show_time,
+                                       :repeat,
+                                       :repeat_period,
+                                       :msg_text);
+    end
+    else
+    begin
+       update tb_messages set fk_user = (select pk_user from tb_users where name = :login),
+                              ver = :ver,
+                              msg_type = :msg_type,
+                              last_send_time = :last_send_time,
+                              creation_time = :creation_time,
+                              show_time = :show_time,
+                              repeat = :repeat_period,
+                              repeat_period = :repeat_period,
+                              msg_text = :msg_text
+                          where pk_message = :pk_message;
+    end
+    res = :pk_message;
+end !!
+set term ; !!
+
+set term !! ;
+create procedure sp_delete_service(name varchar(32))
+as
+declare variable pk_service integer;
+begin
+    select pk_service from tb_services where name = :name into pk_service;
+    if (pk_service is  not null) then
+    begin
+       delete from tb_users_services where fk_service = :pk_service;
+       delete from tb_services where pk_service = :pk_service;
+    end
+end !!
+set term ; !!
+
+set term !! ;
+create procedure sp_add_tariff(name varchar(32), dirs integer)
+as
+declare variable pk_tariff integer;
+begin
+    pk_tariff = gen_id(gn_pk_tariff, 1);
+    insert into tb_tariffs (pk_tariff, name, fee, free, passive_cost, traff_type) values (:pk_tariff, :name, 0, 0, 0, 0);
+    while (dirs > 0) do
+    begin
+        insert into tb_tariffs_params (fk_tariff, dir_num, price_day_a, 
+                                       price_day_b, price_night_a, price_night_b, 
+                                       threshold, time_day_begins, time_day_ends)
+                   values (:pk_tariff, :dirs - 1, 0, 0, 0, 0, 0, '0:0', '0:0');
+       dirs = dirs - 1;
+    end
+end !!
+set term ; !!
+
+set term !! ;
+create procedure sp_delete_tariff(name varchar(32))
+as
+declare variable pk_tariff integer;
+begin
+    select pk_tariff from tb_tariffs where name = :name into pk_tariff;
+    if (pk_tariff is not null) then
+    begin
+       delete from tb_tariffs_params where fk_tariff = :pk_tariff;
+       delete from tb_tariffs where pk_tariff = :pk_tariff;
+    end
+end !!
+set term ; !!
+
+set term !! ;
+create procedure sp_add_user(name varchar(32), dirs integer)
+as
+declare variable pk_user integer;
+declare variable pk_stat integer;
+begin
+    pk_user = gen_id(gn_pk_user, 1);
+    insert into tb_users(pk_user, fk_tariff, fk_tariff_change, fk_corporation, address, always_online, credit, credit_expire, disabled, disabled_detail_stat, email, grp, note, passive, passwd, phone, name, real_name) values (:pk_user, NULL, NULL, NULL, '', 0, 0, 'now', 0, 0, '', '_', '', 0, '', '', :name, '');
+    pk_stat = gen_id(gn_pk_stat, 1);
+    insert into tb_stats values (:pk_stat, :pk_user, 0, 0, 'now', 0, 'now', 0, 'now');
+    while (dirs > 0) do
+    begin
+       insert into tb_stats_traffic (fk_stat, dir_num, upload, download) values (:pk_stat, :dirs - 1, 0, 0);
+       dirs = dirs - 1;
+    end
+end!!
+set term ; !!
+
+set term !! ;
+create procedure sp_delete_user(name varchar(32))
+as
+declare variable pk_user integer;
+begin
+    select pk_user from tb_users where name = :name into pk_user;
+    if (pk_user is not null) then
+    begin
+       delete from tb_users_services where fk_user = :pk_user;
+       delete from tb_params_log where fk_user = :pk_user;
+       delete from tb_detail_stats where fk_user = :pk_user;
+       delete from tb_stats_traffic where fk_stat in (select pk_stat from tb_stats where fk_user = :pk_user);
+       delete from tb_stats where fk_user = :pk_user;
+       delete from tb_sessions_data where fk_session_log in (select pk_session_log from tb_sessions_log where fk_user = :pk_user);
+       delete from tb_sessions_log where fk_user = :pk_user;
+       delete from tb_allowed_ip where fk_user = :pk_user;
+       delete from tb_users_data where fk_user = :pk_user;
+       delete from tb_messages where fk_user = :pk_user;
+       delete from tb_users where pk_user = :pk_user;
+    end
+end !!
+set term ; !!
+
+set term !! ;
+create procedure sp_append_session_log(name varchar(32), event_time timestamp, event_type char(1), ip integer)
+returns(pk_session_log integer)
+as
+begin
+    pk_session_log = gen_id(gn_pk_session_log, 1);
+    insert into tb_sessions_log (pk_session_log, fk_user, event_time, event_type, ip) values (:pk_session_log, (select pk_user from tb_users where name = :name), :event_time, :event_type, :ip);
+end !!
+set term ; !!
+
+set term !! ;
+create procedure sp_add_stat(name varchar(32), cash numeric(10,6), free_mb numeric(10,6), last_activity_time timestamp, last_cash_add numeric(10,6), last_cash_add_time timestamp, passive_time integer, stats_date date)
+returns(pk_stat integer)
+as
+begin
+    pk_stat = gen_id(gn_pk_stat, 1);
+    insert into tb_stats (pk_stat, fk_user, cash, free_mb, last_activity_time, last_cash_add, last_cash_add_time, passive_time, stats_date) values (:pk_stat, (select pk_user from tb_users where name = :name), :cash, :free_mb, :last_activity_time, :last_cash_add, :last_cash_add_time, :passive_time, :stats_date);
+end !!
+set term ; !!
+
+/*
+ *****************************************************************************
+ * -= Создание администратора =-
+ *****************************************************************************
+ */
+
+insert into tb_admins values(0, 'admin', 'geahonjehjfofnhammefahbbbfbmpkmkmmefahbbbfbmpkmkmmefahbbbfbmpkmk', 1, 1, 1, 1, 1, 1, 1, 1, 1);
+
+/* EOF */
diff --git a/projects/stargazer/inst/var/00-mysql-01.sql b/projects/stargazer/inst/var/00-mysql-01.sql
new file mode 100644 (file)
index 0000000..253738a
--- /dev/null
@@ -0,0 +1,5 @@
+/*
+ *  DB migration from v00 to v01 (mysql)
+ */
+
+ALTER TABLE users ADD DisabledDetailStat INT(3) DEFAULT 0;
diff --git a/projects/stargazer/inst/var/01-alter-02.mysql.sql b/projects/stargazer/inst/var/01-alter-02.mysql.sql
new file mode 100644 (file)
index 0000000..1f1b044
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ *  DB migration from v01 to v02 (mysql)
+ */
+
+ALTER TABLE tariffs ADD period VARCHAR(32) NOT NULL DEFAULT 'month';
+
+CREATE TABLE info
+(
+    version INTEGER NOT NULL
+);
+
+INSERT INTO info VALUES (1);
diff --git a/projects/stargazer/inst/var/01-alter-02.postgresql.sql b/projects/stargazer/inst/var/01-alter-02.postgresql.sql
new file mode 100644 (file)
index 0000000..ef6a98c
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ *  DB migration from v01 to v02 (postgres)
+ */
+BEGIN;
+
+CREATE DOMAIN DM_TARIFF_PERIOD AS TEXT NOT NULL
+    CONSTRAINT valid_value CHECK (VALUE = 'month' OR VALUE = 'day');
+
+ALTER TABLE tb_tariffs ADD period DM_TARIFF_PERIOD DEFAULT 'month';
+
+UPDATE tb_info SET version = 7;
+
+COMMIT;
diff --git a/projects/stargazer/inst/var/01-alter-02.sql b/projects/stargazer/inst/var/01-alter-02.sql
new file mode 100644 (file)
index 0000000..628a016
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ *  DB migration from v01 to v02 (firebird)
+ */
+
+CREATE DOMAIN DM_TARIFF_PERIOD AS VARCHAR(32) NOT NULL
+    CHECK (VALUE = 'month' OR VALUE = 'day');
+
+ALTER TABLE tb_tariffs ADD period DM_TARIFF_PERIOD DEFAULT 'month';
+
+CREATE TABLE tb_info
+(
+    version INTEGER NOT NULL
+);
+
+INSERT INTO tb_info VALUES (1);
diff --git a/projects/stargazer/inst/var/02-alter-03.postgresql.sql b/projects/stargazer/inst/var/02-alter-03.postgresql.sql
new file mode 100644 (file)
index 0000000..e8b248b
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ *  DB migration from v02 to v03 (postgres)
+ */
+BEGIN;
+
+CREATE DOMAIN DM_TARIFF_CHANGE_POLICY AS TEXT NOT NULL
+    CONSTRAINT valid_value CHECK (VALUE IN ('allow', 'to_cheap', 'to_expensive', 'deny'));
+
+ALTER TABLE tb_tariffs ADD change_policy DM_TARIFF_CHANGE_POLICY DEFAULT 'allow';
+ALTER TABLE tb_tariffs ADD change_policy_timeout TIMESTAMP NOT NULL DEFAULT '1970-01-01 00:00:00';
+ALTER TABLE tb_tariffs ALTER COLUMN change_policy DROP DEFAULT;
+ALTER TABLE tb_tariffs ALTER COLUMN change_policy_timeout DROP DEFAULT;
+
+UPDATE tb_info SET version = 8;
+
+COMMIT;
diff --git a/projects/stargazer/inst/var/02-alter-03.sql b/projects/stargazer/inst/var/02-alter-03.sql
new file mode 100644 (file)
index 0000000..d274520
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ *  DB migration from v02 to v03 (firebird)
+ */
+
+CREATE DOMAIN DM_TARIFF_CHANGE_POLICY AS  VARCHAR(32) NOT NULL
+    CHECK (VALUE IN ('allow', 'to_cheap', 'to_expensive', 'deny'));
+
+ALTER TABLE tb_tariffs ADD change_policy DM_TARIFF_CHANGE_POLICY DEFAULT 'allow';
+ALTER TABLE tb_tariffs ADD change_policy_timeout DM_MOMENT DEFAULT '1970-01-01 00:00:00';
+
+UPDATE tb_tariffs SET change_policy = 'allow', change_policy_timeout = '1970-01-01 00:00:00';
+
+ALTER TABLE tb_tariffs ALTER COLUMN change_policy DROP DEFAULT;
+ALTER TABLE tb_tariffs ALTER COLUMN change_policy_timeout DROP DEFAULT;
+
+UPDATE tb_info SET version = 2;
diff --git a/projects/stargazer/inst/var/base.dia b/projects/stargazer/inst/var/base.dia
new file mode 100644 (file)
index 0000000..a3d09fa
Binary files /dev/null and b/projects/stargazer/inst/var/base.dia differ
diff --git a/projects/stargazer/inst/var/stargazer/admins/admin.adm b/projects/stargazer/inst/var/stargazer/admins/admin.adm
new file mode 100644 (file)
index 0000000..bfc6cde
--- /dev/null
@@ -0,0 +1,8 @@
+password=geahonjehjfofnhammefahbbbfbmpkmkmmefahbbbfbmpkmkmmefahbbbfbmpkmkaa
+ChgConf=1
+ChgPassword=1
+ChgStat=1
+ChgCash=1
+UsrAddDel=1
+ChgTariff=1
+ChgAdmin=1
diff --git a/projects/stargazer/inst/var/stargazer/tariffs/tariff.tf b/projects/stargazer/inst/var/stargazer/tariffs/tariff.tf
new file mode 100644 (file)
index 0000000..8eb1deb
--- /dev/null
@@ -0,0 +1,84 @@
+Fee=10.000000
+Free=0
+NoDiscount0=1
+NoDiscount1=1
+NoDiscount2=1
+NoDiscount3=1
+NoDiscount4=1
+NoDiscount5=1
+NoDiscount6=1
+NoDiscount7=1
+NoDiscount8=1
+NoDiscount9=1
+PassiveCost=0.000000
+PriceDayA0=0.000000
+PriceDayA1=0.750000
+PriceDayA2=0.000000
+PriceDayA3=0.000000
+PriceDayA4=0.000000
+PriceDayA5=0.000000
+PriceDayA6=0.000000
+PriceDayA7=0.000000
+PriceDayA8=0.000000
+PriceDayA9=0.000000
+PriceDayB0=0.000000
+PriceDayB1=0.750000
+PriceDayB2=0.000000
+PriceDayB3=0.000000
+PriceDayB4=0.000000
+PriceDayB5=0.000000
+PriceDayB6=0.000000
+PriceDayB7=0.000000
+PriceDayB8=0.000000
+PriceDayB9=0.000000
+PriceNightA0=1.000000
+PriceNightA1=0.000000
+PriceNightA2=0.000000
+PriceNightA3=0.000000
+PriceNightA4=0.000000
+PriceNightA5=0.000000
+PriceNightA6=0.000000
+PriceNightA7=0.000000
+PriceNightA8=0.000000
+PriceNightA9=0.000000
+PriceNightB0=1.000000
+PriceNightB1=0.000000
+PriceNightB2=0.000000
+PriceNightB3=0.000000
+PriceNightB4=0.000000
+PriceNightB5=0.000000
+PriceNightB6=0.000000
+PriceNightB7=0.000000
+PriceNightB8=0.000000
+PriceNightB9=0.000000
+SinglePrice0=1
+SinglePrice1=1
+SinglePrice2=0
+SinglePrice3=0
+SinglePrice4=0
+SinglePrice5=0
+SinglePrice6=0
+SinglePrice7=0
+SinglePrice8=0
+SinglePrice9=0
+Threshold0=0
+Threshold1=0
+Threshold2=0
+Threshold3=0
+Threshold4=0
+Threshold5=0
+Threshold6=0
+Threshold7=0
+Threshold8=0
+Threshold9=0
+Time0=0:0-0:0
+Time1=0:0-0:0
+Time2=0:0-0:0
+Time3=0:0-0:0
+Time4=0:0-0:0
+Time5=0:0-0:0
+Time6=0:0-0:0
+Time7=0:0-0:0
+Time8=0:0-0:0
+Time9=0:0-0:0
+TraffType=up+down
diff --git a/projects/stargazer/inst/var/stargazer/users/test/conf b/projects/stargazer/inst/var/stargazer/users/test/conf
new file mode 100644 (file)
index 0000000..16fff5e
--- /dev/null
@@ -0,0 +1,19 @@
+Address=
+AlwaysOnline=0
+CreationTime=1123487395
+Credit=0.000000
+CreditExpire=0
+Down=0
+Email=
+Group=
+Iface=eth1
+IP=192.168.1.1
+Note=
+Passive=0
+Password=123456
+Phone=
+RealName=
+Tariff=tariff
+TariffChange=
+Userdata0=
+Userdata1=
diff --git a/projects/stargazer/inst/var/stargazer/users/test/stat b/projects/stargazer/inst/var/stargazer/users/test/stat
new file mode 100644 (file)
index 0000000..8aa33e0
--- /dev/null
@@ -0,0 +1,26 @@
+Cash=10.000000
+D0=0
+D1=0
+D2=0
+D3=0
+D4=0
+D5=0
+D6=0
+D7=0
+D8=0
+D9=0
+FreeMb=0.000000
+LastActivityTime=0
+LastCashAdd=0
+LastCashAddTime=0
+PassiveTime=0
+U0=0
+U1=0
+U2=0
+U3=0
+U4=0
+U5=0
+U6=0
+U7=0
+U8=0
+U9=0
diff --git a/projects/stargazer/main.cpp b/projects/stargazer/main.cpp
new file mode 100644 (file)
index 0000000..825cba5
--- /dev/null
@@ -0,0 +1,405 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+#include "store_loader.h"
+#include "plugin_mgr.h"
+#include "plugin_runner.h"
+#include "users_impl.h"
+#include "admins_impl.h"
+#include "tariffs_impl.h"
+#include "services_impl.h"
+#include "corps_impl.h"
+#include "traffcounter_impl.h"
+#include "settings_impl.h"
+#include "pidfile.h"
+#include "eventloop.h"
+#include "stg_timer.h"
+
+#include "stg/user.h"
+#include "stg/common.h"
+#include "stg/plugin.h"
+#include "stg/logger.h"
+#include "stg/scriptexecuter.h"
+#include "stg/version.h"
+
+#include <fstream>
+#include <vector>
+#include <set>
+#include <csignal>
+#include <cerrno>
+#include <cstdio>
+#include <cstdlib> // srandom, exit
+
+#include <unistd.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h> // S_IRUSR
+#include <fcntl.h> // create
+
+#ifdef DEBUG
+    #define NO_DAEMON  (1)
+#endif
+
+#define START_FILE "/._ST_ART_ED_"
+
+using STG::SettingsImpl;
+using STG::AdminsImpl;
+using STG::TraffCounterImpl;
+using STG::UsersImpl;
+using STG::TariffsImpl;
+using STG::ServicesImpl;
+using STG::CorporationsImpl;
+using STG::StoreLoader;
+
+namespace
+{
+std::set<pid_t> executers;
+
+void StartTimer();
+int StartScriptExecuter(char* procName, int msgKey, int* msgID);
+int ForkAndWait(const std::string& confDir);
+void KillExecuters();
+
+//-----------------------------------------------------------------------------
+void StartTimer()
+{
+    auto& WriteServLog = STG::Logger::get();
+
+    if (RunStgTimer())
+    {
+        WriteServLog("Cannot start timer. Fatal.");
+        exit(1);
+    }
+    else
+        WriteServLog("Timer thread started successfully.");
+}
+//-----------------------------------------------------------------------------
+#if defined(LINUX) || defined(DARWIN)
+int StartScriptExecuter(char* procName, int msgKey, int* msgID)
+#else
+int StartScriptExecuter(char*, int msgKey, int* msgID)
+#endif
+{
+    auto& WriteServLog = STG::Logger::get();
+
+    if (*msgID == -11)   // If msgID == -11 - first call. Create queue
+    {
+        for (int i = 0; i < 2; i++)
+        {
+            *msgID = msgget(msgKey, IPC_CREAT | IPC_EXCL | 0600);
+
+            if (*msgID == -1)
+            {
+                *msgID = msgget(msgKey, 0);
+                if (*msgID == -1)
+                {
+                    WriteServLog("Message queue not created.");
+                    return -1;
+                }
+                else
+                    msgctl(*msgID, IPC_RMID, NULL);
+            }
+            else
+            {
+                WriteServLog("Message queue created successfully. msgKey=%d msgID=%d", msgKey, *msgID);
+                break;
+            }
+        }
+    }
+
+    const auto pid = fork();
+
+    switch (pid)
+    {
+        case -1:
+            WriteServLog("Fork error!");
+            return -1;
+
+        case 0:
+#if defined(LINUX) || defined(DARWIN)
+            Executer(*msgID, pid, procName);
+#else
+            Executer(*msgID, pid);
+#endif
+            return 1;
+
+        default:
+            if (executers.empty()) {
+#if defined(LINUX) || defined(DARWIN)
+                Executer(*msgID, pid, NULL);
+#else
+                Executer(*msgID, pid);
+#endif
+            }
+            executers.insert(pid);
+    }
+    return 0;
+}
+//-----------------------------------------------------------------------------
+#ifndef NO_DAEMON
+int ForkAndWait(const std::string& confDir)
+#else
+int ForkAndWait(const std::string&)
+#endif
+{
+#ifndef NO_DAEMON
+    const auto pid = fork();
+    const auto startFile = confDir + START_FILE;
+    unlink(startFile.c_str());
+
+    switch (pid)
+    {
+        case -1:
+            return -1;
+            break;
+
+        case 0:
+            close(1);
+            close(2);
+            setsid();
+            break;
+
+        default:
+            struct timespec ts = {0, 200000000};
+            for (int i = 0; i < 120 * 5; i++)
+            {
+                if (access(startFile.c_str(), F_OK) == 0)
+                {
+                    unlink(startFile.c_str());
+                    exit(0);
+                }
+
+                nanosleep(&ts, NULL);
+            }
+            unlink(startFile.c_str());
+            exit(1);
+            break;
+    }
+#endif
+    return 0;
+}
+//-----------------------------------------------------------------------------
+void KillExecuters()
+{
+    auto pid = executers.begin();
+    while (pid != executers.end())
+    {
+        printfd(__FILE__, "KillExecuters pid=%d\n", *pid);
+        kill(*pid, SIGUSR1);
+        ++pid;
+    }
+}
+//-----------------------------------------------------------------------------
+} // namespace anonymous
+//-----------------------------------------------------------------------------
+int main(int argc, char* argv[])
+{
+    int msgID = -11;
+
+    STG::Logger::get().setFileName("/var/log/stargazer.log");
+
+    if (getuid())
+    {
+        printf("You must be root. Exit.\n");
+        return 1;
+    }
+
+    SettingsImpl settings(argc == 2 ? argv[1] : "");
+
+    if (settings.ReadSettings())
+    {
+        auto& WriteServLog = STG::Logger::get();
+
+        if (settings.GetLogFileName() != "")
+            WriteServLog.setFileName(settings.GetLogFileName());
+
+        WriteServLog("ReadSettings error. %s", settings.GetStrError().c_str());
+        return -1;
+    }
+
+#ifndef NO_DAEMON
+    const auto startFile = settings.GetConfDir() + START_FILE;
+#endif
+
+    if (ForkAndWait(settings.GetConfDir()) < 0)
+    {
+        STG::Logger::get()("Fork error!");
+        return -1;
+    }
+
+    auto& WriteServLog = STG::Logger::get();
+    WriteServLog.setFileName(settings.GetLogFileName());
+    WriteServLog("Stg v. %s", SERVER_VERSION);
+
+    for (size_t i = 0; i < settings.GetExecutersNum(); i++)
+    {
+        auto ret = StartScriptExecuter(argv[0], settings.GetExecMsgKey(), &msgID);
+        if (ret < 0)
+        {
+            STG::Logger::get()("Start Script Executer error!");
+            return -1;
+        }
+        if (ret == 1)
+            return 0;
+    }
+
+    PIDFile pidFile(settings.GetPIDFileName());
+
+    struct sigaction sa;
+    memset(&sa, 0, sizeof(sa));
+    sa.sa_handler = SIG_DFL;
+    sigaction(SIGHUP, &sa, NULL); // Apparently FreeBSD ignores SIGHUP by default when launched from rc.d at bot time.
+
+    sigset_t signalSet;
+    sigfillset(&signalSet);
+    pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+    StartTimer();
+    WaitTimer();
+    if (!IsStgTimerRunning())
+    {
+        printfd(__FILE__, "Timer thread not started in 1 sec!\n");
+        WriteServLog("Timer thread not started in 1 sec!");
+        return -1;
+    }
+
+    auto& loop = EVENT_LOOP_SINGLETON::GetInstance();
+
+    StoreLoader storeLoader(settings);
+    if (storeLoader.load())
+    {
+        printfd(__FILE__, "Storage plugin: '%s'\n", storeLoader.GetStrError().c_str());
+        WriteServLog("Storage plugin: '%s'", storeLoader.GetStrError().c_str());
+        return -1;
+    }
+
+    if (loop.Start())
+    {
+        printfd(__FILE__, "Event loop not started.\n");
+        WriteServLog("Event loop not started.");
+        return -1;
+    }
+
+    auto& store = storeLoader.get();
+    WriteServLog("Storage plugin: %s. Loading successfull.", store.GetVersion().c_str());
+
+    AdminsImpl admins(store);
+    TariffsImpl tariffs(&store);
+    ServicesImpl services(&store);
+    CorporationsImpl corps(&store);
+    UsersImpl users(&settings, &store, &tariffs, services, admins.sysAdmin());
+    TraffCounterImpl traffCnt(&users, settings.GetRulesFileName());
+    traffCnt.SetMonitorDir(settings.GetMonitorDir());
+
+    if (users.Start())
+        return -1;
+
+    WriteServLog("Users started successfully.");
+
+    if (traffCnt.Start())
+        return -1;
+
+    WriteServLog("Traffcounter started successfully.");
+
+    STG::PluginManager manager(settings, store, admins, tariffs, services, corps, users, traffCnt);
+
+    srandom(static_cast<unsigned int>(stgTime));
+
+    WriteServLog("Stg started successfully.");
+    WriteServLog("+++++++++++++++++++++++++++++++++++++++++++++");
+
+#ifndef NO_DAEMON
+    creat(startFile.c_str(), S_IRUSR);
+#endif
+
+    bool running = true;
+    while (running)
+    {
+        sigfillset(&signalSet);
+        int sig = 0;
+        sigwait(&signalSet, &sig);
+        int status;
+        switch (sig)
+        {
+            case SIGHUP:
+            {
+                SettingsImpl newSettings(settings);
+                if (newSettings.ReadSettings())
+                    WriteServLog("ReadSettings error. %s", newSettings.GetStrError().c_str());
+                else
+                    settings = newSettings;
+                WriteServLog.setFileName(settings.GetLogFileName());
+                traffCnt.Reload();
+                manager.reload(settings);
+                break;
+            }
+            case SIGTERM:
+                running = false;
+                break;
+            case SIGINT:
+                running = false;
+                break;
+            case SIGPIPE:
+                WriteServLog("Broken pipe!");
+                break;
+            case SIGCHLD:
+                executers.erase(waitpid(-1, &status, WNOHANG));
+                if (executers.empty())
+                    running = false;
+                break;
+            default:
+                WriteServLog("Ignore signal %d", sig);
+                break;
+        }
+    }
+
+    WriteServLog("+++++++++++++++++++++++++++++++++++++++++++++");
+
+    manager.stop();
+
+    if (loop.Stop())
+        WriteServLog("Event loop not stopped.");
+
+    if (!traffCnt.Stop())
+        WriteServLog("Traffcounter: Stop successfull.");
+
+    if (!users.Stop())
+        WriteServLog("Users: Stop successfull.");
+
+    sleep(1);
+    int res = msgctl(msgID, IPC_RMID, NULL);
+    if (res)
+        WriteServLog("Queue was not removed. id=%d", msgID);
+    else
+        WriteServLog("Queue removed successfully.");
+
+    KillExecuters();
+
+    StopStgTimer();
+    WriteServLog("StgTimer: Stop successfull.");
+
+    WriteServLog("Stg stopped successfully.");
+    WriteServLog("---------------------------------------------");
+
+    return 0;
+}
+//-----------------------------------------------------------------------------
diff --git a/projects/stargazer/pidfile.cpp b/projects/stargazer/pidfile.cpp
new file mode 100644 (file)
index 0000000..0f47a25
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+/*
+ $Revision: 1.2 $
+ $Date: 2009/06/09 09:07:32 $
+ $Author: faust $
+ */
+
+/*
+ *  An implementation of RAII pid-file writer
+ */
+
+#include <fstream>
+#include <unistd.h>
+
+#include "pidfile.h"
+
+PIDFile::PIDFile(const std::string & fn)
+    : fileName(fn)
+{
+if (fileName != "")
+    {
+    std::ofstream pf(fileName.c_str());
+    pf << getpid() << std::endl;
+    pf.close();
+    }
+}
+
+PIDFile::~PIDFile()
+{
+if (fileName != "")
+    {
+    unlink(fileName.c_str());
+    }
+}
diff --git a/projects/stargazer/pidfile.h b/projects/stargazer/pidfile.h
new file mode 100644 (file)
index 0000000..2600f7f
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+/*
+ *  Header file for RAII pid-file writer
+ */
+
+/*
+ $Revision: 1.2 $
+ $Date: 2009/06/09 09:07:32 $
+ $Author: faust $
+ */
+
+#ifndef __PID_FILE_H__
+#define __PID_FILE_H__
+
+#include <string>
+
+class PIDFile {
+public:
+    explicit PIDFile(const std::string & fn);
+    ~PIDFile();
+private:
+    std::string fileName;
+};
+
+#endif
diff --git a/projects/stargazer/plugin_mgr.cpp b/projects/stargazer/plugin_mgr.cpp
new file mode 100644 (file)
index 0000000..9d0f136
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#include "plugin_mgr.h"
+
+#include "plugin_runner.h"
+
+#include "admins_impl.h"
+#include "tariffs_impl.h"
+#include "services_impl.h"
+#include "corps_impl.h"
+#include "users_impl.h"
+#include "traffcounter_impl.h"
+#include "settings_impl.h"
+
+#include "stg/logger.h"
+
+using STG::PluginManager;
+using STG::PluginRunner;
+
+namespace
+{
+
+bool StartModCmp(const PluginRunner * lhs, const PluginRunner * rhs)
+{
+    return lhs->GetStartPosition() < rhs->GetStartPosition();
+}
+
+bool StopModCmp(const PluginRunner * lhs, const PluginRunner * rhs)
+{
+    return lhs->GetStopPosition() > rhs->GetStopPosition();
+}
+
+} // namespace anonymous
+
+PluginManager::PluginManager(const SettingsImpl& settings,
+                             Store& store, AdminsImpl& admins, TariffsImpl& tariffs,
+                             ServicesImpl& services, CorporationsImpl& corporations,
+                             UsersImpl& users, TraffCounterImpl& traffcounter)
+    : m_log(Logger::get())
+{
+    std::string basePath = settings.GetModulesPath();
+    const std::vector<ModuleSettings> & modSettings(settings.GetModulesSettings());
+    for (size_t i = 0; i < modSettings.size(); i++)
+    {
+        std::string moduleName = modSettings[i].moduleName;
+        std::string modulePath = basePath + "/mod_" + moduleName + ".so";
+        printfd(__FILE__, "Module: %s\n", modulePath.c_str());
+        try
+        {
+            m_modules.push_back(
+                new PluginRunner(modulePath, moduleName, modSettings[i], admins, tariffs,
+                                  users, services, corporations, traffcounter,
+                                  store, settings)
+            );
+        }
+        catch (const PluginRunner::Error & ex)
+        {
+            m_log(ex.what());
+            printfd(__FILE__, "%s\n", ex.what());
+            // TODO: React
+        }
+    }
+    std::sort(m_modules.begin(), m_modules.end(), StartModCmp);
+    for (size_t i = 0; i < m_modules.size(); ++i)
+    {
+        auto& plugin = m_modules[i]->GetPlugin();
+        if (m_modules[i]->Start())
+        {
+            m_log("Failed to start module '%s': '%s'", plugin.GetVersion().c_str(),
+                                                       plugin.GetStrError().c_str());
+            printfd(__FILE__, "Failed to start module '%s': '%s'\n", plugin.GetVersion().c_str(),
+                                                                   plugin.GetStrError().c_str());
+        }
+        else
+        {
+            m_log("Module '%s' started successfully.", plugin.GetVersion().c_str());
+            printfd(__FILE__, "Module '%s' started successfully.\n", plugin.GetVersion().c_str());
+        }
+    }
+}
+
+PluginManager::~PluginManager()
+{
+    stop();
+    for (size_t i = 0; i < m_modules.size(); ++i)
+        delete m_modules[i];
+}
+
+void PluginManager::reload(const SettingsImpl& settings)
+{
+    const std::vector<ModuleSettings> & modSettings(settings.GetModulesSettings());
+    for (size_t i = 0; i < m_modules.size(); ++i)
+    {
+        for (size_t j = 0; j < modSettings.size(); j++)
+        {
+            if (modSettings[j].moduleName == m_modules[i]->GetName())
+            {
+                auto& plugin = m_modules[i]->GetPlugin();
+                if (m_modules[i]->Reload(modSettings[j]))
+                {
+                    m_log("Error reloading module '%s': '%s'", plugin.GetVersion().c_str(),
+                                                               plugin.GetStrError().c_str());
+                    printfd(__FILE__, "Error reloading module '%s': '%s'\n", plugin.GetVersion().c_str(),
+                                                                             plugin.GetStrError().c_str());
+                }
+                break;
+            }
+        }
+    }
+}
+
+void PluginManager::stop()
+{
+    std::sort(m_modules.begin(), m_modules.end(), StopModCmp);
+    for (size_t i = 0; i < m_modules.size(); ++i)
+    {
+        if (!m_modules[i]->IsRunning())
+            continue;
+        auto& plugin = m_modules[i]->GetPlugin();
+        if (m_modules[i]->Stop())
+        {
+            m_log("Failed to stop module '%s': '%s'", plugin.GetVersion().c_str(),
+                                                      plugin.GetStrError().c_str());
+            printfd(__FILE__, "Failed to stop module '%s': '%s'\n", plugin.GetVersion().c_str(),
+                                                                    plugin.GetStrError().c_str());
+        }
+        else
+        {
+            m_log("Module '%s' stopped successfully.", plugin.GetVersion().c_str());
+            printfd(__FILE__, "Module '%s' stopped successfully.\n", plugin.GetVersion().c_str());
+        }
+    }
+}
diff --git a/projects/stargazer/plugin_mgr.h b/projects/stargazer/plugin_mgr.h
new file mode 100644 (file)
index 0000000..1d402eb
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#pragma once
+
+#include "stg/module_settings.h"
+
+#include <vector>
+
+namespace STG
+{
+
+class SettingsImpl;
+class PluginRunner;
+struct Store;
+class AdminsImpl;
+class TariffsImpl;
+class ServicesImpl;
+class CorporationsImpl;
+class UsersImpl;
+class TraffCounterImpl;
+class Logger;
+
+class PluginManager
+{
+    public:
+        PluginManager(const SettingsImpl& settings,
+                      Store& store, AdminsImpl& admins, TariffsImpl& tariffs,
+                      ServicesImpl& services, CorporationsImpl& corporations,
+                      UsersImpl& users, TraffCounterImpl& traffcounter);
+        ~PluginManager();
+
+        void reload(const SettingsImpl& settings);
+        void stop();
+
+    private:
+        std::vector<PluginRunner*> m_modules;
+        Logger & m_log;
+};
+
+}
diff --git a/projects/stargazer/plugin_runner.cpp b/projects/stargazer/plugin_runner.cpp
new file mode 100644 (file)
index 0000000..8938950
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#include "plugin_runner.h"
+
+#include "stg/common.h"
+
+#include <dlfcn.h>
+#include <unistd.h>
+
+using STG::PluginRunner;
+using STG::Plugin;
+
+//-----------------------------------------------------------------------------
+PluginRunner::PluginRunner(const std::string& fileName,
+                           const std::string& name,
+                           const ModuleSettings& ms,
+                           Admins& admins,
+                           Tariffs& tariffs,
+                           Users& users,
+                           Services& services,
+                           Corporations& corporations,
+                           TraffCounter& traffcounter,
+                           Store& store,
+                           const Settings& settings)
+    : pluginFileName(fileName),
+      pluginName(name),
+      libHandle(NULL),
+      m_plugin(load(ms, admins, tariffs, users, services, corporations,
+                    traffcounter, store, settings))
+{
+}
+//-----------------------------------------------------------------------------
+PluginRunner::~PluginRunner()
+{
+    delete &m_plugin;
+    if (dlclose(libHandle))
+    {
+        errorStr = "Failed to unload plugin '" + pluginFileName + "': " + dlerror();
+        printfd(__FILE__, "PluginRunner::Unload() - %s", errorStr.c_str());
+    }
+}
+//-----------------------------------------------------------------------------
+int PluginRunner::Start()
+{
+    int res = m_plugin.Start();
+    errorStr = m_plugin.GetStrError();
+    return res;
+}
+//-----------------------------------------------------------------------------
+int PluginRunner::Stop()
+{
+    int res = m_plugin.Stop();
+    errorStr = m_plugin.GetStrError();
+    return res;
+}
+//-----------------------------------------------------------------------------
+int PluginRunner::Reload(const ModuleSettings& ms)
+{
+    int res = m_plugin.Reload(ms);
+    errorStr = m_plugin.GetStrError();
+    return res;
+}
+//-----------------------------------------------------------------------------
+Plugin & PluginRunner::load(const ModuleSettings& ms,
+                            Admins& admins,
+                            Tariffs& tariffs,
+                            Users& users,
+                            Services& services,
+                            Corporations& corporations,
+                            TraffCounter& traffcounter,
+                            Store& store,
+                            const Settings& settings)
+{
+    if (pluginFileName.empty())
+    {
+        const std::string msg = "Empty plugin file name.";
+        printfd(__FILE__, "PluginRunner::load() - %s\n", msg.c_str());
+        throw Error(msg);
+    }
+
+    if (access(pluginFileName.c_str(), R_OK))
+    {
+        const std::string msg = "Plugin file '" + pluginFileName + "' is missing or inaccessible.";
+        printfd(__FILE__, "PluginRunner::load() - %s\n", msg.c_str());
+        throw Error(msg);
+    }
+
+    libHandle = dlopen(pluginFileName.c_str(), RTLD_NOW);
+
+    if (!libHandle)
+    {
+        std::string msg = "Error loading plugin '" + pluginFileName + "'";
+        const char* error = dlerror();
+        if (error)
+            msg = msg + ": '" + error + "'";
+        printfd(__FILE__, "PluginRunner::load() - %s\n", msg.c_str());
+        throw Error(msg);
+    }
+
+    using Getter = Plugin* (*)();
+    auto GetPlugin = reinterpret_cast<Getter>(dlsym(libHandle, "GetPlugin"));
+    if (!GetPlugin)
+    {
+        const std::string msg = "Plugin '" + pluginFileName + "' does not have GetPlugin() function. ";
+        printfd(__FILE__, "PluginRunner::load() - %s\n", msg.c_str());
+        throw Error(msg);
+    }
+
+    Plugin* plugin = GetPlugin();
+
+    if (!plugin)
+    {
+        const std::string msg = "Failed to create an instance of plugin '" + pluginFileName + "'.";
+        printfd(__FILE__, "PluginRunner::load() - %s\n", msg.c_str());
+        throw Error(msg);
+    }
+
+    plugin->SetSettings(ms);
+    plugin->SetTariffs(&tariffs);
+    plugin->SetAdmins(&admins);
+    plugin->SetUsers(&users);
+    plugin->SetServices(&services);
+    plugin->SetCorporations(&corporations);
+    plugin->SetTraffcounter(&traffcounter);
+    plugin->SetStore(&store);
+    plugin->SetStgSettings(&settings);
+
+    if (plugin->ParseSettings())
+    {
+        const std::string msg = "Plugin '" + pluginFileName + "' is unable to parse settings. " + plugin->GetStrError();
+        printfd(__FILE__, "PluginRunner::load() - %s\n", msg.c_str());
+        throw Error(msg);
+    }
+
+    return *plugin;
+}
diff --git a/projects/stargazer/plugin_runner.h b/projects/stargazer/plugin_runner.h
new file mode 100644 (file)
index 0000000..1c8bf42
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#pragma once
+
+#include "stg/plugin.h"
+
+#include <string>
+#include <stdexcept>
+#include <cstdint>
+
+namespace STG
+{
+
+struct ModuleSettings;
+struct Settings;
+struct Admins;
+struct Tariffs;
+struct Users;
+struct Services;
+struct Corporations;
+struct TraffCounter;
+struct Store;
+
+//-----------------------------------------------------------------------------
+class PluginRunner {
+public:
+    struct Error : public std::runtime_error {
+        explicit Error(const std::string & msg) : runtime_error(msg) {}
+    };
+
+    PluginRunner(const std::string& pluginFileName,
+                 const std::string& pluginName,
+                 const ModuleSettings& ms,
+                 Admins& admins,
+                 Tariffs& tariffs,
+                 Users& users,
+                 Services& services,
+                 Corporations& corporations,
+                 TraffCounter& traffcounter,
+                 Store& store,
+                 const Settings & settings);
+    ~PluginRunner();
+
+    int             Start();
+    int             Stop();
+    int             Reload(const ModuleSettings& ms);
+    int             Restart();
+    bool            IsRunning() { return m_plugin.IsRunning(); }
+
+    const std::string& GetStrError() const { return errorStr; }
+    Plugin& GetPlugin() { return m_plugin; }
+    const std::string& GetFileName() const { return pluginFileName; }
+    const std::string& GetName() const { return pluginName; }
+
+    uint16_t        GetStartPosition() const { return m_plugin.GetStartPosition(); }
+    uint16_t        GetStopPosition() const { return m_plugin.GetStopPosition(); }
+
+private:
+    Plugin & load(const ModuleSettings& ms,
+                  Admins& admins,
+                  Tariffs& tariffs,
+                  Users& users,
+                  Services& services,
+                  Corporations& corporations,
+                  TraffCounter& traffcounter,
+                  Store& store,
+                  const Settings& settings);
+
+    std::string pluginFileName;
+    std::string pluginName;
+    void*       libHandle;
+
+    Plugin&     m_plugin;
+    std::string errorStr;
+};
+//-----------------------------------------------------------------------------
+}
diff --git a/projects/stargazer/plugins/CMakeLists.txt b/projects/stargazer/plugins/CMakeLists.txt
new file mode 100644 (file)
index 0000000..a8958c4
--- /dev/null
@@ -0,0 +1,158 @@
+if ( BUILD_MOD_AO )
+    add_library ( mod_auth_ao MODULE authorization/ao/ao.cpp )
+    target_link_libraries ( mod_auth_ao scriptexecuter logger common )
+    set_target_properties ( mod_auth_ao PROPERTIES PREFIX "" )
+endif ( BUILD_MOD_AO )
+
+if ( BUILD_MOD_IA )
+    add_library ( mod_auth_ia MODULE authorization/inetaccess/inetaccess.cpp )
+    target_link_libraries ( mod_auth_ia scriptexecuter crypto logger common )
+    set_target_properties ( mod_auth_ia PROPERTIES PREFIX "" )
+    if ( ${CMAKE_SYSTEM_NAME} STREQUAL "Darwin" )
+        set_target_properties ( mod_auth_ia PROPERTIES LINK_FLAGS "-undefined dynamic_lookup" )
+    endif ( ${CMAKE_SYSTEM_NAME} STREQUAL "Darwin" )
+endif ( BUILD_MOD_IA )
+
+if ( BUILD_MOD_CAP_NF )
+    add_library ( mod_cap_nf MODULE capture/cap_nf/cap_nf.cpp )
+    target_link_libraries ( mod_cap_nf logger common )
+    set_target_properties ( mod_cap_nf PROPERTIES PREFIX "" )
+endif ( BUILD_MOD_CAP_NF )
+
+if ( BUILD_MOD_CAP_DIVERT )
+    add_library ( mod_cap_divert MODULE capture/divert_freebsd/divert_cap.cpp )
+    target_link_libraries ( mod_cap_divert logger common )
+    set_target_properties ( mod_cap_divert PROPERTIES PREFIX "" )
+endif ( BUILD_MOD_CAP_DIVERT )
+
+if ( BUILD_MOD_CAP_ETHER_FREEBSD )
+    add_library ( mod_cap_bpf MODULE capture/ether_freebsd/ether_cap.cpp )
+    target_link_libraries ( mod_cap_bpf logger common )
+    set_target_properties ( mod_cap_bpf PROPERTIES PREFIX "" )
+endif ( BUILD_MOD_CAP_ETHER_FREEBSD )
+
+if ( BUILD_MOD_CAP_ETHER_LINUX )
+    add_library ( mod_cap_ether MODULE capture/ether_linux/ether_cap.cpp )
+    target_link_libraries ( mod_cap_ether logger common )
+    set_target_properties ( mod_cap_ether PROPERTIES PREFIX "" )
+endif ( BUILD_MOD_CAP_ETHER_LINUX )
+
+if ( BUILD_MOD_CAP_PCAP )
+    find_package ( PCap REQUIRED )
+    add_library ( mod_cap_pcap MODULE capture/pcap/pcap_cap.cpp )
+    target_link_libraries ( mod_cap_pcap logger common PCap::PCap )
+    set_target_properties ( mod_cap_pcap PROPERTIES PREFIX "" )
+endif ( BUILD_MOD_CAP_PCAP )
+
+if ( BUILD_MOD_CAP_NFQUEUE )
+    find_package ( NFQueue REQUIRED )
+    find_package ( NFNetLink REQUIRED )
+    find_package ( MNL REQUIRED )
+    add_library ( mod_cap_nfqueue MODULE capture/nfqueue/nfqueue.cpp )
+    target_link_libraries ( mod_cap_nfqueue logger common NF::Queue NF::NetLink MNL::MNL )
+    set_target_properties ( mod_cap_nfqueue PROPERTIES PREFIX "" )
+endif ( BUILD_MOD_CAP_NFQUEUE )
+
+if ( BUILD_MOD_SGCONFIG )
+    find_package ( EXPAT REQUIRED )
+    add_library ( mod_conf_sg MODULE configuration/sgconfig/stgconfig.cpp
+                                     configuration/sgconfig/conn.cpp
+                                     configuration/sgconfig/configproto.cpp
+                                     configuration/sgconfig/parser.cpp
+                                     configuration/sgconfig/parser_tariffs.cpp
+                                     configuration/sgconfig/parser_admins.cpp
+                                     configuration/sgconfig/parser_users.cpp
+                                     configuration/sgconfig/parser_services.cpp
+                                     configuration/sgconfig/parser_message.cpp
+                                     configuration/sgconfig/parser_auth_by.cpp
+                                     configuration/sgconfig/parser_user_info.cpp
+                                     configuration/sgconfig/parser_server_info.cpp )
+    target_link_libraries ( mod_conf_sg scriptexecuter crypto logger common EXPAT::EXPAT )
+    set_target_properties ( mod_conf_sg PROPERTIES PREFIX "" )
+    if ( ${CMAKE_SYSTEM_NAME} STREQUAL "Darwin" )
+        set_target_properties ( mod_conf_sg PROPERTIES LINK_FLAGS "-undefined dynamic_lookup" )
+    endif ( ${CMAKE_SYSTEM_NAME} STREQUAL "Darwin" )
+endif ( BUILD_MOD_SGCONFIG )
+
+if ( BUILD_MOD_RPCCONFIG )
+    find_package ( XMLRPC REQUIRED c++ abyss-server )
+    include_directories ( ${XMLRPC_INCLUDE_DIRS} )
+    add_library ( mod_conf_rpc MODULE configuration/rpcconfig/rpcconfig.cpp
+                                      configuration/rpcconfig/user_helper.cpp
+                                      configuration/rpcconfig/tariff_helper.cpp
+                                      configuration/rpcconfig/info_methods.cpp
+                                      configuration/rpcconfig/users_methods.cpp
+                                      configuration/rpcconfig/tariffs_methods.cpp
+                                      configuration/rpcconfig/admins_methods.cpp
+                                      configuration/rpcconfig/messages_methods.cpp )
+                              target_link_libraries ( mod_conf_rpc scriptexecuter logger common ${XMLRPC_LIBRARIES} )
+    set_target_properties ( mod_conf_rpc PROPERTIES PREFIX "" )
+endif ( BUILD_MOD_RPCCONFIG )
+
+if ( BUILD_MOD_PING )
+    add_library ( mod_ping MODULE other/ping/ping.cpp )
+    target_link_libraries ( mod_ping scriptexecuter logger pinger common )
+    set_target_properties ( mod_ping PROPERTIES PREFIX "" )
+endif ( BUILD_MOD_PING )
+
+if ( BUILD_MOD_RSCRYPT )
+    add_library ( mod_remote_script MODULE other/rscript/rscript.cpp other/rscript/nrmap_parser.cpp )
+    target_link_libraries ( mod_remote_script crypto scriptexecuter logger common )
+    set_target_properties ( mod_remote_script PROPERTIES PREFIX "" )
+    if ( ${CMAKE_SYSTEM_NAME} STREQUAL "Darwin" )
+        set_target_properties ( mod_remote_script PROPERTIES LINK_FLAGS "-undefined dynamic_lookup" )
+    endif ( ${CMAKE_SYSTEM_NAME} STREQUAL "Darwin" )
+endif ( BUILD_MOD_RSCRYPT )
+
+if ( BUILD_MOD_SMUX )
+    add_library ( mod_smux MODULE other/smux/smux.cpp
+                                  other/smux/sensors.cpp
+                                  other/smux/tables.cpp
+                                  other/smux/handlers.cpp
+                                  other/smux/utils.cpp
+                                  other/smux/types.cpp )
+    target_link_libraries ( mod_smux scriptexecuter logger smux common )
+    set_target_properties ( mod_smux PROPERTIES PREFIX "" )
+endif ( BUILD_MOD_SMUX )
+
+if ( BUILD_MOD_STORE_FILES )
+    add_library ( mod_store_files MODULE store/files/file_store.cpp )
+    target_link_libraries ( mod_store_files crypto conffiles logger common )
+    set_target_properties ( mod_store_files PROPERTIES PREFIX "" )
+endif ( BUILD_MOD_STORE_FILES )
+
+if ( BUILD_MOD_STORE_FIREBIRD )
+    find_package ( FBClient REQUIRED )
+    add_library ( mod_store_firebird MODULE store/firebird/firebird_store.cpp
+                                            store/firebird/firebird_store_admins.cpp
+                                            store/firebird/firebird_store_corporations.cpp
+                                            store/firebird/firebird_store_messages.cpp
+                                            store/firebird/firebird_store_services.cpp
+                                            store/firebird/firebird_store_tariffs.cpp
+                                            store/firebird/firebird_store_users.cpp
+                                            store/firebird/firebird_store_utils.cpp )
+    target_link_libraries ( mod_store_firebird crypto common logger ibpp FBClient::FBClient )
+    set_target_properties ( mod_store_firebird PROPERTIES PREFIX "" )
+endif ( BUILD_MOD_STORE_FIREBIRD )
+
+if ( BUILD_MOD_STORE_MYSQL )
+    find_package ( MySQLConnector REQUIRED )
+    add_library ( mod_store_mysql MODULE store/mysql/mysql_store.cpp )
+    target_link_libraries ( mod_store_mysql crypto logger common MySQL::Connector )
+    set_target_properties ( mod_store_mysql PROPERTIES PREFIX "" )
+endif ( BUILD_MOD_STORE_MYSQL )
+
+if ( BUILD_MOD_STORE_POSTGRESQL )
+    find_package ( PostgreSQL REQUIRED )
+    include_directories ( ${PostgreSQL_INCLUDE_DIRS} )
+    add_library ( mod_store_postgresql MODULE store/postgresql/postgresql_store.cpp
+                                              store/postgresql/postgresql_store_admins.cpp
+                                              store/postgresql/postgresql_store_corporations.cpp
+                                              store/postgresql/postgresql_store_messages.cpp
+                                              store/postgresql/postgresql_store_services.cpp
+                                              store/postgresql/postgresql_store_tariffs.cpp
+                                              store/postgresql/postgresql_store_users.cpp
+                                              store/postgresql/postgresql_store_utils.cpp )
+                                      target_link_libraries ( mod_store_postgresql crypto logger common ${PostgreSQL_LIBRARIES} )
+    set_target_properties ( mod_store_postgresql PROPERTIES PREFIX "" )
+endif ( BUILD_MOD_STORE_POSTGRESQL )
diff --git a/projects/stargazer/plugins/authorization/ao/ao.cpp b/projects/stargazer/plugins/authorization/ao/ao.cpp
new file mode 100644 (file)
index 0000000..7b6f129
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+#include "ao.h"
+
+#include "stg/user.h"
+#include "stg/users.h"
+#include "stg/user_property.h"
+#include "stg/common.h"
+
+#include <algorithm> // for_each
+#include <functional> // mem_fun_ref
+#include <csignal>
+#include <cassert>
+
+#include <unistd.h>
+
+extern "C" STG::Plugin* GetPlugin()
+{
+    static AUTH_AO plugin;
+    return &plugin;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+std::string AUTH_AO::GetVersion() const
+{
+return "Always Online authorizator v.1.0";
+}
+//-----------------------------------------------------------------------------
+AUTH_AO::AUTH_AO()
+    : users(NULL),
+      isRunning(false),
+      onAddUserNotifier(*this),
+      onDelUserNotifier(*this),
+      logger(STG::PluginLogger::get("auth_ao"))
+{
+}
+//-----------------------------------------------------------------------------
+int AUTH_AO::Start()
+{
+printfd(__FILE__, "AUTH_AO::Start()\n");
+GetUsers();
+
+users->AddNotifierUserAdd(&onAddUserNotifier);
+users->AddNotifierUserDel(&onDelUserNotifier);
+
+std::for_each(userList.begin(), userList.end(), [this](auto user){ UpdateUserAuthorization(user); });
+
+isRunning = true;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_AO::Stop()
+{
+printfd(__FILE__, "AUTH_AO::Stop()\n");
+if (!isRunning)
+    return 0;
+
+users->DelNotifierUserAdd(&onAddUserNotifier);
+users->DelNotifierUserDel(&onDelUserNotifier);
+
+auto it = userList.begin();
+while (it != userList.end())
+    {
+    if ((*it)->IsAuthorizedBy(this))
+        users->Unauthorize((*it)->GetLogin(), this);
+    UnSetUserNotifiers(*it);
+    ++it;
+    }
+isRunning = false;
+return 0;
+}
+//-----------------------------------------------------------------------------
+void AUTH_AO::SetUserNotifiers(UserPtr u)
+{
+// ---------- AlwaysOnline -------------------
+CHG_BEFORE_NOTIFIER<int> BeforeChgAONotifier(*this, u);
+CHG_AFTER_NOTIFIER<int>  AfterChgAONotifier(*this, u);
+
+BeforeChgAONotifierList.push_front(BeforeChgAONotifier);
+AfterChgAONotifierList.push_front(AfterChgAONotifier);
+
+u->GetProperties().alwaysOnline.AddBeforeNotifier(&BeforeChgAONotifierList.front());
+u->GetProperties().alwaysOnline.AddAfterNotifier(&AfterChgAONotifierList.front());
+// ---------- AlwaysOnline end ---------------
+
+// ---------- IP -------------------
+CHG_BEFORE_NOTIFIER<STG::UserIPs> BeforeChgIPNotifier(*this, u);
+CHG_AFTER_NOTIFIER<STG::UserIPs>  AfterChgIPNotifier(*this, u);
+
+BeforeChgIPNotifierList.push_front(BeforeChgIPNotifier);
+AfterChgIPNotifierList.push_front(AfterChgIPNotifier);
+
+u->GetProperties().ips.AddBeforeNotifier(&BeforeChgIPNotifierList.front());
+u->GetProperties().ips.AddAfterNotifier(&AfterChgIPNotifierList.front());
+// ---------- IP end ---------------
+}
+//-----------------------------------------------------------------------------
+void AUTH_AO::UnSetUserNotifiers(UserPtr u)
+{
+// ---      AlwaysOnline        ---
+auto aoBIter = find_if(BeforeChgAONotifierList.begin(),
+                       BeforeChgAONotifierList.end(),
+                       [u](auto notifier){ return notifier.GetUser() == u; });
+
+if (aoBIter != BeforeChgAONotifierList.end())
+    {
+    aoBIter->GetUser()->GetProperties().alwaysOnline.DelBeforeNotifier(&(*aoBIter));
+    BeforeChgAONotifierList.erase(aoBIter);
+    }
+
+auto aoAIter = find_if(AfterChgAONotifierList.begin(),
+                       AfterChgAONotifierList.end(),
+                       [u](auto notifier){ return notifier.GetUser() == u; });
+
+if (aoAIter != AfterChgAONotifierList.end())
+    {
+    aoAIter->GetUser()->GetProperties().alwaysOnline.DelAfterNotifier(&(*aoAIter));
+    AfterChgAONotifierList.erase(aoAIter);
+    }
+// ---      AlwaysOnline end    ---
+
+// ---          IP              ---
+auto ipBIter = std::find_if(BeforeChgIPNotifierList.begin(),
+                            BeforeChgIPNotifierList.end(),
+                            [u](auto notifier){ return notifier.GetUser() == u; });
+
+if (ipBIter != BeforeChgIPNotifierList.end())
+    {
+    ipBIter->GetUser()->GetProperties().ips.DelBeforeNotifier(&(*ipBIter));
+    BeforeChgIPNotifierList.erase(ipBIter);
+    }
+
+auto ipAIter = find_if(AfterChgIPNotifierList.begin(),
+                       AfterChgIPNotifierList.end(),
+                       [u](auto notifier){ return notifier.GetUser() == u; });
+
+if (ipAIter != AfterChgIPNotifierList.end())
+    {
+    ipAIter->GetUser()->GetProperties().ips.DelAfterNotifier(&(*ipAIter));
+    AfterChgIPNotifierList.erase(ipAIter);
+    }
+// ---          IP end          ---
+}
+//-----------------------------------------------------------------------------
+void AUTH_AO::GetUsers()
+{
+UserPtr u;
+int h = users->OpenSearch();
+assert(h && "USERS::OpenSearch is always correct");
+
+while (!users->SearchNext(h, &u))
+    {
+    userList.push_back(u);
+    SetUserNotifiers(u);
+    }
+
+users->CloseSearch(h);
+}
+//-----------------------------------------------------------------------------
+void AUTH_AO::UpdateUserAuthorization(ConstUserPtr u) const
+{
+if (u->GetProperties().alwaysOnline)
+    {
+    auto ips = u->GetProperties().ips.get();
+    if (ips.onlyOneIP())
+        {
+        users->Authorize(u->GetLogin(), ips[0].ip, 0xFFffFFff, this);
+        }
+    }
+}
+//-----------------------------------------------------------------------------
+void AUTH_AO::AddUser(UserPtr u)
+{
+SetUserNotifiers(u);
+userList.push_back(u);
+UpdateUserAuthorization(u);
+}
+//-----------------------------------------------------------------------------
+void AUTH_AO::DelUser(UserPtr u)
+{
+if (u->IsAuthorizedBy(this))
+    users->Unauthorize(u->GetLogin(), this);
+UnSetUserNotifiers(u);
+userList.erase(std::remove(userList.begin(), userList.end(), u), userList.end());
+}
+//-----------------------------------------------------------------------------
+int AUTH_AO::SendMessage(const STG::Message &, uint32_t) const
+{
+errorStr = "Authorization modele \'AlwaysOnline\' does not support sending messages";
+return -1;
+}
+//-----------------------------------------------------------------------------
+template <typename varParamType>
+void CHG_BEFORE_NOTIFIER<varParamType>::Notify(const varParamType &, const varParamType &)
+{
+//EVENT_LOOP_SINGLETON::GetInstance().Enqueue(auth, &AUTH_AO::Unauthorize, user);
+if (user->IsAuthorizedBy(&auth))
+    auth.users->Unauthorize(user->GetLogin(), &auth);
+}
+//-----------------------------------------------------------------------------
+template <typename varParamType>
+void CHG_AFTER_NOTIFIER<varParamType>::Notify(const varParamType &, const varParamType &)
+{
+//EVENT_LOOP_SINGLETON::GetInstance().Enqueue(auth, &AUTH_AO::UpdateUserAuthorization, user);
+auth.UpdateUserAuthorization(user);
+}
+//-----------------------------------------------------------------------------
diff --git a/projects/stargazer/plugins/authorization/ao/ao.h b/projects/stargazer/plugins/authorization/ao/ao.h
new file mode 100644 (file)
index 0000000..dbb2993
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+#pragma once
+
+#include "stg/auth.h"
+#include "stg/module_settings.h"
+#include "stg/store.h"
+#include "stg/notifer.h"
+#include "stg/user_ips.h"
+#include "stg/user.h"
+#include "stg/logger.h"
+
+#include <string>
+#include <vector>
+#include <list>
+
+#include <pthread.h>
+
+namespace STG
+{
+struct Users;
+}
+
+class AUTH_AO;
+
+using UserPtr = STG::User*;
+using ConstUserPtr = const STG::User*;
+
+template <typename T>
+class CHG_BEFORE_NOTIFIER : public STG::PropertyNotifierBase<T> {
+public:
+                CHG_BEFORE_NOTIFIER(AUTH_AO & a, UserPtr u)
+                    : user(u), auth(a) {}
+                CHG_BEFORE_NOTIFIER(const CHG_BEFORE_NOTIFIER<T> & rvalue)
+                    : user(rvalue.user), auth(rvalue.auth) {}
+    void        Notify(const T & oldValue, const T & newValue);
+    UserPtr    GetUser() const { return user; }
+
+private:
+    CHG_BEFORE_NOTIFIER<T> & operator=(const CHG_BEFORE_NOTIFIER<T> & rvalue);
+
+    UserPtr        user;
+    const AUTH_AO & auth;
+};
+//-----------------------------------------------------------------------------
+template <typename T>
+class CHG_AFTER_NOTIFIER : public STG::PropertyNotifierBase<T> {
+public:
+                CHG_AFTER_NOTIFIER(AUTH_AO & a, UserPtr u)
+                    : user(u), auth(a) {}
+                CHG_AFTER_NOTIFIER(const CHG_AFTER_NOTIFIER<T> & rvalue)
+                    : user(rvalue.user), auth(rvalue.auth) {}
+    void        Notify(const T & oldValue, const T & newValue);
+    UserPtr    GetUser() const { return user; }
+
+private:
+    CHG_AFTER_NOTIFIER<T> & operator=(const CHG_AFTER_NOTIFIER<T> & rvalue);
+
+    UserPtr        user;
+    const AUTH_AO & auth;
+};
+//-----------------------------------------------------------------------------
+class AUTH_AO : public STG::Auth {
+public:
+    AUTH_AO();
+
+    void                SetUsers(STG::Users * u) override { users = u; }
+
+    int                 Start() override;
+    int                 Stop() override;
+    int                 Reload(const STG::ModuleSettings & /*ms*/) override { return 0; }
+    bool                IsRunning() override { return isRunning; }
+    void                SetSettings(const STG::ModuleSettings &) override {}
+    int                 ParseSettings() override { return 0; }
+    const std::string & GetStrError() const override { return errorStr; }
+    std::string         GetVersion() const override;
+    uint16_t            GetStartPosition() const override { return 30; }
+    uint16_t            GetStopPosition() const override { return 30; }
+
+    int                 SendMessage(const STG::Message & msg, uint32_t ip) const override;
+
+private:
+    AUTH_AO(const AUTH_AO & rvalue);
+    AUTH_AO & operator=(const AUTH_AO & rvalue);
+
+    void                AddUser(UserPtr u);
+    void                DelUser(UserPtr u);
+
+    void                GetUsers();
+    void                SetUserNotifiers(UserPtr u);
+    void                UnSetUserNotifiers(UserPtr u);
+    void                UpdateUserAuthorization(ConstUserPtr u) const;
+
+    mutable std::string errorStr;
+    STG::Users *             users;
+    std::vector<UserPtr> userList;
+    bool                isRunning;
+    STG::ModuleSettings     settings;
+
+    std::list<CHG_BEFORE_NOTIFIER<int> >      BeforeChgAONotifierList;
+    std::list<CHG_AFTER_NOTIFIER<int> >       AfterChgAONotifierList;
+
+    std::list<CHG_BEFORE_NOTIFIER<STG::UserIPs> > BeforeChgIPNotifierList;
+    std::list<CHG_AFTER_NOTIFIER<STG::UserIPs> >  AfterChgIPNotifierList;
+
+    class ADD_USER_NONIFIER: public STG::NotifierBase<UserPtr> {
+    public:
+        explicit ADD_USER_NONIFIER(AUTH_AO & a) : auth(a) {}
+        virtual ~ADD_USER_NONIFIER() {}
+        void Notify(const UserPtr & user) { auth.AddUser(user); }
+
+    private:
+        ADD_USER_NONIFIER(const ADD_USER_NONIFIER & rvalue);
+        ADD_USER_NONIFIER & operator=(const ADD_USER_NONIFIER & rvalue);
+
+        AUTH_AO & auth;
+    } onAddUserNotifier;
+
+    class DEL_USER_NONIFIER: public STG::NotifierBase<UserPtr> {
+    public:
+        explicit DEL_USER_NONIFIER(AUTH_AO & a) : auth(a) {}
+        virtual ~DEL_USER_NONIFIER() {}
+        void Notify(const UserPtr & user) { auth.DelUser(user); }
+
+    private:
+        DEL_USER_NONIFIER(const DEL_USER_NONIFIER & rvalue);
+        DEL_USER_NONIFIER & operator=(const DEL_USER_NONIFIER & rvalue);
+
+        AUTH_AO & auth;
+    } onDelUserNotifier;
+
+    STG::PluginLogger logger;
+
+    friend class CHG_BEFORE_NOTIFIER<int>;
+    friend class CHG_AFTER_NOTIFIER<int>;
+    friend class CHG_BEFORE_NOTIFIER<STG::UserIPs>;
+    friend class CHG_AFTER_NOTIFIER<STG::UserIPs>;
+
+};
diff --git a/projects/stargazer/plugins/authorization/inetaccess/inetaccess.cpp b/projects/stargazer/plugins/authorization/inetaccess/inetaccess.cpp
new file mode 100644 (file)
index 0000000..b824d59
--- /dev/null
@@ -0,0 +1,1702 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include "inetaccess.h"
+
+#include "stg/common.h"
+#include "stg/locker.h"
+#include "stg/tariff.h"
+#include "stg/settings.h"
+
+#include <algorithm>
+#include <csignal>
+#include <cstdlib>
+#include <cstdio> // snprintf
+#include <cerrno>
+#include <cmath>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <unistd.h> // close
+
+#define IA_PROTO_VER    (6)
+
+extern volatile time_t stgTime;
+
+extern "C" STG::Plugin* GetPlugin()
+{
+    static AUTH_IA plugin;
+    return &plugin;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+AUTH_IA_SETTINGS::AUTH_IA_SETTINGS()
+    : userDelay(0),
+      userTimeout(0),
+      port(0),
+      freeMbShowType(freeMbCash),
+      logProtocolErrors(false)
+{
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA_SETTINGS::ParseSettings(const STG::ModuleSettings & s)
+{
+int p;
+STG::ParamValue pv;
+std::vector<STG::ParamValue>::const_iterator pvi;
+///////////////////////////
+pv.param = "Port";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end() || pvi->value.empty())
+    {
+    errorStr = "Parameter \'Port\' not found.";
+    printfd(__FILE__, "Parameter 'Port' not found\n");
+    return -1;
+    }
+if (ParseIntInRange(pvi->value[0], 2, 65535, &p))
+    {
+    errorStr = "Cannot parse parameter \'Port\': " + errorStr;
+    printfd(__FILE__, "Cannot parse parameter 'Port'\n");
+    return -1;
+    }
+port = static_cast<uint16_t>(p);
+///////////////////////////
+pv.param = "UserDelay";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end() || pvi->value.empty())
+    {
+    errorStr = "Parameter \'UserDelay\' not found.";
+    printfd(__FILE__, "Parameter 'UserDelay' not found\n");
+    return -1;
+    }
+
+if (ParseIntInRange(pvi->value[0], 5, 600, &userDelay))
+    {
+    errorStr = "Cannot parse parameter \'UserDelay\': " + errorStr;
+    printfd(__FILE__, "Cannot parse parameter 'UserDelay'\n");
+    return -1;
+    }
+///////////////////////////
+pv.param = "UserTimeout";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end() || pvi->value.empty())
+    {
+    errorStr = "Parameter \'UserTimeout\' not found.";
+    printfd(__FILE__, "Parameter 'UserTimeout' not found\n");
+    return -1;
+    }
+
+if (ParseIntInRange(pvi->value[0], 15, 1200, &userTimeout))
+    {
+    errorStr = "Cannot parse parameter \'UserTimeout\': " + errorStr;
+    printfd(__FILE__, "Cannot parse parameter 'UserTimeout'\n");
+    return -1;
+    }
+///////////////////////////
+pv.param = "LogProtocolErrors";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end() || pvi->value.empty())
+    logProtocolErrors = false;
+else if (ParseYesNo(pvi->value[0], &logProtocolErrors))
+    {
+    errorStr = "Cannot parse parameter \'LogProtocolErrors\': " + errorStr;
+    printfd(__FILE__, "Cannot parse parameter 'LogProtocolErrors'\n");
+    return -1;
+    }
+/////////////////////////////////////////////////////////////
+std::string freeMbType;
+int n = 0;
+pv.param = "FreeMb";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end() || pvi->value.empty())
+    {
+    errorStr = "Parameter \'FreeMb\' not found.";
+    printfd(__FILE__, "Parameter 'FreeMb' not found\n");
+    return -1;
+    }
+freeMbType = pvi->value[0];
+
+if (strcasecmp(freeMbType.c_str(), "cash") == 0)
+    {
+    freeMbShowType = freeMbCash;
+    }
+else if (strcasecmp(freeMbType.c_str(), "none") == 0)
+    {
+    freeMbShowType = freeMbNone;
+    }
+else if (!str2x(freeMbType.c_str(), n))
+    {
+    if (n < 0 || n >= DIR_NUM)
+        {
+        errorStr = "Incorrect parameter \'" + freeMbType + "\'.";
+        printfd(__FILE__, "%s\n", errorStr.c_str());
+        return -1;
+        }
+    freeMbShowType = (FREEMB)(freeMb0 + n);
+    }
+else
+    {
+    errorStr = "Incorrect parameter \'" + freeMbType + "\'.";
+    printfd(__FILE__, "%s\n", errorStr.c_str());
+    return -1;
+    }
+/////////////////////////////////////////////////////////////
+return 0;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+#ifdef IA_PHASE_DEBUG
+IA_PHASE::IA_PHASE()
+    : phase(1),
+      flog(NULL)
+{
+gettimeofday(&phaseTime, NULL);
+}
+#else
+IA_PHASE::IA_PHASE()
+    : phase(1)
+{
+gettimeofday(&phaseTime, NULL);
+}
+#endif
+//-----------------------------------------------------------------------------
+IA_PHASE::~IA_PHASE()
+{
+#ifdef IA_PHASE_DEBUG
+flog = fopen(log.c_str(), "at");
+if (flog)
+    {
+    fprintf(flog, "IA %s D\n", login.c_str());
+    fclose(flog);
+    }
+#endif
+}
+//-----------------------------------------------------------------------------
+#ifdef IA_PHASE_DEBUG
+void IA_PHASE::SetLogFileName(const string & logFileName)
+{
+log = logFileName + ".ia.log";
+}
+//-----------------------------------------------------------------------------
+void IA_PHASE::SetUserLogin(const string & login)
+{
+IA_PHASE::login = login;
+}
+//-----------------------------------------------------------------------------
+void IA_PHASE::WritePhaseChange(int newPhase)
+{
+UTIME newPhaseTime;
+gettimeofday(&newPhaseTime, NULL);
+flog = fopen(log.c_str(), "at");
+if (flog)
+    {
+    string action = newPhase == phase ? "U" : "C";
+    double delta = newPhaseTime.GetSec() - phaseTime.GetSec();
+    delta += (newPhaseTime.GetUSec() - phaseTime.GetUSec()) * 1.0e-6;
+    fprintf(flog, "IA %s %s oldPhase = %d, newPhase = %d. dt = %.6f\n",
+            login.c_str(),
+            action.c_str(),
+            phase,
+            newPhase,
+            delta);
+    fclose(flog);
+    }
+}
+#endif
+//-----------------------------------------------------------------------------
+void IA_PHASE::SetPhase1()
+{
+#ifdef IA_PHASE_DEBUG
+WritePhaseChange(1);
+#endif
+phase = 1;
+gettimeofday(&phaseTime, NULL);
+}
+//-----------------------------------------------------------------------------
+void IA_PHASE::SetPhase2()
+{
+#ifdef IA_PHASE_DEBUG
+WritePhaseChange(2);
+#endif
+phase = 2;
+gettimeofday(&phaseTime, NULL);
+}
+//-----------------------------------------------------------------------------
+void IA_PHASE::SetPhase3()
+{
+#ifdef IA_PHASE_DEBUG
+WritePhaseChange(3);
+#endif
+phase = 3;
+gettimeofday(&phaseTime, NULL);
+}
+//-----------------------------------------------------------------------------
+void IA_PHASE::SetPhase4()
+{
+#ifdef IA_PHASE_DEBUG
+WritePhaseChange(4);
+#endif
+phase = 4;
+gettimeofday(&phaseTime, NULL);
+}
+//-----------------------------------------------------------------------------
+int IA_PHASE::GetPhase() const
+{
+return phase;
+}
+//-----------------------------------------------------------------------------
+void IA_PHASE::UpdateTime()
+{
+#ifdef IA_PHASE_DEBUG
+WritePhaseChange(phase);
+#endif
+gettimeofday(&phaseTime, NULL);
+}
+//-----------------------------------------------------------------------------
+const UTIME & IA_PHASE::GetTime() const
+{
+return phaseTime;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+AUTH_IA::AUTH_IA()
+    : nonstop(false),
+      isRunningRun(false),
+      isRunningRunTimeouter(false),
+      users(NULL),
+      stgSettings(NULL),
+      listenSocket(-1),
+      enabledDirs(0xFFffFFff),
+      onDelUserNotifier(*this),
+      logger(STG::PluginLogger::get("auth_ia"))
+{
+InitContext("pr7Hhen", 7, &ctxS);
+
+pthread_mutexattr_t attr;
+pthread_mutexattr_init(&attr);
+pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+pthread_mutex_init(&mutex, &attr);
+
+memset(&connSynAck6, 0, sizeof(CONN_SYN_ACK_6));
+memset(&connSynAck8, 0, sizeof(CONN_SYN_ACK_8));
+memset(&disconnSynAck6, 0, sizeof(DISCONN_SYN_ACK_6));
+memset(&disconnSynAck8, 0, sizeof(DISCONN_SYN_ACK_8));
+memset(&aliveSyn6, 0, sizeof(ALIVE_SYN_6));
+memset(&aliveSyn8, 0, sizeof(ALIVE_SYN_8));
+memset(&fin6, 0, sizeof(FIN_6));
+memset(&fin8, 0, sizeof(FIN_8));
+
+printfd(__FILE__, "sizeof(CONN_SYN_6) = %d %d\n",           sizeof(CONN_SYN_6),     Min8(sizeof(CONN_SYN_6)));
+printfd(__FILE__, "sizeof(CONN_SYN_8) = %d %d\n",           sizeof(CONN_SYN_8),     Min8(sizeof(CONN_SYN_8)));
+printfd(__FILE__, "sizeof(CONN_SYN_ACK_6) = %d %d\n",       sizeof(CONN_SYN_ACK_6), Min8(sizeof(CONN_SYN_ACK_6)));
+printfd(__FILE__, "sizeof(CONN_SYN_ACK_8) = %d %d\n",       sizeof(CONN_SYN_ACK_8), Min8(sizeof(CONN_SYN_ACK_8)));
+printfd(__FILE__, "sizeof(CONN_ACK_6) = %d %d\n",           sizeof(CONN_ACK_6),     Min8(sizeof(CONN_ACK_6)));
+printfd(__FILE__, "sizeof(ALIVE_SYN_6) = %d %d\n",          sizeof(ALIVE_SYN_6),    Min8(sizeof(ALIVE_SYN_6)));
+printfd(__FILE__, "sizeof(ALIVE_SYN_8) = %d %d\n",          sizeof(ALIVE_SYN_8),    Min8(sizeof(ALIVE_SYN_8)));
+printfd(__FILE__, "sizeof(ALIVE_ACK_6) = %d %d\n",          sizeof(ALIVE_ACK_6),    Min8(sizeof(ALIVE_ACK_6)));
+printfd(__FILE__, "sizeof(DISCONN_SYN_6) = %d %d\n",        sizeof(DISCONN_SYN_6),  Min8(sizeof(DISCONN_SYN_6)));
+printfd(__FILE__, "sizeof(DISCONN_SYN_ACK_6) = %d %d\n",    sizeof(DISCONN_SYN_ACK_6), Min8(sizeof(DISCONN_SYN_ACK_6)));
+printfd(__FILE__, "sizeof(DISCONN_SYN_ACK_8) = %d %d\n",    sizeof(DISCONN_SYN_ACK_8), Min8(sizeof(DISCONN_SYN_ACK_8)));
+printfd(__FILE__, "sizeof(DISCONN_ACK_6) = %d %d\n",        sizeof(DISCONN_ACK_6),  Min8(sizeof(DISCONN_ACK_6)));
+printfd(__FILE__, "sizeof(FIN_6) = %d %d\n",                sizeof(FIN_6),          Min8(sizeof(FIN_6)));
+printfd(__FILE__, "sizeof(FIN_8) = %d %d\n",                sizeof(FIN_8),          Min8(sizeof(FIN_8)));
+printfd(__FILE__, "sizeof(ERR) = %d %d\n",                  sizeof(ERR),            Min8(sizeof(ERR)));
+printfd(__FILE__, "sizeof(INFO_6) = %d %d\n",               sizeof(INFO_6),         Min8(sizeof(INFO_6)));
+printfd(__FILE__, "sizeof(INFO_7) = %d %d\n",               sizeof(INFO_7),         Min8(sizeof(INFO_7)));
+printfd(__FILE__, "sizeof(INFO_8) = %d %d\n",               sizeof(INFO_8),         Min8(sizeof(INFO_8)));
+
+packetTypes["CONN_SYN"] = CONN_SYN_N;
+packetTypes["CONN_SYN_ACK"] = CONN_SYN_ACK_N;
+packetTypes["CONN_ACK"] = CONN_ACK_N;
+packetTypes["ALIVE_SYN"] = ALIVE_SYN_N;
+packetTypes["ALIVE_ACK"] = ALIVE_ACK_N;
+packetTypes["DISCONN_SYN"] = DISCONN_SYN_N;
+packetTypes["DISCONN_SYN_ACK"] = DISCONN_SYN_ACK_N;
+packetTypes["DISCONN_ACK"] = DISCONN_ACK_N;
+packetTypes["FIN"] = FIN_N;
+packetTypes["ERR"] = ERROR_N;
+}
+//-----------------------------------------------------------------------------
+AUTH_IA::~AUTH_IA()
+{
+pthread_mutex_destroy(&mutex);
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Start()
+{
+users->AddNotifierUserDel(&onDelUserNotifier);
+nonstop = true;
+
+if (PrepareNet())
+    {
+    return -1;
+    }
+
+if (!isRunningRun)
+    {
+    if (pthread_create(&recvThread, NULL, Run, this))
+        {
+        errorStr = "Cannot create thread.";
+        printfd(__FILE__, "Cannot create recv thread\n");
+        logger("Cannot create recv thread.");
+        return -1;
+        }
+    }
+
+if (!isRunningRunTimeouter)
+    {
+    if (pthread_create(&timeouterThread, NULL, RunTimeouter, this))
+        {
+        errorStr = "Cannot create thread.";
+        printfd(__FILE__, "Cannot create timeouter thread\n");
+        logger("Cannot create timeouter thread.");
+        return -1;
+        }
+    }
+errorStr = "";
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Stop()
+{
+if (!IsRunning())
+    return 0;
+
+nonstop = false;
+
+std::for_each(
+        ip2user.begin(),
+        ip2user.end(),
+        UnauthorizeUser(this)
+        );
+
+if (isRunningRun)
+    {
+    //5 seconds to thread stops itself
+    for (int i = 0; i < 25 && isRunningRun; i++)
+        {
+        struct timespec ts = {0, 200000000};
+        nanosleep(&ts, NULL);
+        }
+    }
+
+FinalizeNet();
+
+if (isRunningRunTimeouter)
+    {
+    //5 seconds to thread stops itself
+    for (int i = 0; i < 25 && isRunningRunTimeouter; i++)
+        {
+        struct timespec ts = {0, 200000000};
+        nanosleep(&ts, NULL);
+        }
+    }
+
+users->DelNotifierUserDel(&onDelUserNotifier);
+
+if (isRunningRun || isRunningRunTimeouter)
+    return -1;
+
+printfd(__FILE__, "AUTH_IA::Stoped successfully.\n");
+return 0;
+}
+//-----------------------------------------------------------------------------
+void * AUTH_IA::Run(void * d)
+{
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+AUTH_IA * ia = static_cast<AUTH_IA *>(d);
+
+ia->isRunningRun = true;
+
+char buffer[512];
+
+time_t touchTime = stgTime - MONITOR_TIME_DELAY_SEC;
+
+while (ia->nonstop)
+    {
+    ia->RecvData(buffer, sizeof(buffer));
+    if ((touchTime + MONITOR_TIME_DELAY_SEC <= stgTime) && ia->stgSettings->GetMonitoring())
+        {
+        touchTime = stgTime;
+        std::string monFile = ia->stgSettings->GetMonitorDir() + "/inetaccess_r";
+        TouchFile(monFile);
+        }
+    }
+
+ia->isRunningRun = false;
+return NULL;
+}
+//-----------------------------------------------------------------------------
+void * AUTH_IA::RunTimeouter(void * d)
+{
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+AUTH_IA * ia = static_cast<AUTH_IA *>(d);
+
+ia->isRunningRunTimeouter = true;
+
+int a = -1;
+std::string monFile = ia->stgSettings->GetMonitorDir() + "/inetaccess_t";
+while (ia->nonstop)
+    {
+    struct timespec ts = {0, 20000000};
+    nanosleep(&ts, NULL);
+    ia->Timeouter();
+    // TODO change counter to timer and MONITOR_TIME_DELAY_SEC
+    if (++a % (50 * 60) == 0 && ia->stgSettings->GetMonitoring())
+        {
+        TouchFile(monFile);
+        }
+    }
+
+ia->isRunningRunTimeouter = false;
+return NULL;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::ParseSettings()
+{
+int ret = iaSettings.ParseSettings(settings);
+if (ret)
+    errorStr = iaSettings.GetStrError();
+return ret;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Reload(const STG::ModuleSettings & ms)
+{
+AUTH_IA_SETTINGS newIaSettings;
+if (newIaSettings.ParseSettings(ms))
+    {
+    printfd(__FILE__, "AUTH_IA::Reload() - Failed to reload InetAccess.\n");
+    logger("AUTH_IA: Cannot reload InetAccess. Errors found.");
+    return -1;
+    }
+
+printfd(__FILE__, "AUTH_IA::Reload() -  Reloaded InetAccess successfully.\n");
+logger("AUTH_IA: Reloaded InetAccess successfully.");
+iaSettings = newIaSettings;
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::PrepareNet()
+{
+struct sockaddr_in listenAddr;
+
+listenSocket = socket(AF_INET, SOCK_DGRAM, 0);
+
+if (listenSocket < 0)
+    {
+    errorStr = "Cannot create socket.";
+    logger("Cannot create a socket: %s", strerror(errno));
+    return -1;
+    }
+
+listenAddr.sin_family = AF_INET;
+listenAddr.sin_port = htons(static_cast<uint16_t>(iaSettings.GetUserPort()));
+listenAddr.sin_addr.s_addr = inet_addr("0.0.0.0");
+
+if (bind(listenSocket, (struct sockaddr*)&listenAddr, sizeof(listenAddr)) < 0)
+    {
+    errorStr = "AUTH_IA: Bind failed.";
+    logger("Cannot bind the socket: %s", strerror(errno));
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::FinalizeNet()
+{
+close(listenSocket);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::RecvData(char * buffer, int bufferSize)
+{
+if (!WaitPackets(listenSocket)) // Timeout
+    {
+    return 0;
+    }
+
+struct sockaddr_in outerAddr;
+socklen_t outerAddrLen(sizeof(outerAddr));
+ssize_t dataLen = recvfrom(listenSocket, buffer, bufferSize, 0, (struct sockaddr *)&outerAddr, &outerAddrLen);
+
+if (!dataLen) // EOF
+    {
+    return 0;
+    }
+
+if (dataLen <= 0) // Error
+    {
+    if (errno != EINTR)
+        {
+        printfd(__FILE__, "recvfrom res=%d, error: '%s'\n", dataLen, strerror(errno));
+        logger("recvfrom error: %s", strerror(errno));
+        return -1;
+        }
+    return 0;
+    }
+
+if (dataLen > 256)
+    return -1;
+
+uint32_t sip = outerAddr.sin_addr.s_addr;
+uint16_t sport = htons(outerAddr.sin_port);
+
+int protoVer;
+if (CheckHeader(buffer, sip, &protoVer))
+    return -1;
+
+char login[PASSWD_LEN];  //TODO why PASSWD_LEN ?
+memset(login, 0, PASSWD_LEN);
+
+DecryptString(login, buffer + 8, PASSWD_LEN, &ctxS);
+
+UserPtr user;
+if (users->FindByName(login, &user))
+    {
+    logger("User's connect failed: user '%s' not found. IP %s",
+           login,
+           inet_ntostring(sip).c_str());
+    printfd(__FILE__, "User '%s' NOT found!\n", login);
+    SendError(sip, sport, protoVer, IconvString("Неправильный логин.", "utf8", "koi8-ru"));
+    return -1;
+    }
+
+printfd(__FILE__, "User '%s' FOUND!\n", user->GetLogin().c_str());
+
+if (user->GetProperties().disabled.Get())
+    {
+    logger("Cannont authorize '%s', user is disabled.", login);
+    SendError(sip, sport, protoVer, IconvString("Учетная запись заблокирована.", "utf8", "koi8-ru"));
+    return 0;
+    }
+
+if (user->GetProperties().passive.Get())
+    {
+    logger("Cannont authorize '%s', user is passive.", login);
+    SendError(sip, sport, protoVer, IconvString("Учетная запись заморожена.", "utf8", "koi8-ru"));
+    return 0;
+    }
+
+if (!user->GetProperties().ips.Get().find(sip))
+    {
+    printfd(__FILE__, "User %s. IP address is incorrect. IP %s\n",
+            user->GetLogin().c_str(), inet_ntostring(sip).c_str());
+    logger("User %s. IP address is incorrect. IP %s",
+           user->GetLogin().c_str(), inet_ntostring(sip).c_str());
+    SendError(sip, sport, protoVer, IconvString("Пользователь не опознан. Проверьте IP-адрес.", "utf8", "koi8-ru"));
+    return 0;
+    }
+
+return PacketProcessor(buffer, dataLen, sip, sport, protoVer, user);
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::CheckHeader(const char * buffer, uint32_t sip, int * protoVer)
+{
+if (strncmp(IA_ID, buffer, strlen(IA_ID)) != 0)
+    {
+    printfd(__FILE__, "update needed - IA_ID\n");
+    if (iaSettings.LogProtocolErrors())
+        logger("IP: %s. Header: invalid packed signature.", inet_ntostring(sip).c_str());
+    return -1;
+    }
+
+if (buffer[6] != 0) //proto[0] shoud be 0
+    {
+    printfd(__FILE__, "update needed - PROTO major: %d\n", buffer[6]);
+    if (iaSettings.LogProtocolErrors())
+        logger("IP: %s. Header: invalid protocol major version: %d.", inet_ntostring(sip).c_str(), buffer[6]);
+    return -1;
+    }
+
+if (buffer[7] < 6)
+    {
+    // need update
+    printfd(__FILE__, "update needed - PROTO minor: %d\n", buffer[7]);
+    if (iaSettings.LogProtocolErrors())
+        logger("IP: %s. Header: invalid protocol minor version: %d.", inet_ntostring(sip).c_str(), buffer[7]);
+    return -1;
+    }
+else
+    {
+    *protoVer = buffer[7];
+    }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Timeouter()
+{
+STG_LOCKER lock(&mutex);
+
+std::map<uint32_t, IA_USER>::iterator it;
+it = ip2user.begin();
+
+while (it != ip2user.end())
+    {
+    uint32_t sip = it->first;
+
+    static UTIME currTime;
+    gettimeofday(&currTime, NULL);
+
+    if ((it->second.phase.GetPhase() == 2)
+        && (currTime - it->second.phase.GetTime()) > iaSettings.GetUserDelay())
+        {
+        if (iaSettings.LogProtocolErrors())
+            logger("User '%s'. Protocol version: %d. Phase 2: connect request timeout (%f > %d).", it->second.login.c_str(), it->second.protoVer, (currTime - it->second.phase.GetTime()).AsDouble(), iaSettings.GetUserDelay().GetSec());
+        it->second.phase.SetPhase1();
+        printfd(__FILE__, "Phase changed from 2 to 1. Reason: timeout\n");
+        ip2user.erase(it++);
+        continue;
+        }
+
+    if (it->second.phase.GetPhase() == 3)
+        {
+        if (!it->second.messagesToSend.empty())
+            {
+            if (it->second.protoVer == 6)
+                RealSendMessage6(*it->second.messagesToSend.begin(), sip, it->second);
+
+            if (it->second.protoVer == 7)
+                RealSendMessage7(*it->second.messagesToSend.begin(), sip, it->second);
+
+            if (it->second.protoVer == 8)
+                RealSendMessage8(*it->second.messagesToSend.begin(), sip, it->second);
+
+            it->second.messagesToSend.erase(it->second.messagesToSend.begin());
+            }
+
+        if((currTime - it->second.lastSendAlive) > iaSettings.GetUserDelay())
+            {
+            switch (it->second.protoVer)
+                {
+                case 6:
+                    Send_ALIVE_SYN_6(&(it->second), sip);
+                    break;
+                case 7:
+                    Send_ALIVE_SYN_7(&(it->second), sip);
+                    break;
+                case 8:
+                    Send_ALIVE_SYN_8(&(it->second), sip);
+                    break;
+                }
+
+            gettimeofday(&it->second.lastSendAlive, NULL);
+            }
+
+        if ((currTime - it->second.phase.GetTime()) > iaSettings.GetUserTimeout())
+            {
+            if (iaSettings.LogProtocolErrors())
+                logger("User '%s'. Protocol version: %d. Phase 3: alive timeout (%f > %d).", it->second.login.c_str(), it->second.protoVer, (currTime - it->second.phase.GetTime()).AsDouble(), iaSettings.GetUserTimeout().GetSec());
+            users->Unauthorize(it->second.user->GetLogin(), this);
+            ip2user.erase(it++);
+            continue;
+            }
+        }
+
+    if ((it->second.phase.GetPhase() == 4)
+        && ((currTime - it->second.phase.GetTime()) > iaSettings.GetUserDelay()))
+        {
+        if (iaSettings.LogProtocolErrors())
+            logger("User '%s'. Protocol version: %d. Phase 4: disconnect request timeout (%f > %d).", it->second.login.c_str(), it->second.protoVer, (currTime - it->second.phase.GetTime()).AsDouble(), iaSettings.GetUserDelay().GetSec());
+        it->second.phase.SetPhase3();
+        printfd(__FILE__, "Phase changed from 4 to 3. Reason: timeout\n");
+        }
+
+    ++it;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::PacketProcessor(void * buff, size_t dataLen, uint32_t sip, uint16_t sport, int protoVer, UserPtr user)
+{
+std::string login(user->GetLogin());
+const size_t offset = LOGIN_LEN + 2 + 6; // LOGIN_LEN + sizeOfMagic + sizeOfVer;
+
+STG_LOCKER lock(&mutex);
+std::map<uint32_t, IA_USER>::iterator it(ip2user.find(sip));
+
+if (it == ip2user.end())
+    {
+    UserPtr userPtr;
+    if (!users->FindByIPIdx(sip, &userPtr))
+        {
+        if (userPtr->GetID() != user->GetID())
+            {
+            printfd(__FILE__, "IP address already in use by user '%s'. IP %s, login: '%s'\n",
+                    userPtr->GetLogin().c_str(),
+                    inet_ntostring(sip).c_str(),
+                   login.c_str());
+            logger("IP address is already in use by user '%s'. IP %s, login: '%s'",
+                   userPtr->GetLogin().c_str(),
+                   inet_ntostring(sip).c_str(),
+                   login.c_str());
+            SendError(sip, sport, protoVer, IconvString("IP-адрес уже сипользуется.", "utf8", "koi8-ru"));
+            return 0;
+            }
+        }
+
+    printfd(__FILE__, "Add new user '%s' from ip %s\n",
+            login.c_str(), inet_ntostring(sip).c_str());
+    std::pair<std::map<uint32_t, IA_USER>::iterator, bool> res;
+    res = ip2user.insert(std::make_pair(sip, IA_USER(login, user, sport, protoVer)));
+    it = res.first;
+    #ifdef IA_PHASE_DEBUG
+    it->second.phase.SetLogFileName(stgSettings->GetLogFileName());
+    it->second.phase.SetUserLogin(login);
+    #endif
+    }
+else if (user->GetID() != it->second.user->GetID())
+    {
+    printfd(__FILE__, "IP address already in use by user '%s'. IP %s, login: '%s'\n",
+            it->second.user->GetLogin().c_str(),
+            inet_ntostring(sip).c_str(),
+            user->GetLogin().c_str());
+    logger("IP address is already in use by user '%s'. IP %s, login: '%s'",
+           it->second.user->GetLogin().c_str(),
+           inet_ntostring(sip).c_str(),
+           user->GetLogin().c_str());
+    SendError(sip, sport, protoVer, IconvString("IP-адрес уже используется.", "utf8", "koi8-ru"));
+    return 0;
+    }
+
+IA_USER * iaUser = &(it->second);
+
+if (iaUser->password != user->GetProperties().password.Get())
+    {
+    const std::string & password = user->GetProperties().password.Get();
+    InitContext(password.c_str(), password.length(), &iaUser->ctx);
+    iaUser->password = user->GetProperties().password.Get();
+    }
+
+DecryptString(static_cast<char *>(buff) + offset, static_cast<char *>(buff) + offset, (dataLen - offset), &iaUser->ctx);
+
+char packetName[IA_MAX_TYPE_LEN];
+strncpy(packetName,  static_cast<char *>(buff) + offset + 4, IA_MAX_TYPE_LEN);
+packetName[IA_MAX_TYPE_LEN - 1] = 0;
+
+std::map<std::string, int>::iterator pi(packetTypes.find(packetName));
+if (pi == packetTypes.end())
+    {
+    SendError(sip, sport, protoVer, IconvString("Неправильный логин или пароль.", "utf8", "koi8-ru"));
+    printfd(__FILE__, "Login or password is wrong!\n");
+    logger("User's connect failed. User: '%s', ip %s. Wrong login or password",
+           login.c_str(),
+           inet_ntostring(sip).c_str());
+    ip2user.erase(it);
+    return 0;
+    }
+
+if (user->IsAuthorizedBy(this) && user->GetCurrIP() != sip)
+    {
+    printfd(__FILE__, "Login %s already in use from ip %s. IP %s\n",
+            login.c_str(), inet_ntostring(user->GetCurrIP()).c_str(),
+            inet_ntostring(sip).c_str());
+    logger("Login '%s' is already in use from ip %s. IP %s",
+           login.c_str(),
+           inet_ntostring(user->GetCurrIP()).c_str(),
+           inet_ntostring(sip).c_str());
+    SendError(sip, sport, protoVer, IconvString("Логин уже используется.", "utf8", "koi8-ru"));
+    ip2user.erase(it);
+    return 0;
+    }
+
+switch (pi->second)
+    {
+    case CONN_SYN_N:
+        switch (protoVer)
+            {
+            case 6:
+                if (Process_CONN_SYN_6(static_cast<CONN_SYN_6 *>(buff), &(it->second), sip))
+                    return -1;
+                return Send_CONN_SYN_ACK_6(iaUser, sip);
+            case 7:
+                if (Process_CONN_SYN_7(static_cast<CONN_SYN_7 *>(buff), &(it->second), sip))
+                    return -1;
+                return Send_CONN_SYN_ACK_7(iaUser, sip);
+            case 8:
+                if (Process_CONN_SYN_8(static_cast<CONN_SYN_8 *>(buff), &(it->second), sip))
+                    return -1;
+                return Send_CONN_SYN_ACK_8(iaUser, sip);
+            }
+        break;
+
+    case CONN_ACK_N:
+        switch (protoVer)
+            {
+            case 6:
+                if (Process_CONN_ACK_6(static_cast<CONN_ACK_6 *>(buff), iaUser, sip))
+                    return -1;
+                return Send_ALIVE_SYN_6(iaUser, sip);
+            case 7:
+                if (Process_CONN_ACK_7(static_cast<CONN_ACK_6 *>(buff), iaUser, sip))
+                    return -1;
+                return Send_ALIVE_SYN_7(iaUser, sip);
+            case 8:
+                if (Process_CONN_ACK_8(static_cast<CONN_ACK_8 *>(buff), iaUser, sip))
+                    return -1;
+                return Send_ALIVE_SYN_8(iaUser, sip);
+            }
+        break;
+
+    case ALIVE_ACK_N:
+        switch (protoVer)
+            {
+            case 6:
+                return Process_ALIVE_ACK_6(static_cast<ALIVE_ACK_6 *>(buff), iaUser, sip);
+            case 7:
+                return Process_ALIVE_ACK_7(static_cast<ALIVE_ACK_6 *>(buff), iaUser, sip);
+            case 8:
+                return Process_ALIVE_ACK_8(static_cast<ALIVE_ACK_8 *>(buff), iaUser, sip);
+            }
+        break;
+
+    case DISCONN_SYN_N:
+        switch (protoVer)
+            {
+            case 6:
+                if (Process_DISCONN_SYN_6(static_cast<DISCONN_SYN_6 *>(buff), iaUser, sip))
+                    return -1;
+                return Send_DISCONN_SYN_ACK_6(iaUser, sip);
+            case 7:
+                if (Process_DISCONN_SYN_7(static_cast<DISCONN_SYN_6 *>(buff), iaUser, sip))
+                    return -1;
+                return Send_DISCONN_SYN_ACK_7(iaUser, sip);
+            case 8:
+                if (Process_DISCONN_SYN_8(static_cast<DISCONN_SYN_8 *>(buff), iaUser, sip))
+                    return -1;
+                return Send_DISCONN_SYN_ACK_8(iaUser, sip);
+            }
+        break;
+
+    case DISCONN_ACK_N:
+        switch (protoVer)
+            {
+            case 6:
+                if (Process_DISCONN_ACK_6(static_cast<DISCONN_ACK_6 *>(buff), iaUser, sip, it))
+                    return -1;
+                return Send_FIN_6(iaUser, sip, it);
+            case 7:
+                if (Process_DISCONN_ACK_7(static_cast<DISCONN_ACK_6 *>(buff), iaUser, sip, it))
+                    return -1;
+                return Send_FIN_7(iaUser, sip, it);
+            case 8:
+                if (Process_DISCONN_ACK_8(static_cast<DISCONN_ACK_8 *>(buff), iaUser, sip, it))
+                    return -1;
+                return Send_FIN_8(iaUser, sip, it);
+            }
+        break;
+    }
+
+return -1;
+}
+//-----------------------------------------------------------------------------
+void AUTH_IA::DelUser(UserPtr u)
+{
+
+uint32_t ip = u->GetCurrIP();
+
+if (!ip)
+    return;
+
+std::map<uint32_t, IA_USER>::iterator it;
+
+STG_LOCKER lock(&mutex);
+it = ip2user.find(ip);
+if (it == ip2user.end())
+    {
+    //Nothing to delete
+    printfd(__FILE__, "Nothing to delete\n");
+    return;
+    }
+
+if (it->second.user == u)
+    {
+    printfd(__FILE__, "User removed!\n");
+    users->Unauthorize(u->GetLogin(), this);
+    ip2user.erase(it);
+    }
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::SendError(uint32_t ip, uint16_t port, int protoVer, const std::string & text)
+{
+struct sockaddr_in sendAddr;
+ssize_t res;
+switch (protoVer)
+    {
+    case 6:
+    case 7:
+        ERR err;
+        memset(&err, 0, sizeof(ERR));
+
+        sendAddr.sin_family = AF_INET;
+        sendAddr.sin_port = htons(port);
+        sendAddr.sin_addr.s_addr = ip;
+
+        err.len = 1;
+        strncpy((char*)err.type, "ERR", 16);
+        strncpy((char*)err.text, text.c_str(), MAX_MSG_LEN);
+
+        #ifdef ARCH_BE
+        SwapBytes(err.len);
+        #endif
+
+        res = sendto(listenSocket, &err, sizeof(err), 0, (struct sockaddr*)&sendAddr, sizeof(sendAddr));
+        printfd(__FILE__, "SendError %d bytes sent\n", res);
+        break;
+
+    case 8:
+        ERR_8 err8;
+        memset(&err8, 0, sizeof(ERR_8));
+
+        sendAddr.sin_family = AF_INET;
+        sendAddr.sin_port = htons(port);
+        sendAddr.sin_addr.s_addr = ip;
+
+        err8.len = 256;
+        strncpy((char*)err8.type, "ERR", 16);
+        strncpy((char*)err8.text, text.c_str(), MAX_MSG_LEN);
+
+        #ifdef ARCH_BE
+        SwapBytes(err8.len);
+        #endif
+
+        res = sendto(listenSocket, &err8, sizeof(err8), 0, (struct sockaddr*)&sendAddr, sizeof(sendAddr));
+        printfd(__FILE__, "SendError_8 %d bytes sent\n", res);
+        break;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Send(uint32_t ip, uint16_t port, const char * buffer, size_t len)
+{
+struct sockaddr_in sendAddr;
+
+sendAddr.sin_family = AF_INET;
+sendAddr.sin_port = htons(port);
+sendAddr.sin_addr.s_addr = ip;
+
+if (sendto(listenSocket, buffer, len, 0, (struct sockaddr*)&sendAddr, sizeof(sendAddr)) == static_cast<ssize_t>(len))
+    return 0;
+
+return -1;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::SendMessage(const STG::Message & msg, uint32_t ip) const
+{
+printfd(__FILE__, "SendMessage userIP=%s\n", inet_ntostring(ip).c_str());
+
+std::map<uint32_t, IA_USER>::iterator it;
+
+STG_LOCKER lock(&mutex);
+it = ip2user.find(ip);
+if (it == ip2user.end())
+    {
+    errorStr = "Unknown user.";
+    return -1;
+    }
+it->second.messagesToSend.push_back(msg);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::RealSendMessage6(const STG::Message & msg, uint32_t ip, IA_USER & user)
+{
+printfd(__FILE__, "RealSendMessage 6 user=%s\n", user.login.c_str());
+
+INFO_6 info;
+memset(&info, 0, sizeof(INFO_6));
+
+info.len = 256;
+strncpy((char*)info.type, "INFO", 16);
+info.infoType = 'I';
+strncpy((char*)info.text, msg.text.c_str(), 235);
+info.text[234] = 0;
+
+size_t len = info.len;
+#ifdef ARCH_BE
+SwapBytes(info.len);
+#endif
+
+char buffer[256];
+memcpy(buffer, &info, sizeof(INFO_6));
+EncryptString(buffer, buffer, len, &user.ctx);
+return Send(ip, iaSettings.GetUserPort(), buffer, len);
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::RealSendMessage7(const STG::Message & msg, uint32_t ip, IA_USER & user)
+{
+printfd(__FILE__, "RealSendMessage 7 user=%s\n", user.login.c_str());
+
+INFO_7 info;
+memset(&info, 0, sizeof(INFO_7));
+
+info.len = 264;
+strncpy((char*)info.type, "INFO_7", 16);
+info.infoType = static_cast<int8_t>(msg.header.type);
+info.showTime = static_cast<int8_t>(msg.header.showTime);
+info.sendTime = msg.header.creationTime;
+
+size_t len = info.len;
+#ifdef ARCH_BE
+SwapBytes(info.len);
+SwapBytes(info.sendTime);
+#endif
+
+strncpy((char*)info.text, msg.text.c_str(), MAX_MSG_LEN - 1);
+info.text[MAX_MSG_LEN - 1] = 0;
+
+char buffer[300];
+memcpy(buffer, &info, sizeof(INFO_7));
+
+EncryptString(buffer, buffer, len, &user.ctx);
+return Send(ip, iaSettings.GetUserPort(), buffer, len);
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::RealSendMessage8(const STG::Message & msg, uint32_t ip, IA_USER & user)
+{
+printfd(__FILE__, "RealSendMessage 8 user=%s\n", user.login.c_str());
+
+INFO_8 info;
+memset(&info, 0, sizeof(INFO_8));
+
+info.len = 1056;
+strncpy((char*)info.type, "INFO_8", 16);
+info.infoType = static_cast<int8_t>(msg.header.type);
+info.showTime = static_cast<int8_t>(msg.header.showTime);
+info.sendTime = msg.header.creationTime;
+
+strncpy((char*)info.text, msg.text.c_str(), IA_MAX_MSG_LEN_8 - 1);
+info.text[IA_MAX_MSG_LEN_8 - 1] = 0;
+
+size_t len = info.len;
+#ifdef ARCH_BE
+SwapBytes(info.len);
+SwapBytes(info.sendTime);
+#endif
+
+char buffer[1500];
+memcpy(buffer, &info, sizeof(INFO_8));
+
+EncryptString(buffer, buffer, len, &user.ctx);
+return Send(ip, user.port, buffer, len);
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_CONN_SYN_6(CONN_SYN_6 *, IA_USER * iaUser, uint32_t)
+{
+if (!(iaUser->phase.GetPhase() == 1 || iaUser->phase.GetPhase() == 3))
+    return -1;
+
+enabledDirs = 0xFFffFFff;
+
+iaUser->phase.SetPhase2();
+printfd(__FILE__, "Phase changed from %d to 2. Reason: CONN_SYN_6\n", iaUser->phase.GetPhase());
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_CONN_SYN_7(CONN_SYN_7 * connSyn, IA_USER * iaUser, uint32_t sip)
+{
+return Process_CONN_SYN_6(connSyn, iaUser, sip);
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_CONN_SYN_8(CONN_SYN_8 * connSyn, IA_USER * iaUser, uint32_t sip)
+{
+#ifdef ARCH_BE
+SwapBytes(connSyn->dirs);
+#endif
+int ret = Process_CONN_SYN_6(reinterpret_cast<CONN_SYN_6 *>(connSyn), iaUser, sip);
+enabledDirs = connSyn->dirs;
+return ret;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_CONN_ACK_6(CONN_ACK_6 * connAck, IA_USER * iaUser, uint32_t sip)
+{
+#ifdef ARCH_BE
+SwapBytes(connAck->len);
+SwapBytes(connAck->rnd);
+#endif
+printfd( __FILE__, "CONN_ACK_6 %s\n", connAck->type);
+
+if ((iaUser->phase.GetPhase() == 2) && (connAck->rnd == iaUser->rnd + 1))
+    {
+    iaUser->phase.UpdateTime();
+
+    iaUser->lastSendAlive = iaUser->phase.GetTime();
+    if (users->Authorize(iaUser->login, sip, enabledDirs, this))
+        {
+        iaUser->phase.SetPhase3();
+        printfd(__FILE__, "Phase changed from 2 to 3. Reason: CONN_ACK_6\n");
+        return 0;
+        }
+    else
+        {
+        errorStr = iaUser->user->GetStrError();
+        if (iaSettings.LogProtocolErrors())
+            logger("IP: %s. User '%s'. Protocol version: %d. CONN_ACK: phase 2, authorization error ('%s').", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, errorStr.c_str());
+        iaUser->phase.SetPhase1();
+        ip2user.erase(sip);
+        printfd(__FILE__, "Phase changed from 2 to 1. Reason: failed to authorize user\n");
+        return -1;
+        }
+    }
+printfd(__FILE__, "Invalid phase or control number. Phase: %d. Control number: %d, expected: %d\n", iaUser->phase.GetPhase(), connAck->rnd, iaUser->rnd + 1);
+if (iaSettings.LogProtocolErrors())
+    {
+    if (iaUser->phase.GetPhase() != 2)
+        logger("IP: %s. User '%s'. Protocol version: %d. CONN_ACK: invalid phase, expected 2, got %d.", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, iaUser->phase.GetPhase());
+    if (connAck->rnd != iaUser->rnd + 1)
+        logger("IP: %s. User '%s'. Protocol version: %d. CONN_ACK: invalid control number, expected %d, got %d.", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, (iaUser->rnd + 1), connAck->rnd);
+    }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_CONN_ACK_7(CONN_ACK_7 * connAck, IA_USER * iaUser, uint32_t sip)
+{
+return Process_CONN_ACK_6(connAck, iaUser, sip);
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_CONN_ACK_8(CONN_ACK_8 * connAck, IA_USER * iaUser, uint32_t sip)
+{
+#ifdef ARCH_BE
+SwapBytes(connAck->len);
+SwapBytes(connAck->rnd);
+#endif
+printfd( __FILE__, "CONN_ACK_8 %s\n", connAck->type);
+
+if ((iaUser->phase.GetPhase() == 2) && (connAck->rnd == iaUser->rnd + 1))
+    {
+    iaUser->phase.UpdateTime();
+    iaUser->lastSendAlive = iaUser->phase.GetTime();
+    if (users->Authorize(iaUser->login, sip, enabledDirs, this))
+        {
+        iaUser->phase.SetPhase3();
+        printfd(__FILE__, "Phase changed from 2 to 3. Reason: CONN_ACK_8\n");
+        return 0;
+        }
+    else
+        {
+        errorStr = iaUser->user->GetStrError();
+        if (iaSettings.LogProtocolErrors())
+            logger("IP: %s. User '%s'. Protocol version: %d. CONN_ACK: phase 2, authorization error ('%s').", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, errorStr.c_str());
+        iaUser->phase.SetPhase1();
+        ip2user.erase(sip);
+        printfd(__FILE__, "Phase changed from 2 to 1. Reason: failed to authorize user\n");
+        return -1;
+        }
+    }
+printfd(__FILE__, "Invalid phase or control number. Phase: %d. Control number: %d, expected: %d\n", iaUser->phase.GetPhase(), connAck->rnd, iaUser->rnd + 1);
+if (iaSettings.LogProtocolErrors())
+    {
+    if (iaUser->phase.GetPhase() != 2)
+        logger("IP: %s. User '%s'. Protocol version: %d. CONN_ACK: invalid phase, expected 2, got %d.", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, iaUser->phase.GetPhase());
+    if (connAck->rnd != iaUser->rnd + 1)
+        logger("IP: %s. User '%s'. Protocol version: %d. CONN_ACK: invalid control number, expected %d, got %d.", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, (iaUser->rnd + 1), connAck->rnd);
+    }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_ALIVE_ACK_6(ALIVE_ACK_6 * aliveAck, IA_USER * iaUser, uint32_t)
+{
+#ifdef ARCH_BE
+SwapBytes(aliveAck->len);
+SwapBytes(aliveAck->rnd);
+#endif
+printfd(__FILE__, "ALIVE_ACK_6\n");
+if ((iaUser->phase.GetPhase() == 3) && (aliveAck->rnd == iaUser->rnd + 1))
+    {
+    iaUser->phase.UpdateTime();
+    #ifdef IA_DEBUG
+    iaUser->aliveSent = false;
+    #endif
+    }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_ALIVE_ACK_7(ALIVE_ACK_7 * aliveAck, IA_USER * iaUser, uint32_t sip)
+{
+return Process_ALIVE_ACK_6(aliveAck, iaUser, sip);
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_ALIVE_ACK_8(ALIVE_ACK_8 * aliveAck, IA_USER * iaUser, uint32_t)
+{
+#ifdef ARCH_BE
+SwapBytes(aliveAck->len);
+SwapBytes(aliveAck->rnd);
+#endif
+printfd(__FILE__, "ALIVE_ACK_8\n");
+if ((iaUser->phase.GetPhase() == 3) && (aliveAck->rnd == iaUser->rnd + 1))
+    {
+    iaUser->phase.UpdateTime();
+    #ifdef IA_DEBUG
+    iaUser->aliveSent = false;
+    #endif
+    }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_DISCONN_SYN_6(DISCONN_SYN_6 *, IA_USER * iaUser, uint32_t sip)
+{
+printfd(__FILE__, "DISCONN_SYN_6\n");
+if (iaUser->phase.GetPhase() != 3)
+    {
+    if (iaSettings.LogProtocolErrors())
+        logger("IP: %s. User '%s'. Protocol version: %d. DISCONN_SYN: invalid phase, expected 3, got %d.", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, iaUser->phase.GetPhase());
+    printfd(__FILE__, "Invalid phase. Expected 3, actual %d\n", iaUser->phase.GetPhase());
+    errorStr = "Incorrect request DISCONN_SYN";
+    return -1;
+    }
+
+iaUser->phase.SetPhase4();
+printfd(__FILE__, "Phase changed from 3 to 4. Reason: DISCONN_SYN_6\n");
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_DISCONN_SYN_7(DISCONN_SYN_7 * disconnSyn, IA_USER * iaUser, uint32_t sip)
+{
+return Process_DISCONN_SYN_6(disconnSyn, iaUser, sip);
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_DISCONN_SYN_8(DISCONN_SYN_8 *, IA_USER * iaUser, uint32_t sip)
+{
+if (iaUser->phase.GetPhase() != 3)
+    {
+    if (iaSettings.LogProtocolErrors())
+        logger("IP: %s. User '%s'. Protocol version: %d. DISCONN_SYN: invalid phase, expected 3, got %d.", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, iaUser->phase.GetPhase());
+    errorStr = "Incorrect request DISCONN_SYN";
+    printfd(__FILE__, "Invalid phase. Expected 3, actual %d\n", iaUser->phase.GetPhase());
+    return -1;
+    }
+
+iaUser->phase.SetPhase4();
+printfd(__FILE__, "Phase changed from 3 to 4. Reason: DISCONN_SYN_6\n");
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_DISCONN_ACK_6(DISCONN_ACK_6 * disconnAck,
+                                   IA_USER * iaUser,
+                                   uint32_t sip,
+                                   std::map<uint32_t, IA_USER>::iterator)
+{
+#ifdef ARCH_BE
+SwapBytes(disconnAck->len);
+SwapBytes(disconnAck->rnd);
+#endif
+printfd(__FILE__, "DISCONN_ACK_6\n");
+if (!((iaUser->phase.GetPhase() == 4) && (disconnAck->rnd == iaUser->rnd + 1)))
+    {
+    if (iaSettings.LogProtocolErrors())
+        {
+        if (iaUser->phase.GetPhase() != 4)
+            logger("IP: %s. User '%s'. Protocol version: %d. DISCONN_ACK: invalid phase, expected 4, got %d.", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, iaUser->phase.GetPhase());
+        if (disconnAck->rnd != iaUser->rnd + 1)
+            logger("IP: %s. User '%s'. Protocol version: %d. DISCONN_ACK: invalid control number, expected %d, got %d.", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, (iaUser->rnd + 1), disconnAck->rnd);
+        }
+    printfd(__FILE__, "Invalid phase or control number. Phase: %d. Control number: %d\n", iaUser->phase.GetPhase(), disconnAck->rnd);
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_DISCONN_ACK_7(DISCONN_ACK_7 * disconnAck, IA_USER * iaUser, uint32_t sip, std::map<uint32_t, IA_USER>::iterator it)
+{
+return Process_DISCONN_ACK_6(disconnAck, iaUser, sip, it);
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Process_DISCONN_ACK_8(DISCONN_ACK_8 * disconnAck, IA_USER * iaUser, uint32_t sip, std::map<uint32_t, IA_USER>::iterator)
+{
+#ifdef ARCH_BE
+SwapBytes(disconnAck->len);
+SwapBytes(disconnAck->rnd);
+#endif
+printfd(__FILE__, "DISCONN_ACK_8\n");
+if (!((iaUser->phase.GetPhase() == 4) && (disconnAck->rnd == iaUser->rnd + 1)))
+    {
+    if (iaSettings.LogProtocolErrors())
+        {
+        if (iaUser->phase.GetPhase() != 4)
+            logger("IP: %s. User '%s'. Protocol version: %d. DISCONN_ACK: invalid phase, expected 4, got %d.", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, iaUser->phase.GetPhase());
+        if (disconnAck->rnd != iaUser->rnd + 1)
+            logger("IP: %s. User '%s'. Protocol version: %d. DISCONN_ACK: invalid control number, expected %d, got %d.", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, (iaUser->rnd + 1), disconnAck->rnd);
+        }
+    printfd(__FILE__, "Invalid phase or control number. Phase: %d. Control number: %d\n", iaUser->phase.GetPhase(), disconnAck->rnd);
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Send_CONN_SYN_ACK_6(IA_USER * iaUser, uint32_t sip)
+{
+//+++ Fill static data in connSynAck +++
+// TODO Move this code. It must be executed only once
+connSynAck6.len = Min8(sizeof(CONN_SYN_ACK_6));
+strcpy((char*)connSynAck6.type, "CONN_SYN_ACK");
+for (int j = 0; j < DIR_NUM; j++)
+    {
+    strncpy((char*)connSynAck6.dirName[j],
+            stgSettings->GetDirName(j).c_str(),
+            sizeof(string16));
+
+    connSynAck6.dirName[j][sizeof(string16) - 1] = 0;
+    }
+//--- Fill static data in connSynAck ---
+
+iaUser->rnd = static_cast<uint32_t>(random());
+connSynAck6.rnd = iaUser->rnd;
+
+printfd(__FILE__, "Sending CONN_SYN_ACK with control number %d.\n", iaUser->rnd);
+
+connSynAck6.userTimeOut = iaSettings.GetUserTimeout().GetSec();
+connSynAck6.aliveDelay = iaSettings.GetUserDelay().GetSec();
+
+#ifdef ARCH_BE
+SwapBytes(connSynAck6.len);
+SwapBytes(connSynAck6.rnd);
+SwapBytes(connSynAck6.userTimeOut);
+SwapBytes(connSynAck6.aliveDelay);
+#endif
+
+EncryptString((char*)&connSynAck6, (char*)&connSynAck6, Min8(sizeof(CONN_SYN_ACK_6)), &iaUser->ctx);
+return Send(sip, iaSettings.GetUserPort(), (char*)&connSynAck6, Min8(sizeof(CONN_SYN_ACK_6)));;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Send_CONN_SYN_ACK_7(IA_USER * iaUser, uint32_t sip)
+{
+return Send_CONN_SYN_ACK_6(iaUser, sip);
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Send_CONN_SYN_ACK_8(IA_USER * iaUser, uint32_t sip)
+{
+strcpy((char*)connSynAck8.hdr.magic, IA_ID);
+connSynAck8.hdr.protoVer[0] = 0;
+connSynAck8.hdr.protoVer[1] = 8;
+
+//+++ Fill static data in connSynAck +++
+// TODO Move this code. It must be executed only once
+connSynAck8.len = Min8(sizeof(CONN_SYN_ACK_8));
+strcpy((char*)connSynAck8.type, "CONN_SYN_ACK");
+for (int j = 0; j < DIR_NUM; j++)
+    {
+    strncpy((char*)connSynAck8.dirName[j],
+            stgSettings->GetDirName(j).c_str(),
+            sizeof(string16));
+
+    connSynAck8.dirName[j][sizeof(string16) - 1] = 0;
+    }
+//--- Fill static data in connSynAck ---
+
+iaUser->rnd = static_cast<uint32_t>(random());
+connSynAck8.rnd = iaUser->rnd;
+
+printfd(__FILE__, "Sending CONN_SYN_ACK with control number %d.\n", iaUser->rnd);
+
+connSynAck8.userTimeOut = iaSettings.GetUserTimeout().GetSec();
+connSynAck8.aliveDelay = iaSettings.GetUserDelay().GetSec();
+
+#ifdef ARCH_BE
+SwapBytes(connSynAck8.len);
+SwapBytes(connSynAck8.rnd);
+SwapBytes(connSynAck8.userTimeOut);
+SwapBytes(connSynAck8.aliveDelay);
+#endif
+
+EncryptString((char*)&connSynAck8, (char*)&connSynAck8, Min8(sizeof(CONN_SYN_ACK_8)), &iaUser->ctx);
+return Send(sip, iaUser->port, (char*)&connSynAck8, Min8(sizeof(CONN_SYN_ACK_8)));
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Send_ALIVE_SYN_6(IA_USER * iaUser, uint32_t sip)
+{
+aliveSyn6.len = Min8(sizeof(ALIVE_SYN_6));
+aliveSyn6.rnd = iaUser->rnd = static_cast<uint32_t>(random());
+
+strcpy((char*)aliveSyn6.type, "ALIVE_SYN");
+
+for (int i = 0; i < DIR_NUM; i++)
+    {
+    aliveSyn6.md[i] = iaUser->user->GetProperties().down.Get()[i];
+    aliveSyn6.mu[i] = iaUser->user->GetProperties().up.Get()[i];
+
+    aliveSyn6.sd[i] = iaUser->user->GetSessionDownload()[i];
+    aliveSyn6.su[i] = iaUser->user->GetSessionUpload()[i];
+    }
+
+//TODO
+int dn = iaSettings.GetFreeMbShowType();
+const auto tf = iaUser->user->GetTariff();
+
+if (dn < DIR_NUM)
+    {
+    double p = tf->GetPriceWithTraffType(aliveSyn6.mu[dn],
+                                         aliveSyn6.md[dn],
+                                         dn,
+                                         stgTime);
+    p *= 1024 * 1024;
+    if (std::fabs(p) < 1.0e-3)
+        {
+        snprintf((char*)aliveSyn6.freeMb, IA_FREEMB_LEN, "---");
+        }
+    else
+        {
+        double fmb = iaUser->user->GetProperties().freeMb;
+        fmb = fmb < 0 ? 0 : fmb;
+        snprintf((char*)aliveSyn6.freeMb, IA_FREEMB_LEN, "%.3f", fmb / p);
+        }
+    }
+else
+    {
+    if (freeMbNone == iaSettings.GetFreeMbShowType())
+        {
+        aliveSyn6.freeMb[0] = 0;
+        }
+    else
+        {
+        double fmb = iaUser->user->GetProperties().freeMb;
+        fmb = fmb < 0 ? 0 : fmb;
+        snprintf((char*)aliveSyn6.freeMb, IA_FREEMB_LEN, "C%.3f", fmb);
+        }
+    }
+
+#ifdef IA_DEBUG
+if (iaUser->aliveSent)
+    {
+    printfd(__FILE__, "========= ALIVE_ACK_6(7) TIMEOUT !!! %s =========\n", iaUser->login.c_str());
+    }
+iaUser->aliveSent = true;
+#endif
+
+aliveSyn6.cash =(int64_t) (iaUser->user->GetProperties().cash.Get() * 1000.0);
+if (!stgSettings->GetShowFeeInCash())
+    aliveSyn6.cash -= (int64_t)(tf->GetFee() * 1000.0);
+
+#ifdef ARCH_BE
+SwapBytes(aliveSyn6.len);
+SwapBytes(aliveSyn6.rnd);
+SwapBytes(aliveSyn6.cash);
+for (int i = 0; i < DIR_NUM; ++i)
+    {
+    SwapBytes(aliveSyn6.mu[i]);
+    SwapBytes(aliveSyn6.md[i]);
+    SwapBytes(aliveSyn6.su[i]);
+    SwapBytes(aliveSyn6.sd[i]);
+    }
+#endif
+
+EncryptString((char*)&aliveSyn6, (char*)&aliveSyn6, Min8(sizeof(aliveSyn6)), &iaUser->ctx);
+return Send(sip, iaSettings.GetUserPort(), (char*)&aliveSyn6, Min8(sizeof(aliveSyn6)));
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Send_ALIVE_SYN_7(IA_USER * iaUser, uint32_t sip)
+{
+return Send_ALIVE_SYN_6(iaUser, sip);
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Send_ALIVE_SYN_8(IA_USER * iaUser, uint32_t sip)
+{
+strcpy((char*)aliveSyn8.hdr.magic, IA_ID);
+aliveSyn8.hdr.protoVer[0] = 0;
+aliveSyn8.hdr.protoVer[1] = 8;
+
+aliveSyn8.len = Min8(sizeof(ALIVE_SYN_8));
+aliveSyn8.rnd = iaUser->rnd = static_cast<uint32_t>(random());
+
+strcpy((char*)aliveSyn8.type, "ALIVE_SYN");
+
+for (int i = 0; i < DIR_NUM; i++)
+    {
+    aliveSyn8.md[i] = iaUser->user->GetProperties().down.Get()[i];
+    aliveSyn8.mu[i] = iaUser->user->GetProperties().up.Get()[i];
+
+    aliveSyn8.sd[i] = iaUser->user->GetSessionDownload()[i];
+    aliveSyn8.su[i] = iaUser->user->GetSessionUpload()[i];
+    }
+
+//TODO
+int dn = iaSettings.GetFreeMbShowType();
+
+if (dn < DIR_NUM)
+    {
+    const auto tf = iaUser->user->GetTariff();
+    double p = tf->GetPriceWithTraffType(aliveSyn8.mu[dn],
+                                         aliveSyn8.md[dn],
+                                         dn,
+                                         stgTime);
+    p *= 1024 * 1024;
+    if (std::fabs(p) < 1.0e-3)
+        {
+        snprintf((char*)aliveSyn8.freeMb, IA_FREEMB_LEN, "---");
+        }
+    else
+        {
+        double fmb = iaUser->user->GetProperties().freeMb;
+        fmb = fmb < 0 ? 0 : fmb;
+        snprintf((char*)aliveSyn8.freeMb, IA_FREEMB_LEN, "%.3f", fmb / p);
+        }
+    }
+else
+    {
+    if (freeMbNone == iaSettings.GetFreeMbShowType())
+        {
+        aliveSyn8.freeMb[0] = 0;
+        }
+    else
+        {
+        double fmb = iaUser->user->GetProperties().freeMb;
+        fmb = fmb < 0 ? 0 : fmb;
+        snprintf((char*)aliveSyn8.freeMb, IA_FREEMB_LEN, "C%.3f", fmb);
+        }
+    }
+
+#ifdef IA_DEBUG
+if (iaUser->aliveSent)
+    {
+    printfd(__FILE__, "========= ALIVE_ACK_8 TIMEOUT !!! =========\n");
+    }
+iaUser->aliveSent = true;
+#endif
+
+const auto tf = iaUser->user->GetTariff();
+
+aliveSyn8.cash =(int64_t) (iaUser->user->GetProperties().cash.Get() * 1000.0);
+if (!stgSettings->GetShowFeeInCash())
+    aliveSyn8.cash -= (int64_t)(tf->GetFee() * 1000.0);
+
+#ifdef ARCH_BE
+SwapBytes(aliveSyn8.len);
+SwapBytes(aliveSyn8.rnd);
+SwapBytes(aliveSyn8.cash);
+SwapBytes(aliveSyn8.status);
+for (int i = 0; i < DIR_NUM; ++i)
+    {
+    SwapBytes(aliveSyn8.mu[i]);
+    SwapBytes(aliveSyn8.md[i]);
+    SwapBytes(aliveSyn8.su[i]);
+    SwapBytes(aliveSyn8.sd[i]);
+    }
+#endif
+
+EncryptString((char*)&aliveSyn8, (char*)&aliveSyn8, Min8(sizeof(aliveSyn8)), &iaUser->ctx);
+return Send(sip, iaUser->port, (char*)&aliveSyn8, Min8(sizeof(aliveSyn8)));
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Send_DISCONN_SYN_ACK_6(IA_USER * iaUser, uint32_t sip)
+{
+disconnSynAck6.len = Min8(sizeof(DISCONN_SYN_ACK_6));
+strcpy((char*)disconnSynAck6.type, "DISCONN_SYN_ACK");
+disconnSynAck6.rnd = iaUser->rnd = static_cast<uint32_t>(random());
+
+#ifdef ARCH_BE
+SwapBytes(disconnSynAck6.len);
+SwapBytes(disconnSynAck6.rnd);
+#endif
+
+EncryptString((char*)&disconnSynAck6, (char*)&disconnSynAck6, Min8(sizeof(disconnSynAck6)), &iaUser->ctx);
+return Send(sip, iaSettings.GetUserPort(), (char*)&disconnSynAck6, Min8(sizeof(disconnSynAck6)));
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Send_DISCONN_SYN_ACK_7(IA_USER * iaUser, uint32_t sip)
+{
+return Send_DISCONN_SYN_ACK_6(iaUser, sip);
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Send_DISCONN_SYN_ACK_8(IA_USER * iaUser, uint32_t sip)
+{
+strcpy((char*)disconnSynAck8.hdr.magic, IA_ID);
+disconnSynAck8.hdr.protoVer[0] = 0;
+disconnSynAck8.hdr.protoVer[1] = 8;
+
+disconnSynAck8.len = Min8(sizeof(DISCONN_SYN_ACK_8));
+strcpy((char*)disconnSynAck8.type, "DISCONN_SYN_ACK");
+disconnSynAck8.rnd = iaUser->rnd = static_cast<uint32_t>(random());
+
+#ifdef ARCH_BE
+SwapBytes(disconnSynAck8.len);
+SwapBytes(disconnSynAck8.rnd);
+#endif
+
+EncryptString((char*)&disconnSynAck8, (char*)&disconnSynAck8, Min8(sizeof(disconnSynAck8)), &iaUser->ctx);
+return Send(sip, iaUser->port, (char*)&disconnSynAck8, Min8(sizeof(disconnSynAck8)));
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Send_FIN_6(IA_USER * iaUser, uint32_t sip, std::map<uint32_t, IA_USER>::iterator it)
+{
+fin6.len = Min8(sizeof(FIN_6));
+strcpy((char*)fin6.type, "FIN");
+strcpy((char*)fin6.ok, "OK");
+
+#ifdef ARCH_BE
+SwapBytes(fin6.len);
+#endif
+
+EncryptString((char*)&fin6, (char*)&fin6, Min8(sizeof(fin6)), &iaUser->ctx);
+
+users->Unauthorize(iaUser->login, this);
+
+int res = Send(sip, iaSettings.GetUserPort(), (char*)&fin6, Min8(sizeof(fin6)));
+
+ip2user.erase(it);
+
+return res;
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Send_FIN_7(IA_USER * iaUser, uint32_t sip, std::map<uint32_t, IA_USER>::iterator it)
+{
+return Send_FIN_6(iaUser, sip, it);
+}
+//-----------------------------------------------------------------------------
+int AUTH_IA::Send_FIN_8(IA_USER * iaUser, uint32_t sip, std::map<uint32_t, IA_USER>::iterator it)
+{
+strcpy((char*)fin8.hdr.magic, IA_ID);
+fin8.hdr.protoVer[0] = 0;
+fin8.hdr.protoVer[1] = 8;
+
+fin8.len = Min8(sizeof(FIN_8));
+strcpy((char*)fin8.type, "FIN");
+strcpy((char*)fin8.ok, "OK");
+
+#ifdef ARCH_BE
+SwapBytes(fin8.len);
+#endif
+
+EncryptString((char*)&fin8, (char*)&fin8, Min8(sizeof(fin8)), &iaUser->ctx);
+
+users->Unauthorize(iaUser->login, this);
+
+int res = Send(sip, iaUser->port, (char*)&fin8, Min8(sizeof(fin8)));
+
+ip2user.erase(it);
+
+return res;
+}
diff --git a/projects/stargazer/plugins/authorization/inetaccess/inetaccess.h b/projects/stargazer/plugins/authorization/inetaccess/inetaccess.h
new file mode 100644 (file)
index 0000000..83e4d7a
--- /dev/null
@@ -0,0 +1,376 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+#pragma once
+
+#include "stg/auth.h"
+#include "stg/store.h"
+#include "stg/module_settings.h"
+#include "stg/notifer.h"
+#include "stg/user_ips.h"
+#include "stg/user.h"
+#include "stg/users.h"
+#include "stg/user_property.h"
+#include "stg/ia_packets.h"
+#include "stg/blowfish.h"
+#include "stg/logger.h"
+#include "stg/utime.h"
+#include "stg/logger.h"
+
+#include <cstring>
+#include <ctime>
+#include <cstdint>
+#include <string>
+#include <map>
+#include <list>
+#include <functional>
+#include <utility>
+
+#include <sys/time.h>
+#include <pthread.h>
+
+//#define IA_DEBUG (1)
+//#define IA_PHASE_DEBUG (1)
+
+class AUTH_IA;
+//-----------------------------------------------------------------------------
+enum FREEMB {
+    freeMb0 = 0,
+    freeMb1,
+    freeMb2,
+    freeMb3,
+    freeMb4,
+    freeMb5,
+    freeMb6,
+    freeMb7,
+    freeMb8,
+    freeMb9,
+    freeMb10,
+    freeMb11,
+    freeMb12,
+    freeMb13,
+    freeMb14,
+    freeMb15,
+    freeMb16,
+    freeMb17,
+    freeMb18,
+    freeMb19,
+    freeMbCash = 100,
+    freeMbNone = 101
+};
+//-----------------------------------------------------------------------------
+class IA_PHASE {
+public:
+    IA_PHASE();
+    ~IA_PHASE();
+
+    void    SetPhase1();
+    void    SetPhase2();
+    void    SetPhase3();
+    void    SetPhase4();
+    int     GetPhase() const;
+
+    void    UpdateTime();
+    const UTIME & GetTime() const;
+
+    #ifdef IA_PHASE_DEBUG
+    void    SetUserLogin(const std::string & login);
+    void    SetLogFileName(const std::string & logFileName);
+    #endif
+
+private:
+    int             phase;
+    UTIME           phaseTime;
+
+    #ifdef IA_PHASE_DEBUG
+    void WritePhaseChange(int newPhase);
+    std::string log;
+    std::string login;
+    FILE * flog;
+    #endif
+};
+//-----------------------------------------------------------------------------
+struct IA_USER {
+    using ConstUserPtr = const STG::User*;
+    IA_USER()
+        : user(NULL),
+          lastSendAlive(0),
+          rnd(static_cast<uint32_t>(random())),
+          port(0),
+          protoVer(0),
+          password("NO PASSWORD")
+    {
+    unsigned char keyL[PASSWD_LEN];
+    memset(keyL, 0, PASSWD_LEN);
+    strncpy((char *)keyL, password.c_str(), PASSWD_LEN);
+    Blowfish_Init(&ctx, keyL, PASSWD_LEN);
+
+    #ifdef IA_DEBUG
+    aliveSent = false;
+    #endif
+    }
+
+    IA_USER(const IA_USER & u)
+        : login(u.login),
+          user(u.user),
+          phase(u.phase),
+          lastSendAlive(u.lastSendAlive),
+          rnd(u.rnd),
+          port(u.port),
+          ctx(),
+          messagesToSend(u.messagesToSend),
+          protoVer(u.protoVer),
+          password(u.password)
+    {
+    #ifdef IA_DEBUG
+    aliveSent  = u.aliveSent;
+    #endif
+    memcpy(&ctx, &u.ctx, sizeof(BLOWFISH_CTX));
+    }
+
+    IA_USER(const std::string & l,
+            ConstUserPtr u,
+            uint16_t p,
+            int ver)
+        : login(l),
+          user(u),
+          lastSendAlive(0),
+          rnd(static_cast<uint32_t>(random())),
+          port(p),
+          messagesToSend(),
+          protoVer(ver),
+          password(user->GetProperties().password.Get())
+    {
+    unsigned char keyL[PASSWD_LEN];
+    memset(keyL, 0, PASSWD_LEN);
+    strncpy((char *)keyL, password.c_str(), PASSWD_LEN);
+    Blowfish_Init(&ctx, keyL, PASSWD_LEN);
+
+    #ifdef IA_DEBUG
+    aliveSent = false;
+    #endif
+    }
+
+    std::string     login;
+    ConstUserPtr  user;
+    IA_PHASE        phase;
+    UTIME           lastSendAlive;
+    uint32_t        rnd;
+    uint16_t        port;
+    BLOWFISH_CTX    ctx;
+    std::vector<STG::Message> messagesToSend;
+    int             protoVer;
+    std::string     password;
+    #ifdef IA_DEBUG
+    bool            aliveSent;
+    #endif
+
+private:
+    IA_USER & operator=(const IA_USER & rvalue);
+};
+//-----------------------------------------------------------------------------
+class AUTH_IA_SETTINGS {
+public:
+                    AUTH_IA_SETTINGS();
+    virtual         ~AUTH_IA_SETTINGS() {}
+    const std::string & GetStrError() const { return errorStr; }
+    int             ParseSettings(const STG::ModuleSettings & s);
+    UTIME           GetUserDelay() const { return UTIME(userDelay); }
+    UTIME           GetUserTimeout() const { return UTIME(userTimeout); }
+    uint16_t        GetUserPort() const { return port; }
+    FREEMB          GetFreeMbShowType() const { return freeMbShowType; }
+    bool            LogProtocolErrors() const { return logProtocolErrors; }
+
+private:
+    int             userDelay;
+    int             userTimeout;
+    uint16_t        port;
+    std::string     errorStr;
+    FREEMB          freeMbShowType;
+    bool            logProtocolErrors;
+};
+//-----------------------------------------------------------------------------
+class AUTH_IA;
+using UserPtr = STG::User*;
+//-----------------------------------------------------------------------------
+class DEL_USER_NOTIFIER: public STG::NotifierBase<UserPtr> {
+public:
+    explicit DEL_USER_NOTIFIER(AUTH_IA & a) : auth(a) {}
+    virtual ~DEL_USER_NOTIFIER() {}
+
+    void Notify(const UserPtr & user);
+private:
+    DEL_USER_NOTIFIER(const DEL_USER_NOTIFIER & rvalue);
+    DEL_USER_NOTIFIER & operator=(const DEL_USER_NOTIFIER & rvalue);
+
+    AUTH_IA & auth;
+};
+//-----------------------------------------------------------------------------
+class AUTH_IA : public STG::Auth {
+friend class DEL_USER_NOTIFIER;
+public:
+                        AUTH_IA();
+                        ~AUTH_IA() override;
+
+    void                SetUsers(STG::Users * u) override { users = u; }
+    void                SetStgSettings(const STG::Settings * s) override { stgSettings = s; }
+    void                SetSettings(const STG::ModuleSettings & s) override { settings = s; }
+    int                 ParseSettings() override;
+
+    int                 Start() override;
+    int                 Stop() override;
+    int                 Reload(const STG::ModuleSettings & ms) override;
+    bool                IsRunning() override { return isRunningRunTimeouter || isRunningRun; }
+
+    const std::string & GetStrError() const override { return errorStr; }
+    std::string         GetVersion() const override { return "InetAccess authorization plugin v.1.4"; }
+    uint16_t            GetStartPosition() const override { return 30; }
+    uint16_t            GetStopPosition() const override { return 30; }
+
+    int                 SendMessage(const STG::Message & msg, uint32_t ip) const override;
+
+private:
+    AUTH_IA(const AUTH_IA & rvalue);
+    AUTH_IA & operator=(const AUTH_IA & rvalue);
+
+    static void *       Run(void *);
+    static void *       RunTimeouter(void * d);
+    int                 PrepareNet();
+    int                 FinalizeNet();
+    void                DelUser(UserPtr u);
+    int                 RecvData(char * buffer, int bufferSize);
+    int                 CheckHeader(const char * buffer, uint32_t sip, int * protoVer);
+    int                 PacketProcessor(void * buff, size_t dataLen, uint32_t sip, uint16_t sport, int protoVer, UserPtr user);
+
+    int                 Process_CONN_SYN_6(CONN_SYN_6 * connSyn, IA_USER * iaUser, uint32_t sip);
+    int                 Process_CONN_SYN_7(CONN_SYN_7 * connSyn, IA_USER * iaUser, uint32_t sip);
+    int                 Process_CONN_SYN_8(CONN_SYN_8 * connSyn, IA_USER * iaUser, uint32_t sip);
+
+    int                 Process_CONN_ACK_6(CONN_ACK_6 * connAck, IA_USER * iaUser, uint32_t sip);
+    int                 Process_CONN_ACK_7(CONN_ACK_7 * connAck, IA_USER * iaUser, uint32_t sip);
+    int                 Process_CONN_ACK_8(CONN_ACK_8 * connAck, IA_USER * iaUser, uint32_t sip);
+
+    int                 Process_ALIVE_ACK_6(ALIVE_ACK_6 * aliveAck, IA_USER * iaUser, uint32_t sip);
+    int                 Process_ALIVE_ACK_7(ALIVE_ACK_7 * aliveAck, IA_USER * iaUser, uint32_t sip);
+    int                 Process_ALIVE_ACK_8(ALIVE_ACK_8 * aliveAck, IA_USER * iaUser, uint32_t sip);
+
+    int                 Process_DISCONN_SYN_6(DISCONN_SYN_6 * disconnSyn, IA_USER * iaUser, uint32_t sip);
+    int                 Process_DISCONN_SYN_7(DISCONN_SYN_7 * disconnSyn, IA_USER * iaUser, uint32_t sip);
+    int                 Process_DISCONN_SYN_8(DISCONN_SYN_8 * disconnSyn, IA_USER * iaUser, uint32_t sip);
+
+    int                 Process_DISCONN_ACK_6(DISCONN_ACK_6 * disconnSyn,
+                                              IA_USER * iaUser,
+                                              uint32_t sip,
+                                              std::map<uint32_t, IA_USER>::iterator it);
+    int                 Process_DISCONN_ACK_7(DISCONN_ACK_7 * disconnSyn,
+                                              IA_USER * iaUser,
+                                              uint32_t sip,
+                                              std::map<uint32_t, IA_USER>::iterator it);
+    int                 Process_DISCONN_ACK_8(DISCONN_ACK_8 * disconnSyn,
+                                              IA_USER * iaUser,
+                                              uint32_t sip,
+                                              std::map<uint32_t, IA_USER>::iterator it);
+
+    int                 Send_CONN_SYN_ACK_6(IA_USER * iaUser, uint32_t sip);
+    int                 Send_CONN_SYN_ACK_7(IA_USER * iaUser, uint32_t sip);
+    int                 Send_CONN_SYN_ACK_8(IA_USER * iaUser, uint32_t sip);
+
+    int                 Send_ALIVE_SYN_6(IA_USER * iaUser, uint32_t sip);
+    int                 Send_ALIVE_SYN_7(IA_USER * iaUser, uint32_t sip);
+    int                 Send_ALIVE_SYN_8(IA_USER * iaUser, uint32_t sip);
+
+    int                 Send_DISCONN_SYN_ACK_6(IA_USER * iaUser, uint32_t sip);
+    int                 Send_DISCONN_SYN_ACK_7(IA_USER * iaUser, uint32_t sip);
+    int                 Send_DISCONN_SYN_ACK_8(IA_USER * iaUser, uint32_t sip);
+
+    int                 Send_FIN_6(IA_USER * iaUser, uint32_t sip, std::map<uint32_t, IA_USER>::iterator it);
+    int                 Send_FIN_7(IA_USER * iaUser, uint32_t sip, std::map<uint32_t, IA_USER>::iterator it);
+    int                 Send_FIN_8(IA_USER * iaUser, uint32_t sip, std::map<uint32_t, IA_USER>::iterator it);
+
+    int                 Timeouter();
+
+    int                 SendError(uint32_t ip, uint16_t port, int protoVer, const std::string & text);
+    int                 Send(uint32_t ip, uint16_t port, const char * buffer, size_t len);
+    int                 RealSendMessage6(const STG::Message & msg, uint32_t ip, IA_USER & user);
+    int                 RealSendMessage7(const STG::Message & msg, uint32_t ip, IA_USER & user);
+    int                 RealSendMessage8(const STG::Message & msg, uint32_t ip, IA_USER & user);
+
+    BLOWFISH_CTX        ctxS;        //for loginS
+
+    mutable std::string errorStr;
+    AUTH_IA_SETTINGS    iaSettings;
+    STG::ModuleSettings settings;
+
+    bool                nonstop;
+
+    bool                isRunningRun;
+    bool                isRunningRunTimeouter;
+
+    STG::Users *             users;
+    const STG::Settings *    stgSettings;
+
+    mutable std::map<uint32_t, IA_USER> ip2user;
+
+    pthread_t           recvThread;
+    pthread_t           timeouterThread;
+    mutable pthread_mutex_t mutex;
+
+    int                 listenSocket;
+
+    CONN_SYN_ACK_6      connSynAck6;
+    CONN_SYN_ACK_8      connSynAck8;
+
+    DISCONN_SYN_ACK_6   disconnSynAck6;
+    DISCONN_SYN_ACK_8   disconnSynAck8;
+
+    ALIVE_SYN_6         aliveSyn6;
+    ALIVE_SYN_8         aliveSyn8;
+    FIN_6               fin6;
+    FIN_8               fin8;
+
+    std::map<std::string, int> packetTypes;
+
+    uint32_t            enabledDirs;
+
+    DEL_USER_NOTIFIER   onDelUserNotifier;
+
+    STG::PluginLogger   logger;
+
+    friend class UnauthorizeUser;
+};
+//-----------------------------------------------------------------------------
+class UnauthorizeUser : std::unary_function<const std::pair<uint32_t, IA_USER> &, void> {
+    public:
+        explicit UnauthorizeUser(AUTH_IA * a) : auth(a) {}
+        UnauthorizeUser(const UnauthorizeUser & rvalue) : auth(rvalue.auth) {}
+        void operator()(const std::pair<uint32_t, IA_USER> & p)
+        {
+            auth->users->Unauthorize(p.second.user->GetLogin(), auth);
+        }
+    private:
+        UnauthorizeUser & operator=(const UnauthorizeUser & rvalue);
+
+        AUTH_IA * auth;
+};
+//-----------------------------------------------------------------------------
+inline
+void DEL_USER_NOTIFIER::Notify(const UserPtr & user)
+{
+    auth.DelUser(user);
+}
diff --git a/projects/stargazer/plugins/capture/cap_nf/cap_nf.cpp b/projects/stargazer/plugins/capture/cap_nf/cap_nf.cpp
new file mode 100644 (file)
index 0000000..817ed71
--- /dev/null
@@ -0,0 +1,441 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+Date: 16.05.2008
+*/
+
+/*
+* Author : Maxim Mamontov <faust@stg.dp.ua>
+*/
+
+/*
+$Revision: 1.11 $
+$Date: 2010/09/10 06:41:06 $
+$Author: faust $
+*/
+
+#include "cap_nf.h"
+
+#include "stg/common.h"
+#include "stg/raw_ip_packet.h"
+#include "stg/traffcounter.h"
+
+#include <vector>
+
+#include <csignal>
+#include <cerrno>
+#include <cstring>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+namespace
+{
+
+struct NF_HEADER {
+    uint16_t version;   // Protocol version
+    uint16_t count;     // Flows count
+    uint32_t uptime;    // System uptime
+    uint32_t timestamp; // UNIX timestamp
+    uint32_t nsecs;     // Residual nanoseconds
+    uint32_t flowSeq;   // Sequence counter
+    uint8_t  eType;     // Engine type
+    uint8_t  eID;       // Engine ID
+    uint16_t sInterval; // Sampling mode and interval
+};
+
+struct NF_DATA {
+    uint32_t srcAddr;   // Flow source address
+    uint32_t dstAddr;   // Flow destination address
+    uint32_t nextHop;   // IP addres on next hop router
+    uint16_t inSNMP;    // SNMP index of input iface
+    uint16_t outSNMP;   // SNMP index of output iface
+    uint32_t packets;   // Packets in flow
+    uint32_t octets;    // Total number of bytes in flow
+    uint32_t timeStart; // Uptime on first packet in flow
+    uint32_t timeFinish;// Uptime on last packet in flow
+    uint16_t srcPort;   // Flow source port
+    uint16_t dstPort;   // Flow destination port
+    uint8_t  pad1;      // 1-byte padding
+    uint8_t  TCPFlags;  // Cumulative OR of TCP flags
+    uint8_t  proto;     // IP protocol type (tcp, udp, etc.)
+    uint8_t  tos;       // IP Type of Service (ToS)
+    uint16_t srcAS;     // Source BGP autonomous system number
+    uint16_t dstAS;     // Destination BGP autonomus system number
+    uint8_t  srcMask;   // Source address mask in "slash" notation
+    uint8_t  dstMask;   // Destination address mask in "slash" notation
+    uint16_t pad2;      // 2-byte padding
+};
+
+#define BUF_SIZE (sizeof(NF_HEADER) + 30 * sizeof(NF_DATA))
+
+}
+
+extern "C" STG::Plugin* GetPlugin()
+{
+    static NF_CAP plugin;
+    return &plugin;
+}
+
+NF_CAP::NF_CAP()
+    : traffCnt(NULL),
+      runningTCP(false),
+      runningUDP(false),
+      stoppedTCP(true),
+      stoppedUDP(true),
+      portT(0),
+      portU(0),
+      sockTCP(-1),
+      sockUDP(-1),
+      logger(STG::PluginLogger::get("cap_nf"))
+{
+}
+
+int NF_CAP::ParseSettings()
+{
+std::vector<STG::ParamValue>::iterator it;
+for (it = settings.moduleParams.begin(); it != settings.moduleParams.end(); ++it)
+    {
+    if (it->param == "TCPPort" && !it->value.empty())
+        {
+        if (str2x(it->value[0], portT))
+            {
+            errorStr = "Invalid TCPPort value";
+            printfd(__FILE__, "Error: Invalid TCPPort value\n");
+            return -1;
+            }
+        continue;
+        }
+    if (it->param == "UDPPort" && !it->value.empty())
+        {
+        if (str2x(it->value[0], portU))
+            {
+            errorStr = "Invalid UDPPort value";
+            printfd(__FILE__, "Error: Invalid UDPPort value\n");
+            return -1;
+            }
+        continue;
+        }
+    printfd(__FILE__, "'%s' is not a valid module param\n", it->param.c_str());
+    }
+return 0;
+}
+
+int NF_CAP::Start()
+{
+if (portU > 0)
+    {
+    if (OpenUDP())
+        {
+        return -1;
+        }
+    runningUDP = true;
+    if (pthread_create(&tidUDP, NULL, RunUDP, this))
+        {
+        runningUDP = false;
+        CloseUDP();
+        errorStr = "Cannot create UDP thread";
+        logger("Cannot create UDP thread.");
+        printfd(__FILE__, "Error: Cannot create UDP thread\n");
+        return -1;
+        }
+    }
+if (portT > 0)
+    {
+    if (OpenTCP())
+        {
+        return -1;
+        }
+    runningTCP = true;
+    if (pthread_create(&tidTCP, NULL, RunTCP, this))
+        {
+        runningTCP = false;
+        CloseTCP();
+        logger("Cannot create TCP thread.");
+        errorStr = "Cannot create TCP thread";
+        printfd(__FILE__, "Error: Cannot create TCP thread\n");
+        return -1;
+        }
+    }
+return 0;
+}
+
+int NF_CAP::Stop()
+{
+runningTCP = runningUDP = false;
+if (portU && !stoppedUDP)
+    {
+    CloseUDP();
+    for (int i = 0; i < 25 && !stoppedUDP; ++i)
+        {
+        struct timespec ts = {0, 200000000};
+        nanosleep(&ts, NULL);
+        }
+    if (stoppedUDP)
+        {
+        pthread_join(tidUDP, NULL);
+        }
+    else
+        {
+        if (pthread_kill(tidUDP, SIGUSR1))
+            {
+            errorStr = "Error sending signal to UDP thread";
+            logger("Error sending sugnal to UDP thread.");
+            printfd(__FILE__, "Error: Error sending signal to UDP thread\n");
+            return -1;
+            }
+        printfd(__FILE__, "UDP thread NOT stopped\n");
+        logger("Cannot stop UDP thread.");
+        }
+    }
+if (portT && !stoppedTCP)
+    {
+    CloseTCP();
+    for (int i = 0; i < 25 && !stoppedTCP; ++i)
+        {
+        struct timespec ts = {0, 200000000};
+        nanosleep(&ts, NULL);
+        }
+    if (stoppedTCP)
+        {
+        pthread_join(tidTCP, NULL);
+        }
+    else
+        {
+        if (pthread_kill(tidTCP, SIGUSR1))
+            {
+            errorStr = "Error sending signal to TCP thread";
+            logger("Error sending signal to TCP thread.");
+            printfd(__FILE__, "Error: Error sending signal to TCP thread\n");
+            return -1;
+            }
+        printfd(__FILE__, "TCP thread NOT stopped\n");
+        logger("Cannot stop TCP thread.");
+        }
+    }
+return 0;
+}
+
+bool NF_CAP::OpenUDP()
+{
+struct sockaddr_in sin;
+sockUDP = socket(PF_INET, SOCK_DGRAM, 0);
+if (sockUDP <= 0)
+    {
+    errorStr = "Error opening UDP socket";
+    logger("Cannot create UDP socket: %s", strerror(errno));
+    printfd(__FILE__, "Error: Error opening UDP socket\n");
+    return true;
+    }
+sin.sin_family = AF_INET;
+sin.sin_port = htons(portU);
+sin.sin_addr.s_addr = inet_addr("0.0.0.0");
+if (bind(sockUDP, (struct sockaddr *)&sin, sizeof(sin)))
+    {
+    errorStr = "Error binding UDP socket";
+    logger("Cannot bind UDP socket: %s", strerror(errno));
+    printfd(__FILE__, "Error: Error binding UDP socket\n");
+    return true;
+    }
+return false;
+}
+
+bool NF_CAP::OpenTCP()
+{
+struct sockaddr_in sin;
+sockTCP = socket(PF_INET, SOCK_STREAM, 0);
+if (sockTCP <= 0)
+    {
+    errorStr = "Error opening TCP socket";
+    logger("Cannot create TCP socket: %s", strerror(errno));
+    printfd(__FILE__, "Error: Error opening TCP socket\n");
+    return true;
+    }
+sin.sin_family = AF_INET;
+sin.sin_port = htons(portT);
+sin.sin_addr.s_addr = inet_addr("0.0.0.0");
+if (bind(sockTCP, (struct sockaddr *)&sin, sizeof(sin)))
+    {
+    errorStr = "Error binding TCP socket";
+    logger("Cannot bind TCP socket: %s", strerror(errno));
+    printfd(__FILE__, "Error: Error binding TCP socket\n");
+    return true;
+    }
+if (listen(sockTCP, 1))
+    {
+    errorStr = "Error listening on TCP socket";
+    logger("Cannot listen on TCP socket: %s", strerror(errno));
+    printfd(__FILE__, "Error: Error listening TCP socket\n");
+    return true;
+    }
+return false;
+}
+
+void * NF_CAP::RunUDP(void * c)
+{
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+NF_CAP * cap = static_cast<NF_CAP *>(c);
+cap->stoppedUDP = false;
+while (cap->runningUDP)
+    {
+    if (!WaitPackets(cap->sockUDP))
+        {
+        continue;
+        }
+
+    // Data
+    struct sockaddr_in sin;
+    socklen_t slen = sizeof(sin);
+    uint8_t buf[BUF_SIZE];
+    ssize_t res = recvfrom(cap->sockUDP, buf, BUF_SIZE, 0, reinterpret_cast<struct sockaddr *>(&sin), &slen);
+    if (!cap->runningUDP)
+        break;
+
+    if (res < 0)
+        {
+        cap->logger("recvfrom error: %s", strerror(errno));
+        continue;
+        }
+
+    if (res == 0) // EOF
+        {
+        continue;
+        }
+
+    if (res < 24)
+        {
+        if (errno != EINTR)
+            {
+            cap->errorStr = "Invalid data received";
+            printfd(__FILE__, "Error: Invalid data received through UDP\n");
+            }
+        continue;
+        }
+
+    cap->ParseBuffer(buf, res);
+    }
+cap->stoppedUDP = true;
+return NULL;
+}
+
+void * NF_CAP::RunTCP(void * c)
+{
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+NF_CAP * cap = static_cast<NF_CAP *>(c);
+cap->stoppedTCP = false;
+while (cap->runningTCP)
+    {
+    if (!WaitPackets(cap->sockTCP))
+        {
+        continue;
+        }
+
+    // Data
+    struct sockaddr_in sin;
+    socklen_t slen = sizeof(sin);
+    int sd = accept(cap->sockTCP, reinterpret_cast<struct sockaddr *>(&sin), &slen);
+    if (!cap->runningTCP)
+        break;
+
+    if (sd <= 0)
+        {
+        if (sd < 0)
+            cap->logger("accept error: %s", strerror(errno));
+        continue;
+        }
+
+    if (!WaitPackets(sd))
+        {
+        close(sd);
+        continue;
+        }
+
+    uint8_t buf[BUF_SIZE];
+    ssize_t res = recv(sd, buf, BUF_SIZE, MSG_WAITALL);
+
+    if (res < 0)
+        cap->logger("recv error: %s", strerror(errno));
+
+    close(sd);
+
+    if (!cap->runningTCP)
+        break;
+
+    if (res == 0) // EOF
+        {
+        continue;
+        }
+
+    // Wrong logic!
+    // Need to check actual data length and wait all data to receive
+    if (res < 24)
+        {
+        continue;
+        }
+
+    cap->ParseBuffer(buf, res);
+    }
+cap->stoppedTCP = true;
+return NULL;
+}
+
+void NF_CAP::ParseBuffer(uint8_t * buf, ssize_t size)
+{
+STG::RawPacket ip;
+NF_HEADER * hdr = reinterpret_cast<NF_HEADER *>(buf);
+if (htons(hdr->version) != 5)
+    {
+    return;
+    }
+
+int packets = htons(hdr->count);
+
+if (packets < 0 || packets > 30)
+    {
+    return;
+    }
+
+if (24 + 48 * packets != size)
+    {
+    // See 'wrong logic' upper
+    return;
+    }
+
+for (int i = 0; i < packets; ++i)
+    {
+    NF_DATA * data = reinterpret_cast<NF_DATA *>(buf + 24 + i * 48);
+
+    ip.rawPacket.header.ipHeader.ip_v = 4;
+    ip.rawPacket.header.ipHeader.ip_hl = 5;
+    ip.rawPacket.header.ipHeader.ip_p = data->proto;
+    ip.dataLen = ntohl(data->octets);
+    ip.rawPacket.header.ipHeader.ip_src.s_addr = data->srcAddr;
+    ip.rawPacket.header.ipHeader.ip_dst.s_addr = data->dstAddr;
+    ip.rawPacket.header.sPort = data->srcPort;
+    ip.rawPacket.header.dPort = data->dstPort;
+
+    traffCnt->process(ip);
+    }
+}
diff --git a/projects/stargazer/plugins/capture/cap_nf/cap_nf.h b/projects/stargazer/plugins/capture/cap_nf/cap_nf.h
new file mode 100644 (file)
index 0000000..b9f45c5
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+Date: 16.05.2008
+*/
+
+/*
+* Author : Maxim Mamontov <faust@stg.dp.ua>
+*/
+
+/*
+$Revision: 1.5 $
+$Date: 2009/12/13 12:56:07 $
+$Author: faust $
+*/
+#pragma once
+
+#include "stg/plugin.h"
+#include "stg/module_settings.h"
+#include "stg/logger.h"
+
+#include <string>
+#include <cstdint>
+
+#include <pthread.h>
+#include <unistd.h> // close
+
+#define VERSION "cap_nf v. 0.4"
+#define START_POS 40
+#define STOP_POS 40
+
+namespace STG
+{
+
+struct Users;
+struct Tariffs;
+struct Admins;
+struct TraffCounter;
+struct Store;
+struct Settings;
+
+}
+
+class NF_CAP : public STG::Plugin {
+public:
+    NF_CAP();
+
+    void            SetTraffcounter(STG::TraffCounter * tc) override { traffCnt = tc; }
+    void            SetSettings(const STG::ModuleSettings & s) override { settings = s; }
+    int             ParseSettings() override;
+
+    int             Start() override;
+    int             Stop() override;
+    int             Reload(const STG::ModuleSettings & /*ms*/) override { return 0; }
+
+    bool            IsRunning() override { return runningTCP || runningUDP; }
+    const std::string & GetStrError() const override { return errorStr; }
+    std::string     GetVersion() const override { return VERSION; }
+    uint16_t        GetStartPosition() const override { return START_POS; }
+    uint16_t        GetStopPosition() const override { return STOP_POS; }
+
+private:
+    NF_CAP(const NF_CAP & rvalue);
+    NF_CAP & operator=(const NF_CAP & rvalue);
+
+    STG::TraffCounter * traffCnt;
+    STG::ModuleSettings settings;
+    pthread_t tidTCP;
+    pthread_t tidUDP;
+    bool runningTCP;
+    bool runningUDP;
+    bool stoppedTCP;
+    bool stoppedUDP;
+    uint16_t portT;
+    uint16_t portU;
+    int sockTCP;
+    int sockUDP;
+    mutable std::string errorStr;
+    STG::PluginLogger logger;
+
+    static void * RunUDP(void *);
+    static void * RunTCP(void *);
+    void ParseBuffer(uint8_t * buf, ssize_t size);
+
+    bool OpenTCP();
+    bool OpenUDP();
+    void CloseTCP() { close(sockTCP); }
+    void CloseUDP() { close(sockUDP); }
+};
diff --git a/projects/stargazer/plugins/capture/divert_freebsd/divert_cap.cpp b/projects/stargazer/plugins/capture/divert_freebsd/divert_cap.cpp
new file mode 100644 (file)
index 0000000..2898468
--- /dev/null
@@ -0,0 +1,316 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+* Author : Boris Mikhailenko <stg34@stg.dp.ua>
+*/
+
+/*
+$Revision: 1.13 $
+$Date: 2010/09/10 06:43:03 $
+*/
+
+#include "divert_cap.h"
+
+#include "stg/traffcounter.h"
+#include "stg/raw_ip_packet.h"
+#include "stg/common.h"
+
+#include <algorithm>
+#include <vector>
+
+#include <cstdio>
+#include <cstring>
+#include <cerrno>
+#include <cstdlib>
+#include <csignal>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <sys/uio.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/poll.h>
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#define BUFF_LEN (16384) /* max mtu -> lo=16436  TODO why?*/
+
+//-----------------------------------------------------------------------------
+struct DIVERT_DATA {
+int sock;
+short int port;
+char iface[10];
+};
+//-----------------------------------------------------------------------------
+pollfd pollddiv;
+DIVERT_DATA cddiv;  //capture data
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+extern "C" STG::Plugin* GetPlugin()
+{
+    static DIVERT_CAP plugin;
+    return &plugin;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+std::string DIVERT_CAP::GetVersion() const
+{
+return "cap_divert v.1.0";
+}
+//-----------------------------------------------------------------------------
+DIVERT_CAP::DIVERT_CAP()
+    : port(0),
+      disableForwarding(false),
+      nonstop(false),
+      isRunning(false),
+      traffCnt(NULL),
+      logger(STG::PluginLogger::get("cap_divert"))
+{
+}
+//-----------------------------------------------------------------------------
+int DIVERT_CAP::Start()
+{
+if (isRunning)
+    return 0;
+
+if (DivertCapOpen() < 0)
+    {
+    errorStr = "Cannot open socket!";
+    printfd(__FILE__, "Cannot open socket\n");
+    return -1;
+    }
+
+nonstop = true;
+
+if (pthread_create(&thread, NULL, Run, this))
+    {
+    errorStr = "Cannot create thread.";
+    logger("Cannot create thread.");
+    printfd(__FILE__, "Cannot create thread\n");
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int DIVERT_CAP::Stop()
+{
+if (!isRunning)
+    return 0;
+
+DivertCapClose();
+
+nonstop = false;
+
+//5 seconds to thread stops itself
+int i;
+for (i = 0; i < 25; i++)
+    {
+    if (!isRunning)
+        break;
+
+    struct timespec ts = {0, 200000000};
+    nanosleep(&ts, NULL);
+    }
+
+//after 5 seconds waiting thread still running. now killing it
+if (isRunning)
+    {
+    if (pthread_kill(thread, SIGINT))
+        {
+        errorStr = "Cannot kill thread.";
+        logger("Cannot send signal to thread.");
+        printfd(__FILE__, "Cannot kill thread\n");
+        return -1;
+        }
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+void * DIVERT_CAP::Run(void * d)
+{
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+DIVERT_CAP * dc = static_cast<DIVERT_CAP *>(d);
+dc->isRunning = true;
+
+char buffer[STG::packetSize + 14];
+while (dc->nonstop)
+    {
+    STG::RawPacket rp;
+    dc->DivertCapRead(buffer, sizeof(buffer), NULL);
+
+    if (buffer[12] != 0x8)
+        continue;
+
+    memcpy(&rp.rawPacket, &buffer[14], STG::packetSize);
+
+    dc->traffCnt->process(rp);
+    }
+
+dc->isRunning = false;
+return NULL;
+}
+//-----------------------------------------------------------------------------
+int DIVERT_CAP::DivertCapOpen()
+{
+memset(&pollddiv, 0, sizeof(pollddiv));
+memset(&cddiv, 0, sizeof(DIVERT_DATA));
+
+strcpy(cddiv.iface, "foo");
+cddiv.port = port;
+
+DivertCapOpen(0);
+pollddiv.events = POLLIN;
+pollddiv.fd = cddiv.sock;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int DIVERT_CAP::DivertCapOpen(int)
+{
+int ret;
+cddiv.sock = socket(PF_INET, SOCK_RAW, IPPROTO_DIVERT);
+if (cddiv.sock < 0)
+    {
+    errorStr = "Create divert socket error.";
+    logger("Cannot create a socket: %s", strerror(errno));
+    printfd(__FILE__, "Cannot create divert socket\n");
+    return -1;
+    }
+
+struct sockaddr_in divAddr;
+
+memset(&divAddr, 0, sizeof(divAddr));
+
+divAddr.sin_family = AF_INET;
+divAddr.sin_port = htons(cddiv.port);
+divAddr.sin_addr.s_addr = INADDR_ANY;
+
+ret = bind(cddiv.sock, (struct sockaddr *)&divAddr, sizeof(divAddr));
+
+if (ret < 0)
+    {
+    errorStr = "Bind divert socket error.";
+    logger("Cannot bind the scoket: %s", strerror(errno));
+    printfd(__FILE__, "Cannot bind divert socket\n");
+    return -1;
+    }
+
+return cddiv.sock;
+}
+//-----------------------------------------------------------------------------
+int DIVERT_CAP::DivertCapRead(char * b, int blen, char ** iface)
+{
+poll(&pollddiv, 1, -1);
+
+if (pollddiv.revents & POLLIN)
+    {
+    DivertCapRead(b, blen, iface, 0);
+    pollddiv.revents = 0;
+    return 0;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int DIVERT_CAP::DivertCapRead(char * b, int blen, char ** iface, int)
+{
+static char buf[BUFF_LEN];
+static struct sockaddr_in divertaddr;
+static int bytes;
+static socklen_t divertaddrSize = sizeof(divertaddr);
+
+if ((bytes = recvfrom (cddiv.sock, buf, BUFF_LEN,
+                       0, (struct sockaddr*) &divertaddr, &divertaddrSize)) > 50)
+    {
+    memcpy(b + 14, buf, blen - 14);
+    b[12] = 0x8;
+
+    if (iface)
+        *iface = cddiv.iface;
+
+    if (!disableForwarding)
+        {
+        if (sendto(cddiv.sock, buf, bytes, 0, (struct sockaddr*)&divertaddr, divertaddrSize) < 0)
+            logger("sendto error: %s", strerror(errno));
+        }
+    }
+else
+    {
+    if (bytes < 0)
+        logger("recvfrom error: %s", strerror(errno));
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int DIVERT_CAP::DivertCapClose()
+{
+close(cddiv.sock);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int DIVERT_CAP::ParseSettings()
+{
+int p;
+STG::ParamValue pv;
+std::vector<STG::ParamValue>::const_iterator pvi;
+
+pv.param = "Port";
+pvi = std::find(settings.moduleParams.begin(), settings.moduleParams.end(), pv);
+if (pvi == settings.moduleParams.end() || pvi->value.empty())
+    {
+    p = 15701;
+    }
+else if (ParseIntInRange(pvi->value[0], 1, 65535, &p))
+    {
+    errorStr = "Cannot parse parameter \'Port\': " + errorStr;
+    printfd(__FILE__, "Cannot parse parameter 'Port'\n");
+    return -1;
+    }
+
+port = p;
+
+bool d = false;
+pv.param = "DisableForwarding";
+pvi = std::find(settings.moduleParams.begin(), settings.moduleParams.end(), pv);
+if (pvi == settings.moduleParams.end() || pvi->value.empty())
+    {
+    disableForwarding = false;
+    }
+else if (ParseYesNo(pvi->value[0], &d))
+    {
+    errorStr = "Cannot parse parameter \'DisableForwarding\': " + errorStr;
+    printfd(__FILE__, "Cannot parse parameter 'DisableForwarding'\n");
+    return -1;
+    }
+
+disableForwarding = d;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
diff --git a/projects/stargazer/plugins/capture/divert_freebsd/divert_cap.h b/projects/stargazer/plugins/capture/divert_freebsd/divert_cap.h
new file mode 100644 (file)
index 0000000..290754f
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+/*
+ Author : Boris Mikhailenko <stg34@stg.dp.ua>
+*/
+
+#pragma once
+
+#include "stg/plugin.h"
+#include "stg/module_settings.h"
+#include "stg/logger.h"
+
+#include <string>
+
+#include <pthread.h>
+
+namespace STG
+{
+struct Users;
+struct Tariffs;
+struct Admins;
+struct TraffCounter;
+struct Settings;
+}
+
+//-----------------------------------------------------------------------------
+class DIVERT_CAP : public STG::Plugin {
+public:
+    DIVERT_CAP();
+
+    void                SetTraffcounter(STG::TraffCounter * tc) override { traffCnt = tc; }
+
+    int                 Start() override;
+    int                 Stop() override;
+    int                 Reload(const STG::ModuleSettings & /*ms*/) override { return 0; }
+    bool                IsRunning() override { return isRunning; }
+
+    void                SetSettings(const STG::ModuleSettings & s) override { settings = s; }
+    int                 ParseSettings() override;
+    const std::string & GetStrError() const override { return errorStr; }
+    std::string         GetVersion() const override;
+    uint16_t            GetStartPosition() const override { return 40; }
+    uint16_t            GetStopPosition() const override { return 40; }
+
+private:
+    DIVERT_CAP(const DIVERT_CAP & rvalue);
+    DIVERT_CAP & operator=(const DIVERT_CAP & rvalue);
+
+    static void *       Run(void *);
+
+    int                 DivertCapOpen();
+    int                 DivertCapOpen(int n);
+    int                 DivertCapRead(char * buffer, int blen, char ** iface);
+    int                 DivertCapRead(char * buffer, int blen, char ** iface, int n);
+    int                 DivertCapClose();
+
+    STG::ModuleSettings     settings;
+
+    int                 port;
+    bool                disableForwarding;
+
+    mutable std::string errorStr;
+
+    pthread_t           thread;
+
+    bool                nonstop;
+    bool                isRunning;
+
+    STG::TraffCounter *      traffCnt;
+
+    STG::PluginLogger       logger;
+};
diff --git a/projects/stargazer/plugins/capture/ether_freebsd/ether_cap.cpp b/projects/stargazer/plugins/capture/ether_freebsd/ether_cap.cpp
new file mode 100644 (file)
index 0000000..f063da9
--- /dev/null
@@ -0,0 +1,359 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+Date: 18.09.2002
+*/
+
+/*
+* Author : Boris Mikhailenko <stg34@stg.dp.ua>
+*/
+
+/*
+$Revision: 1.19 $
+$Date: 2009/03/24 11:20:15 $
+$Author: faust $
+*/
+
+#include "ether_cap.h"
+
+#include "stg/common.h"
+#include "stg/raw_ip_packet.h"
+#include "stg/traffcounter.h"
+
+#include <cerrno>
+#include <cstdio>
+#include <cstring>
+#include <cstdlib>
+#include <csignal>
+
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+
+#include <net/bpf.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+//#define CAP_DEBUG 1
+
+extern "C" STG::Plugin* GetPlugin()
+{
+    static BPF_CAP plugin;
+    return &plugin;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+int BPF_CAP_SETTINGS::ParseSettings(const STG::ModuleSettings & s)
+{
+iface.erase(iface.begin(), iface.end());
+
+if (s.moduleParams.empty())
+    {
+    errorStr = "Parameter \'iface\' not found.";
+    printfd(__FILE__, "Parameter 'iface' not found\n");
+    return -1;
+    }
+
+for (unsigned i = 0; i < s.moduleParams.size(); i++)
+    {
+    if (s.moduleParams[i].param != "iface")
+        {
+        errorStr = "Parameter \'" + s.moduleParams[i].param + "\' unrecognized.";
+        printfd(__FILE__, "Invalid parameter: '%s'\n", s.moduleParams[i].param.c_str());
+        return -1;
+        }
+    for (unsigned j = 0; j < s.moduleParams[i].value.size(); j++)
+        {
+        iface.push_back(s.moduleParams[i].value[j]);
+        }
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+std::string BPF_CAP_SETTINGS::GetIface(unsigned int num)
+{
+if (num >= iface.size())
+    {
+    return "";
+    }
+return iface[num];
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+std::string BPF_CAP::GetVersion() const
+{
+return "cap_bpf v.1.0";
+}
+//-----------------------------------------------------------------------------
+BPF_CAP::BPF_CAP()
+    : nonstop(false),
+      isRunning(false),
+      capSock(-1),
+      traffCnt(NULL),
+      logger(STG::PluginLogger::get("cap_bpf"))
+{
+}
+//-----------------------------------------------------------------------------
+int BPF_CAP::ParseSettings()
+{
+int ret = capSettings.ParseSettings(settings);
+if (ret)
+    {
+    errorStr = capSettings.GetStrError();
+    return ret;
+    }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int BPF_CAP::Start()
+{
+if (isRunning)
+    return 0;
+
+if (BPFCapOpen() < 0)
+    {
+    //errorStr = "Cannot open bpf device!";
+    return -1;
+    }
+
+nonstop = true;
+
+if (pthread_create(&thread, NULL, Run, this))
+    {
+    errorStr = "Cannot create thread.";
+    logger("Cannot create thread.");
+    printfd(__FILE__, "Cannot create thread\n");
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int BPF_CAP::Stop()
+{
+if (!isRunning)
+    return 0;
+
+BPFCapClose();
+
+nonstop = false;
+
+//5 seconds to thread stops itself
+int i;
+for (i = 0; i < 25; i++)
+    {
+    if (!isRunning)
+        break;
+
+    struct timespec ts = {0, 200000000};
+    nanosleep(&ts, NULL);
+    }
+
+//after 5 seconds waiting thread still running. now killing it
+if (isRunning)
+    {
+    //TODO pthread_cancel()
+    if (pthread_kill(thread, SIGINT))
+        {
+        errorStr = "Cannot kill thread.";
+        logger("Cannot send signal to thread.");
+        printfd(__FILE__, "Cannot kill thread\n");
+        return -1;
+        }
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+void * BPF_CAP::Run(void * d)
+{
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+BPF_CAP * dc = static_cast<BPF_CAP *>(d);
+dc->isRunning = true;
+
+uint8_t hdr[96]; //68 + 14 + 4(size) + 9(SYS_IFACE) + 1(align to 4) = 96
+
+STG::RawPacket *  rpp = (STG::RawPacket *)&hdr[14];
+memset(hdr, 0, sizeof(hdr));
+
+rpp->dataLen = -1;
+char * iface;
+
+while (dc->nonstop)
+    {
+    if (dc->BPFCapRead((char*)&hdr, 68 + 14, &iface))
+        continue;
+
+    if (!(hdr[12] == 0x8 && hdr[13] == 0x0))
+        continue;
+
+    dc->traffCnt->process(*rpp);
+    }
+
+dc->isRunning = false;
+return NULL;
+}
+//-----------------------------------------------------------------------------
+int BPF_CAP::BPFCapOpen()
+{
+int i = 0;
+BPF_DATA bd;
+pollfd pd;
+
+while ((bd.iface = capSettings.GetIface(i)) != "")
+    {
+    bpfData.push_back(bd);
+    if (BPFCapOpen(&bpfData[i]) < 0)
+        {
+        return -1;
+        }
+
+    pd.events = POLLIN;
+    pd.fd = bpfData[i].fd;
+    polld.push_back(pd);
+    i++;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int BPF_CAP::BPFCapOpen(BPF_DATA * bd)
+{
+char devbpf[20];
+int i = 0;
+int l = BUFF_LEN;
+int im = 1;
+struct ifreq ifr;
+
+do
+    {
+    sprintf(devbpf, "/dev/bpf%d", i);
+    i++;
+    bd->fd = open(devbpf, O_RDONLY);
+    } while(bd->fd < 0 && errno == EBUSY);
+
+if (bd->fd < 0)
+    {
+    errorStr = "Can't capture packets. Open bpf device for " + bd->iface + " error.";
+    logger("Cannot open device for interface '%s': %s", bd->iface.c_str(), strerror(errno));
+    printfd(__FILE__, "Cannot open BPF device\n");
+    return -1;
+    }
+
+strncpy(ifr.ifr_name, bd->iface.c_str(), sizeof(ifr.ifr_name));
+
+if (ioctl(bd->fd, BIOCSBLEN, (caddr_t)&l) < 0)
+    {
+    errorStr = bd->iface + " BIOCSBLEN " + std::string(strerror(errno));
+    logger("ioctl (BIOCSBLEN) error for interface '%s': %s", bd->iface.c_str(), strerror(errno));
+    printfd(__FILE__, "ioctl failed: '%s'\n", errorStr.c_str());
+    return -1;
+    }
+
+if (ioctl(bd->fd, BIOCSETIF, (caddr_t)&ifr) < 0)
+    {
+    errorStr = bd->iface + " BIOCSETIF " + std::string(strerror(errno));
+    logger("ioctl (BIOCSETIF) error for interface '%s': %s", bd->iface.c_str(), strerror(errno));
+    printfd(__FILE__, "ioctl failed: '%s'\n", errorStr.c_str());
+    return -1;
+    }
+
+if (ioctl(bd->fd, BIOCIMMEDIATE, &im) < 0)
+    {
+    errorStr = bd->iface + " BIOCIMMEDIATE " + std::string(strerror(errno));
+    logger("ioctl (BIOCIMMEDIATE) error for interface '%s': %s", bd->iface.c_str(), strerror(errno));
+    printfd(__FILE__, "ioctl failed: '%s'\n", errorStr.c_str());
+    return -1;
+    }
+
+return bd->fd;
+}
+//-----------------------------------------------------------------------------
+int BPF_CAP::BPFCapClose()
+{
+for (unsigned int i = 0; i < bpfData.size(); i++)
+    close(bpfData[i].fd);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int BPF_CAP::BPFCapRead(char * buffer, int blen, char ** capIface)
+{
+poll(&polld[0], polld.size(), -1);
+
+for (unsigned int i = 0; i < polld.size(); i++)
+    {
+    if (polld[i].revents & POLLIN)
+        {
+        if (BPFCapRead(buffer, blen, capIface, &bpfData[i]))
+            {
+            polld[i].revents = 0;
+            continue;
+            }
+        polld[i].revents = 0;
+        return 0;
+        }
+    }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int BPF_CAP::BPFCapRead(char * buffer, int blen, char **, BPF_DATA * bd)
+{
+if (bd->canRead)
+    {
+    bd->r = read(bd->fd, bd->buffer, BUFF_LEN);
+    if (bd->r < 0)
+        {
+        logger("read error: %s", strerror(errno));
+        struct timespec ts = {0, 20000000};
+        nanosleep(&ts, NULL);
+        return -1;
+        }
+
+    bd->p = bd->buffer;
+    bd->bh = (struct bpf_hdr*)bd->p;
+    bd->canRead = 0;
+    }
+
+if(bd->r > bd->sum)
+    {
+    memcpy(buffer, (char*)(bd->p) + bd->bh->bh_hdrlen, blen);
+
+    bd->sum += BPF_WORDALIGN(bd->bh->bh_hdrlen + bd->bh->bh_caplen);
+    bd->p = bd->p + BPF_WORDALIGN(bd->bh->bh_hdrlen + bd->bh->bh_caplen);
+    bd->bh = (struct bpf_hdr*)bd->p;
+    }
+
+if(bd->r <= bd->sum)
+    {
+    bd->canRead = 1;
+    bd->sum = 0;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
diff --git a/projects/stargazer/plugins/capture/ether_freebsd/ether_cap.h b/projects/stargazer/plugins/capture/ether_freebsd/ether_cap.h
new file mode 100644 (file)
index 0000000..07380bd
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+ /*
+ $Revision: 1.11 $
+ $Date: 2009/06/23 11:32:27 $
+ $Author: faust $
+ */
+
+/*
+* Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+*/
+
+#pragma once
+
+#include "stg/plugin.h"
+#include "stg/module_settings.h"
+#include "stg/logger.h"
+
+#include <string>
+#include <vector>
+#include <cstdint>
+
+#include <pthread.h>
+#include <sys/poll.h>
+
+#define BUFF_LEN (128)
+
+namespace STG
+{
+struct TraffCounter;
+}
+
+//-----------------------------------------------------------------------------
+struct BPF_DATA {
+    BPF_DATA()
+        {
+        fd = 0;
+        p = NULL;
+        r = 0;
+        sum = 0;
+        memset(buffer, 0, BUFF_LEN);
+        bh = NULL;
+        canRead = 1;
+        iface = "";
+        };
+
+    BPF_DATA(const BPF_DATA & bd)
+        {
+        fd = bd.fd;
+        p = bd.p;
+        r = bd.r;
+        sum = bd.sum;
+        memcpy(buffer, bd.buffer, BUFF_LEN);
+        bh = bd.bh;
+        canRead = bd.canRead;
+        iface = bd.iface;
+        };
+
+int              fd;
+uint8_t *        p;
+int              r;
+int              sum;
+uint8_t          buffer[BUFF_LEN];
+struct bpf_hdr * bh;
+int              canRead;
+std::string      iface;
+};
+//-----------------------------------------------------------------------------
+class BPF_CAP_SETTINGS {
+public:
+    const std::string & GetStrError() const { return errorStr; }
+    int             ParseSettings(const STG::ModuleSettings & s);
+    std::string     GetIface(unsigned int num);
+
+private:
+    std::vector<std::string> iface;
+    mutable std::string errorStr;
+};
+//-----------------------------------------------------------------------------
+class BPF_CAP : public STG::Plugin {
+public:
+                        BPF_CAP();
+
+    void                SetTraffcounter(STG::TraffCounter * tc) override { traffCnt = tc; }
+
+    int                 Start() override;
+    int                 Stop() override;
+    int                 Reload(const STG::ModuleSettings & /*ms*/) override { return 0; }
+    bool                IsRunning() override { return isRunning; }
+
+    void                SetSettings(const STG::ModuleSettings & s) override { settings = s; }
+    int                 ParseSettings() override;
+
+    const std::string & GetStrError() const override { return errorStr; }
+    std::string         GetVersion() const override;
+    uint16_t            GetStartPosition() const override { return 40; }
+    uint16_t            GetStopPosition() const override { return 40; }
+
+private:
+    BPF_CAP(const BPF_CAP & rvalue);
+    BPF_CAP & operator=(const BPF_CAP & rvalue);
+
+    static void *       Run(void *);
+    int                 BPFCapOpen();
+    int                 BPFCapOpen(BPF_DATA * bd);
+    int                 BPFCapClose();
+    int                 BPFCapRead(char * buffer, int blen, char ** iface);
+    int                 BPFCapRead(char * buffer, int blen, char ** iface, BPF_DATA * bd);
+
+    BPF_CAP_SETTINGS      capSettings;
+
+    mutable std::string   errorStr;
+
+    std::vector<BPF_DATA> bpfData;
+    std::vector<pollfd>   polld;
+
+    pthread_t             thread;
+    bool                  nonstop;
+    bool                  isRunning;
+    int                   capSock;
+    STG::ModuleSettings       settings;
+
+    STG::TraffCounter *        traffCnt;
+
+    STG::PluginLogger         logger;
+};
diff --git a/projects/stargazer/plugins/capture/ether_linux/ether_cap.cpp b/projects/stargazer/plugins/capture/ether_linux/ether_cap.cpp
new file mode 100644 (file)
index 0000000..7ca6c01
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+Date: 18.09.2002
+*/
+
+/*
+* Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+*/
+
+/*
+$Revision: 1.23 $
+$Date: 2009/12/13 13:45:13 $
+*/
+
+#include "ether_cap.h"
+
+#include "stg/common.h"
+#include "stg/raw_ip_packet.h"
+#include "stg/traffcounter.h"
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <cerrno>
+#include <csignal>
+
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <linux/if_ether.h>
+#include <linux/if_packet.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+
+//#define CAP_DEBUG 1
+
+extern "C" STG::Plugin* GetPlugin()
+{
+    static ETHER_CAP plugin;
+    return &plugin;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+std::string ETHER_CAP::GetVersion() const
+{
+return "cap_ether v.1.2";
+}
+//-----------------------------------------------------------------------------
+ETHER_CAP::ETHER_CAP()
+    : nonstop(false),
+      isRunning(false),
+      capSock(-1),
+      traffCnt(NULL),
+      logger(STG::PluginLogger::get("cap_ether"))
+{
+}
+//-----------------------------------------------------------------------------
+int ETHER_CAP::Start()
+{
+if (isRunning)
+    return 0;
+
+if (EthCapOpen() < 0)
+    {
+    errorStr = "Cannot open socket!";
+    printfd(__FILE__, "Cannot open socket\n");
+    return -1;
+    }
+
+nonstop = true;
+
+if (pthread_create(&thread, NULL, Run, this))
+    {
+    errorStr = "Cannot create thread.";
+    logger("Cannot create thread.");
+    printfd(__FILE__, "Cannot create thread\n");
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int ETHER_CAP::Stop()
+{
+if (!isRunning)
+    return 0;
+
+nonstop = false;
+
+//5 seconds to thread stops itself
+for (int i = 0; i < 25 && isRunning; i++)
+    {
+    struct timespec ts = {0, 200000000};
+    nanosleep(&ts, NULL);
+    }
+//after 5 seconds waiting thread still running. now killing it
+if (isRunning)
+    {
+    if (pthread_kill(thread, SIGUSR1))
+        {
+        errorStr = "Cannot kill thread.";
+        logger("Cannot send signal to thread.");
+        return -1;
+        }
+    for (int i = 0; i < 25 && isRunning; ++i)
+        {
+        struct timespec ts = {0, 200000000};
+        nanosleep(&ts, NULL);
+        }
+    if (isRunning)
+        {
+        errorStr = "ETHER_CAP not stopped.";
+        logger("Cannot stop thread.");
+        printfd(__FILE__, "Cannot stop thread\n");
+        return -1;
+        }
+    else
+        {
+        pthread_join(thread, NULL);
+        }
+    }
+
+EthCapClose();
+return 0;
+}
+//-----------------------------------------------------------------------------
+void * ETHER_CAP::Run(void * d)
+{
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+ETHER_CAP * dc = static_cast<ETHER_CAP *>(d);
+dc->isRunning = true;
+
+struct ETH_IP
+{
+uint16_t    ethHdr[8];
+STG::RawPacket  rp;
+char        padding[4];
+char        padding1[8];
+};
+
+char ethip[sizeof(ETH_IP)];
+
+memset(&ethip, 0, sizeof(ETH_IP));
+
+ETH_IP * ethIP = static_cast<ETH_IP *>(static_cast<void *>(&ethip));
+ethIP->rp.dataLen = -1;
+
+char * iface = NULL;
+
+while (dc->nonstop)
+    {
+    if (dc->EthCapRead(&ethip, 68 + 14, &iface))
+        {
+        continue;
+        }
+
+    if (ethIP->ethHdr[7] != 0x8)
+        continue;
+
+    dc->traffCnt->process(ethIP->rp);
+    }
+
+dc->isRunning = false;
+return NULL;
+}
+//-----------------------------------------------------------------------------
+int ETHER_CAP::EthCapOpen()
+{
+capSock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+if (capSock < 0)
+    logger("Cannot create socket: %s", strerror(errno));
+return capSock;
+}
+//-----------------------------------------------------------------------------
+int ETHER_CAP::EthCapClose()
+{
+close(capSock);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int ETHER_CAP::EthCapRead(void * buffer, int blen, char **)
+{
+struct sockaddr_ll  addr;
+int addrLen;
+
+if (!WaitPackets(capSock))
+    {
+    return ENODATA;
+    }
+
+addrLen = sizeof(addr);
+
+if (recvfrom(capSock, ((char*)buffer) + 2, blen, 0, (struct sockaddr *)&addr, (socklen_t*)&addrLen) < 0)
+    {
+    logger("recvfrom error: %s", strerror(errno));
+    return ENODATA;
+    }
+
+return 0;
+}
diff --git a/projects/stargazer/plugins/capture/ether_linux/ether_cap.h b/projects/stargazer/plugins/capture/ether_linux/ether_cap.h
new file mode 100644 (file)
index 0000000..cf776a4
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+ /*
+ $Revision: 1.12 $
+ $Date: 2009/12/13 13:45:13 $
+ */
+
+/*
+* Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+*/
+
+#pragma once
+
+#include <pthread.h>
+
+#include <string>
+
+#include "stg/plugin.h"
+#include "stg/module_settings.h"
+#include "stg/logger.h"
+
+namespace STG
+{
+
+struct Users;
+struct Tariffs;
+struct Admins;
+struct TraffCounter;
+struct Settings;
+
+}
+
+//-----------------------------------------------------------------------------
+class ETHER_CAP : public STG::Plugin {
+public:
+    ETHER_CAP();
+
+    void                SetTraffcounter(STG::TraffCounter * tc) { traffCnt = tc; }
+
+    int                 Start();
+    int                 Stop();
+    int                 Reload(const STG::ModuleSettings & /*ms*/) { return 0; }
+    bool                IsRunning() { return isRunning; }
+
+    int                 ParseSettings() { return 0; }
+    const std::string & GetStrError() const { return errorStr; }
+    std::string         GetVersion() const;
+    uint16_t            GetStartPosition() const { return 40; }
+    uint16_t            GetStopPosition() const { return 40; }
+
+private:
+    ETHER_CAP(const ETHER_CAP & rvalue);
+    ETHER_CAP & operator=(const ETHER_CAP & rvalue);
+
+    static void *       Run(void *);
+    int                 EthCapOpen();
+    int                 EthCapClose();
+    int                 EthCapRead(void * buffer, int blen, char ** iface);
+
+    mutable std::string errorStr;
+
+    pthread_t           thread;
+    bool                nonstop;
+    bool                isRunning;
+    int                 capSock;
+
+    STG::TraffCounter *      traffCnt;
+
+    STG::PluginLogger       logger;
+};
diff --git a/projects/stargazer/plugins/capture/nfqueue/nfqueue.cpp b/projects/stargazer/plugins/capture/nfqueue/nfqueue.cpp
new file mode 100644 (file)
index 0000000..3c79c1b
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+* Author : Maxim Mamontov <faust@stargazer.dp.ua>
+*/
+
+#include "nfqueue.h"
+
+#include "stg/traffcounter.h"
+#include "stg/common.h"
+#include "stg/raw_ip_packet.h"
+
+extern "C" {
+
+#include <linux/netfilter.h>  /* Defines verdicts (NF_ACCEPT, etc) */
+#include <libnetfilter_queue/libnetfilter_queue.h>
+
+}
+
+#include <cerrno>
+#include <csignal>
+
+#include <arpa/inet.h> // ntohl
+
+#include <unistd.h> // read
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+namespace
+{
+
+int Callback(struct nfq_q_handle * queueHandle, struct nfgenmsg * /*msg*/,
+             struct nfq_data * nfqData, void *data)
+{
+int id = 0;
+
+struct nfqnl_msg_packet_hdr * packetHeader = nfq_get_msg_packet_hdr(nfqData);
+if (packetHeader == NULL)
+    return 0;
+
+id = ntohl(packetHeader->packet_id);
+
+unsigned char * payload = NULL;
+
+if (nfq_get_payload(nfqData, &payload) < 0 || payload == NULL)
+    return id;
+
+STG::RawPacket packet;
+
+memcpy(&packet.rawPacket, payload, sizeof(packet.rawPacket));
+
+NFQ_CAP * cap = static_cast<NFQ_CAP *>(data);
+
+cap->Process(packet);
+
+return nfq_set_verdict(queueHandle, id, NF_ACCEPT, 0, NULL);
+}
+
+}
+
+extern "C" STG::Plugin* GetPlugin()
+{
+    static NFQ_CAP plugin;
+    return &plugin;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+std::string NFQ_CAP::GetVersion() const
+{
+return "cap_nfqueue v.1.0";
+}
+//-----------------------------------------------------------------------------
+NFQ_CAP::NFQ_CAP()
+    : nonstop(false),
+      isRunning(false),
+      queueNumber(0),
+      nfqHandle(NULL),
+      queueHandle(NULL),
+      traffCnt(NULL),
+      logger(STG::PluginLogger::get("cap_nfqueue"))
+{
+}
+//-----------------------------------------------------------------------------
+int NFQ_CAP::ParseSettings()
+{
+for (size_t i = 0; i < settings.moduleParams.size(); i++)
+    if (settings.moduleParams[i].param == "queueNumber" && !settings.moduleParams[i].value.empty())
+        if (str2x(settings.moduleParams[i].value[0], queueNumber) < 0)
+            {
+            errorStr = "Queue number should be a number. Got: '" + settings.moduleParams[i].param + "'";
+            logger(errorStr);
+            return -1;
+            }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int NFQ_CAP::Start()
+{
+if (isRunning)
+    return 0;
+
+nfqHandle = nfq_open();
+if (nfqHandle == NULL)
+    {
+    errorStr = "Failed to initialize netfilter queue.";
+    logger(errorStr);
+    return -1;
+    }
+
+if (nfq_unbind_pf(nfqHandle, AF_INET) < 0)
+    {
+    errorStr = "Failed to unbind netfilter queue from IP handling.";
+    logger(errorStr);
+    return -1;
+    }
+
+if (nfq_bind_pf(nfqHandle, AF_INET) < 0)
+    {
+    errorStr = "Failed to bind netfilter queue to IP handling.";
+    logger(errorStr);
+    return -1;
+    }
+
+queueHandle = nfq_create_queue(nfqHandle, queueNumber, &Callback, this);
+if (queueHandle == NULL)
+    {
+    errorStr = "Failed to create queue " + std::to_string(queueNumber) + ".";
+    logger(errorStr);
+    return -1;
+    }
+
+if (nfq_set_mode(queueHandle, NFQNL_COPY_PACKET, 0xffFF) < 0)
+    {
+    errorStr = "Failed to set queue " + std::to_string(queueNumber) + " mode.";
+    logger(errorStr);
+    return -1;
+    }
+
+nonstop = true;
+
+if (pthread_create(&thread, NULL, Run, this))
+    {
+    errorStr = "Cannot create thread.";
+    logger("Cannot create thread.");
+    printfd(__FILE__, "Cannot create thread\n");
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int NFQ_CAP::Stop()
+{
+if (!isRunning)
+    return 0;
+
+nonstop = false;
+
+//5 seconds to thread stops itself
+for (int i = 0; i < 25 && isRunning; i++)
+    {
+    struct timespec ts = {0, 200000000};
+    nanosleep(&ts, NULL);
+    }
+//after 5 seconds waiting thread still running. now killing it
+if (isRunning)
+    {
+    if (pthread_kill(thread, SIGUSR1))
+        {
+        errorStr = "Cannot kill thread.";
+        logger("Cannot send signal to thread.");
+        return -1;
+        }
+    for (int i = 0; i < 25 && isRunning; ++i)
+        {
+        struct timespec ts = {0, 200000000};
+        nanosleep(&ts, NULL);
+        }
+    if (isRunning)
+        {
+        errorStr = "NFQ_CAP not stopped.";
+        logger("Cannot stop thread.");
+        printfd(__FILE__, "Cannot stop thread\n");
+        return -1;
+        }
+    }
+
+pthread_join(thread, NULL);
+
+nfq_destroy_queue(queueHandle);
+nfq_close(nfqHandle);
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+void * NFQ_CAP::Run(void * d)
+{
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+NFQ_CAP * dc = static_cast<NFQ_CAP *>(d);
+dc->isRunning = true;
+
+int fd = nfq_fd(dc->nfqHandle);
+char buf[4096];
+
+while (dc->nonstop)
+    {
+        if (!WaitPackets(fd))
+            continue;
+
+        int rv = read(fd, buf, sizeof(buf));
+        if (rv < 0)
+            {
+            dc->errorStr = std::string("Read error: ") + strerror(errno);
+            dc->logger(dc->errorStr);
+            break;
+            }
+        nfq_handle_packet(dc->nfqHandle, buf, rv);
+    }
+
+dc->isRunning = false;
+return NULL;
+}
+//-----------------------------------------------------------------------------
+void NFQ_CAP::Process(const STG::RawPacket & packet)
+{
+traffCnt->process(packet);
+}
diff --git a/projects/stargazer/plugins/capture/nfqueue/nfqueue.h b/projects/stargazer/plugins/capture/nfqueue/nfqueue.h
new file mode 100644 (file)
index 0000000..7d71bcd
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+* Author : Maxim Mamontov <faust@stargazer.dp.ua>
+*/
+
+#pragma once
+
+#include "stg/plugin.h"
+#include "stg/module_settings.h"
+#include "stg/logger.h"
+
+#include <string>
+#include <vector>
+
+#include <pthread.h>
+
+namespace STG
+{
+
+struct Users;
+struct Tariffs;
+struct Admins;
+struct TraffCounter;
+struct Settings;
+struct RawPacket;
+
+}
+
+struct nfq_handle;
+struct nfq_q_handle;
+
+class NFQ_CAP : public STG::Plugin {
+public:
+    NFQ_CAP();
+
+    void                SetTraffcounter(STG::TraffCounter * tc) override { traffCnt = tc; }
+
+    int                 Start() override;
+    int                 Stop() override;
+    int                 Reload(const STG::ModuleSettings & /*ms*/) override { return 0; }
+    bool                IsRunning() override { return isRunning; }
+
+    void                SetSettings(const STG::ModuleSettings & s) override { settings = s; }
+    int                 ParseSettings() override;
+
+    const std::string & GetStrError() const override { return errorStr; }
+    std::string         GetVersion() const override;
+    uint16_t            GetStartPosition() const override { return 40; }
+    uint16_t            GetStopPosition() const override { return 40; }
+
+    void                Process(const STG::RawPacket & packet);
+
+private:
+    NFQ_CAP(const NFQ_CAP & rvalue);
+    NFQ_CAP & operator=(const NFQ_CAP & rvalue);
+
+    static void *       Run(void *);
+
+    mutable std::string errorStr;
+
+    pthread_t           thread;
+    bool                nonstop;
+    bool                isRunning;
+    STG::ModuleSettings     settings;
+
+    size_t              queueNumber;
+
+    struct nfq_handle * nfqHandle;
+    struct nfq_q_handle * queueHandle;
+
+    STG::TraffCounter *      traffCnt;
+
+    STG::PluginLogger       logger;
+};
diff --git a/projects/stargazer/plugins/capture/pcap/pcap_cap.cpp b/projects/stargazer/plugins/capture/pcap/pcap_cap.cpp
new file mode 100644 (file)
index 0000000..394487f
--- /dev/null
@@ -0,0 +1,296 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+* Author : Maxim Mamontov <faust@stargazer.dp.ua>
+*/
+
+#include "pcap_cap.h"
+
+#include "stg/traffcounter.h"
+#include "stg/common.h"
+#include "stg/raw_ip_packet.h"
+
+#include <signal.h>
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+namespace
+{
+
+const size_t SNAP_LEN = 1518;
+const size_t ETHER_ADDR_LEN = 6;
+
+struct ETH
+{
+u_char     ether_dhost[ETHER_ADDR_LEN];    /* destination host address */
+u_char     ether_shost[ETHER_ADDR_LEN];    /* source host address */
+u_short    ether_type;                     /* IP? ARP? RARP? etc */
+};
+
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+extern "C" STG::Plugin* GetPlugin()
+{
+    static PCAP_CAP plugin;
+    return &plugin;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+std::string PCAP_CAP::GetVersion() const
+{
+return "pcap_cap v.1.0";
+}
+//-----------------------------------------------------------------------------
+PCAP_CAP::PCAP_CAP()
+    : nonstop(false),
+      isRunning(false),
+      traffCnt(NULL),
+      logger(STG::PluginLogger::get("pcap_cap"))
+{
+}
+//-----------------------------------------------------------------------------
+int PCAP_CAP::ParseSettings()
+{
+devices.erase(devices.begin(), devices.end());
+
+if (settings.moduleParams.empty())
+    {
+    devices.push_back(DEV());
+    logger("Defaulting to pseudo-device 'any'.");
+    return 0;
+    }
+
+for (size_t i = 0; i < settings.moduleParams.size(); i++)
+    if (settings.moduleParams[i].param == "interfaces")
+        for (size_t j = 0; j < settings.moduleParams[i].value.size(); j++)
+            devices.push_back(DEV(settings.moduleParams[i].value[j]));
+
+for (size_t i = 0; i < settings.moduleParams.size(); i++)
+    if (settings.moduleParams[i].param == "filters")
+        for (size_t j = 0; j < settings.moduleParams[i].value.size(); j++)
+            if (j < devices.size())
+                devices[j].filterExpression = settings.moduleParams[i].value[j];
+
+if (devices.empty())
+    {
+    devices.push_back(DEV());
+    logger("Defaulting to pseudo-device 'all'.");
+    return 0;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int PCAP_CAP::Start()
+{
+if (isRunning)
+    return 0;
+
+DEV_MAP::iterator it(devices.begin());
+while (it != devices.end())
+    {
+    bpf_u_int32 mask;
+    bpf_u_int32 net;
+    char errbuf[PCAP_ERRBUF_SIZE];
+
+    /* get network number and mask associated with capture device */
+    if (pcap_lookupnet(it->device.c_str(), &net, &mask, errbuf) == -1)
+        {
+        errorStr = "Couldn't get netmask for device " + it->device + ": " + errbuf;
+        logger(errorStr);
+        printfd(__FILE__, "%s\n", errorStr.c_str());
+        return -1;
+        }
+
+    /* open capture device */
+    it->handle = pcap_open_live(it->device.c_str(), SNAP_LEN, 1, 1000, errbuf);
+    if (it->handle == NULL)
+        {
+        errorStr = "Couldn't open device " + it->device + ": " + errbuf;
+        logger(errorStr);
+        printfd(__FILE__, "%s\n", errorStr.c_str());
+        return -1;
+        }
+
+    if (pcap_setnonblock(it->handle, true, errbuf) == -1)
+        {
+        errorStr = "Couldn't put device " + it->device + " into non-blocking mode: " + errbuf;
+        logger(errorStr);
+        printfd(__FILE__, "%s\n", errorStr.c_str());
+        return -1;
+        }
+
+    /* make sure we're capturing on an Ethernet device [2] */
+    if (pcap_datalink(it->handle) != DLT_EN10MB)
+        {
+        errorStr = it->device + " is not an Ethernet";
+        logger(errorStr);
+        printfd(__FILE__, "%s\n", errorStr.c_str());
+        return -1;
+        }
+
+    /* compile the filter expression */
+    if (pcap_compile(it->handle, &it->filter, it->filterExpression.c_str(), 0, net) == -1)
+        {
+        errorStr = "Couldn't parse filter " + it->filterExpression + ": " + pcap_geterr(it->handle);
+        logger(errorStr);
+        printfd(__FILE__, "%s\n", errorStr.c_str());
+        return -1;
+        }
+
+    /* apply the compiled filter */
+    if (pcap_setfilter(it->handle, &it->filter) == -1)
+        {
+        errorStr = "Couldn't install filter " + it->filterExpression + ": " + pcap_geterr(it->handle);
+        logger(errorStr);
+        printfd(__FILE__, "%s\n", errorStr.c_str());
+        return -1;
+        }
+
+    it->fd = pcap_get_selectable_fd(it->handle);
+    if (it->fd == -1)
+        {
+        errorStr = "Couldn't get a file descriptor for " + it->device + ": " + pcap_geterr(it->handle);
+        logger(errorStr);
+        printfd(__FILE__, "%s\n", errorStr.c_str());
+        return -1;
+        }
+
+    ++it;
+    }
+
+nonstop = true;
+
+if (pthread_create(&thread, NULL, Run, this))
+    {
+    errorStr = "Cannot create thread.";
+    logger("Cannot create thread.");
+    printfd(__FILE__, "Cannot create thread\n");
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int PCAP_CAP::Stop()
+{
+if (!isRunning)
+    return 0;
+
+nonstop = false;
+
+//5 seconds to thread stops itself
+for (int i = 0; i < 25 && isRunning; i++)
+    {
+    struct timespec ts = {0, 200000000};
+    nanosleep(&ts, NULL);
+    }
+//after 5 seconds waiting thread still running. now killing it
+if (isRunning)
+    {
+    if (pthread_kill(thread, SIGUSR1))
+        {
+        errorStr = "Cannot kill thread.";
+        logger("Cannot send signal to thread.");
+        return -1;
+        }
+    for (int i = 0; i < 25 && isRunning; ++i)
+        {
+        struct timespec ts = {0, 200000000};
+        nanosleep(&ts, NULL);
+        }
+    if (isRunning)
+        {
+        errorStr = "PCAP_CAP not stopped.";
+        logger("Cannot stop thread.");
+        printfd(__FILE__, "Cannot stop thread\n");
+        return -1;
+        }
+    }
+
+pthread_join(thread, NULL);
+
+for (DEV_MAP::iterator it(devices.begin()); it != devices.end(); ++it)
+    {
+    pcap_freecode(&it->filter);
+    pcap_close(it->handle);
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+void * PCAP_CAP::Run(void * d)
+{
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+PCAP_CAP * dc = static_cast<PCAP_CAP *>(d);
+dc->isRunning = true;
+
+fd_set fds;
+FD_ZERO(&fds);
+int maxFd = 0;
+for (DEV_MAP::const_iterator it(dc->devices.begin()); it != dc->devices.end(); ++it)
+    {
+    FD_SET(it->fd, &fds);
+    maxFd = std::max(maxFd, it->fd);
+    }
+
+while (dc->nonstop)
+    {
+    fd_set rfds = fds;
+    struct timeval tv = {0, 500000};
+
+    if (select(maxFd + 1, &rfds, NULL, NULL, &tv) > 0)
+        dc->TryRead(rfds);
+    }
+
+dc->isRunning = false;
+return NULL;
+}
+
+void PCAP_CAP::TryRead(const fd_set & set)
+{
+for (DEV_MAP::const_iterator it(devices.begin()); it != devices.end(); ++it)
+    if (FD_ISSET(it->fd, &set))
+        TryReadDev(*it);
+}
+
+void PCAP_CAP::TryReadDev(const DEV & dev)
+{
+struct pcap_pkthdr * header;
+const u_char * packet;
+if (pcap_next_ex(dev.handle, &header, &packet) == -1)
+    {
+    printfd(__FILE__, "Failed to read data from '%s': %s\n", dev.device.c_str(), pcap_geterr(dev.handle));
+    return;
+    }
+
+const ETH * eth = reinterpret_cast<const ETH *>(packet);
+if (eth->ether_type != 0x8)
+    return;
+
+STG::RawPacket ip;
+memcpy(&ip.rawPacket, packet + 14, sizeof(ip.rawPacket));
+traffCnt->process(ip);
+}
diff --git a/projects/stargazer/plugins/capture/pcap/pcap_cap.h b/projects/stargazer/plugins/capture/pcap/pcap_cap.h
new file mode 100644 (file)
index 0000000..f47c6b8
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+* Author : Maxim Mamontov <faust@stargazer.dp.ua>
+*/
+
+#pragma once
+
+#include "stg/plugin.h"
+#include "stg/module_settings.h"
+#include "stg/logger.h"
+
+#include <string>
+#include <vector>
+
+#include <pcap.h>
+#include <pthread.h>
+#include <sys/select.h>
+
+namespace STG
+{
+
+struct Users;
+struct Tariffs;
+struct Admins;
+struct TraffCounter;
+struct Settings;
+
+}
+
+struct DEV
+{
+    DEV() : device("any"), filterExpression("ip"), handle(NULL), fd(-1) {}
+    DEV(const std::string & d) : device(d), filterExpression("ip"), handle(NULL), fd(-1) {}
+    DEV(const std::string & d, const std::string & f)
+        : device(d), filterExpression(f), handle(NULL), fd(-1) {}
+
+    std::string device;
+    std::string filterExpression;
+    pcap_t * handle;
+    struct bpf_program filter;
+    int fd;
+};
+
+typedef std::vector<DEV> DEV_MAP;
+
+class PCAP_CAP : public STG::Plugin {
+public:
+    PCAP_CAP();
+
+    void                SetTraffcounter(STG::TraffCounter * tc) override { traffCnt = tc; }
+
+    int                 Start() override;
+    int                 Stop() override;
+    int                 Reload(const STG::ModuleSettings & /*ms*/) override { return 0; }
+    bool                IsRunning() override { return isRunning; }
+
+    void                SetSettings(const STG::ModuleSettings & s) override { settings = s; }
+    int                 ParseSettings() override;
+
+    const std::string & GetStrError() const override { return errorStr; }
+    std::string         GetVersion() const override;
+    uint16_t            GetStartPosition() const override { return 40; }
+    uint16_t            GetStopPosition() const override { return 40; }
+
+private:
+    PCAP_CAP(const PCAP_CAP & rvalue);
+    PCAP_CAP & operator=(const PCAP_CAP & rvalue);
+
+    void TryRead(const fd_set & set);
+    void TryReadDev(const DEV & dev);
+
+    static void *       Run(void *);
+
+    mutable std::string errorStr;
+
+    pthread_t           thread;
+    bool                nonstop;
+    bool                isRunning;
+    STG::ModuleSettings     settings;
+    DEV_MAP             devices;
+
+    STG::TraffCounter *      traffCnt;
+
+    STG::PluginLogger       logger;
+};
diff --git a/projects/stargazer/plugins/configuration/rpcconfig/admins_methods.cpp b/projects/stargazer/plugins/configuration/rpcconfig/admins_methods.cpp
new file mode 100644 (file)
index 0000000..d8fb012
--- /dev/null
@@ -0,0 +1,257 @@
+#include "admins_methods.h"
+#include "rpcconfig.h"
+
+#include "stg/common.h"
+
+#include "stg/admins.h"
+#include "stg/admin.h"
+#include "stg/admin_conf.h"
+
+#include <ostream> // xmlrpc-c devs have missed something :)
+
+//------------------------------------------------------------------------------
+
+void METHOD_ADMIN_GET::execute(xmlrpc_c::paramList const & paramList,
+                               xmlrpc_c::value *   const   retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string login = paramList.getString(1);
+paramList.verifyEnd(2);
+
+std::map<std::string, xmlrpc_c::value> structVal;
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+    {
+    structVal["result"] = xmlrpc_c::value_boolean(false);
+    *retvalPtr = xmlrpc_c::value_struct(structVal);
+    return;
+    }
+
+STG::Admin * admin;
+
+if (admins->find(login, &admin))
+    {
+    structVal["result"] = xmlrpc_c::value_boolean(false);
+    *retvalPtr = xmlrpc_c::value_struct(structVal);
+    return;
+    }
+
+structVal["result"] = xmlrpc_c::value_boolean(true);
+structVal["login"] = xmlrpc_c::value_string(admin->login());
+structVal["password"] = xmlrpc_c::value_string(admin->password());
+
+const auto priv = admin->priv();
+
+structVal["user_stat"] = xmlrpc_c::value_boolean(priv.userStat);
+structVal["user_conf"] = xmlrpc_c::value_boolean(priv.userConf);
+structVal["user_cash"] = xmlrpc_c::value_boolean(priv.userCash);
+structVal["user_passwd"] = xmlrpc_c::value_boolean(priv.userPasswd);
+structVal["user_add_del"] = xmlrpc_c::value_boolean(priv.userAddDel);
+structVal["admin_chg"] = xmlrpc_c::value_boolean(priv.adminChg);
+structVal["tariff_chg"] = xmlrpc_c::value_boolean(priv.tariffChg);
+
+*retvalPtr = xmlrpc_c::value_struct(structVal);
+}
+
+//------------------------------------------------------------------------------
+
+void METHOD_ADMIN_ADD::execute(xmlrpc_c::paramList const & paramList,
+                               xmlrpc_c::value *   const   retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string login = paramList.getString(1);
+paramList.verifyEnd(2);
+
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+    {
+    printfd(__FILE__, "METHOD_ADMIN_ADD::execute(): 'Not logged or cookie timeout'\n");
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+
+STG::Admin * admin;
+
+if (admins->find(adminInfo.admin, &admin))
+    {
+    printfd(__FILE__, "METHOD_ADMIN_ADD::execute(): 'Invalid admin (logged)'\n");
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+
+if (admins->add(login, *admin))
+    {
+    printfd(__FILE__, "METHOD_ADMIN_ADD::execute(): 'Failed to add admin'\n");
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+
+*retvalPtr = xmlrpc_c::value_boolean(true);
+}
+
+//------------------------------------------------------------------------------
+
+void METHOD_ADMIN_DEL::execute(xmlrpc_c::paramList const & paramList,
+                               xmlrpc_c::value *   const   retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string login = paramList.getString(1);
+paramList.verifyEnd(2);
+
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+
+STG::Admin * admin;
+
+if (admins->find(adminInfo.admin, &admin))
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+
+if (admins->del(login, *admin))
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+
+*retvalPtr = xmlrpc_c::value_boolean(true);
+}
+
+//------------------------------------------------------------------------------
+
+void METHOD_ADMIN_CHG::execute(xmlrpc_c::paramList const & paramList,
+                               xmlrpc_c::value *   const   retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string login = paramList.getString(1);
+xmlrpc_c::value_struct info(paramList.getStruct(2));
+paramList.verifyEnd(3);
+
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+
+STG::Admin * loggedAdmin;
+
+if (admins->find(adminInfo.admin, &loggedAdmin))
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+
+STG::Admin * admin;
+
+if (admins->find(login, &admin))
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+
+STG::AdminConf conf;
+
+conf.priv = admin->priv();
+conf.password = admin->password();
+conf.login = login;
+
+std::map<std::string, xmlrpc_c::value> structVal = info;
+
+std::map<std::string, xmlrpc_c::value>::iterator it;
+
+if ((it = structVal.find("password")) != structVal.end())
+    {
+    conf.password = xmlrpc_c::value_string(it->second);
+    }
+
+if ((it = structVal.find("user_stat")) != structVal.end())
+    {
+    conf.priv.userStat = xmlrpc_c::value_boolean(it->second);
+    }
+
+if ((it = structVal.find("user_conf")) != structVal.end())
+    {
+    conf.priv.userConf = xmlrpc_c::value_boolean(it->second);
+    }
+
+if ((it = structVal.find("user_cash")) != structVal.end())
+    {
+    conf.priv.userCash = xmlrpc_c::value_boolean(it->second);
+    }
+
+if ((it = structVal.find("user_passwd")) != structVal.end())
+    {
+    conf.priv.userPasswd = xmlrpc_c::value_boolean(it->second);
+    }
+
+if ((it = structVal.find("user_add_del")) != structVal.end())
+    {
+    conf.priv.userAddDel = xmlrpc_c::value_boolean(it->second);
+    }
+
+if ((it = structVal.find("admin_chg")) != structVal.end())
+    {
+    conf.priv.adminChg = xmlrpc_c::value_boolean(it->second);
+    }
+
+if ((it = structVal.find("tariff_chg")) != structVal.end())
+    {
+    conf.priv.tariffChg = xmlrpc_c::value_boolean(it->second);
+    }
+
+if (admins->change(conf, *loggedAdmin))
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    }
+
+*retvalPtr = xmlrpc_c::value_boolean(true);
+}
+
+//------------------------------------------------------------------------------
+
+void METHOD_ADMINS_GET::execute(xmlrpc_c::paramList const & paramList,
+                                xmlrpc_c::value *   const   retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+paramList.verifyEnd(1);
+
+std::map<std::string, xmlrpc_c::value> mainStructVal;
+std::vector<xmlrpc_c::value> retval;
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+    {
+    mainStructVal["result"] = xmlrpc_c::value_boolean(false);
+    *retvalPtr = xmlrpc_c::value_struct(mainStructVal);
+    return;
+    }
+
+admins->fmap([&retval](const auto& admin)
+    {
+        const std::map<std::string, xmlrpc_c::value> structVal{
+            {"result", xmlrpc_c::value_boolean(true)},
+            {"login", xmlrpc_c::value_string(admin.login())},
+            {"password", xmlrpc_c::value_string(admin.password())},
+            {"user_stat", xmlrpc_c::value_boolean(admin.priv().userStat)},
+            {"user_conf", xmlrpc_c::value_boolean(admin.priv().userConf)},
+            {"user_cash", xmlrpc_c::value_boolean(admin.priv().userCash)},
+            {"user_passwd", xmlrpc_c::value_boolean(admin.priv().userPasswd)},
+            {"user_add_del", xmlrpc_c::value_boolean(admin.priv().userAddDel)},
+            {"admin_chg", xmlrpc_c::value_boolean(admin.priv().adminChg)},
+            {"tariff_chg", xmlrpc_c::value_boolean(admin.priv().tariffChg)}
+        };
+        retval.push_back(xmlrpc_c::value_struct(structVal));
+    });
+
+*retvalPtr = xmlrpc_c::value_array(retval);
+}
diff --git a/projects/stargazer/plugins/configuration/rpcconfig/admins_methods.h b/projects/stargazer/plugins/configuration/rpcconfig/admins_methods.h
new file mode 100644 (file)
index 0000000..43c8073
--- /dev/null
@@ -0,0 +1,113 @@
+#pragma once
+
+#include <xmlrpc-c/base.hpp>
+#include <xmlrpc-c/registry.hpp>
+
+namespace STG
+{
+
+struct Admins;
+
+}
+
+class RPC_CONFIG;
+
+class METHOD_ADMIN_GET : public xmlrpc_c::method {
+public:
+    METHOD_ADMIN_GET(RPC_CONFIG * c,
+                     STG::Admins * a)
+        : config(c),
+          admins(a)
+    {
+    }
+
+    void execute(xmlrpc_c::paramList const & paramList,
+                 xmlrpc_c::value * const retvalPtr);
+
+private:
+    METHOD_ADMIN_GET(const METHOD_ADMIN_GET & rvalue);
+    METHOD_ADMIN_GET & operator=(const METHOD_ADMIN_GET & rvalue);
+
+    RPC_CONFIG * config;
+    STG::Admins * admins;
+};
+
+class METHOD_ADMIN_ADD : public xmlrpc_c::method {
+public:
+    METHOD_ADMIN_ADD(RPC_CONFIG * c,
+                     STG::Admins * a)
+        : config(c),
+          admins(a)
+    {
+    }
+
+    void execute(xmlrpc_c::paramList const & paramList,
+                 xmlrpc_c::value * const retvalPtr);
+
+private:
+    METHOD_ADMIN_ADD(const METHOD_ADMIN_ADD & rvalue);
+    METHOD_ADMIN_ADD & operator=(const METHOD_ADMIN_ADD & rvalue);
+
+    RPC_CONFIG * config;
+    STG::Admins * admins;
+};
+
+class METHOD_ADMIN_DEL : public xmlrpc_c::method {
+public:
+    METHOD_ADMIN_DEL(RPC_CONFIG * c,
+                     STG::Admins * a)
+        : config(c),
+          admins(a)
+    {
+    }
+
+    void execute(xmlrpc_c::paramList const & paramList,
+                 xmlrpc_c::value * const retvalPtr);
+
+private:
+    METHOD_ADMIN_DEL(const METHOD_ADMIN_DEL & rvalue);
+    METHOD_ADMIN_DEL & operator=(const METHOD_ADMIN_DEL & rvalue);
+
+    RPC_CONFIG * config;
+    STG::Admins * admins;
+};
+
+class METHOD_ADMIN_CHG : public xmlrpc_c::method {
+public:
+    METHOD_ADMIN_CHG(RPC_CONFIG * c,
+                     STG::Admins * a)
+        : config(c),
+          admins(a)
+    {
+    }
+
+    void execute(xmlrpc_c::paramList const & paramList,
+                 xmlrpc_c::value * const retvalPtr);
+
+private:
+    METHOD_ADMIN_CHG(const METHOD_ADMIN_CHG & rvalue);
+    METHOD_ADMIN_CHG & operator=(const METHOD_ADMIN_CHG & rvalue);
+
+    RPC_CONFIG * config;
+    STG::Admins * admins;
+};
+
+class METHOD_ADMINS_GET : public xmlrpc_c::method {
+public:
+    METHOD_ADMINS_GET(RPC_CONFIG * c,
+                      STG::Admins * a)
+        : config(c),
+          admins(a)
+    {
+    }
+
+    void execute(xmlrpc_c::paramList const & paramList,
+                 xmlrpc_c::value * const retvalPtr);
+
+private:
+    METHOD_ADMINS_GET(const METHOD_ADMINS_GET & rvalue);
+    METHOD_ADMINS_GET & operator=(const METHOD_ADMINS_GET & rvalue);
+
+    RPC_CONFIG * config;
+    STG::Admins * admins;
+};
diff --git a/projects/stargazer/plugins/configuration/rpcconfig/info_methods.cpp b/projects/stargazer/plugins/configuration/rpcconfig/info_methods.cpp
new file mode 100644 (file)
index 0000000..e0c371c
--- /dev/null
@@ -0,0 +1,92 @@
+#include "info_methods.h"
+#include "rpcconfig.h"
+
+#include "stg/users.h"
+#include "stg/tariffs.h"
+#include "stg/version.h"
+#include "stg/common.h"
+#include "stg/const.h"
+
+#include <ostream> // xmlrpc-c devs have missed something :)
+
+#include <sys/utsname.h>
+
+void METHOD_INFO::execute(xmlrpc_c::paramList const & paramList,
+                          xmlrpc_c::value *   const   retvalPtr)
+{
+paramList.verifyEnd(0);
+std::map<std::string, xmlrpc_c::value> structVal;
+
+std::string un;
+struct utsname utsn;
+
+uname(&utsn);
+un[0] = 0;
+
+un += utsn.sysname;
+un += " ";
+un += utsn.release;
+un += " ";
+un += utsn.machine;
+un += " ";
+un += utsn.nodename;
+
+structVal["version"] = xmlrpc_c::value_string(SERVER_VERSION);
+structVal["tariff_num"] = xmlrpc_c::value_int(static_cast<int>(tariffs->Count()));
+structVal["tariff"] = xmlrpc_c::value_int(2);
+structVal["users_num"] = xmlrpc_c::value_int(static_cast<int>(users->Count()));
+structVal["uname"] = xmlrpc_c::value_string(un);
+structVal["dir_num"] = xmlrpc_c::value_int(DIR_NUM);
+structVal["day_fee"] = xmlrpc_c::value_int(static_cast<int>(dayFee));
+
+std::vector<xmlrpc_c::value> dirnameVal;
+
+for (int i = 0; i< DIR_NUM; i++)
+    {
+    dirnameVal.push_back(xmlrpc_c::value_string(IconvString(dirNames[i], "KOI8-RU", "UTF-8")));
+    }
+
+structVal["dir_names"] = xmlrpc_c::value_array(dirnameVal);
+
+*retvalPtr = xmlrpc_c::value_struct(structVal);
+}
+
+void METHOD_LOGIN::execute(xmlrpc_c::paramList const & paramList,
+                           xmlrpc_c::value *   const   retvalPtr)
+{
+std::string login = paramList.getString(0);
+std::string password = paramList.getString(1);
+paramList.verifyEnd(2);
+
+std::map<std::string, xmlrpc_c::value> structVal;
+
+std::string cookie;
+if (config->CheckAdmin(login, password, &cookie))
+    {
+    structVal["result"] = xmlrpc_c::value_boolean(false);
+    structVal["cookie"] = xmlrpc_c::value_string("");
+    }
+else
+    {
+    structVal["result"] = xmlrpc_c::value_boolean(true);
+    structVal["cookie"] = xmlrpc_c::value_string(cookie);
+    }
+
+*retvalPtr = xmlrpc_c::value_struct(structVal);
+}
+
+void METHOD_LOGOUT::execute(xmlrpc_c::paramList const & paramList,
+                            xmlrpc_c::value *   const   retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+paramList.verifyEnd(1);
+
+if (config->LogoutAdmin(cookie))
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    }
+else
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(true);
+    }
+}
diff --git a/projects/stargazer/plugins/configuration/rpcconfig/info_methods.h b/projects/stargazer/plugins/configuration/rpcconfig/info_methods.h
new file mode 100644 (file)
index 0000000..709a066
--- /dev/null
@@ -0,0 +1,82 @@
+#pragma once
+
+#include <xmlrpc-c/base.hpp>
+#include <xmlrpc-c/registry.hpp>
+
+#include <string>
+#include <vector>
+
+namespace STG
+{
+
+struct Settings;
+struct Users;
+struct Tariffs;
+
+}
+
+// Forward declaration
+class RPC_CONFIG;
+
+class METHOD_INFO : public xmlrpc_c::method
+{
+public:
+    METHOD_INFO(STG::Tariffs * t,
+                STG::Users * u,
+                size_t df,
+                const std::vector<std::string> & dn)
+        : tariffs(t),
+          users(u),
+          dayFee(df),
+          dirNames(dn)
+    {
+    }
+
+    void execute(xmlrpc_c::paramList const & paramList,
+                 xmlrpc_c::value *   const   retvalP);
+
+private:
+    METHOD_INFO(const METHOD_INFO & rvalue);
+    METHOD_INFO & operator=(const METHOD_INFO & rvalue);
+
+    STG::Tariffs * tariffs;
+    STG::Users * users;
+    size_t dayFee;
+    const std::vector<std::string> & dirNames;
+};
+
+class METHOD_LOGIN : public xmlrpc_c::method
+{
+public:
+    explicit METHOD_LOGIN(RPC_CONFIG * c)
+        : config(c)
+    {
+    }
+
+    void execute(xmlrpc_c::paramList const & paramList,
+                 xmlrpc_c::value *   const   retvalP);
+
+private:
+    METHOD_LOGIN(const METHOD_LOGIN & rvalue);
+    METHOD_LOGIN & operator=(const METHOD_LOGIN & rvalue);
+
+    RPC_CONFIG * config;
+};
+
+class METHOD_LOGOUT : public xmlrpc_c::method
+{
+public:
+    explicit METHOD_LOGOUT(RPC_CONFIG * c)
+        : config(c)
+    {
+    }
+
+    void execute(xmlrpc_c::paramList const & paramList,
+                 xmlrpc_c::value *   const   retvalP);
+
+private:
+    METHOD_LOGOUT(const METHOD_LOGOUT & rvalue);
+    METHOD_LOGOUT & operator=(const METHOD_LOGOUT & rvalue);
+
+    RPC_CONFIG * config;
+};
diff --git a/projects/stargazer/plugins/configuration/rpcconfig/messages_methods.cpp b/projects/stargazer/plugins/configuration/rpcconfig/messages_methods.cpp
new file mode 100644 (file)
index 0000000..854b276
--- /dev/null
@@ -0,0 +1,100 @@
+#include "messages_methods.h"
+#include "rpcconfig.h"
+
+#include "stg/users.h"
+#include "stg/user.h"
+#include "stg/message.h"
+#include "stg/common.h"
+
+#include <ostream> // xmlrpc-c devs have missed something :)
+
+extern volatile time_t stgTime;
+
+//------------------------------------------------------------------------------
+
+void METHOD_MESSAGE_SEND::execute(xmlrpc_c::paramList const & paramList,
+                                  xmlrpc_c::value *   const   retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::vector<xmlrpc_c::value> logins(paramList.getArray(1));
+std::map<std::string, xmlrpc_c::value> msgInfo(paramList.getStruct(2));
+paramList.verifyEnd(3);
+
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+
+STG::Message message;
+
+std::map<std::string, xmlrpc_c::value>::iterator it;
+
+if ((it = msgInfo.find("version")) == msgInfo.end())
+    {
+    message.header.ver = 1; // Default value
+    }
+else
+    {
+    message.header.ver = xmlrpc_c::value_int(it->second);
+    }
+
+if ((it = msgInfo.find("type")) == msgInfo.end())
+    {
+    message.header.type = 1; // default value
+    }
+else
+    {
+    message.header.type = xmlrpc_c::value_int(it->second);
+    }
+
+if ((it = msgInfo.find("repeat")) == msgInfo.end())
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+message.header.repeat = xmlrpc_c::value_int(it->second);
+
+if ((it = msgInfo.find("repeat_period")) == msgInfo.end())
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+message.header.repeatPeriod = xmlrpc_c::value_int(it->second);
+
+if ((it = msgInfo.find("show_time")) == msgInfo.end())
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+message.header.showTime = xmlrpc_c::value_int(it->second);
+
+if ((it = msgInfo.find("text")) == msgInfo.end())
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+message.text = IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "CP1251");
+
+message.header.creationTime = static_cast<int>(stgTime);
+message.header.lastSendTime = 0;
+
+std::vector<xmlrpc_c::value>::iterator lit;
+for (lit = logins.begin(); lit != logins.end(); ++lit)
+    {
+    using UserPtr = STG::User*;
+    UserPtr ui;
+    if (users->FindByName(xmlrpc_c::value_string(*lit), &ui))
+        {
+        printfd(__FILE__, "METHOD_MESSAGE_SEND::execute(): 'User '%s' not found'\n", std::string(xmlrpc_c::value_string(*lit)).c_str());
+        }
+    else
+        {
+        ui->AddMessage(&message);
+        }
+    }
+
+*retvalPtr = xmlrpc_c::value_boolean(true);
+}
diff --git a/projects/stargazer/plugins/configuration/rpcconfig/messages_methods.h b/projects/stargazer/plugins/configuration/rpcconfig/messages_methods.h
new file mode 100644 (file)
index 0000000..210ef69
--- /dev/null
@@ -0,0 +1,33 @@
+#pragma once
+
+#include <xmlrpc-c/base.hpp>
+#include <xmlrpc-c/registry.hpp>
+
+namespace STG
+{
+
+struct Users;
+
+}
+
+class RPC_CONFIG;
+
+class METHOD_MESSAGE_SEND : public xmlrpc_c::method {
+public:
+    METHOD_MESSAGE_SEND(RPC_CONFIG * c,
+                     STG::Users * u)
+        : config(c),
+          users(u)
+    {
+    }
+
+    void execute(xmlrpc_c::paramList const & paramList,
+                 xmlrpc_c::value * const retvalPtr);
+
+private:
+    METHOD_MESSAGE_SEND(const METHOD_MESSAGE_SEND & rvalue);
+    METHOD_MESSAGE_SEND & operator=(const METHOD_MESSAGE_SEND & rvalue);
+
+    RPC_CONFIG * config;
+    STG::Users * users;
+};
diff --git a/projects/stargazer/plugins/configuration/rpcconfig/rpcconfig.cpp b/projects/stargazer/plugins/configuration/rpcconfig/rpcconfig.cpp
new file mode 100644 (file)
index 0000000..2d45f10
--- /dev/null
@@ -0,0 +1,471 @@
+#include "rpcconfig.h"
+
+#include "info_methods.h"
+#include "users_methods.h"
+#include "tariffs_methods.h"
+#include "admins_methods.h"
+#include "messages_methods.h"
+
+#include "stg/admins.h"
+#include "stg/admin.h"
+#include "stg/module_settings.h"
+#include "stg/settings.h"
+#include "stg/common.h"
+#include "stg/const.h"
+
+#include <algorithm>
+#include <vector>
+#include <ostream> // xmlrpc-c devs have missed something :)
+#include <cstdlib>
+#include <csignal>
+#include <cerrno>
+#include <cstring>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+
+RPC_CONFIG_SETTINGS::RPC_CONFIG_SETTINGS()
+    : port(0),
+      cookieTimeout(0)
+{
+}
+
+int RPC_CONFIG_SETTINGS::ParseSettings(const STG::ModuleSettings & s)
+{
+STG::ParamValue pv;
+pv.param = "Port";
+std::vector<STG::ParamValue>::const_iterator pvi;
+pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end() || pvi->value.empty())
+    {
+    errorStr = "Parameter \'Port\' not found.";
+    printfd(__FILE__, "Parameter 'Port' not found\n");
+    return -1;
+    }
+int p;
+if (ParseIntInRange(pvi->value[0], 2, 65535, &p))
+    {
+    errorStr = "Cannot parse parameter \'Port\': " + errorStr;
+    printfd(__FILE__, "Cannot parse parameter 'Port'\n");
+    return -1;
+    }
+port = static_cast<uint16_t>(p);
+
+pv.param = "CookieTimeout";
+pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end() || pvi->value.empty())
+    {
+    cookieTimeout = 1800; // 30 * 60
+    }
+else
+    {
+    if (str2x(pvi->value[0], cookieTimeout))
+        {
+        errorStr = "Incorrect value of CookieTimeout: \'" + pvi->value[0] + "\'";
+        printfd(__FILE__, "Incorrect value of 'CookieTimeout'\n");
+        return -1;
+        }
+    }
+
+return 0;
+}
+
+extern "C" STG::Plugin* GetPlugin()
+{
+    static RPC_CONFIG plugin;
+    return &plugin;
+}
+
+RPC_CONFIG::RPC_CONFIG()
+    : users(NULL),
+      admins(NULL),
+      tariffs(NULL),
+      store(NULL),
+      fd(-1),
+      rpcServer(NULL),
+      running(false),
+      stopped(true),
+      dayFee(0),
+      logger(STG::PluginLogger::get("conf_rpc"))
+{
+}
+
+RPC_CONFIG::~RPC_CONFIG()
+{
+// delete server
+delete rpcServer;
+}
+
+int RPC_CONFIG::ParseSettings()
+{
+int ret = rpcConfigSettings.ParseSettings(settings);
+
+if (ret)
+    errorStr = rpcConfigSettings.GetStrError();
+
+return ret;
+}
+
+void RPC_CONFIG::SetStgSettings(const STG::Settings * s)
+{
+    dayFee = s->GetDayFee();
+    dirNames.erase(dirNames.begin(), dirNames.end());
+    for (size_t i = 0; i < DIR_NUM; ++i) {
+        dirNames.push_back(s->GetDirName(i));
+    }
+}
+
+int RPC_CONFIG::Start()
+{
+InitiateRegistry();
+running = true;
+
+fd = socket(AF_INET, SOCK_STREAM, 0);
+if (fd < 0)
+    {
+    errorStr = "Failed to create socket";
+    logger("Cannot create a socket: %s", strerror(errno));
+    printfd(__FILE__, "Failed to create listening socket: %s\n", strerror(errno));
+    return -1;
+    }
+
+int flag = 1;
+
+if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)))
+    {
+    errorStr = "Setsockopt failed.";
+    logger("setsockopt error: %s", strerror(errno));
+    printfd(__FILE__, "Setsockopt failed: %s\n", strerror(errno));
+    return -1;
+    }
+
+struct sockaddr_in addr;
+addr.sin_family = AF_INET;
+addr.sin_port = htons(rpcConfigSettings.GetPort());
+addr.sin_addr.s_addr = inet_addr("0.0.0.0");
+
+if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)))
+    {
+    logger("Cannot bind the socket: %s", strerror(errno));
+    errorStr = "Failed to bind socket";
+    printfd(__FILE__, "Failed to bind listening socket: %s\n", strerror(errno));
+    return -1;
+    }
+
+if (listen(fd, 10))
+    {
+    logger("Cannot listen the socket: %s", strerror(errno));
+    errorStr = "Failed to listen socket";
+    printfd(__FILE__, "Failed to listen listening socket: %s\n", strerror(errno));
+    return -1;
+    }
+
+rpcServer = new xmlrpc_c::serverAbyss(
+        xmlrpc_c::serverAbyss::constrOpt()
+        .registryP(&rpcRegistry)
+        .logFileName("/var/log/stargazer_rpc.log")
+        .socketFd(fd)
+        );
+
+if (pthread_create(&tid, NULL, Run, this))
+    {
+    errorStr = "Failed to create RPC thread";
+    logger("Cannot create RPC thread.");
+    printfd(__FILE__, "Failed to crate RPC thread\n");
+    return -1;
+    }
+
+return 0;
+}
+
+int RPC_CONFIG::Stop()
+{
+running = false;
+for (int i = 0; i < 5 && !stopped; ++i)
+    {
+    struct timespec ts = {0, 200000000};
+    nanosleep(&ts, NULL);
+    }
+
+if (!stopped)
+    {
+    running = true;
+    logger("Cannot stop RPC thread.");
+    printfd(__FILE__, "Failed to stop RPC thread\n");
+    errorStr = "Failed to stop RPC thread";
+    return -1;
+    }
+else
+    {
+    pthread_join(tid, NULL);
+    }
+
+close(fd);
+
+return 0;
+}
+
+void * RPC_CONFIG::Run(void * rc)
+{
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+RPC_CONFIG * config = static_cast<RPC_CONFIG *>(rc);
+
+config->stopped = false;
+while (config->running)
+    {
+    if (WaitPackets(config->fd))
+        config->rpcServer->runOnce();
+    }
+config->stopped = true;
+
+return NULL;
+}
+
+bool RPC_CONFIG::GetAdminInfo(const std::string & cookie,
+                              ADMIN_INFO * info)
+{
+std::map<std::string,
+         ADMIN_INFO>::iterator it;
+
+it = cookies.find(cookie);
+
+if (it == cookies.end())
+    {
+    return true;
+    }
+
+if (difftime(it->second.accessTime, time(NULL)) >
+    rpcConfigSettings.GetCookieTimeout())
+    {
+    cookies.erase(it);
+    return true;
+    }
+
+// Update access time
+time(&it->second.accessTime);
+*info = it->second;
+return false;
+}
+
+bool RPC_CONFIG::CheckAdmin(const std::string & login,
+                            const std::string & password,
+                            std::string * cookie)
+{
+STG::Admin * admin = NULL;
+
+if (!admins->correct(login, password, &admin))
+    {
+    logger("Attempt to connect with invalid credentials. Login: %s", login.c_str());
+    return true;
+    }
+
+ADMIN_INFO info;
+time(&info.accessTime);
+info.admin = login;
+info.priviledges = admin->priv();
+*cookie = GetCookie();
+cookies[*cookie] = info;
+
+return false;
+}
+
+bool RPC_CONFIG::LogoutAdmin(const std::string & cookie)
+{
+std::map<std::string,
+         ADMIN_INFO>::iterator it;
+
+it = cookies.find(cookie);
+
+if (it == cookies.end())
+    {
+    return true;
+    }
+
+cookies.erase(it);
+
+return false;
+}
+
+std::string RPC_CONFIG::GetCookie() const
+{
+std::string charset("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890");
+std::string cookie;
+
+for (int i = 0; i < 64; ++i)
+    {
+    cookie += charset[rand() % charset.length()];
+    };
+
+return cookie;
+}
+
+void RPC_CONFIG::InitiateRegistry()
+{
+// manage registry
+xmlrpc_c::methodPtr const methodInfoPtr(new METHOD_INFO(
+            tariffs,
+            users,
+            dayFee,
+            dirNames
+            ));
+rpcRegistry.addMethod("stargazer.info", methodInfoPtr);
+
+xmlrpc_c::methodPtr const methodLoginPtr(new METHOD_LOGIN(
+            this
+            ));
+rpcRegistry.addMethod("stargazer.login", methodLoginPtr);
+
+xmlrpc_c::methodPtr const methodLogoutPtr(new METHOD_LOGOUT(
+            this
+            ));
+rpcRegistry.addMethod("stargazer.logout", methodLogoutPtr);
+
+xmlrpc_c::methodPtr const methodGetUserPtr(new METHOD_USER_GET(
+            this,
+            users
+            ));
+rpcRegistry.addMethod("stargazer.get_user", methodGetUserPtr);
+
+xmlrpc_c::methodPtr const methodAddUserPtr(new METHOD_USER_ADD(
+            this,
+            admins,
+            users
+            ));
+rpcRegistry.addMethod("stargazer.add_user", methodAddUserPtr);
+
+xmlrpc_c::methodPtr const methodDelUserPtr(new METHOD_USER_DEL(
+            this,
+            admins,
+            users
+            ));
+rpcRegistry.addMethod("stargazer.del_user", methodDelUserPtr);
+
+xmlrpc_c::methodPtr const methodGetUsersPtr(new METHOD_USERS_GET(
+            this,
+            users
+            ));
+rpcRegistry.addMethod("stargazer.get_users", methodGetUsersPtr);
+
+xmlrpc_c::methodPtr const methodChgUserPtr(new METHOD_USER_CHG(
+            this,
+            admins,
+            tariffs,
+            store,
+            users
+            ));
+rpcRegistry.addMethod("stargazer.chg_user", methodChgUserPtr);
+
+xmlrpc_c::methodPtr const methodAddCashPtr(new METHOD_USER_CASH_ADD(
+            this,
+            admins,
+            store,
+            users
+            ));
+rpcRegistry.addMethod("stargazer.add_user_cash", methodAddCashPtr);
+
+xmlrpc_c::methodPtr const methodSetCashPtr(new METHOD_USER_CASH_SET(
+            this,
+            admins,
+            store,
+            users
+            ));
+rpcRegistry.addMethod("stargazer.set_user_cash", methodSetCashPtr);
+
+xmlrpc_c::methodPtr const methodTariffChangePtr(new METHOD_USER_TARIFF_CHANGE(
+            this,
+            admins,
+            tariffs,
+            store,
+            users
+            ));
+rpcRegistry.addMethod("stargazer.chg_user_tariff", methodTariffChangePtr);
+
+xmlrpc_c::methodPtr const methodGetTariffPtr(new METHOD_TARIFF_GET(
+            this,
+            tariffs
+            ));
+rpcRegistry.addMethod("stargazer.get_tariff", methodGetTariffPtr);
+
+xmlrpc_c::methodPtr const methodChgTariffPtr(new METHOD_TARIFF_CHG(
+            this,
+            admins,
+            tariffs
+            ));
+rpcRegistry.addMethod("stargazer.chg_tariff", methodChgTariffPtr);
+
+xmlrpc_c::methodPtr const methodGetTariffsPtr(new METHOD_TARIFFS_GET(
+            this,
+            tariffs
+            ));
+rpcRegistry.addMethod("stargazer.get_tariffs", methodGetTariffsPtr);
+
+xmlrpc_c::methodPtr const methodAddTariffPtr(new METHOD_TARIFF_ADD(
+            this,
+            admins,
+            tariffs
+            ));
+rpcRegistry.addMethod("stargazer.add_tariff", methodAddTariffPtr);
+
+xmlrpc_c::methodPtr const methodDelTariffPtr(new METHOD_TARIFF_DEL(
+            this,
+            admins,
+            tariffs,
+            users
+            ));
+rpcRegistry.addMethod("stargazer.del_tariff", methodDelTariffPtr);
+
+xmlrpc_c::methodPtr const methodGetAdminPtr(new METHOD_ADMIN_GET(
+            this,
+            admins
+            ));
+rpcRegistry.addMethod("stargazer.get_admin", methodGetAdminPtr);
+
+xmlrpc_c::methodPtr const methodAddAdminPtr(new METHOD_ADMIN_ADD(
+            this,
+            admins
+            ));
+rpcRegistry.addMethod("stargazer.add_admin", methodAddAdminPtr);
+
+xmlrpc_c::methodPtr const methodDelAdminPtr(new METHOD_ADMIN_DEL(
+            this,
+            admins
+            ));
+rpcRegistry.addMethod("stargazer.del_admin", methodDelAdminPtr);
+
+xmlrpc_c::methodPtr const methodChgAdminPtr(new METHOD_ADMIN_CHG(
+            this,
+            admins
+            ));
+rpcRegistry.addMethod("stargazer.chg_admin", methodChgAdminPtr);
+
+xmlrpc_c::methodPtr const methodGetAdminsPtr(new METHOD_ADMINS_GET(
+            this,
+            admins
+            ));
+rpcRegistry.addMethod("stargazer.get_admins", methodGetAdminsPtr);
+
+xmlrpc_c::methodPtr const methodSendMessagePtr(new METHOD_MESSAGE_SEND(
+            this,
+            users
+            ));
+rpcRegistry.addMethod("stargazer.send_user_message", methodSendMessagePtr);
+
+xmlrpc_c::methodPtr const methodGetOnlinIPsPtr(new METHOD_GET_ONLINE_IPS(
+            this,
+            users
+            ));
+rpcRegistry.addMethod("stargazer.get_online_ips", methodGetOnlinIPsPtr);
+
+xmlrpc_c::methodPtr const methodGetUserAuthByPtr(new METHOD_GET_USER_AUTH_BY(
+            this,
+            users
+            ));
+rpcRegistry.addMethod("stargazer.get_user_auth_by", methodGetUserAuthByPtr);
+}
+
diff --git a/projects/stargazer/plugins/configuration/rpcconfig/rpcconfig.h b/projects/stargazer/plugins/configuration/rpcconfig/rpcconfig.h
new file mode 100644 (file)
index 0000000..e7c800d
--- /dev/null
@@ -0,0 +1,118 @@
+#pragma once
+
+#include "stg/plugin.h"
+#include "stg/admin_conf.h"
+#include "stg/module_settings.h"
+#include "stg/logger.h"
+
+#include <xmlrpc-c/base.hpp>
+#include <xmlrpc-c/registry.hpp>
+#include <xmlrpc-c/server_abyss.hpp>
+
+#include <ctime>
+#include <cstdint>
+#include <string>
+#include <map>
+#include <vector>
+
+#include <pthread.h>
+
+#define RPC_CONFIG_VERSION "Stargazer RPC v. 0.2"
+
+namespace STG
+{
+
+struct Admins;
+struct Tariffs;
+struct Users;
+struct Store;
+
+}
+
+class RPC_CONFIG_SETTINGS
+{
+public:
+                         RPC_CONFIG_SETTINGS();
+    virtual              ~RPC_CONFIG_SETTINGS() {}
+    const std::string &  GetStrError() const { return errorStr; }
+    int                  ParseSettings(const STG::ModuleSettings & s);
+    uint16_t             GetPort() const { return port; }
+    double               GetCookieTimeout() const { return cookieTimeout; }
+
+private:
+    std::string  errorStr;
+    uint16_t     port;
+    double       cookieTimeout;
+};
+
+struct ADMIN_INFO
+{
+    ADMIN_INFO()
+        : admin(),
+          accessTime(0),
+          priviledges()
+    {}
+
+    std::string admin;
+    time_t      accessTime;
+    STG::Priv        priviledges;
+};
+
+class RPC_CONFIG : public STG::Plugin
+{
+public:
+    RPC_CONFIG();
+    ~RPC_CONFIG() override;
+
+    void                SetUsers(STG::Users * u) override { users = u; }
+    void                SetTariffs(STG::Tariffs * t) override { tariffs = t; }
+    void                SetAdmins(STG::Admins * a) override { admins = a; }
+    void                SetStore(STG::Store * s) override { store = s; }
+    void                SetStgSettings(const STG::Settings * s) override;
+    void                SetSettings(const STG::ModuleSettings & s) override { settings = s; }
+    int                 ParseSettings() override;
+
+    int                 Start() override;
+    int                 Stop() override;
+    int                 Reload(const STG::ModuleSettings & /*ms*/) override { return 0; }
+    bool                IsRunning() override { return running && !stopped; }
+
+    const std::string & GetStrError() const override { return errorStr; }
+    std::string         GetVersion() const override { return RPC_CONFIG_VERSION; }
+    uint16_t            GetStartPosition() const override { return 20; }
+    uint16_t            GetStopPosition() const override { return 20; }
+
+    bool                GetAdminInfo(const std::string & cookie,
+                                     ADMIN_INFO * info);
+    bool                CheckAdmin(const std::string & login,
+                                   const std::string & password,
+                                   std::string * cookie);
+    bool                LogoutAdmin(const std::string & cookie);
+
+private:
+    RPC_CONFIG(const RPC_CONFIG & rvalue);
+    RPC_CONFIG & operator=(const RPC_CONFIG & rvalue);
+
+    static void *           Run(void *);
+    std::string             GetCookie() const;
+    void                    InitiateRegistry();
+
+    mutable std::string     errorStr;
+    RPC_CONFIG_SETTINGS     rpcConfigSettings;
+    STG::Users *                 users;
+    STG::Admins *                admins;
+    STG::Tariffs *               tariffs;
+    STG::Store *                 store;
+    STG::ModuleSettings         settings;
+    int                     fd;
+    xmlrpc_c::registry      rpcRegistry;
+    xmlrpc_c::serverAbyss * rpcServer;
+    bool                    running;
+    bool                    stopped;
+    pthread_t               tid;
+    std::map<std::string,
+             ADMIN_INFO>    cookies;
+    size_t                  dayFee;
+    std::vector<std::string> dirNames;
+    STG::PluginLogger           logger;
+};
diff --git a/projects/stargazer/plugins/configuration/rpcconfig/tariff_helper.cpp b/projects/stargazer/plugins/configuration/rpcconfig/tariff_helper.cpp
new file mode 100644 (file)
index 0000000..a6ec1fe
--- /dev/null
@@ -0,0 +1,116 @@
+#include "tariff_helper.h"
+
+#include "stg/tariff_conf.h"
+#include "stg/common.h"
+#include "stg/const.h"
+
+#include <ostream> // xmlrpc-c devs have missed something :)
+
+void TARIFF_HELPER::GetTariffInfo(xmlrpc_c::value * info) const
+{
+std::map<std::string, xmlrpc_c::value> structVal;
+
+structVal["result"] = xmlrpc_c::value_boolean(true);
+structVal["name"] = xmlrpc_c::value_string(data.tariffConf.name);
+structVal["fee"] = xmlrpc_c::value_double(data.tariffConf.fee);
+structVal["freemb"] = xmlrpc_c::value_double(data.tariffConf.free);
+structVal["passivecost"] = xmlrpc_c::value_double(data.tariffConf.passiveCost);
+structVal["traffType"] = xmlrpc_c::value_int(data.tariffConf.traffType);
+structVal["period"] = xmlrpc_c::value_string(STG::Tariff::toString(data.tariffConf.period));
+structVal["changePolicy"] = xmlrpc_c::value_string(STG::Tariff::toString(data.tariffConf.changePolicy));
+structVal["changePolicyTimeout"] = xmlrpc_c::value_string(formatTime(data.tariffConf.changePolicyTimeout));
+
+std::vector<xmlrpc_c::value> prices(DIR_NUM);
+
+for (unsigned i = 0; i < DIR_NUM; ++i)
+    {
+    std::map<std::string, xmlrpc_c::value> dirPrice;
+    dirPrice["hday"] = xmlrpc_c::value_int(data.dirPrice[i].hDay);
+    dirPrice["mday"] = xmlrpc_c::value_int(data.dirPrice[i].mDay);
+    dirPrice["hnight"] = xmlrpc_c::value_int(data.dirPrice[i].hNight);
+    dirPrice["mnight"] = xmlrpc_c::value_int(data.dirPrice[i].mNight);
+    dirPrice["pricedaya"] = xmlrpc_c::value_double(data.dirPrice[i].priceDayA * 1024 * 1024);
+    dirPrice["pricedayb"] = xmlrpc_c::value_double(data.dirPrice[i].priceDayB * 1024 * 1024);
+    dirPrice["pricenighta"] = xmlrpc_c::value_double(data.dirPrice[i].priceNightA * 1024 * 1024);
+    dirPrice["pricenightb"] = xmlrpc_c::value_double(data.dirPrice[i].priceNightB * 1024 * 1024);
+    dirPrice["threshold"] = xmlrpc_c::value_int(data.dirPrice[i].threshold);
+    dirPrice["singleprice"] = xmlrpc_c::value_boolean(data.dirPrice[i].singlePrice);
+    dirPrice["nodiscount"] = xmlrpc_c::value_boolean(data.dirPrice[i].noDiscount);
+    prices[i] = xmlrpc_c::value_struct(dirPrice);
+    }
+
+structVal["dirprices"] = xmlrpc_c::value_array(prices);
+
+*info = xmlrpc_c::value_struct(structVal);
+}
+
+bool TARIFF_HELPER::SetTariffInfo(const xmlrpc_c::value & info)
+{
+std::map<std::string, xmlrpc_c::value> structVal(
+    static_cast<std::map<std::string, xmlrpc_c::value> >(xmlrpc_c::value_struct(info))
+    );
+
+std::map<std::string, xmlrpc_c::value>::iterator it;
+
+if ((it = structVal.find("fee")) != structVal.end())
+    {
+    data.tariffConf.fee = xmlrpc_c::value_double(it->second);
+    }
+
+if ((it = structVal.find("freemb")) != structVal.end())
+    {
+    data.tariffConf.free = xmlrpc_c::value_double(it->second);
+    }
+
+if ((it = structVal.find("passivecost")) != structVal.end())
+    {
+    data.tariffConf.passiveCost = xmlrpc_c::value_double(it->second);
+    }
+
+if ((it = structVal.find("traffType")) != structVal.end())
+    {
+    data.tariffConf.traffType = static_cast<STG::Tariff::TraffType>(xmlrpc_c::value_int(it->second).cvalue());
+    }
+
+if ((it = structVal.find("period")) != structVal.end())
+    {
+    data.tariffConf.period = STG::Tariff::parsePeriod(xmlrpc_c::value_string(it->second));
+    }
+
+if ((it = structVal.find("changePolicy")) != structVal.end())
+    {
+    data.tariffConf.changePolicy = STG::Tariff::parseChangePolicy(xmlrpc_c::value_string(it->second));
+    }
+
+if ((it = structVal.find("changePolicyTimeout")) != structVal.end())
+    {
+    data.tariffConf.changePolicyTimeout = readTime(xmlrpc_c::value_string(it->second));
+    }
+
+if ((it = structVal.find("dirprices")) != structVal.end())
+    {
+    std::vector<xmlrpc_c::value> prices(
+            xmlrpc_c::value_array(it->second).vectorValueValue()
+            );
+
+    for (unsigned i = 0; i < DIR_NUM; ++i)
+        {
+        std::map<std::string, xmlrpc_c::value> dirPrice(
+            static_cast<std::map<std::string, xmlrpc_c::value> >(xmlrpc_c::value_struct(prices[i]))
+            );
+        data.dirPrice[i].mDay = xmlrpc_c::value_int(dirPrice["mday"]);
+        data.dirPrice[i].hDay = xmlrpc_c::value_int(dirPrice["hday"]);
+        data.dirPrice[i].mNight = xmlrpc_c::value_int(dirPrice["mnight"]);
+        data.dirPrice[i].hNight = xmlrpc_c::value_int(dirPrice["hnight"]);
+        data.dirPrice[i].priceDayA = xmlrpc_c::value_double(dirPrice["pricedaya"]) / 1024 / 1024;
+        data.dirPrice[i].priceDayB = xmlrpc_c::value_double(dirPrice["pricedayb"]) / 1024 / 1024;
+        data.dirPrice[i].priceNightA = xmlrpc_c::value_double(dirPrice["pricenighta"]) / 1024 / 1024;
+        data.dirPrice[i].priceNightB = xmlrpc_c::value_double(dirPrice["pricenightb"]) / 1024 / 1024;
+        data.dirPrice[i].threshold = xmlrpc_c::value_int(dirPrice["threshold"]);
+        data.dirPrice[i].singlePrice = xmlrpc_c::value_boolean(dirPrice["singleprice"]);
+        data.dirPrice[i].noDiscount = xmlrpc_c::value_boolean(dirPrice["nodiscount"]);
+        }
+    }
+
+return false;
+}
diff --git a/projects/stargazer/plugins/configuration/rpcconfig/tariff_helper.h b/projects/stargazer/plugins/configuration/rpcconfig/tariff_helper.h
new file mode 100644 (file)
index 0000000..9f68a74
--- /dev/null
@@ -0,0 +1,23 @@
+#pragma once
+
+#include <xmlrpc-c/base.hpp>
+
+namespace STG
+{
+
+struct TariffData;
+
+}
+
+class TARIFF_HELPER
+{
+public:
+    explicit TARIFF_HELPER(STG::TariffData & td)
+        : data(td)
+    {}
+
+    void GetTariffInfo(xmlrpc_c::value * info) const;
+    bool SetTariffInfo(const xmlrpc_c::value & info);
+private:
+    STG::TariffData & data;
+};
diff --git a/projects/stargazer/plugins/configuration/rpcconfig/tariffs_methods.cpp b/projects/stargazer/plugins/configuration/rpcconfig/tariffs_methods.cpp
new file mode 100644 (file)
index 0000000..2047202
--- /dev/null
@@ -0,0 +1,196 @@
+#include <ostream> // xmlrpc-c devs have missed something :)
+
+#include "tariffs_methods.h"
+#include "rpcconfig.h"
+#include "tariff_helper.h"
+
+#include "stg/tariffs.h"
+#include "stg/tariff.h"
+#include "stg/tariff_conf.h"
+#include "stg/users.h"
+#include "stg/admins.h"
+#include "stg/admin.h"
+
+void METHOD_TARIFF_GET::execute(xmlrpc_c::paramList const & paramList,
+                                xmlrpc_c::value *   const   retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string name = paramList.getString(1);
+paramList.verifyEnd(2);
+
+std::map<std::string, xmlrpc_c::value> structVal;
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+    {
+    structVal["result"] = xmlrpc_c::value_boolean(false);
+    *retvalPtr = xmlrpc_c::value_struct(structVal);
+    return;
+    }
+
+const auto tariff = tariffs->FindByName(name);
+
+if (!tariff)
+    {
+    structVal["result"] = xmlrpc_c::value_boolean(false);
+    *retvalPtr = xmlrpc_c::value_struct(structVal);
+    return;
+    }
+
+auto td = tariff->GetTariffData();
+
+TARIFF_HELPER helper(td);
+
+helper.GetTariffInfo(retvalPtr);
+}
+
+void METHOD_TARIFF_CHG::execute(xmlrpc_c::paramList const & paramList,
+                                xmlrpc_c::value *   const   retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string name = paramList.getString(1);
+xmlrpc_c::value_struct info(paramList.getStruct(2));
+paramList.verifyEnd(3);
+
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+
+STG::Admin * admin;
+
+if (admins->find(adminInfo.admin, &admin))
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+
+const auto tariff = tariffs->FindByName(name);
+
+if (!tariff)
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+
+auto td = tariff->GetTariffData();
+
+TARIFF_HELPER helper(td);
+
+helper.SetTariffInfo(info);
+
+if (tariffs->Chg(td, admin))
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+
+*retvalPtr = xmlrpc_c::value_boolean(true);
+}
+
+void METHOD_TARIFFS_GET::execute(xmlrpc_c::paramList const & paramList,
+                                 xmlrpc_c::value *   const   retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+paramList.verifyEnd(1);
+
+std::map<std::string, xmlrpc_c::value> structVal;
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+    {
+    structVal["result"] = xmlrpc_c::value_boolean(false);
+    *retvalPtr = xmlrpc_c::value_struct(structVal);
+    return;
+    }
+
+std::vector<xmlrpc_c::value> tariffsInfo;
+
+
+std::vector<STG::TariffData> dataList;
+tariffs->GetTariffsData(&dataList);
+auto it = dataList.begin();
+for (; it != dataList.end(); ++it)
+    {
+    xmlrpc_c::value info;
+    auto td = *it; // 'cause TARIFF_HELPER work in both ways and take not const referense
+    TARIFF_HELPER helper(td);
+    helper.GetTariffInfo(&info);
+    tariffsInfo.push_back(info);
+    }
+
+*retvalPtr = xmlrpc_c::value_array(tariffsInfo);
+}
+
+void METHOD_TARIFF_ADD::execute(xmlrpc_c::paramList const & paramList,
+                                xmlrpc_c::value *   const   retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string tariff = paramList.getString(1);
+paramList.verifyEnd(2);
+
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+
+STG::Admin * admin;
+
+if (admins->find(adminInfo.admin, &admin))
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+
+if (tariffs->Add(tariff, admin))
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+
+*retvalPtr = xmlrpc_c::value_boolean(true);
+}
+
+void METHOD_TARIFF_DEL::execute(xmlrpc_c::paramList const & paramList,
+                                xmlrpc_c::value *   const   retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string tariff = paramList.getString(1);
+paramList.verifyEnd(2);
+
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+
+STG::Admin * admin;
+
+if (admins->find(adminInfo.admin, &admin))
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+
+if (users->TariffInUse(tariff))
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+
+if (tariffs->Del(tariff, admin))
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+
+*retvalPtr = xmlrpc_c::value_boolean(true);
+}
diff --git a/projects/stargazer/plugins/configuration/rpcconfig/tariffs_methods.h b/projects/stargazer/plugins/configuration/rpcconfig/tariffs_methods.h
new file mode 100644 (file)
index 0000000..4f4d668
--- /dev/null
@@ -0,0 +1,127 @@
+#pragma once
+
+#include <xmlrpc-c/base.hpp>
+#include <xmlrpc-c/registry.hpp>
+
+namespace STG
+{
+
+struct Tariffs;
+struct Users;
+struct Admins;
+
+}
+
+class RPC_CONFIG;
+
+class METHOD_TARIFF_GET : public xmlrpc_c::method {
+public:
+    METHOD_TARIFF_GET(RPC_CONFIG * c,
+                      STG::Tariffs * t)
+        : config(c),
+          tariffs(t)
+    {
+    }
+
+    void execute(xmlrpc_c::paramList const & paramList,
+                 xmlrpc_c::value *   const   retvalPtr);
+
+private:
+    METHOD_TARIFF_GET(const METHOD_TARIFF_GET & rvalue);
+    METHOD_TARIFF_GET & operator=(const METHOD_TARIFF_GET & rvalue);
+
+    RPC_CONFIG * config;
+    STG::Tariffs * tariffs;
+};
+
+class METHOD_TARIFF_CHG : public xmlrpc_c::method {
+public:
+    METHOD_TARIFF_CHG(RPC_CONFIG * c,
+                      STG::Admins * a,
+                      STG::Tariffs * t)
+        : config(c),
+          admins(a),
+          tariffs(t)
+    {
+    }
+
+    void execute(xmlrpc_c::paramList const & paramList,
+                 xmlrpc_c::value *   const   retvalPtr);
+
+private:
+    METHOD_TARIFF_CHG(const METHOD_TARIFF_CHG & rvalue);
+    METHOD_TARIFF_CHG & operator=(const METHOD_TARIFF_CHG & rvalue);
+
+    RPC_CONFIG * config;
+    STG::Admins * admins;
+    STG::Tariffs * tariffs;
+};
+
+class METHOD_TARIFFS_GET : public xmlrpc_c::method {
+public:
+    METHOD_TARIFFS_GET(RPC_CONFIG * c,
+                      STG::Tariffs * t)
+        : config(c),
+          tariffs(t)
+    {
+    }
+
+    void execute(xmlrpc_c::paramList const & paramList,
+                 xmlrpc_c::value *   const   retvalPtr);
+
+private:
+    METHOD_TARIFFS_GET(const METHOD_TARIFFS_GET & rvalue);
+    METHOD_TARIFFS_GET & operator=(const METHOD_TARIFFS_GET & rvalue);
+
+    RPC_CONFIG * config;
+    STG::Tariffs * tariffs;
+};
+
+class METHOD_TARIFF_ADD : public xmlrpc_c::method {
+public:
+    METHOD_TARIFF_ADD(RPC_CONFIG * c,
+                      STG::Admins * a,
+                      STG::Tariffs * t)
+        : config(c),
+          admins(a),
+          tariffs(t)
+    {
+    }
+
+    void execute(xmlrpc_c::paramList const & paramList,
+                 xmlrpc_c::value *   const   retvalP);
+
+private:
+    METHOD_TARIFF_ADD(const METHOD_TARIFF_ADD & rvalue);
+    METHOD_TARIFF_ADD & operator=(const METHOD_TARIFF_ADD & rvalue);
+
+    RPC_CONFIG * config;
+    STG::Admins * admins;
+    STG::Tariffs * tariffs;
+};
+
+class METHOD_TARIFF_DEL : public xmlrpc_c::method {
+public:
+    METHOD_TARIFF_DEL(RPC_CONFIG * c,
+                      STG::Admins * a,
+                      STG::Tariffs * t,
+                      STG::Users * u)
+        : config(c),
+          admins(a),
+          tariffs(t),
+          users(u)
+    {
+    }
+
+    void execute(xmlrpc_c::paramList const & paramList,
+                 xmlrpc_c::value *   const   retvalP);
+
+private:
+    METHOD_TARIFF_DEL(const METHOD_TARIFF_DEL & rvalue);
+    METHOD_TARIFF_DEL & operator=(const METHOD_TARIFF_DEL & rvalue);
+
+    RPC_CONFIG * config;
+    STG::Admins * admins;
+    STG::Tariffs * tariffs;
+    STG::Users * users;
+};
diff --git a/projects/stargazer/plugins/configuration/rpcconfig/user_helper.cpp b/projects/stargazer/plugins/configuration/rpcconfig/user_helper.cpp
new file mode 100644 (file)
index 0000000..7a7a9b9
--- /dev/null
@@ -0,0 +1,401 @@
+#include "user_helper.h"
+
+#include "stg/tariffs.h"
+#include "stg/tariff.h"
+#include "stg/admin.h"
+#include "stg/store.h"
+#include "stg/users.h"
+#include "stg/user.h"
+#include "stg/user_ips.h"
+#include "stg/user_property.h"
+#include "stg/common.h"
+#include "stg/const.h"
+
+#include <cmath>
+
+//------------------------------------------------------------------------------
+
+void USER_HELPER::GetUserInfo(xmlrpc_c::value * info,
+                              bool hidePassword)
+{
+std::map<std::string, xmlrpc_c::value> structVal;
+
+structVal["result"] = xmlrpc_c::value_boolean(true);
+structVal["login"] = xmlrpc_c::value_string(ptr->GetLogin());
+
+if (!hidePassword)
+    {
+    structVal["password"] = xmlrpc_c::value_string(ptr->GetProperties().password.Get());
+    }
+else
+    {
+    structVal["password"] = xmlrpc_c::value_string("++++++++");
+    }
+
+structVal["cash"] = xmlrpc_c::value_double(ptr->GetProperties().cash.Get());
+structVal["freemb"] = xmlrpc_c::value_double(ptr->GetProperties().freeMb.Get());
+structVal["credit"] = xmlrpc_c::value_double(ptr->GetProperties().credit.Get());
+
+if (ptr->GetProperties().nextTariff.Get() != "")
+    {
+    structVal["tariff"] = xmlrpc_c::value_string(
+            ptr->GetProperties().tariffName.Get() +
+            "/" +
+            ptr->GetProperties().nextTariff.Get()
+            );
+    }
+else
+    {
+    structVal["tariff"] = xmlrpc_c::value_string(ptr->GetProperties().tariffName.Get());
+    }
+
+structVal["note"] = xmlrpc_c::value_string(IconvString(ptr->GetProperties().note, "KOI8-RU", "UTF-8"));
+
+structVal["phone"] = xmlrpc_c::value_string(IconvString(ptr->GetProperties().phone, "KOI8-RU", "UTF-8"));
+
+structVal["address"] = xmlrpc_c::value_string(IconvString(ptr->GetProperties().address, "KOI8-RU", "UTF-8"));
+
+structVal["email"] = xmlrpc_c::value_string(IconvString(ptr->GetProperties().email, "KOI8-RU", "UTF-8"));
+
+std::vector<xmlrpc_c::value> userdata;
+
+userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperties().userdata0.Get(), "KOI8-RU", "UTF-8")));
+userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperties().userdata1.Get(), "KOI8-RU", "UTF-8")));
+userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperties().userdata2.Get(), "KOI8-RU", "UTF-8")));
+userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperties().userdata3.Get(), "KOI8-RU", "UTF-8")));
+userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperties().userdata4.Get(), "KOI8-RU", "UTF-8")));
+userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperties().userdata5.Get(), "KOI8-RU", "UTF-8")));
+userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperties().userdata6.Get(), "KOI8-RU", "UTF-8")));
+userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperties().userdata7.Get(), "KOI8-RU", "UTF-8")));
+userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperties().userdata8.Get(), "KOI8-RU", "UTF-8")));
+userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperties().userdata9.Get(), "KOI8-RU", "UTF-8")));
+
+structVal["userdata"] = xmlrpc_c::value_array(userdata);
+
+structVal["name"] = xmlrpc_c::value_string(IconvString(ptr->GetProperties().realName, "KOI8-RU", "UTF-8"));
+
+structVal["group"] = xmlrpc_c::value_string(IconvString(ptr->GetProperties().group, "KOI8-RU", "UTF-8"));
+
+structVal["status"] = xmlrpc_c::value_boolean(ptr->GetConnected());
+structVal["aonline"] = xmlrpc_c::value_boolean(ptr->GetProperties().alwaysOnline.Get());
+structVal["currip"] = xmlrpc_c::value_string(inet_ntostring(ptr->GetCurrIP()));
+structVal["pingtime"] = xmlrpc_c::value_int(static_cast<int>(ptr->GetPingTime()));
+structVal["ips"] = xmlrpc_c::value_string(ptr->GetProperties().ips.Get().toString());
+
+std::map<std::string, xmlrpc_c::value> traffInfo;
+std::vector<xmlrpc_c::value> mu(DIR_NUM);
+std::vector<xmlrpc_c::value> md(DIR_NUM);
+std::vector<xmlrpc_c::value> su(DIR_NUM);
+std::vector<xmlrpc_c::value> sd(DIR_NUM);
+
+auto upload = ptr->GetProperties().up.Get();
+auto download = ptr->GetProperties().down.Get();
+auto supload = ptr->GetSessionUpload();
+auto sdownload = ptr->GetSessionDownload();
+
+for (int j = 0; j < DIR_NUM; j++)
+    {
+    mu[j] = xmlrpc_c::value_string(std::to_string(upload[j]));
+    md[j] = xmlrpc_c::value_string(std::to_string(download[j]));
+    su[j] = xmlrpc_c::value_string(std::to_string(supload[j]));
+    sd[j] = xmlrpc_c::value_string(std::to_string(sdownload[j]));
+    }
+
+traffInfo["mu"] = xmlrpc_c::value_array(mu);
+traffInfo["md"] = xmlrpc_c::value_array(md);
+traffInfo["su"] = xmlrpc_c::value_array(su);
+traffInfo["sd"] = xmlrpc_c::value_array(sd);
+
+structVal["traff"] = xmlrpc_c::value_struct(traffInfo);
+
+structVal["down"] = xmlrpc_c::value_boolean(ptr->GetProperties().disabled.Get());
+structVal["disableddetailstat"] = xmlrpc_c::value_boolean(ptr->GetProperties().disabledDetailStat.Get());
+structVal["passive"] = xmlrpc_c::value_boolean(ptr->GetProperties().passive.Get());
+structVal["lastcash"] = xmlrpc_c::value_double(ptr->GetProperties().lastCashAdd.Get());
+structVal["lasttimecash"] = xmlrpc_c::value_int(static_cast<int>(ptr->GetProperties().lastCashAddTime.Get()));
+structVal["lastactivitytime"] = xmlrpc_c::value_int(static_cast<int>(ptr->GetProperties().lastActivityTime.Get()));
+structVal["creditexpire"] = xmlrpc_c::value_int(static_cast<int>(ptr->GetProperties().creditExpire.Get()));
+
+*info = xmlrpc_c::value_struct(structVal);
+}
+
+//------------------------------------------------------------------------------
+
+bool USER_HELPER::SetUserInfo(const xmlrpc_c::value & info,
+                              const STG::Admin& admin,
+                              const std::string & login,
+                              const STG::Store & store,
+                              STG::Tariffs * tariffs)
+{
+std::map<std::string, xmlrpc_c::value> structVal(
+    static_cast<std::map<std::string, xmlrpc_c::value> >(xmlrpc_c::value_struct(info))
+    );
+
+std::map<std::string, xmlrpc_c::value>::iterator it;
+
+bool check = false;
+bool alwaysOnline = ptr->GetProperties().alwaysOnline;
+if ((it = structVal.find("aonline")) != structVal.end())
+    {
+    check = true;
+    alwaysOnline = xmlrpc_c::value_boolean(it->second);
+    }
+bool onlyOneIP = ptr->GetProperties().ips.ConstData().onlyOneIP();
+if ((it = structVal.find("ips")) != structVal.end())
+    {
+    check = true;
+    onlyOneIP = STG::UserIPs::parse(xmlrpc_c::value_string(it->second)).onlyOneIP();
+    }
+
+if (check && alwaysOnline && !onlyOneIP)
+    {
+    printfd(__FILE__, "Requested change leads to a forbidden state: AlwaysOnline with multiple IP's\n");
+    return true;
+    }
+
+if ((it = structVal.find("ips")) != structVal.end())
+    {
+    auto ips = STG::UserIPs::parse(xmlrpc_c::value_string(it->second));
+
+    for (size_t i = 0; i < ips.count(); ++i)
+        {
+        using ConstUserPtr = const STG::User*;
+        ConstUserPtr user;
+        uint32_t ip = ips[i].ip;
+        if (users.IsIPInUse(ip, login, &user))
+            {
+            printfd(__FILE__, "Trying to assign an IP %s to '%s' that is already in use by '%s'\n", inet_ntostring(ip).c_str(), login.c_str(), user->GetLogin().c_str());
+            return true;
+            }
+        }
+
+    if (!ptr->GetProperties().ips.Set(ips, admin, login, store))
+        return true;
+    }
+
+if ((it = structVal.find("aonline")) != structVal.end())
+    {
+    bool value(xmlrpc_c::value_boolean(it->second));
+    if (ptr->GetProperties().alwaysOnline.Get() != value)
+        if (!ptr->GetProperties().alwaysOnline.Set(value, admin, login, store))
+            return true;
+    }
+
+if ((it = structVal.find("password")) != structVal.end())
+    {
+    std::string value(xmlrpc_c::value_string(it->second));
+    if (ptr->GetProperties().password.Get() != value)
+        if (!ptr->GetProperties().password.Set(value, admin, login, store))
+            return true;
+    }
+
+if ((it = structVal.find("address")) != structVal.end())
+    {
+    std::string value(IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "KOI8-RU"));
+    if (ptr->GetProperties().address.Get() != value)
+        if (!ptr->GetProperties().address.Set(value, admin, login, store))
+            return true;
+    }
+
+if ((it = structVal.find("phone")) != structVal.end())
+    {
+    std::string value(IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "KOI8-RU"));
+    if (ptr->GetProperties().phone.Get() != value)
+        if (!ptr->GetProperties().phone.Set(value, admin, login, store))
+            return true;
+    }
+
+if ((it = structVal.find("email")) != structVal.end())
+    {
+    std::string value(IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "KOI8-RU"));
+    if (ptr->GetProperties().email.Get() != value)
+        if (!ptr->GetProperties().email.Set(value, admin, login, store))
+            return true;
+    }
+
+if ((it = structVal.find("cash")) != structVal.end())
+    {
+    double value(xmlrpc_c::value_double(it->second));
+    if (std::fabs(ptr->GetProperties().cash.Get() - value) > 1.0e-3)
+        if (!ptr->GetProperties().cash.Set(value, admin, login, store))
+            return true;
+    }
+
+if ((it = structVal.find("creditexpire")) != structVal.end())
+    {
+    time_t value(xmlrpc_c::value_int(it->second));
+    if (ptr->GetProperties().creditExpire.Get() != value)
+        if (!ptr->GetProperties().creditExpire.Set(value, admin, login, store))
+            return true;
+    }
+
+if ((it = structVal.find("credit")) != structVal.end())
+    {
+    double value(xmlrpc_c::value_double(it->second));
+    if (std::fabs(ptr->GetProperties().credit.Get() - value) > 1.0e-3)
+        if (!ptr->GetProperties().credit.Set(value, admin, login, store))
+            return true;
+    }
+
+if ((it = structVal.find("freemb")) != structVal.end())
+    {
+    double value(xmlrpc_c::value_double(it->second));
+    if (std::fabs(ptr->GetProperties().freeMb.Get() - value) > 1.0e-3)
+        if (!ptr->GetProperties().freeMb.Set(value, admin, login, store))
+            return true;
+    }
+
+if ((it = structVal.find("down")) != structVal.end())
+    {
+    bool value(xmlrpc_c::value_boolean(it->second));
+    if (ptr->GetProperties().disabled.Get() != value)
+        if (!ptr->GetProperties().disabled.Set(value, admin, login, store))
+            return true;
+    }
+
+if ((it = structVal.find("passive")) != structVal.end())
+    {
+    bool value(xmlrpc_c::value_boolean(it->second));
+    if (ptr->GetProperties().passive.Get() != value)
+        if (!ptr->GetProperties().passive.Set(value, admin, login, store))
+            return true;
+    }
+
+if ((it = structVal.find("disableddetailstat")) != structVal.end())
+    {
+    bool value(xmlrpc_c::value_boolean(it->second));
+    if (ptr->GetProperties().disabledDetailStat.Get() != value)
+        if (!ptr->GetProperties().disabledDetailStat.Set(value, admin, login, store))
+            return true;
+    }
+
+if ((it = structVal.find("name")) != structVal.end())
+    {
+    std::string value(IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "KOI8-RU"));
+    if (ptr->GetProperties().realName.Get() != value)
+        if (!ptr->GetProperties().realName.Set(value, admin, login, store))
+            return true;
+    }
+
+if ((it = structVal.find("group")) != structVal.end())
+    {
+    std::string value(IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "KOI8-RU"));
+    if (ptr->GetProperties().group.Get() != value)
+        if (!ptr->GetProperties().group.Set(value, admin, login, store))
+            return true;
+    }
+
+if ((it = structVal.find("note")) != structVal.end())
+    {
+    std::string value(IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "KOI8-RU"));
+    if (ptr->GetProperties().note.Get() != value)
+        if (!ptr->GetProperties().note.Set(value, admin, login, store))
+            return true;
+    }
+
+if ((it = structVal.find("userdata")) != structVal.end())
+    {
+    std::vector<STG::UserPropertyLogged<std::string> *> userdata;
+    userdata.push_back(ptr->GetProperties().userdata0.GetPointer());
+    userdata.push_back(ptr->GetProperties().userdata1.GetPointer());
+    userdata.push_back(ptr->GetProperties().userdata2.GetPointer());
+    userdata.push_back(ptr->GetProperties().userdata3.GetPointer());
+    userdata.push_back(ptr->GetProperties().userdata4.GetPointer());
+    userdata.push_back(ptr->GetProperties().userdata5.GetPointer());
+    userdata.push_back(ptr->GetProperties().userdata6.GetPointer());
+    userdata.push_back(ptr->GetProperties().userdata7.GetPointer());
+    userdata.push_back(ptr->GetProperties().userdata8.GetPointer());
+    userdata.push_back(ptr->GetProperties().userdata9.GetPointer());
+
+    std::vector<xmlrpc_c::value> udata(
+        xmlrpc_c::value_array(it->second).vectorValueValue()
+        );
+
+    for (unsigned i = 0; i < userdata.size(); ++i)
+        {
+        std::string value(IconvString(xmlrpc_c::value_string(udata[i]), "UTF-8", "KOI8-RU"));
+        if (userdata[i]->Get() != value)
+            if (!userdata[i]->Set(value, admin, login, store))
+                return true;
+        }
+    }
+
+if ((it = structVal.find("traff")) != structVal.end())
+    {
+    std::map<std::string, xmlrpc_c::value> traff(
+        static_cast<std::map<std::string, xmlrpc_c::value> >(xmlrpc_c::value_struct(it->second))
+        );
+
+    auto dtData = ptr->GetProperties().up.Get();
+    if ((it = traff.find("mu")) != traff.end())
+        {
+        std::vector<xmlrpc_c::value> data(xmlrpc_c::value_array(it->second).vectorValueValue());
+
+        for (int i = 0; i < std::min(DIR_NUM, static_cast<int>(data.size())); ++i)
+            {
+            int64_t value;
+            if (str2x(xmlrpc_c::value_string(data[i]), value))
+                printfd(__FILE__, "USER_HELPER::SetUserInfo(): 'Invalid month upload value'\n");
+            else
+                dtData[i] = value;
+            }
+        if (!ptr->GetProperties().up.Set(dtData, admin, login, store))
+            return true;
+        }
+    dtData = ptr->GetProperties().down.Get();
+    if ((it = traff.find("md")) != traff.end())
+        {
+        std::vector<xmlrpc_c::value> data(xmlrpc_c::value_array(it->second).vectorValueValue());
+
+        for (int i = 0; i < std::min(DIR_NUM, static_cast<int>(data.size())); ++i)
+            {
+            int64_t value;
+            if (str2x(xmlrpc_c::value_string(data[i]), value))
+                printfd(__FILE__, "USER_HELPER::SetUserInfo(): 'Invalid month download value'\n");
+            else
+                dtData[i] = value;
+            }
+        if (!ptr->GetProperties().down.Set(dtData, admin, login, store))
+            return true;
+        }
+    }
+
+if ((it = structVal.find("tariff")) != structVal.end())
+    {
+    std::string tariff(xmlrpc_c::value_string(it->second));
+    size_t pos = tariff.find('/');
+    std::string nextTariff;
+    if (pos != std::string::npos)
+        {
+        nextTariff = tariff.substr(pos + 1);
+        tariff = tariff.substr(0, pos);
+        }
+
+    const auto newTariff = tariffs->FindByName(tariff);
+    if (newTariff)
+        {
+        const auto currentTariff = ptr->GetTariff();
+        std::string message = currentTariff->TariffChangeIsAllowed(*newTariff, stgTime);
+        if (message.empty())
+            {
+            if (ptr->GetProperties().tariffName.Get() != tariff)
+                {
+                if (!ptr->GetProperties().tariffName.Set(tariff, admin, login, store))
+                    return true;
+                }
+            }
+        else
+            {
+                STG::PluginLogger::get("conf_rpc")("Tariff change is prohibited for user %s. %s", ptr->GetLogin().c_str(), message.c_str());
+            }
+        }
+
+    if (nextTariff != "" &&
+        tariffs->FindByName(nextTariff))
+        if (ptr->GetProperties().nextTariff.Get() != nextTariff)
+            if (!ptr->GetProperties().nextTariff.Set(tariff, admin, login, store))
+                return true;
+    }
+
+return false;
+}
diff --git a/projects/stargazer/plugins/configuration/rpcconfig/user_helper.h b/projects/stargazer/plugins/configuration/rpcconfig/user_helper.h
new file mode 100644 (file)
index 0000000..5457c95
--- /dev/null
@@ -0,0 +1,38 @@
+#pragma once
+
+#include <string>
+
+#include <xmlrpc-c/base.hpp>
+
+namespace STG
+{
+
+struct Admin;
+struct Store;
+struct Tariffs;
+struct User;
+struct Users;
+
+}
+
+class USER_HELPER
+{
+public:
+    using UserPtr = STG::User*;
+    USER_HELPER(UserPtr & p, STG::Users & us)
+        : ptr(p),
+          users(us)
+    {
+    }
+
+    void GetUserInfo(xmlrpc_c::value * info,
+                     bool hidePassword = false);
+    bool SetUserInfo(const xmlrpc_c::value & info,
+                     const STG::Admin& admin,
+                     const std::string & login,
+                     const STG::Store & store,
+                     STG::Tariffs * tariffs);
+private:
+    UserPtr & ptr;
+    STG::Users & users;
+};
diff --git a/projects/stargazer/plugins/configuration/rpcconfig/users_methods.cpp b/projects/stargazer/plugins/configuration/rpcconfig/users_methods.cpp
new file mode 100644 (file)
index 0000000..650f7b3
--- /dev/null
@@ -0,0 +1,552 @@
+#include "users_methods.h"
+#include "rpcconfig.h"
+#include "user_helper.h"
+
+#include "stg/users.h"
+#include "stg/admins.h"
+#include "stg/tariffs.h"
+#include "stg/tariff.h"
+#include "stg/user.h"
+#include "stg/user_property.h"
+#include "stg/common.h"
+
+#include <cerrno>
+
+using UserPtr = STG::User*;
+
+//------------------------------------------------------------------------------
+
+void METHOD_USER_GET::execute(xmlrpc_c::paramList const & paramList,
+                              xmlrpc_c::value *   const   retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string login = paramList.getString(1);
+paramList.verifyEnd(2);
+
+std::map<std::string, xmlrpc_c::value> structVal;
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+    {
+    structVal["result"] = xmlrpc_c::value_boolean(false);
+    *retvalPtr = xmlrpc_c::value_struct(structVal);
+    return;
+    }
+
+UserPtr u;
+
+if (users->FindByName(login, &u))
+    {
+    structVal["result"] = xmlrpc_c::value_boolean(false);
+    *retvalPtr = xmlrpc_c::value_struct(structVal);
+    return;
+    }
+
+USER_HELPER uhelper(u, *users);
+
+if (!adminInfo.priviledges.userConf || !adminInfo.priviledges.userPasswd)
+    {
+    uhelper.GetUserInfo(retvalPtr, true);
+    return;
+    }
+
+uhelper.GetUserInfo(retvalPtr);
+}
+
+//------------------------------------------------------------------------------
+
+void METHOD_USER_ADD::execute(xmlrpc_c::paramList const & paramList,
+                              xmlrpc_c::value *   const   retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string login = paramList.getString(1);
+paramList.verifyEnd(2);
+
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+
+STG::Admin * admin = NULL;
+
+if (admins->find(adminInfo.admin, &admin))
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+
+UserPtr u;
+
+if (users->FindByName(login, &u))
+    {
+    if (users->Add(login, admin))
+        {
+        *retvalPtr = xmlrpc_c::value_boolean(false);
+        return;
+        }
+
+    *retvalPtr = xmlrpc_c::value_boolean(true);
+    return;
+    }
+
+*retvalPtr = xmlrpc_c::value_boolean(false);
+return;
+}
+
+//------------------------------------------------------------------------------
+
+void METHOD_USER_DEL::execute(xmlrpc_c::paramList const & paramList,
+                              xmlrpc_c::value *   const   retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string login = paramList.getString(1);
+paramList.verifyEnd(2);
+
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+
+STG::Admin * admin;
+
+if (admins->find(adminInfo.admin, &admin))
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+
+UserPtr u;
+
+if (!users->FindByName(login, &u))
+    {
+    users->Del(login, admin);
+    *retvalPtr = xmlrpc_c::value_boolean(true);
+    return;
+    }
+
+*retvalPtr = xmlrpc_c::value_boolean(false);
+return;
+}
+
+//------------------------------------------------------------------------------
+
+void METHOD_USERS_GET::execute(xmlrpc_c::paramList const & paramList,
+                               xmlrpc_c::value *   const   retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+paramList.verifyEnd(1);
+
+std::map<std::string, xmlrpc_c::value> structVal;
+std::vector<xmlrpc_c::value> retval;
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+    {
+    structVal["result"] = xmlrpc_c::value_boolean(false);
+    *retvalPtr = xmlrpc_c::value_struct(structVal);
+    return;
+    }
+
+bool hidePassword = !adminInfo.priviledges.userConf ||
+                    !adminInfo.priviledges.userPasswd;
+
+UserPtr u;
+
+int h = users->OpenSearch();
+if (!h)
+    {
+    printfd(__FILE__, "users->OpenSearch() error\n");
+    users->CloseSearch(h);
+    return;
+    }
+
+while (1)
+    {
+    if (users->SearchNext(h, &u))
+        {
+        break;
+        }
+
+    xmlrpc_c::value info;
+
+    USER_HELPER uhelper(u, *users);
+
+    uhelper.GetUserInfo(&info, hidePassword);
+
+    retval.push_back(info);
+    }
+
+*retvalPtr = xmlrpc_c::value_array(retval);
+}
+
+//------------------------------------------------------------------------------
+
+void METHOD_USER_CHG::execute(xmlrpc_c::paramList const & paramList,
+                              xmlrpc_c::value *   const   retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string login = paramList.getString(1);
+xmlrpc_c::value_struct info(paramList.getStruct(2));
+paramList.verifyEnd(3);
+
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+
+STG::Admin * admin;
+
+if (admins->find(adminInfo.admin, &admin))
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+
+UserPtr u;
+
+if (users->FindByName(login, &u))
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+
+USER_HELPER uhelper(u, *users);
+
+if (!adminInfo.priviledges.userConf || !adminInfo.priviledges.userPasswd)
+    {
+    uhelper.SetUserInfo(info, *admin, login, *store, tariffs);
+    }
+else
+    {
+    uhelper.SetUserInfo(info, *admin, login, *store, tariffs);
+    }
+
+u->WriteConf();
+u->WriteStat();
+
+*retvalPtr = xmlrpc_c::value_boolean(true);
+}
+
+//------------------------------------------------------------------------------
+
+void METHOD_USER_CASH_ADD::execute(xmlrpc_c::paramList const & paramList,
+                                   xmlrpc_c::value *   const   retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string login = paramList.getString(1);
+double amount = paramList.getDouble(2);
+std::string comment = IconvString(paramList.getString(3), "UTF-8", "KOI8-R");
+paramList.verifyEnd(4);
+
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+
+STG::Admin * admin;
+
+if (admins->find(adminInfo.admin, &admin))
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+
+UserPtr u;
+
+if (users->FindByName(login, &u))
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+
+double cash = u->GetProperties().cash.Get();
+cash += amount;
+
+if (!u->GetProperties().cash.Set(cash, *admin, login, *store, comment))
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+
+u->WriteStat();
+
+*retvalPtr = xmlrpc_c::value_boolean(true);
+}
+
+//------------------------------------------------------------------------------
+
+void METHOD_USER_CASH_SET::execute(xmlrpc_c::paramList const & paramList,
+                                   xmlrpc_c::value *   const   retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string login = paramList.getString(1);
+double cash = paramList.getDouble(2);
+std::string comment = IconvString(paramList.getString(3), "UTF-8", "KOI8-R");
+paramList.verifyEnd(4);
+
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+
+STG::Admin * admin;
+
+if (admins->find(adminInfo.admin, &admin))
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+
+UserPtr u;
+
+if (users->FindByName(login, &u))
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+
+if (!u->GetProperties().cash.Set(cash, *admin, login, *store, comment))
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+
+u->WriteStat();
+
+*retvalPtr = xmlrpc_c::value_boolean(true);
+}
+
+//------------------------------------------------------------------------------
+
+void METHOD_USER_TARIFF_CHANGE::execute(xmlrpc_c::paramList const & paramList,
+                                        xmlrpc_c::value *   const   retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string login = paramList.getString(1);
+std::string tariff = paramList.getString(2);
+bool delayed = paramList.getBoolean(3);
+std::string comment = IconvString(paramList.getString(4), "UTF-8", "KOI8-R");
+paramList.verifyEnd(5);
+
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+
+STG::Admin * admin;
+
+if (admins->find(adminInfo.admin, &admin))
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+
+UserPtr u;
+
+if (users->FindByName(login, &u))
+    {
+    *retvalPtr = xmlrpc_c::value_boolean(false);
+    return;
+    }
+
+if (tariffs->FindByName(tariff))
+    {
+    if (delayed)
+        {
+        if (u->GetProperties().nextTariff.Set(tariff, *admin, login, *store, comment))
+            {
+            u->WriteConf();
+            *retvalPtr = xmlrpc_c::value_boolean(true);
+            return;
+            }
+        }
+    else
+        {
+        const auto newTariff = tariffs->FindByName(tariff);
+        if (newTariff)
+            {
+            const auto currentTariff = u->GetTariff();
+            std::string message = currentTariff->TariffChangeIsAllowed(*newTariff, stgTime);
+            if (message.empty())
+                {
+                if (u->GetProperties().tariffName.Set(tariff, *admin, login, *store, comment))
+                    {
+                    u->ResetNextTariff();
+                    u->WriteConf();
+                    *retvalPtr = xmlrpc_c::value_boolean(true);
+                    return;
+                    }
+                }
+            else
+                {
+                    STG::PluginLogger::get("conf_rpc")("Tariff change is prohibited for user %s. %s", u->GetLogin().c_str(), message.c_str());
+                }
+            }
+        }
+    }
+
+*retvalPtr = xmlrpc_c::value_boolean(false);
+}
+
+//------------------------------------------------------------------------------
+
+void METHOD_GET_ONLINE_IPS::execute(xmlrpc_c::paramList const & paramList,
+                                    xmlrpc_c::value *   const   retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+typedef std::vector<xmlrpc_c::value> ValueVector;
+ValueVector subnetsStr = paramList.getArray(1);
+paramList.verifyEnd(2);
+
+std::vector<STG::IPMask> subnets;
+
+for (ValueVector::const_iterator it(subnetsStr.begin()); it != subnetsStr.end(); ++it)
+    {
+    STG::IPMask ipm;
+    if (ParseNet(xmlrpc_c::value_string(*it), ipm))
+        {
+        printfd(__FILE__, "METHOD_GET_ONLINE_IPS::execute(): Failed to parse subnet ('%s')\n", std::string(xmlrpc_c::value_string(*it)).c_str());
+        }
+    else
+        {
+        subnets.push_back(ipm);
+        }
+    }
+
+std::map<std::string, xmlrpc_c::value> structVal;
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+    {
+    structVal["result"] = xmlrpc_c::value_boolean(false);
+    *retvalPtr = xmlrpc_c::value_struct(structVal);
+    return;
+    }
+
+ValueVector ips;
+
+UserPtr u;
+
+int handle = users->OpenSearch();
+if (!handle)
+    {
+    printfd(__FILE__, "users->OpenSearch() error\n");
+    users->CloseSearch(handle);
+    return;
+    }
+
+while (1)
+    {
+    if (users->SearchNext(handle, &u))
+        {
+        break;
+        }
+
+    if (u->GetAuthorized())
+        {
+        uint32_t ip = u->GetCurrIP();
+
+        for (std::vector<STG::IPMask>::const_iterator it(subnets.begin()); it != subnets.end(); ++it)
+            {
+            if ((it->ip & it->mask) == (ip & it->mask))
+                {
+                ips.push_back(xmlrpc_c::value_string(inet_ntostring(u->GetCurrIP())));
+                break;
+                }
+            }
+        }
+    }
+
+structVal["ips"] = xmlrpc_c::value_array(ips);
+
+*retvalPtr = xmlrpc_c::value_struct(structVal);
+}
+
+bool METHOD_GET_ONLINE_IPS::ParseNet(const std::string & net, STG::IPMask & ipm) const
+{
+size_t pos = net.find_first_of('/');
+
+if (pos == std::string::npos)
+    {
+    printfd(__FILE__, "METHOD_GET_ONLINE_IPS::ParseNet(): Network address is not in CIDR-notation\n");
+    return true;
+    }
+
+int res = inet_pton(AF_INET, net.substr(0, pos).c_str(), &ipm.ip);
+
+if (res < 0)
+    {
+    printfd(__FILE__, "METHOD_GET_ONLINE_IPS::ParseNet(): '%s'\n", strerror(errno));
+    return true;
+    }
+else if (res == 0)
+    {
+    printfd(__FILE__, "METHOD_GET_ONLINE_IPS::ParseNet(): Invalid network address\n", strerror(errno));
+    return true;
+    }
+
+if (str2x(net.substr(pos + 1, net.length() - pos - 1), ipm.mask))
+    {
+    printfd(__FILE__, "METHOD_GET_ONLINE_IPS::ParseNet(): Invalid network mask\n");
+    return true;
+    }
+if (ipm.mask > 32)
+    {
+    printfd(__FILE__, "METHOD_GET_ONLINE_IPS::ParseNet(): Network mask is out of range\n");
+    return true;
+    }
+ipm.mask = htonl(0xffFFffFF << (32 - ipm.mask));
+
+return false;
+}
+
+void METHOD_GET_USER_AUTH_BY::execute(xmlrpc_c::paramList const & paramList,
+                                      xmlrpc_c::value *   const   retvalPtr)
+{
+std::string cookie = paramList.getString(0);
+std::string login = paramList.getString(1);
+paramList.verifyEnd(2);
+
+std::map<std::string, xmlrpc_c::value> structVal;
+ADMIN_INFO adminInfo;
+
+if (config->GetAdminInfo(cookie, &adminInfo))
+    {
+    structVal["result"] = xmlrpc_c::value_boolean(false);
+    *retvalPtr = xmlrpc_c::value_struct(structVal);
+    return;
+    }
+
+UserPtr u;
+
+if (users->FindByName(login, &u))
+    {
+    structVal["result"] = xmlrpc_c::value_boolean(false);
+    *retvalPtr = xmlrpc_c::value_struct(structVal);
+    return;
+    }
+
+std::vector<std::string> list(u->GetAuthorizers());
+std::vector<xmlrpc_c::value> authList;
+for (std::vector<std::string>::const_iterator it = list.begin(); it != list.end(); ++it)
+    authList.push_back(xmlrpc_c::value_string(*it));
+*retvalPtr = xmlrpc_c::value_array(authList);
+}
diff --git a/projects/stargazer/plugins/configuration/rpcconfig/users_methods.h b/projects/stargazer/plugins/configuration/rpcconfig/users_methods.h
new file mode 100644 (file)
index 0000000..f03e988
--- /dev/null
@@ -0,0 +1,255 @@
+#pragma once
+
+#include <xmlrpc-c/base.hpp>
+#include <xmlrpc-c/registry.hpp>
+
+namespace STG
+{
+
+struct Admins;
+struct Tariffs;
+struct Users;
+struct Store;
+struct IPMask;
+
+}
+
+class RPC_CONFIG;
+
+class METHOD_USER_GET : public xmlrpc_c::method {
+public:
+    METHOD_USER_GET(RPC_CONFIG * c,
+                    STG::Users * u)
+        : config(c),
+          users(u)
+    {
+    }
+
+    void execute(xmlrpc_c::paramList const & paramList,
+                 xmlrpc_c::value *   const   retvalP);
+
+private:
+    METHOD_USER_GET(const METHOD_USER_GET & rvalue);
+    METHOD_USER_GET & operator=(const METHOD_USER_GET & rvalue);
+
+    RPC_CONFIG * config;
+    STG::Users * users;
+};
+
+class METHOD_USER_ADD : public xmlrpc_c::method {
+public:
+    METHOD_USER_ADD(RPC_CONFIG * c,
+                    STG::Admins * a,
+                    STG::Users * u)
+        : config(c),
+          admins(a),
+          users(u)
+    {
+    }
+
+    void execute(xmlrpc_c::paramList const & paramList,
+                 xmlrpc_c::value *   const   retvalP);
+
+private:
+    METHOD_USER_ADD(const METHOD_USER_ADD & rvalue);
+    METHOD_USER_ADD & operator=(const METHOD_USER_ADD & rvalue);
+
+    RPC_CONFIG * config;
+    STG::Admins * admins;
+    STG::Users * users;
+};
+
+class METHOD_USER_DEL : public xmlrpc_c::method {
+public:
+    METHOD_USER_DEL(RPC_CONFIG * c,
+                    STG::Admins * a,
+                    STG::Users * u)
+        : config(c),
+          admins(a),
+          users(u)
+    {
+    }
+
+    void execute(xmlrpc_c::paramList const & paramList,
+                 xmlrpc_c::value *   const   retvalP);
+
+private:
+    METHOD_USER_DEL(const METHOD_USER_DEL & rvalue);
+    METHOD_USER_DEL & operator=(const METHOD_USER_DEL & rvalue);
+
+    RPC_CONFIG * config;
+    STG::Admins * admins;
+    STG::Users * users;
+};
+
+class METHOD_USERS_GET : public xmlrpc_c::method {
+public:
+    METHOD_USERS_GET(RPC_CONFIG * c,
+                     STG::Users * u)
+        : config(c),
+          users(u)
+    {
+    }
+
+    void execute(xmlrpc_c::paramList const & paramList,
+                 xmlrpc_c::value *   const   retvalP);
+
+private:
+    METHOD_USERS_GET(const METHOD_USERS_GET & rvalue);
+    METHOD_USERS_GET & operator=(const METHOD_USERS_GET & rvalue);
+
+    RPC_CONFIG * config;
+    STG::Users * users;
+};
+
+class METHOD_USER_CHG : public xmlrpc_c::method {
+public:
+    METHOD_USER_CHG(RPC_CONFIG * c,
+                    STG::Admins * a,
+                    STG::Tariffs * t,
+                    STG::Store * s,
+                    STG::Users * u)
+        : config(c),
+          admins(a),
+          tariffs(t),
+          store(s),
+          users(u)
+    {
+    }
+
+    void execute(xmlrpc_c::paramList const & paramList,
+                 xmlrpc_c::value *   const   retvalP);
+
+private:
+    METHOD_USER_CHG(const METHOD_USER_CHG & rvalue);
+    METHOD_USER_CHG & operator=(const METHOD_USER_CHG & rvalue);
+
+    RPC_CONFIG * config;
+    STG::Admins * admins;
+    STG::Tariffs * tariffs;
+    STG::Store * store;
+    STG::Users * users;
+};
+
+class METHOD_USER_CASH_ADD : public xmlrpc_c::method {
+public:
+    METHOD_USER_CASH_ADD(RPC_CONFIG * c,
+                         STG::Admins * a,
+                         STG::Store * s,
+                         STG::Users * u)
+        : config(c),
+          admins(a),
+          store(s),
+          users(u)
+    {
+    }
+
+    void execute(xmlrpc_c::paramList const & paramList,
+                 xmlrpc_c::value *   const   retvalP);
+
+private:
+    METHOD_USER_CASH_ADD(const METHOD_USER_CASH_ADD & rvalue);
+    METHOD_USER_CASH_ADD & operator=(const METHOD_USER_CASH_ADD & rvalue);
+
+    RPC_CONFIG * config;
+    STG::Admins * admins;
+    STG::Store * store;
+    STG::Users * users;
+};
+
+class METHOD_USER_CASH_SET : public xmlrpc_c::method {
+public:
+    METHOD_USER_CASH_SET(RPC_CONFIG * c,
+                         STG::Admins * a,
+                         STG::Store * s,
+                         STG::Users * u)
+        : config(c),
+          admins(a),
+          store(s),
+          users(u)
+    {
+    }
+
+    void execute(xmlrpc_c::paramList const & paramList,
+                 xmlrpc_c::value *   const   retvalP);
+
+private:
+    METHOD_USER_CASH_SET(const METHOD_USER_CASH_SET & rvalue);
+    METHOD_USER_CASH_SET & operator=(const METHOD_USER_CASH_SET & rvalue);
+
+    RPC_CONFIG * config;
+    STG::Admins * admins;
+    STG::Store * store;
+    STG::Users * users;
+};
+
+class METHOD_USER_TARIFF_CHANGE : public xmlrpc_c::method {
+public:
+    METHOD_USER_TARIFF_CHANGE(RPC_CONFIG * c,
+                              STG::Admins * a,
+                              STG::Tariffs * t,
+                              STG::Store * s,
+                              STG::Users * u)
+        : config(c),
+          admins(a),
+          tariffs(t),
+          store(s),
+          users(u)
+    {
+    }
+
+    void execute(xmlrpc_c::paramList const & paramList,
+                 xmlrpc_c::value *   const   retvalP);
+
+private:
+    METHOD_USER_TARIFF_CHANGE(const METHOD_USER_TARIFF_CHANGE & rvalue);
+    METHOD_USER_TARIFF_CHANGE & operator=(const METHOD_USER_TARIFF_CHANGE & rvalue);
+
+    RPC_CONFIG * config;
+    STG::Admins * admins;
+    STG::Tariffs * tariffs;
+    STG::Store * store;
+    STG::Users * users;
+};
+
+class METHOD_GET_ONLINE_IPS : public xmlrpc_c::method {
+public:
+    METHOD_GET_ONLINE_IPS(RPC_CONFIG * c,
+                          STG::Users * u)
+        : config(c),
+          users(u)
+    {
+    }
+
+    void execute(xmlrpc_c::paramList const & paramList,
+                 xmlrpc_c::value *   const   retvalP);
+
+private:
+    METHOD_GET_ONLINE_IPS(const METHOD_GET_ONLINE_IPS & rvalue);
+    METHOD_GET_ONLINE_IPS & operator=(const METHOD_GET_ONLINE_IPS & rvalue);
+
+    RPC_CONFIG * config;
+    STG::Users * users;
+
+    bool ParseNet(const std::string & net, STG::IPMask & ipm) const;
+};
+
+class METHOD_GET_USER_AUTH_BY : public xmlrpc_c::method {
+public:
+    METHOD_GET_USER_AUTH_BY(RPC_CONFIG * c,
+                            STG::Users * u)
+        : config(c),
+          users(u)
+    {
+    }
+
+    void execute(xmlrpc_c::paramList const & paramList,
+                 xmlrpc_c::value *   const   retvalP);
+
+private:
+    METHOD_GET_USER_AUTH_BY(const METHOD_GET_ONLINE_IPS & rvalue);
+    METHOD_GET_USER_AUTH_BY & operator=(const METHOD_GET_ONLINE_IPS & rvalue);
+
+    RPC_CONFIG * config;
+    STG::Users * users;
+};
diff --git a/projects/stargazer/plugins/configuration/sgconfig/configproto.cpp b/projects/stargazer/plugins/configuration/sgconfig/configproto.cpp
new file mode 100644 (file)
index 0000000..0119790
--- /dev/null
@@ -0,0 +1,327 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#include "configproto.h"
+
+#include "conn.h"
+
+#include "parser_server_info.h"
+#include "parser_admins.h"
+#include "parser_tariffs.h"
+#include "parser_users.h"
+#include "parser_services.h"
+#include "parser_message.h"
+#include "parser_user_info.h"
+#include "parser_auth_by.h"
+
+#include "stg/common.h"
+#include "stg/logger.h"
+
+#include <algorithm>
+#include <functional>
+#include <vector>
+#include <csignal>
+#include <cstring>
+#include <cerrno>
+#include <cassert>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+namespace SP = STG::PARSER;
+
+CONFIGPROTO::CONFIGPROTO(STG::PluginLogger & l)
+    : m_settings(NULL),
+      m_admins(NULL),
+      m_tariffs(NULL),
+      m_users(NULL),
+      m_services(NULL),
+      m_corporations(NULL),
+      m_store(NULL),
+      m_port(0),
+      m_bindAddress("0.0.0.0"),
+      m_running(false),
+      m_stopped(true),
+      m_logger(l),
+      m_listenSocket(-1)
+{
+}
+
+CONFIGPROTO::~CONFIGPROTO()
+{
+    {
+    std::deque<STG::Conn *>::iterator it;
+    for (it = m_conns.begin(); it != m_conns.end(); ++it)
+        delete *it;
+    }
+    {
+    BASE_PARSER::REGISTRY::iterator it;
+    for (it = m_registry.begin(); it != m_registry.end(); ++it)
+        delete it->second;
+    }
+}
+
+int CONFIGPROTO::Prepare()
+{
+    sigset_t sigmask, oldmask;
+    sigemptyset(&sigmask);
+    sigaddset(&sigmask, SIGINT);
+    sigaddset(&sigmask, SIGTERM);
+    sigaddset(&sigmask, SIGUSR1);
+    sigaddset(&sigmask, SIGHUP);
+    pthread_sigmask(SIG_BLOCK, &sigmask, &oldmask);
+    m_listenSocket = socket(PF_INET, SOCK_STREAM, 0);
+
+    if (m_listenSocket < 0)
+    {
+        m_errorStr = std::string("Cannot create listen socket: '") + strerror(errno) + "'.";
+        m_logger(m_errorStr);
+        return -1;
+    }
+
+    int dummy = 1;
+
+    if (setsockopt(m_listenSocket, SOL_SOCKET, SO_REUSEADDR, &dummy, 4) != 0)
+    {
+        m_errorStr = std::string("Failed to set SO_REUSEADDR to the listen socket: '") + strerror(errno) + "'.";
+        m_logger(m_errorStr);
+        return -1;
+    }
+
+    if (!Bind())
+        return -1;
+
+    if (listen(m_listenSocket, 64) == -1) // TODO: backlog length
+    {
+        m_errorStr = std::string("Failed to start listening for connections: '") + strerror(errno) + "'.";
+        m_logger(m_errorStr);
+        return -1;
+    }
+
+    RegisterParsers();
+
+    m_running = true;
+    m_stopped = false;
+    return 0;
+}
+
+int CONFIGPROTO::Stop()
+{
+    m_running = false;
+    for (int i = 0; i < 5 && !m_stopped; ++i)
+    {
+        struct timespec ts = {0, 200000000};
+        nanosleep(&ts, NULL);
+    }
+
+    if (!m_stopped)
+    {
+        m_errorStr = "Cannot stop listenign thread.";
+        m_logger(m_errorStr);
+        return -1;
+    }
+
+    shutdown(m_listenSocket, SHUT_RDWR);
+    close(m_listenSocket);
+    return 0;
+}
+
+void CONFIGPROTO::Run()
+{
+    while (m_running)
+    {
+        fd_set fds;
+
+        BuildFDSet(fds);
+
+        struct timeval tv;
+        tv.tv_sec = 0;
+        tv.tv_usec = 500000;
+
+        int res = select(MaxFD() + 1, &fds, NULL, NULL, &tv);
+        if (res < 0)
+        {
+            m_errorStr = std::string("'select' is failed: '") + strerror(errno) + "'.";
+            printfd(__FILE__, "%s\n", m_errorStr.c_str());
+            m_logger(m_errorStr);
+            break;
+        }
+        if (!m_running)
+            break;
+        if (res > 0)
+            HandleEvents(fds);
+
+        CleanupConns();
+    }
+    m_stopped = true;
+}
+
+bool CONFIGPROTO::Bind()
+{
+    const hostent * he = gethostbyname(m_bindAddress.c_str());
+    if (he == NULL)
+    {
+        m_errorStr = "Failed to resolve name '" + m_bindAddress + "': '" + hstrerror(h_errno) + "'.";
+        printfd(__FILE__, "%s\n", m_errorStr.c_str());
+        m_logger(m_errorStr);
+        return false;
+    }
+
+    char ** ptr = he->h_addr_list;
+    while (*ptr != NULL)
+    {
+        struct sockaddr_in listenAddr;
+        listenAddr.sin_family = PF_INET;
+        listenAddr.sin_port = htons(m_port);
+        listenAddr.sin_addr.s_addr = *reinterpret_cast<in_addr_t *>(*ptr);
+
+        printfd(__FILE__, "Trying to bind to %s:%d\n", inet_ntostring(listenAddr.sin_addr.s_addr).c_str(), m_port);
+
+        if (bind(m_listenSocket, reinterpret_cast<sockaddr *>(&listenAddr), sizeof(listenAddr)) == 0)
+            return true;
+
+        m_errorStr = std::string("Cannot bind listen socket: '") + strerror(errno) + "'.";
+        printfd(__FILE__, "%s\n", m_errorStr.c_str());
+        m_logger(m_errorStr);
+
+        ++ptr;
+    }
+
+    return false;
+}
+
+void CONFIGPROTO::RegisterParsers()
+{
+    assert(m_settings != NULL);
+    assert(m_store != NULL);
+    assert(m_admins != NULL);
+    assert(m_users != NULL);
+    assert(m_tariffs != NULL);
+    assert(m_services != NULL);
+    assert(m_corporations != NULL);
+
+    SP::GET_SERVER_INFO::FACTORY::Register(m_registry, *m_settings, *m_users, *m_tariffs);
+
+    SP::GET_ADMINS::FACTORY::Register(m_registry, *m_admins);
+    SP::ADD_ADMIN::FACTORY::Register(m_registry, *m_admins);
+    SP::DEL_ADMIN::FACTORY::Register(m_registry, *m_admins);
+    SP::CHG_ADMIN::FACTORY::Register(m_registry, *m_admins);
+
+    SP::GET_TARIFFS::FACTORY::Register(m_registry, *m_tariffs);
+    SP::ADD_TARIFF::FACTORY::Register(m_registry, *m_tariffs);
+    SP::DEL_TARIFF::FACTORY::Register(m_registry, *m_tariffs, *m_users);
+    SP::CHG_TARIFF::FACTORY::Register(m_registry, *m_tariffs);
+
+    SP::GET_USERS::FACTORY::Register(m_registry, *m_users);
+    SP::GET_USER::FACTORY::Register(m_registry, *m_users);
+    SP::ADD_USER::FACTORY::Register(m_registry, *m_users);
+    SP::DEL_USER::FACTORY::Register(m_registry, *m_users);
+    SP::CHG_USER::FACTORY::Register(m_registry, *m_users, *m_store, *m_tariffs);
+    SP::CHECK_USER::FACTORY::Register(m_registry, *m_users);
+
+    SP::GET_SERVICES::FACTORY::Register(m_registry, *m_services);
+    SP::GET_SERVICE::FACTORY::Register(m_registry, *m_services);
+    SP::ADD_SERVICE::FACTORY::Register(m_registry, *m_services);
+    SP::DEL_SERVICE::FACTORY::Register(m_registry, *m_services);
+    SP::CHG_SERVICE::FACTORY::Register(m_registry, *m_services);
+
+    SP::SEND_MESSAGE::FACTORY::Register(m_registry, *m_users);
+
+    SP::AUTH_BY::FACTORY::Register(m_registry, *m_users);
+
+    SP::USER_INFO::FACTORY::Register(m_registry, *m_users);
+}
+
+int CONFIGPROTO::MaxFD() const
+{
+    int maxFD = m_listenSocket;
+    std::deque<STG::Conn *>::const_iterator it;
+    for (it = m_conns.begin(); it != m_conns.end(); ++it)
+        if (maxFD < (*it)->Sock())
+            maxFD = (*it)->Sock();
+    return maxFD;
+}
+
+void CONFIGPROTO::BuildFDSet(fd_set & fds) const
+{
+    FD_ZERO(&fds);
+    FD_SET(m_listenSocket, &fds);
+    std::deque<STG::Conn *>::const_iterator it;
+    for (it = m_conns.begin(); it != m_conns.end(); ++it)
+        FD_SET((*it)->Sock(), &fds);
+}
+
+void CONFIGPROTO::CleanupConns()
+{
+    std::deque<STG::Conn *>::iterator pos;
+    for (pos = m_conns.begin(); pos != m_conns.end(); ++pos)
+        if (((*pos)->IsDone() && !(*pos)->IsKeepAlive()) || !(*pos)->IsOk())
+        {
+            delete *pos;
+            *pos = NULL;
+        }
+
+    pos = std::remove(m_conns.begin(), m_conns.end(), static_cast<STG::Conn *>(NULL));
+    m_conns.erase(pos, m_conns.end());
+}
+
+void CONFIGPROTO::HandleEvents(const fd_set & fds)
+{
+    if (FD_ISSET(m_listenSocket, &fds))
+        AcceptConnection();
+    else
+    {
+        std::deque<STG::Conn *>::iterator it;
+        for (it = m_conns.begin(); it != m_conns.end(); ++it)
+            if (FD_ISSET((*it)->Sock(), &fds))
+                (*it)->Read();
+    }
+}
+
+void CONFIGPROTO::AcceptConnection()
+{
+    struct sockaddr_in outerAddr;
+    socklen_t outerAddrLen(sizeof(outerAddr));
+    int sock = accept(m_listenSocket, reinterpret_cast<sockaddr *>(&outerAddr), &outerAddrLen);
+
+    if (sock < 0)
+    {
+        m_errorStr = std::string("Failed to accept connection: '") + strerror(errno) + "'.";
+        printfd(__FILE__, "%s\n", m_errorStr.c_str());
+        m_logger(m_errorStr);
+        return;
+    }
+
+    assert(m_admins != NULL);
+
+    try
+    {
+        m_conns.push_back(new STG::Conn(m_registry, *m_admins, sock, outerAddr, m_logger));
+        printfd(__FILE__, "New connection from %s:%d. Total connections: %d\n", inet_ntostring(m_conns.back()->IP()).c_str(), m_conns.back()->Port(), m_conns.size());
+    }
+    catch (const STG::Conn::Error & error)
+    {
+        // Unlikely.
+        m_logger(std::string("Failed to create new client connection: '") + error.what() + "'.");
+    }
+}
diff --git a/projects/stargazer/plugins/configuration/sgconfig/configproto.h b/projects/stargazer/plugins/configuration/sgconfig/configproto.h
new file mode 100644 (file)
index 0000000..7721938
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#pragma once
+
+#include "parser.h"
+
+#include "stg/module_settings.h"
+
+#include <string>
+#include <deque>
+#include <cstdint>
+
+#include <sys/select.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+namespace STG
+{
+
+struct Settings;
+struct Admins;
+struct Tariffs;
+struct Users;
+struct Services;
+struct Corporations;
+struct Store;
+class PluginLogger;
+
+class Conn;
+
+}
+
+class CONFIGPROTO {
+public:
+    explicit CONFIGPROTO(STG::PluginLogger & l);
+    ~CONFIGPROTO();
+
+    void SetPort(uint16_t port) { m_port = port; }
+    void SetBindAddress(const std::string & address) { m_bindAddress = address; }
+    void SetSettings(const STG::Settings * settings) { m_settings = settings; }
+    void SetAdmins(STG::Admins * admins) { m_admins = admins; }
+    void SetTariffs(STG::Tariffs * tariffs) { m_tariffs = tariffs; }
+    void SetUsers(STG::Users * users) { m_users = users; }
+    void SetStore(STG::Store * store) { m_store = store; }
+    void SetServices(STG::Services * services) { m_services = services; }
+    void SetCorporations(STG::Corporations * corporations) { m_corporations = corporations; }
+
+    int Prepare();
+    int Stop();
+    const std::string & GetStrError() const { return m_errorStr; }
+    void Run();
+
+private:
+    CONFIGPROTO(const CONFIGPROTO & rvalue);
+    CONFIGPROTO & operator=(const CONFIGPROTO & rvalue);
+
+    const STG::Settings * m_settings;
+    STG::Admins *         m_admins;
+    STG::Tariffs *        m_tariffs;
+    STG::Users *          m_users;
+    STG::Services *       m_services;
+    STG::Corporations *   m_corporations;
+    STG::Store *          m_store;
+
+    uint16_t         m_port;
+    std::string      m_bindAddress;
+    bool             m_running;
+    bool             m_stopped;
+    STG::PluginLogger &   m_logger;
+    int              m_listenSocket;
+
+    std::string      m_errorStr;
+
+    BASE_PARSER::REGISTRY m_registry;
+    std::deque<STG::Conn *> m_conns;
+
+    bool Bind();
+
+    void RegisterParsers();
+
+    int MaxFD() const;
+    void BuildFDSet(fd_set & fds) const;
+    void CleanupConns();
+    void HandleEvents(const fd_set & fds);
+    void AcceptConnection();
+};
diff --git a/projects/stargazer/plugins/configuration/sgconfig/conn.cpp b/projects/stargazer/plugins/configuration/sgconfig/conn.cpp
new file mode 100644 (file)
index 0000000..92d7479
--- /dev/null
@@ -0,0 +1,307 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#include "conn.h"
+
+#include "stg/admins.h"
+#include "stg/admin.h"
+#include "stg/logger.h"
+#include "stg/blowfish.h"
+#include "stg/bfstream.h"
+#include "stg/common.h"
+
+#include <cassert>
+#include <cstring>
+#include <cerrno>
+
+#include <unistd.h>
+#include <sys/socket.h>
+
+using STG::Conn;
+
+const char Conn::STG_HEADER[] = "SG04";
+const char Conn::OK_HEADER[] = "OKHD";
+const char Conn::ERR_HEADER[] = "ERHD";
+const char Conn::OK_LOGIN[] = "OKLG";
+const char Conn::ERR_LOGIN[] = "ERLG";
+const char Conn::OK_LOGINS[] = "OKLS";
+const char Conn::ERR_LOGINS[] = "ERLS";
+
+Conn::Conn(const BASE_PARSER::REGISTRY & registry,
+           Admins & admins, int sock, const sockaddr_in& addr,
+           PluginLogger & logger)
+    : m_registry(registry),
+      m_admins(admins),
+      m_admin(NULL),
+      m_sock(sock),
+      m_addr(addr),
+      m_keepAlive(false),
+      m_parser(NULL),
+      m_xmlParser(XML_ParserCreate(NULL)),
+      m_state(HEADER),
+      m_buffer(m_header),
+      m_bufferSize(sizeof(m_header)),
+      m_stream(NULL),
+      m_logger(logger),
+#ifdef DUMPCRYPTO
+      m_dataState(false, *this),
+      m_dumper(endpoint())
+#else
+      m_dataState(false, *this)
+#endif
+{
+    if (m_xmlParser == NULL)
+        throw Error("Failed to create XML parser.");
+
+    XML_ParserReset(m_xmlParser, NULL);
+    XML_SetElementHandler(m_xmlParser, ParseXMLStart, ParseXMLEnd);
+    XML_SetUserData(m_xmlParser, this);
+}
+
+Conn::~Conn()
+{
+    shutdown(m_sock, SHUT_RDWR);
+    close(m_sock);
+
+    XML_ParserFree(m_xmlParser);
+
+    delete m_stream;
+    delete m_parser;
+}
+
+bool Conn::Read()
+{
+    ssize_t res = read(m_sock, m_buffer, m_bufferSize);
+    if (res < 0)
+    {
+        m_state = ERROR;
+        Log(__FILE__, "Failed to read data from " + endpoint() + ". Reason: '" + strerror(errno) + "'");
+        return false;
+    }
+    if (res == 0 && m_state != DATA) // EOF is ok for data.
+    {
+        m_state = ERROR;
+        Log(__FILE__, "Failed to read data from " + endpoint() + ". Unexpected EOF.");
+        return false;
+    }
+#ifdef DUMPCRYPTO
+    m_dumper.write(m_buffer, res);
+#endif
+    m_bufferSize -= res;
+    m_buffer = static_cast<char*>(m_buffer) + res;
+    return HandleBuffer(res);
+}
+
+bool Conn::WriteAnswer(const void* buffer, size_t size)
+{
+    ssize_t res = write(m_sock, buffer, size);
+    if (res < 0)
+    {
+        m_state = ERROR;
+        Log(__FILE__, "Failed to write data to " + endpoint() + ". Reason: '" + strerror(errno) + "'.");
+        return false;
+    }
+    return true;
+}
+
+BASE_PARSER * Conn::GetParser(const std::string & tag) const
+{
+    BASE_PARSER::REGISTRY::const_iterator it = m_registry.find(ToLower(tag));
+    if (it == m_registry.end())
+        return NULL;
+    return it->second->create(*m_admin);
+}
+
+bool Conn::HandleBuffer(size_t size)
+{
+    if (m_state == DATA)
+        return HandleData(size);
+
+    if (m_bufferSize > 0)
+        return true;
+
+    switch (m_state)
+    {
+        case HEADER: return HandleHeader();
+        case LOGIN: return HandleLogin();
+        case CRYPTO_LOGIN: return HandleCryptoLogin();
+        default: return true;
+    }
+
+    return true;
+}
+
+bool Conn::HandleHeader()
+{
+    if (strncmp(m_header, STG_HEADER, sizeof(m_header)) != 0)
+    {
+        Log(__FILE__, "Received invalid header from " + endpoint() + ".");
+        WriteAnswer(ERR_HEADER, sizeof(ERR_HEADER) - 1); // Without \0
+        m_state = ERROR;
+        return false;
+    }
+    m_state = LOGIN;
+    m_buffer = m_login;
+    m_bufferSize = sizeof(m_login);
+    return WriteAnswer(OK_HEADER, sizeof(OK_HEADER) - 1); // Without \0
+}
+
+bool Conn::HandleLogin()
+{
+    if (m_admins.find(m_login, &m_admin)) // ADMINS::Find returns true on error.
+    {
+        std::string login(m_login, strnlen(m_login, sizeof(m_login)));
+        Log(__FILE__, "Received invalid login '" + ToPrintable(login) + "' from " + endpoint() + ".");
+        WriteAnswer(ERR_LOGIN, sizeof(ERR_LOGIN) - 1); // Without \0
+        m_state = ERROR;
+        return false;
+    }
+    m_admin->setIP(IP());
+    m_state = CRYPTO_LOGIN;
+    m_buffer = m_cryptoLogin;
+    m_bufferSize = sizeof(m_cryptoLogin);
+    return WriteAnswer(OK_LOGIN, sizeof(OK_LOGIN) - 1); // Without \0
+}
+
+bool Conn::HandleCryptoLogin()
+{
+    char login[ADM_LOGIN_LEN + 1];
+    BLOWFISH_CTX ctx;
+    InitContext(m_admin->password().c_str(), ADM_PASSWD_LEN, &ctx);
+    DecryptString(login, m_cryptoLogin, ADM_LOGIN_LEN, &ctx);
+
+    if (strncmp(m_login, login, sizeof(login)) != 0)
+    {
+        Log(__FILE__, "Attempt to connect with wrong password from " + m_admin->login() + "@" + endpoint() + ".");
+        WriteAnswer(ERR_LOGINS, sizeof(ERR_LOGINS) - 1); // Without \0
+        m_state = ERROR;
+        return false;
+    }
+
+    m_state = DATA;
+    m_buffer = m_data;
+    m_bufferSize = sizeof(m_data);
+    m_stream = new STG::DECRYPT_STREAM(m_admin->password(), DataCallback, &m_dataState);
+    return WriteAnswer(OK_LOGINS, sizeof(OK_LOGINS) - 1); // Without \0
+}
+
+bool Conn::HandleData(size_t size)
+{
+    m_stream->Put(m_data, size, size == 0 || memchr(m_data, 0, size) != NULL);
+    m_buffer = m_data;
+    return m_stream->IsOk();
+}
+
+bool Conn::DataCallback(const void * block, size_t size, void * data)
+{
+    assert(data != NULL);
+    DataState& state = *static_cast<DataState *>(data);
+
+    const char * xml = static_cast<const char *>(block);
+    size_t length = strnlen(xml, size);
+
+    state.final = state.final || length < size || size == 0;
+
+    if (XML_Parse(state.conn.m_xmlParser, xml, length, state.final) == XML_STATUS_ERROR)
+    {
+        state.conn.Log(__FILE__, "Received invalid XML from " + state.conn.m_admin->login() + "@" + state.conn.endpoint() + ".");
+        printfd(__FILE__, "XML parse error at line %d, %d: %s. Is final: %d\n",
+                  static_cast<int>(XML_GetCurrentLineNumber(state.conn.m_xmlParser)),
+                  static_cast<int>(XML_GetCurrentColumnNumber(state.conn.m_xmlParser)),
+                  XML_ErrorString(XML_GetErrorCode(state.conn.m_xmlParser)), (int)state.final);
+        printfd(__FILE__, "Data block: '%s' of size %d\n", xml, length);
+        state.conn.m_state = ERROR;
+        return false;
+    }
+
+    if (state.final)
+    {
+        if (!state.conn.WriteResponse())
+        {
+            state.conn.Log(__FILE__, "Failed to write response to " + state.conn.m_admin->login() + "@" + state.conn.endpoint() + ".");
+            state.conn.m_state = ERROR;
+            return false;
+        }
+        state.conn.m_state = DONE;
+    }
+
+    return true;
+}
+
+void Conn::ParseXMLStart(void * data, const char * el, const char ** attr)
+{
+    assert(data != NULL);
+    Conn & conn = *static_cast<Conn *>(data);
+
+    if (conn.m_parser == NULL)
+        conn.m_parser = conn.GetParser(el);
+
+    if (conn.m_parser == NULL)
+    {
+        conn.Log(__FILE__, "Received unknown command '" + std::string(el) + "' from " + conn.m_admin->login() + "@" + conn.endpoint() + ".");
+        conn.m_state = ERROR;
+        return;
+    }
+
+    conn.m_parser->Start(data, el, attr);
+}
+
+void Conn::ParseXMLEnd(void * data, const char * el)
+{
+    assert(data != NULL);
+    Conn & conn = *static_cast<Conn *>(data);
+
+    if (conn.m_parser == NULL)
+    {
+        // No need to log it.
+        conn.m_state = ERROR;
+        return;
+    }
+
+    conn.m_parser->End(data, el);
+}
+
+bool Conn::WriteResponse()
+{
+    STG::ENCRYPT_STREAM stream(m_admin->password(), WriteCallback, this);
+    std::string answer;
+    if (m_parser != NULL)
+        answer = m_parser->GetAnswer();
+    else
+        answer = "<Error result=\"Unknown command.\"/>";
+    delete m_parser;
+    m_parser = NULL;
+    printfd(__FILE__, "Writing %d bytes of answer.\n", answer.length());
+    stream.Put(answer.c_str(), answer.length() + 1 /* including \0 */, true /* final */);
+    return stream.IsOk();
+}
+
+bool Conn::WriteCallback(const void * block, size_t size, void * data)
+{
+    assert(data != NULL);
+    Conn & conn = *static_cast<Conn *>(data);
+    return WriteAll(conn.m_sock, block, size);;
+}
+
+void Conn::Log(const char * file, const std::string & message)
+{
+    printfd(file, "%s\n", message.c_str());
+    m_logger(message);
+}
diff --git a/projects/stargazer/plugins/configuration/sgconfig/conn.h b/projects/stargazer/plugins/configuration/sgconfig/conn.h
new file mode 100644 (file)
index 0000000..c96be90
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#pragma once
+
+#include "parser.h"
+
+#include "dumphelpers.h"
+
+#include "stg/const.h"
+
+#include <stdexcept>
+#include <string>
+#include <cstdint>
+
+#include <expat.h>
+
+#include <netinet/in.h>
+
+namespace STG
+{
+
+struct Settings;
+struct Admins;
+struct Users;
+struct Tariffs;
+struct Admin;
+class PluginLogger;
+
+class DECRYPT_STREAM;
+
+class Conn
+{
+    public:
+        struct Error : public std::runtime_error
+        {
+            explicit Error(const std::string& message) : runtime_error(message.c_str()) {}
+        };
+
+        Conn(const BASE_PARSER::REGISTRY & registry,
+             Admins & admins, int sock, const sockaddr_in& addr,
+             PluginLogger & logger);
+        ~Conn();
+
+        int Sock() const { return m_sock; }
+        uint32_t IP() const { return *(uint32_t *)(&m_addr.sin_addr); }
+        uint16_t Port() const { return ntohs(m_addr.sin_port); }
+
+        std::string endpoint() const { return inet_ntostring(IP()) + ":" + std::to_string(Port()); }
+
+        bool Read();
+
+        bool IsOk() const { return m_state != ERROR; }
+        bool IsDone() const { return m_state == DONE; }
+        bool IsKeepAlive() const { return m_keepAlive; }
+
+        void SetKeepAlive() { m_keepAlive = true; }
+
+    private:
+
+        static const char STG_HEADER[5];
+        static const char OK_HEADER[5];
+        static const char ERR_HEADER[5];
+        static const char OK_LOGIN[5];
+        static const char ERR_LOGIN[5];
+        static const char OK_LOGINS[5];
+        static const char ERR_LOGINS[5];
+
+        const BASE_PARSER::REGISTRY & m_registry;
+
+        Admins & m_admins;
+
+        Admin * m_admin;
+
+        int m_sock;
+        sockaddr_in m_addr;
+        bool m_keepAlive;
+
+        BASE_PARSER * m_parser;
+
+        XML_Parser m_xmlParser;
+
+        enum { HEADER, LOGIN, CRYPTO_LOGIN, DATA, DONE, ERROR } m_state;
+
+        void * m_buffer;
+        size_t m_bufferSize;
+        char m_header[sizeof(STG_HEADER) - 1]; // Without \0
+        char m_login[ADM_LOGIN_LEN]; // Without \0
+        char m_cryptoLogin[ADM_LOGIN_LEN]; // Without \0
+        char m_data[1024];
+        STG::DECRYPT_STREAM * m_stream;
+        PluginLogger &  m_logger;
+
+        BASE_PARSER * GetParser(const std::string & tag) const;
+
+        bool HandleBuffer(size_t size);
+
+        bool HandleHeader();
+        bool HandleLogin();
+        bool HandleCryptoLogin();
+        bool HandleData(size_t size);
+
+        bool WriteAnswer(const void* buffer, size_t size);
+        bool WriteResponse();
+
+        void Log(const char * file, const std::string & message);
+
+        struct DataState
+        {
+            DataState(bool f, Conn & c) : final(f), conn(c) {}
+            bool final;
+            Conn & conn;
+        } m_dataState;
+
+#ifdef DUMPCRYPTO
+        Dumper m_dumper;
+#endif
+
+        static bool DataCallback(const void * block, size_t size, void * data);
+        static void ParseXMLStart(void * data, const char * el, const char ** attr);
+        static void ParseXMLEnd(void * data, const char * el);
+        static bool WriteCallback(const void * block, size_t size, void * data);
+};
+
+}
diff --git a/projects/stargazer/plugins/configuration/sgconfig/dumphelpers.h b/projects/stargazer/plugins/configuration/sgconfig/dumphelpers.h
new file mode 100644 (file)
index 0000000..86bf197
--- /dev/null
@@ -0,0 +1,85 @@
+#ifndef __STG_DUMP_HELPERS_H__
+#define __STG_DUMP_HELPERS_H__
+
+#include "stg/common.h"
+
+#include <string>
+#include <fstream>
+#include <sstream>
+#include <iomanip>
+
+#include <cstddef>
+#include <ctime>
+
+namespace STG
+{
+
+class Dumper
+{
+    public:
+        explicit Dumper(const std::string& tag)
+            : m_stream(getName(tag).c_str())
+        {
+        }
+        ~Dumper() {}
+
+        void write(const void* data, size_t size)
+        {
+            writePrefix();
+            m_stream << " ";
+            writeHEX(data, size);
+        }
+
+    private:
+        std::ofstream m_stream;
+
+        tm getTime() const
+        {
+            time_t now = time(NULL);
+            tm localTime;
+            localtime_r(&now, &localTime);
+            return localTime;
+        }
+
+        std::string getName(const std::string& tag) const
+        {
+            tm localTime = getTime();
+
+            std::ostringstream res;
+            res << tag
+                << "-" << (localTime.tm_year + 1900) << twoDigit(localTime.tm_mon + 1) << twoDigit(localTime.tm_mday)
+                << "-" << twoDigit(localTime.tm_hour) << twoDigit(localTime.tm_min) << twoDigit(localTime.tm_sec)
+                << ".data";
+
+            return res.str();
+        }
+
+        void writePrefix()
+        {
+            tm localTime = getTime();
+            m_stream << "[" << (localTime.tm_year + 1900) << "-" << twoDigit(localTime.tm_mon + 1) << "-" << twoDigit(localTime.tm_mday)
+                     << " " << twoDigit(localTime.tm_hour) << ":" << twoDigit(localTime.tm_min) << ":" << twoDigit(localTime.tm_sec)
+                     << "]";
+        }
+
+        void writeHEX(const void* data, size_t size)
+        {
+            m_stream << "(" << std::setw(4) << std::setfill(' ') << size << ") ";
+            const unsigned char* pos = static_cast<const unsigned char*>(data);
+            for (size_t i = 0; i < size; ++i)
+                m_stream << std::hex << std::setw(2) << std::setfill('0') << static_cast<unsigned int>(*pos++);
+            m_stream << std::dec << "\n";
+        }
+
+        std::string twoDigit(int value) const
+        {
+            std::string res = std::to_string(value);
+            if (res.length() < 2)
+                res = "0" + res;
+            return res;
+        }
+};
+
+} // namespace STG
+
+#endif
diff --git a/projects/stargazer/plugins/configuration/sgconfig/parser.cpp b/projects/stargazer/plugins/configuration/sgconfig/parser.cpp
new file mode 100644 (file)
index 0000000..0371798
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+#include "parser.h"
+
+#include <cstring>
+
+//-----------------------------------------------------------------------------
+//  BASE PARSER
+//-----------------------------------------------------------------------------
+int BASE_PARSER::Start(void *, const char * el, const char **)
+{
+    if (strcasecmp(el, m_tag.c_str()) == 0)
+        return 0;
+
+    return -1;
+}
+//-----------------------------------------------------------------------------
+int BASE_PARSER::End(void *, const char * el)
+{
+    if (m_depth < 2)
+    {
+        if (strcasecmp(el, m_tag.c_str()) != 0)
+            return -1;
+        CreateAnswer();
+    }
+
+    --m_depth;
+    return 0;
+}
diff --git a/projects/stargazer/plugins/configuration/sgconfig/parser.h b/projects/stargazer/plugins/configuration/sgconfig/parser.h
new file mode 100644 (file)
index 0000000..5dd339b
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+#pragma once
+
+#include <string>
+#include <map>
+
+namespace STG
+{
+struct Admin;
+}
+
+class BASE_PARSER
+{
+    public:
+        struct FACTORY
+        {
+            virtual ~FACTORY() {}
+            virtual BASE_PARSER * create(const STG::Admin & admin) = 0;
+        };
+        typedef std::map<std::string, FACTORY *> REGISTRY;
+
+        BASE_PARSER(const STG::Admin & admin, const std::string & t)
+            : m_currAdmin(admin),
+              m_depth(0),
+              m_tag(t)
+        {}
+        virtual ~BASE_PARSER() {}
+        virtual int Start(void * data, const char * el, const char ** attr);
+        virtual int End(void * data, const char * el);
+
+        const std::string & GetAnswer() const { return m_answer; }
+        const std::string & GetTag() const { return m_tag; }
+        std::string GetOpenTag() const { return "<" + m_tag + ">"; }
+        std::string GetCloseTag() const { return "</" + m_tag + ">"; }
+
+    protected:
+        BASE_PARSER(const BASE_PARSER & rvalue);
+        BASE_PARSER & operator=(const BASE_PARSER & rvalue);
+
+        const STG::Admin & m_currAdmin;
+        size_t        m_depth;
+        std::string   m_answer;
+        std::string   m_tag;
+
+    private:
+        virtual void CreateAnswer() = 0;
+};
diff --git a/projects/stargazer/plugins/configuration/sgconfig/parser_admins.cpp b/projects/stargazer/plugins/configuration/sgconfig/parser_admins.cpp
new file mode 100644 (file)
index 0000000..bc47b7f
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#include "parser_admins.h"
+
+#include "stg/admins.h"
+#include "stg/admin.h"
+#include "stg/admin_conf.h"
+
+#include <strings.h> // strcasecmp
+
+using STG::PARSER::GET_ADMINS;
+using STG::PARSER::ADD_ADMIN;
+using STG::PARSER::DEL_ADMIN;
+using STG::PARSER::CHG_ADMIN;
+
+const char * GET_ADMINS::tag = "GetAdmins";
+const char * ADD_ADMIN::tag  = "AddAdmin";
+const char * DEL_ADMIN::tag  = "DelAdmin";
+const char * CHG_ADMIN::tag  = "ChgAdmin";
+
+void GET_ADMINS::CreateAnswer()
+{
+    const auto& priv = m_currAdmin.priv();
+    if (!priv.adminChg)
+    {
+        m_answer = "<Error Result=\"Error. Access denied.\"/>";
+        return;
+    }
+
+    m_answer = "<Admins>";
+    m_admins.fmap([this](const Admin& admin)
+                  {
+                      const unsigned int p = (admin.priv().userStat << 0) +
+                                             (admin.priv().userConf << 2) +
+                                             (admin.priv().userCash << 4) +
+                                             (admin.priv().userPasswd << 6) +
+                                             (admin.priv().userAddDel << 8) +
+                                             (admin.priv().adminChg << 10) +
+                                             (admin.priv().tariffChg << 12);
+                      m_answer += "<admin login=\"" + admin.login() + "\" priv=\"" + std::to_string(p) + "\"/>";
+                  });
+    m_answer += "</Admins>";
+}
+
+int DEL_ADMIN::Start(void *, const char * el, const char ** attr)
+{
+    if (strcasecmp(el, m_tag.c_str()) == 0)
+    {
+        m_admin = attr[1];
+        return 0;
+    }
+    return -1;
+}
+
+void DEL_ADMIN::CreateAnswer()
+{
+    if (m_admins.del(m_admin, m_currAdmin) == 0)
+        m_answer = "<" + m_tag + " Result=\"Ok\"/>";
+    else
+        m_answer = "<" + m_tag + " Result=\"Error. " + m_admins.strError() + "\"/>";
+}
+
+int ADD_ADMIN::Start(void *, const char *el, const char **attr)
+{
+    if (strcasecmp(el, m_tag.c_str()) == 0)
+    {
+        m_admin = attr[1];
+        return 0;
+    }
+    return -1;
+}
+
+void ADD_ADMIN::CreateAnswer()
+{
+    if (m_admins.add(m_admin, m_currAdmin) == 0)
+        m_answer = "<" + m_tag + " Result=\"Ok\"/>";
+    else
+        m_answer = "<" + m_tag + " Result=\"Error. " + m_admins.strError() + "\"/>";
+}
+
+int CHG_ADMIN::Start(void *, const char * el, const char ** attr)
+{
+    if (strcasecmp(el, m_tag.c_str()) == 0)
+    {
+        for (size_t i = 0; i < 6; i += 2)
+        {
+            printfd(__FILE__, "PARSER_CHG_ADMIN::attr[%d] = %s\n", i, attr[i]);
+            if (attr[i] == NULL)
+                break;
+
+            if (strcasecmp(attr[i], "Login") == 0)
+            {
+                login = attr[i + 1];
+                continue;
+            }
+
+            if (strcasecmp(attr[i], "Priv") == 0)
+            {
+                privAsString = attr[i + 1];
+                continue;
+            }
+
+            if (strcasecmp(attr[i], "Password") == 0)
+            {
+                password = attr[i + 1];
+                continue;
+            }
+        }
+
+        return 0;
+    }
+    return -1;
+}
+
+void CHG_ADMIN::CreateAnswer()
+{
+    if (!login.empty())
+    {
+        Admin * origAdmin = NULL;
+
+        if (m_admins.find(login, &origAdmin))
+        {
+            m_answer = "<" + m_tag + " Result = \"Admin '" + login + "' is not found.\"/>";
+            return;
+        }
+
+        AdminConf conf(origAdmin->conf());
+
+        if (!password.empty())
+            conf.password = password.data();
+
+        if (!privAsString.empty())
+        {
+            int p = 0;
+            if (str2x(privAsString.data().c_str(), p) < 0)
+            {
+                m_answer = "<" + m_tag + " Result = \"Incorrect parameter Priv.\"/>";
+                return;
+            }
+
+            conf.priv = Priv(p);
+        }
+
+        if (m_admins.change(conf, m_currAdmin) != 0)
+            m_answer = "<" + m_tag + " Result = \"" + m_admins.strError() + "\"/>";
+        else
+            m_answer = "<" + m_tag + " Result = \"Ok\"/>";
+    }
+    else
+        m_answer = "<" + m_tag + " Result = \"Incorrect parameter login.\"/>";
+}
diff --git a/projects/stargazer/plugins/configuration/sgconfig/parser_admins.h b/projects/stargazer/plugins/configuration/sgconfig/parser_admins.h
new file mode 100644 (file)
index 0000000..423ac3c
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#pragma once
+
+#include "parser.h"
+
+#include "stg/common.h"
+#include "stg/optional.h"
+
+#include <string>
+
+namespace STG
+{
+
+struct Admins;
+struct Admin;
+
+namespace PARSER
+{
+
+class GET_ADMINS: public BASE_PARSER
+{
+    public:
+        class FACTORY : public BASE_PARSER::FACTORY
+        {
+            public:
+                explicit FACTORY(const Admins & admins) : m_admins(admins) {}
+                virtual BASE_PARSER * create(const Admin & admin) { return new GET_ADMINS(admin, m_admins); }
+                static void Register(REGISTRY & registry, const Admins & admins)
+                { registry[ToLower(tag)] = new FACTORY(admins); }
+            private:
+                const Admins & m_admins;
+        };
+
+        static const char * tag;
+
+        GET_ADMINS(const Admin & admin, const Admins & admins)
+            : BASE_PARSER(admin, tag), m_admins(admins) {}
+
+    private:
+        const Admins & m_admins;
+
+        void CreateAnswer();
+};
+
+class ADD_ADMIN: public BASE_PARSER
+{
+    public:
+        class FACTORY : public BASE_PARSER::FACTORY
+        {
+            public:
+                explicit FACTORY(Admins & admins) : m_admins(admins) {}
+                virtual BASE_PARSER * create(const Admin & admin) { return new ADD_ADMIN(admin, m_admins); }
+                static void Register(REGISTRY & registry, Admins & admins)
+                { registry[ToLower(tag)] = new FACTORY(admins); }
+            private:
+                Admins & m_admins;
+        };
+
+        static const char * tag;
+
+        ADD_ADMIN(const Admin & admin, Admins & admins)
+            : BASE_PARSER(admin, tag), m_admins(admins) {}
+        int Start(void * data, const char * el, const char ** attr);
+
+    private:
+        std::string m_admin;
+        Admins & m_admins;
+
+        void CreateAnswer();
+};
+
+class DEL_ADMIN: public BASE_PARSER
+{
+    public:
+        class FACTORY : public BASE_PARSER::FACTORY
+        {
+            public:
+                explicit FACTORY(Admins & admins) : m_admins(admins) {}
+                virtual BASE_PARSER * create(const Admin & admin) { return new DEL_ADMIN(admin, m_admins); }
+                static void Register(REGISTRY & registry, Admins & admins)
+                { registry[ToLower(tag)] = new FACTORY(admins); }
+            private:
+                Admins & m_admins;
+        };
+
+        static const char * tag;
+
+        DEL_ADMIN(const Admin & admin, Admins & admins)
+            : BASE_PARSER(admin, tag), m_admins(admins) {}
+        int Start(void * data, const char * el, const char ** attr);
+
+    private:
+        std::string m_admin;
+        Admins & m_admins;
+
+        void CreateAnswer();
+};
+
+class CHG_ADMIN: public BASE_PARSER
+{
+    public:
+        class FACTORY : public BASE_PARSER::FACTORY
+        {
+            public:
+                explicit FACTORY(Admins & admins) : m_admins(admins) {}
+                virtual BASE_PARSER * create(const Admin & admin) { return new CHG_ADMIN(admin, m_admins); }
+                static void Register(REGISTRY & registry, Admins & admins)
+                { registry[ToLower(tag)] = new FACTORY(admins); }
+            private:
+                Admins & m_admins;
+        };
+
+        static const char * tag;
+
+        CHG_ADMIN(const Admin & admin, Admins & admins)
+            : BASE_PARSER(admin, tag), m_admins(admins) {}
+        int Start(void * data, const char * el, const char ** attr);
+
+    private:
+        std::string login;
+        Optional<std::string> password;
+        Optional<std::string> privAsString;
+        Admins & m_admins;
+
+        void CreateAnswer();
+};
+
+} // namespace PARSER
+} // namespace STG
diff --git a/projects/stargazer/plugins/configuration/sgconfig/parser_auth_by.cpp b/projects/stargazer/plugins/configuration/sgconfig/parser_auth_by.cpp
new file mode 100644 (file)
index 0000000..7e38a11
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#include "parser_auth_by.h"
+
+#include "stg/users.h"
+#include "stg/user.h"
+
+#include <cstring>
+
+using STG::PARSER::AUTH_BY;
+
+const char * AUTH_BY::tag = "GetUserAuthBy";
+
+int AUTH_BY::Start(void * /*data*/, const char *el, const char **attr)
+{
+    if (strcasecmp(el, m_tag.c_str()) != 0)
+        return -1;
+
+    if (!attr[1])
+        return -1;
+
+    m_login = attr[1];
+    return 0;
+}
+
+void AUTH_BY::CreateAnswer()
+{
+    using ConstUserPtr = const User*;
+    ConstUserPtr u;
+    if (m_users.FindByName(m_login, &u))
+    {
+        m_answer = "<AuthorizedBy result=\"error\" reason=\"User not found.\"/>";
+        return;
+    }
+
+    m_answer = "<AuthorizedBy result=\"ok\">";
+    std::vector<std::string> list(u->GetAuthorizers());
+    for (std::vector<std::string>::const_iterator it = list.begin(); it != list.end(); ++it)
+        m_answer += "<Auth name=\"" + *it + "\"/>";
+    m_answer += "</AuthorizedBy>";
+}
diff --git a/projects/stargazer/plugins/configuration/sgconfig/parser_auth_by.h b/projects/stargazer/plugins/configuration/sgconfig/parser_auth_by.h
new file mode 100644 (file)
index 0000000..5016474
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#pragma once
+
+#include "parser.h"
+
+#include "stg/common.h"
+
+#include <string>
+
+namespace STG
+{
+
+struct Admin;
+struct Users;
+
+namespace PARSER
+{
+
+class AUTH_BY : public BASE_PARSER
+{
+    public:
+        class FACTORY : public BASE_PARSER::FACTORY
+        {
+            public:
+                explicit FACTORY(const Users & users) : m_users(users) {}
+                virtual BASE_PARSER * create(const Admin & admin) { return new AUTH_BY(admin, m_users); }
+                static void Register(REGISTRY & registry, const Users & users)
+                { registry[ToLower(tag)] = new FACTORY(users); }
+            private:
+                const Users & m_users;
+        };
+
+        static const char * tag;
+
+        AUTH_BY(const Admin & admin, const Users & users)
+            : BASE_PARSER(admin, tag), m_users(users) {}
+        int Start(void * data, const char * el, const char ** attr);
+
+    private:
+        const Users & m_users;
+        std::string m_login;
+
+        void CreateAnswer();
+};
+
+} // namespace PARSER
+} // namespace STG
diff --git a/projects/stargazer/plugins/configuration/sgconfig/parser_message.cpp b/projects/stargazer/plugins/configuration/sgconfig/parser_message.cpp
new file mode 100644 (file)
index 0000000..b460799
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#include "parser_message.h"
+
+#include "stg/users.h"
+#include "stg/user.h"
+
+#include <cstring>
+
+extern volatile time_t stgTime; // So sad...
+
+using STG::PARSER::SEND_MESSAGE;
+
+const char * SEND_MESSAGE::tag = "Message";
+
+int SEND_MESSAGE::Start(void *, const char *el, const char **attr)
+{
+    if (strcasecmp(el, m_tag.c_str()) != 0)
+        return -1;
+
+    for (size_t i = 0; i < 14; i++)
+        if (attr[i] == NULL)
+        {
+            m_result = res_params_error;
+            CreateAnswer();
+            printfd(__FILE__, "To few parameters\n");
+            return 0;
+        }
+
+    for (size_t i = 0; i < 14; i += 2)
+    {
+        if (strcasecmp(attr[i], "login") == 0)
+            ParseLogins(attr[i + 1]);
+
+        if (strcasecmp(attr[i], "MsgVer") == 0)
+        {
+            str2x(attr[i + 1], m_msg.header.ver);
+            if (m_msg.header.ver != 1)
+                m_result = res_params_error;
+        }
+
+        if (strcasecmp(attr[i], "MsgType") == 0)
+        {
+            str2x(attr[i + 1], m_msg.header.type);
+            if (m_msg.header.type != 1)
+                m_result = res_params_error;
+        }
+
+        if (strcasecmp(attr[i], "Repeat") == 0)
+        {
+            str2x(attr[i + 1], m_msg.header.repeat);
+            if (m_msg.header.repeat < 0)
+                m_result = res_params_error;
+        }
+
+        if (strcasecmp(attr[i], "RepeatPeriod") == 0)
+            str2x(attr[i + 1], m_msg.header.repeatPeriod);
+
+        if (strcasecmp(attr[i], "ShowTime") == 0)
+            str2x(attr[i + 1], m_msg.header.showTime);
+
+        if (strcasecmp(attr[i], "Text") == 0)
+        {
+            Decode21str(m_msg.text, attr[i + 1]);
+            m_result = res_ok;
+        }
+    }
+    return 0;
+}
+
+int SEND_MESSAGE::End(void *, const char *el)
+{
+    if (strcasecmp(el, m_tag.c_str()) != 0)
+        return -1;
+
+    m_result = res_unknown;
+    for (unsigned i = 0; i < m_logins.size(); i++)
+    {
+        if (m_users.FindByName(m_logins[i], &m_user))
+        {
+            printfd(__FILE__, "User not found. %s\n", m_logins[i].c_str());
+            continue;
+        }
+        m_msg.header.creationTime = static_cast<unsigned int>(stgTime);
+        m_user->AddMessage(&m_msg);
+        m_result = res_ok;
+    }
+    CreateAnswer();
+    return 0;
+}
+
+int SEND_MESSAGE::ParseLogins(const char * login)
+{
+    char * p;
+    char * l = new char[strlen(login) + 1];
+    strcpy(l, login);
+    p = strtok(l, ":");
+    m_logins.clear();
+    while (p)
+    {
+        m_logins.push_back(p);
+        p = strtok(NULL, ":");
+    }
+
+    delete[] l;
+    return 0;
+}
+
+void SEND_MESSAGE::CreateAnswer()
+{
+    switch (m_result)
+    {
+        case res_ok:
+            m_answer = "<SendMessageResult value=\"ok\"/>";
+            break;
+        case res_params_error:
+            m_answer = "<SendMessageResult value=\"Parameters error.\"/>";
+            break;
+        case res_unknown:
+            m_answer = "<SendMessageResult value=\"Unknown user.\"/>";
+            break;
+    }
+}
diff --git a/projects/stargazer/plugins/configuration/sgconfig/parser_message.h b/projects/stargazer/plugins/configuration/sgconfig/parser_message.h
new file mode 100644 (file)
index 0000000..3f75993
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#pragma once
+
+#include "parser.h"
+
+#include "stg/message.h"
+#include "stg/common.h"
+
+#include <vector>
+#include <string>
+
+namespace STG
+{
+
+struct Users;
+struct User;
+
+namespace PARSER
+{
+
+class SEND_MESSAGE: public BASE_PARSER
+{
+    public:
+        class FACTORY : public BASE_PARSER::FACTORY
+        {
+            public:
+                explicit FACTORY(Users & users) : m_users(users) {}
+                virtual BASE_PARSER * create(const Admin & admin) { return new SEND_MESSAGE(admin, m_users); }
+                static void Register(REGISTRY & registry, Users & users)
+                { registry[ToLower(tag)] = new FACTORY(users); }
+            private:
+                Users & m_users;
+        };
+
+        static const char * tag;
+
+        SEND_MESSAGE(const Admin & admin, Users & users)
+            : BASE_PARSER(admin, tag), m_users(users), m_result(res_ok), m_user(NULL) {}
+        int Start(void *data, const char *el, const char **attr);
+        int End(void *data, const char *el);
+
+    private:
+        Users & m_users;
+        std::vector<std::string> m_logins;
+        enum { res_ok, res_params_error, res_unknown } m_result;
+        STG::Message m_msg;
+        User * m_user;
+
+        int ParseLogins(const char * logins);
+        void CreateAnswer();
+};
+
+} // namespace PARSER
+} // namespace STG
diff --git a/projects/stargazer/plugins/configuration/sgconfig/parser_server_info.cpp b/projects/stargazer/plugins/configuration/sgconfig/parser_server_info.cpp
new file mode 100644 (file)
index 0000000..1b47d57
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#include "parser_server_info.h"
+
+#include "stg/settings.h"
+#include "stg/users.h"
+#include "stg/tariffs.h"
+#include "stg/version.h"
+#include "stg/const.h"
+
+#include <string>
+#include <cstring>
+
+#include <sys/utsname.h>
+
+using STG::PARSER::GET_SERVER_INFO;
+
+const char * GET_SERVER_INFO::tag = "GetServerInfo";
+
+void GET_SERVER_INFO::CreateAnswer()
+{
+    struct utsname utsn;
+    uname(&utsn);
+
+    std::string name = std::string(utsn.sysname) + " " +
+                       utsn.release + " " +
+                       utsn.machine + " " +
+                       utsn.nodename;
+
+    m_answer = std::string("<ServerInfo><version value=\"") + SERVER_VERSION + "\"/>" +
+               "<tariff_num value=\"" + std::to_string(m_tariffs.Count()) + "\"/>" +
+               "<tariff value=\"2\"/>" +
+               "<user_num value=\"" + std::to_string(m_users.Count()) + "\"/>" +
+               "<uname value=\"" + name + "\"/>" +
+               "<dir_num value=\"" + std::to_string(DIR_NUM) + "\"/>" +
+               "<day_fee value=\"" + std::to_string(m_settings.GetDayFee()) + "\"/>";
+
+    for (size_t i = 0; i< DIR_NUM; i++)
+        m_answer += "<dir_name_" + std::to_string(i) + " value=\"" + Encode12str(m_settings.GetDirName(i)) + "\"/>";
+
+    m_answer += "</ServerInfo>";
+}
diff --git a/projects/stargazer/plugins/configuration/sgconfig/parser_server_info.h b/projects/stargazer/plugins/configuration/sgconfig/parser_server_info.h
new file mode 100644 (file)
index 0000000..fad2412
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#pragma once
+
+#include "parser.h"
+
+#include "stg/common.h"
+
+namespace STG
+{
+
+struct Admin;
+struct Settings;
+struct Users;
+struct Tariffs;
+
+namespace PARSER
+{
+
+class GET_SERVER_INFO: public BASE_PARSER {
+    public:
+        class FACTORY : public BASE_PARSER::FACTORY
+        {
+            public:
+                FACTORY(const Settings & settings, const Users & users, const Tariffs & tariffs)
+                    : m_settings(settings), m_users(users), m_tariffs(tariffs) {}
+                virtual BASE_PARSER * create(const Admin & admin) { return new GET_SERVER_INFO(admin, m_settings, m_users, m_tariffs); }
+                static void Register(REGISTRY & registry, const Settings & settings, const Users & users, const Tariffs & tariffs)
+                { registry[ToLower(tag)] = new FACTORY(settings, users, tariffs); }
+            private:
+                const Settings & m_settings;
+                const Users & m_users;
+                const Tariffs & m_tariffs;
+        };
+
+        static const char * tag;
+
+        GET_SERVER_INFO(const Admin & admin,
+                        const Settings & settings,
+                        const Users & users,
+                        const Tariffs & tariffs)
+            : BASE_PARSER(admin, tag),
+              m_settings(settings),
+              m_users(users),
+              m_tariffs(tariffs)
+        {}
+
+    private:
+        const Settings & m_settings;
+        const Users & m_users;
+        const Tariffs & m_tariffs;
+
+        void CreateAnswer();
+};
+
+}
+}
diff --git a/projects/stargazer/plugins/configuration/sgconfig/parser_services.cpp b/projects/stargazer/plugins/configuration/sgconfig/parser_services.cpp
new file mode 100644 (file)
index 0000000..118d819
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#include "parser_services.h"
+
+#include "stg/services.h"
+
+#include <strings.h> // strcasecmp
+
+using STG::PARSER::GET_SERVICES;
+using STG::PARSER::GET_SERVICE;
+using STG::PARSER::ADD_SERVICE;
+using STG::PARSER::DEL_SERVICE;
+using STG::PARSER::CHG_SERVICE;
+
+const char * GET_SERVICES::tag = "GetServices";
+const char * GET_SERVICE::tag  = "AddService";
+const char * ADD_SERVICE::tag  = "AddService";
+const char * DEL_SERVICE::tag  = "DelService";
+const char * CHG_SERVICE::tag  = "SetService";
+
+void GET_SERVICES::CreateAnswer()
+{
+    // TODO: no priviledges implemented yet
+    /*const PRIV * priv = m_currAdmin.GetPriv();
+    if (!priv->serviceChg)
+    {
+        m_answer = "<Error Result=\"Error. Access denied.\"/>";
+        return;
+    }*/
+
+    m_answer = "<Services>";
+    ServiceConf conf;
+    int h = m_services.OpenSearch();
+    while (m_services.SearchNext(h, &conf) == 0)
+    {
+        m_answer += "<Service name=\"" + conf.name +
+                    "\" comment=\"" + Encode12str(conf.comment) +
+                    "\" cost=\"" + std::to_string(conf.cost) +
+                    "\" payDay=\"" + std::to_string(conf.payDay) + "\"/>";
+    }
+    m_services.CloseSearch(h);
+    m_answer += "</Services>";
+}
+
+int GET_SERVICE::Start(void *, const char * el, const char ** attr)
+{
+    if (strcasecmp(el, m_tag.c_str()) == 0)
+    {
+        m_name = attr[1];
+        return 0;
+    }
+    return -1;
+}
+
+void GET_SERVICE::CreateAnswer()
+{
+    // TODO: no priviledges implemented yet
+    /*const PRIV * priv = m_currAdmin.GetPriv();
+    if (!priv->serviceChg)
+    {
+        m_answer = "<Error Result=\"Error. Access denied.\"/>";
+        return;
+    }*/
+
+    ServiceConf conf;
+    if (!m_services.Find(m_name, &conf))
+        m_answer = "<Error result=\"Service '" + m_name + "' does not exist.\"/>";
+    else
+        m_answer += "<" + m_tag + " name=\"" + conf.name +
+                    "\" comment=\"" + Encode12str(conf.comment) +
+                    "\" cost=\"" + std::to_string(conf.cost) +
+                    "\" payDay=\"" + std::to_string(conf.payDay) + "\"/>";
+}
+
+int ADD_SERVICE::Start(void *, const char * el, const char ** attr)
+{
+    if (strcasecmp(el, m_tag.c_str()) == 0)
+    {
+        m_name = attr[1];
+        return 0;
+    }
+    return -1;
+}
+
+void ADD_SERVICE::CreateAnswer()
+{
+    ServiceConf conf(m_name);
+    if (m_services.Add(conf, &m_currAdmin) == 0)
+        m_answer = "<" + m_tag + " result=\"Ok\"/>";
+    else
+        m_answer = "<" + m_tag + " result=\"" + m_services.GetStrError() + "\"/>";
+}
+
+int DEL_SERVICE::Start(void *, const char * el, const char ** attr)
+{
+    if (strcasecmp(el, m_tag.c_str()) == 0)
+    {
+        m_name = attr[1];
+        return 0;
+    }
+    return -1;
+}
+
+void DEL_SERVICE::CreateAnswer()
+{
+    if (m_services.Del(m_name, &m_currAdmin) == 0)
+        m_answer = "<" + m_tag + " result=\"Ok\"/>";
+    else
+        m_answer = "<" + m_tag + " result=\"" + m_services.GetStrError() + "\"/>";
+}
+
+int CHG_SERVICE::Start(void *, const char * el, const char ** attr)
+{
+    if (strcasecmp(el, m_tag.c_str()) == 0)
+    {
+        for (size_t i = 0; i < 8; i += 2)
+        {
+            if (attr[i] == NULL)
+                break;
+
+            if (strcasecmp(attr[i], "name") == 0)
+            {
+                m_service.name = attr[i + 1];
+                continue;
+            }
+
+            if (strcasecmp(attr[i], "comment") == 0)
+            {
+                m_service.comment = Decode21str(attr[i + 1]);
+                continue;
+            }
+
+            if (strcasecmp(attr[i], "cost") == 0)
+            {
+                double cost = 0;
+                if (str2x(attr[i + 1], cost) == 0)
+                    m_service.cost = cost;
+                else
+                    printfd(__FILE__, "Bad cast from '%s' to double\n", attr[i + 1]);
+                // TODO: log it
+                continue;
+            }
+
+            if (strcasecmp(attr[i], "payDay") == 0)
+            {
+                unsigned payDay;
+                if (str2x(attr[i + 1], payDay) == 0)
+                    m_service.payDay = payDay;
+                else
+                    printfd(__FILE__, "Bad cast from '%s' to unsigned\n", attr[i + 1]);
+                // TODO: log it
+                continue;
+            }
+        }
+
+        return 0;
+    }
+    return -1;
+}
+
+void CHG_SERVICE::CreateAnswer()
+{
+    if (m_service.name.empty())
+    {
+        m_answer = "<" + m_tag + " result=\"Empty service name.\"/>";
+        return;
+    }
+
+    if (!m_services.Exists(m_service.name.const_data()))
+    {
+        m_answer = "<" + m_tag + " result = \"Service '" + m_service.name.const_data() + "' does not exist.\"/>";
+        return;
+    }
+
+    ServiceConf orig;
+    m_services.Find(m_service.name.const_data(), &orig);
+
+    ServiceConfOpt conf(orig);
+    conf.splice(m_service);
+
+    if (m_services.Change(conf.get({}), &m_currAdmin) != 0)
+        m_answer = "<" + m_tag + " result = \"" + m_services.GetStrError() + "\"/>";
+    else
+        m_answer = "<" + m_tag + " result = \"Ok\"/>";
+}
diff --git a/projects/stargazer/plugins/configuration/sgconfig/parser_services.h b/projects/stargazer/plugins/configuration/sgconfig/parser_services.h
new file mode 100644 (file)
index 0000000..6eb67e0
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#pragma once
+
+#include "parser.h"
+
+#include "stg/service_conf.h"
+
+#include "stg/common.h"
+
+#include <string>
+
+namespace STG
+{
+
+struct Services;
+
+namespace PARSER
+{
+
+class GET_SERVICES: public BASE_PARSER
+{
+    public:
+        class FACTORY : public BASE_PARSER::FACTORY
+        {
+            public:
+                FACTORY(const Services & services) : m_services(services) {}
+                virtual BASE_PARSER * create(const Admin & admin) { return new GET_SERVICES(admin, m_services); }
+                static void Register(REGISTRY & registry, const Services & services)
+                { registry[ToLower(tag)] = new FACTORY(services); }
+            private:
+                const Services & m_services;
+        };
+
+        static const char * tag;
+
+        GET_SERVICES(const Admin & admin, const Services & services)
+            : BASE_PARSER(admin, tag), m_services(services) {}
+
+    private:
+        const Services & m_services;
+
+        void CreateAnswer();
+};
+
+class GET_SERVICE: public BASE_PARSER
+{
+    public:
+        class FACTORY : public BASE_PARSER::FACTORY
+        {
+            public:
+                FACTORY(const Services & services) : m_services(services) {}
+                virtual BASE_PARSER * create(const Admin & admin) { return new GET_SERVICE(admin, m_services); }
+                static void Register(REGISTRY & registry, Services & services)
+                { registry[ToLower(tag)] = new FACTORY(services); }
+            private:
+                const Services & m_services;
+        };
+
+        static const char * tag;
+
+        GET_SERVICE(const Admin & admin, const Services & services)
+            : BASE_PARSER(admin, tag), m_services(services) {}
+        int Start(void * data, const char * el, const char ** attr);
+
+    private:
+        std::string m_name;
+        const Services & m_services;
+
+        void CreateAnswer();
+};
+
+class ADD_SERVICE: public BASE_PARSER
+{
+    public:
+        class FACTORY : public BASE_PARSER::FACTORY
+        {
+            public:
+                FACTORY(Services & services) : m_services(services) {}
+                virtual BASE_PARSER * create(const Admin & admin) { return new ADD_SERVICE(admin, m_services); }
+                static void Register(REGISTRY & registry, Services & services)
+                { registry[ToLower(tag)] = new FACTORY(services); }
+            private:
+                Services & m_services;
+        };
+
+        static const char * tag;
+
+        ADD_SERVICE(const Admin & admin, Services & services)
+            : BASE_PARSER(admin, tag), m_services(services) {}
+        int Start(void * data, const char * el, const char ** attr);
+
+    private:
+        std::string m_name;
+        Services & m_services;
+
+        void CreateAnswer();
+};
+
+class DEL_SERVICE: public BASE_PARSER
+{
+    public:
+        class FACTORY : public BASE_PARSER::FACTORY
+        {
+            public:
+                FACTORY(Services & services) : m_services(services) {}
+                virtual BASE_PARSER * create(const Admin & admin) { return new DEL_SERVICE(admin, m_services); }
+                static void Register(REGISTRY & registry, Services & services)
+                { registry[ToLower(tag)] = new FACTORY(services); }
+            private:
+                Services & m_services;
+        };
+
+        static const char * tag;
+
+        DEL_SERVICE(const Admin & admin, Services & services)
+            : BASE_PARSER(admin, tag), m_services(services) {}
+        int Start(void * data, const char * el, const char ** attr);
+
+    private:
+        std::string m_name;
+        Services & m_services;
+
+        void CreateAnswer();
+};
+
+class CHG_SERVICE: public BASE_PARSER
+{
+    public:
+        class FACTORY : public BASE_PARSER::FACTORY
+        {
+            public:
+                FACTORY(Services & services) : m_services(services) {}
+                virtual BASE_PARSER * create(const Admin & admin) { return new CHG_SERVICE(admin, m_services); }
+                static void Register(REGISTRY & registry, Services & services)
+                { registry[ToLower(tag)] = new FACTORY(services); }
+            private:
+                Services & m_services;
+        };
+
+        static const char * tag;
+
+        CHG_SERVICE(const Admin & admin, Services & services)
+            : BASE_PARSER(admin, tag), m_services(services) {}
+        int Start(void * data, const char * el, const char ** attr);
+
+    private:
+        ServiceConfOpt m_service;
+        Services & m_services;
+
+        void CreateAnswer();
+};
+
+} // namespace PARSER
+} // namespace STG
diff --git a/projects/stargazer/plugins/configuration/sgconfig/parser_tariffs.cpp b/projects/stargazer/plugins/configuration/sgconfig/parser_tariffs.cpp
new file mode 100644 (file)
index 0000000..8f8e8db
--- /dev/null
@@ -0,0 +1,327 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#include "parser_tariffs.h"
+
+#include "stg/tariffs.h"
+#include "stg/users.h"
+#include "stg/optional.h"
+
+#include <cstdio> // snprintf
+#include <cstring>
+
+using STG::PARSER::GET_TARIFFS;
+using STG::PARSER::ADD_TARIFF;
+using STG::PARSER::DEL_TARIFF;
+using STG::PARSER::CHG_TARIFF;
+
+const char * GET_TARIFFS::tag = "GetTariffs";
+const char * ADD_TARIFF::tag  = "AddTariff";
+const char * DEL_TARIFF::tag  = "DelTariff";
+const char * CHG_TARIFF::tag  = "SetTariff";
+
+namespace
+{
+
+const double pt_mega = 1024 * 1024;
+
+template <typename A, typename C, typename F>
+std::string AOS2String(const A & array, size_t size, const F C::* field, F multiplier)
+{
+    std::string res;
+    for (size_t i = 0; i < size; ++i)
+    {
+        if (!res.empty())
+            res += "/";
+        res += std::to_string((array[i].*field) * multiplier);
+    }
+    return res;
+}
+
+template <typename T>
+bool str2res(const std::string& source, STG::Optional<T>& dest, T divisor)
+{
+    T value = 0;
+    if (str2x(source, value))
+        return false;
+    dest = value / divisor;
+    return true;
+}
+
+template <typename A, typename C, typename F>
+bool String2AOS(const std::string & source, A & array, size_t size, STG::Optional<F> C::* field, F divisor)
+{
+    size_t index = 0;
+    std::string::size_type from = 0;
+    std::string::size_type pos = 0;
+    while (index < size && (pos = source.find('/', from)) != std::string::npos)
+    {
+        if (!str2res(source.substr(from, pos - from), array[index].*field, divisor))
+            return false;
+        from = pos + 1;
+        ++index;
+    }
+    if (str2res(source.substr(from), array[index].*field, divisor))
+        return false;
+    return true;
+}
+
+}
+
+void GET_TARIFFS::CreateAnswer()
+{
+    m_answer = "<Tariffs>";
+
+    std::vector<TariffData> dataList;
+    m_tariffs.GetTariffsData(&dataList);
+    auto it = dataList.begin();
+    for (; it != dataList.end(); ++it)
+        {
+        m_answer += "<tariff name=\"" + it->tariffConf.name + "\">";
+
+        for (size_t i = 0; i < DIR_NUM; i++)
+            m_answer += "<Time" + std::to_string(i) + " value=\"" +
+                std::to_string(it->dirPrice[i].hDay)   + ":" + std::to_string(it->dirPrice[i].mDay)   + "-" +
+                std::to_string(it->dirPrice[i].hNight) + ":" + std::to_string(it->dirPrice[i].mNight) + "\"/>";
+
+        m_answer += "<PriceDayA value=\"" + AOS2String(it->dirPrice, DIR_NUM, &DirPriceData::priceDayA, pt_mega) + "\"/>" +
+                  "<PriceDayB value=\"" + AOS2String(it->dirPrice, DIR_NUM, &DirPriceData::priceDayB, pt_mega) + "\"/>" +
+                  "<PriceNightA value=\"" + AOS2String(it->dirPrice, DIR_NUM, &DirPriceData::priceNightA, pt_mega) + "\"/>" +
+                  "<PriceNightB value=\"" + AOS2String(it->dirPrice, DIR_NUM, &DirPriceData::priceNightB, pt_mega) + "\"/>" +
+                  "<Threshold value=\"" + AOS2String(it->dirPrice, DIR_NUM, &DirPriceData::threshold, 1) + "\"/>" +
+                  "<SinglePrice value=\"" + AOS2String(it->dirPrice, DIR_NUM, &DirPriceData::singlePrice, 1) + "\"/>" +
+                  "<NoDiscount value=\"" + AOS2String(it->dirPrice, DIR_NUM, &DirPriceData::noDiscount, 1) + "\"/>" +
+                  "<Fee value=\"" + std::to_string(it->tariffConf.fee) + "\"/>" +
+                  "<PassiveCost value=\"" + std::to_string(it->tariffConf.passiveCost) + "\"/>" +
+                  "<Free value=\"" + std::to_string(it->tariffConf.free) + "\"/>" +
+                  "<TraffType value=\"" + Tariff::toString(it->tariffConf.traffType) + "\"/>" +
+                  "<Period value=\"" + Tariff::toString(it->tariffConf.period) + "\"/>" +
+                  "<ChangePolicy value=\"" + Tariff::toString(it->tariffConf.changePolicy) + "\"/>" +
+                  "<ChangePolicyTimeout value=\"" + std::to_string(it->tariffConf.changePolicyTimeout) + "\"/>" +
+                  "</tariff>";
+        }
+
+    m_answer += "</Tariffs>";
+}
+
+int ADD_TARIFF::Start(void *, const char * el, const char ** attr)
+{
+    if (strcasecmp(el, m_tag.c_str()) != 0)
+        return -1;
+
+    if (attr[1] == NULL)
+        return -1;
+
+    tariff = attr[1];
+    return 0;
+}
+
+void ADD_TARIFF::CreateAnswer()
+{
+    if (m_tariffs.Add(tariff, &m_currAdmin) == 0)
+        m_answer = "<" + m_tag + " Result=\"Ok\"/>";
+    else
+        m_answer = "<" + m_tag + " Result=\"Error. " + m_tariffs.GetStrError() + "\"/>";
+}
+
+int DEL_TARIFF::Start(void *, const char * el, const char ** attr)
+{
+    if (strcasecmp(el, m_tag.c_str()) != 0)
+        return -1;
+
+    if (attr[1] == NULL)
+        return -1;
+
+    tariff = attr[1];
+    return 0;
+}
+
+void DEL_TARIFF::CreateAnswer()
+{
+    if (m_users.TariffInUse(tariff))
+        m_answer = "<" + m_tag + " Result=\"Error. Tariff \'" + tariff + "\' cannot be deleted, it is in use.\"/>";
+    else if (m_tariffs.Del(tariff, &m_currAdmin) == 0)
+        m_answer = "<" + m_tag + " Result=\"Ok\"/>";
+    else
+        m_answer = "<" + m_tag + " Result=\"Error. " + m_tariffs.GetStrError() + "\"/>";
+}
+
+int CHG_TARIFF::Start(void *, const char * el, const char ** attr)
+{
+    m_depth++;
+
+    if (m_depth == 1)
+    {
+        if (strcasecmp(el, m_tag.c_str()) == 0)
+        {
+            const auto tariff = m_tariffs.FindByName(attr[1]);
+            if (tariff != NULL)
+                td = tariff->GetTariffData();
+            else
+                return -1;
+            return 0;
+        }
+    }
+    else
+    {
+        if (strcasecmp(el, "PriceDayA") == 0)
+        {
+            if (!String2AOS(attr[1], td.dirPrice, DIR_NUM, &DirPriceDataOpt::priceDayA, pt_mega))
+                return -1; // TODO: log it
+            else
+                return 0;
+        }
+
+        if (strcasecmp(el, "PriceDayB") == 0)
+        {
+            if (!String2AOS(attr[1], td.dirPrice, DIR_NUM, &DirPriceDataOpt::priceDayB, pt_mega))
+                return -1; // TODO: log it
+            else
+                return 0;
+        }
+
+        if (strcasecmp(el, "PriceNightA") == 0)
+        {
+            if (!String2AOS(attr[1], td.dirPrice, DIR_NUM, &DirPriceDataOpt::priceNightA, pt_mega))
+                return -1; // TODO: log it
+            else
+                return 0;
+        }
+
+        if (strcasecmp(el, "PriceNightB") == 0)
+        {
+            if (!String2AOS(attr[1], td.dirPrice, DIR_NUM, &DirPriceDataOpt::priceNightB, pt_mega))
+                return -1; // TODO: log it
+            else
+                return 0;
+        }
+
+        if (strcasecmp(el, "Threshold") == 0)
+        {
+            if (!String2AOS(attr[1], td.dirPrice, DIR_NUM, &DirPriceDataOpt::threshold, 1))
+                return -1; // TODO: log it
+            else
+                return 0;
+        }
+
+        if (strcasecmp(el, "SinglePrice") == 0)
+        {
+            if (!String2AOS(attr[1], td.dirPrice, DIR_NUM, &DirPriceDataOpt::singlePrice, 1))
+                return -1; // TODO: log it
+            else
+                return 0;
+        }
+
+        if (strcasecmp(el, "NoDiscount") == 0)
+        {
+            if (!String2AOS(attr[1], td.dirPrice, DIR_NUM, &DirPriceDataOpt::noDiscount, 1))
+                return -1; // TODO: log it
+            else
+                return 0;
+        }
+
+        for (int j = 0; j < DIR_NUM; j++)
+        {
+            char st[50];
+            snprintf(st, 50, "Time%d", j);
+            if (strcasecmp(el, st) == 0)
+            {
+                int h1 = 0;
+                int m1 = 0;
+                int h2 = 0;
+                int m2 = 0;
+                if (ParseTariffTimeStr(attr[1], h1, m1, h2, m2) == 0)
+                    {
+                    td.dirPrice[j].hDay = h1;
+                    td.dirPrice[j].mDay = m1;
+                    td.dirPrice[j].hNight = h2;
+                    td.dirPrice[j].mNight = m2;
+                    }
+                return 0;
+            }
+        }
+
+        if (strcasecmp(el, "Fee") == 0)
+        {
+            double fee;
+            if (strtodouble2(attr[1], fee) == 0)
+                td.tariffConf.fee = fee;
+            return 0;
+        }
+
+        if (strcasecmp(el, "PassiveCost") == 0)
+        {
+            double pc;
+            if (strtodouble2(attr[1], pc) == 0)
+                td.tariffConf.passiveCost = pc;
+            return 0;
+        }
+
+        if (strcasecmp(el, "Free") == 0)
+        {
+            double free;
+            if (strtodouble2(attr[1], free) == 0)
+                td.tariffConf.free = free;
+            return 0;
+        }
+
+        if (strcasecmp(el, "TraffType") == 0)
+        {
+            td.tariffConf.traffType = Tariff::parseTraffType(attr[1]);
+            return 0;
+        }
+
+        if (strcasecmp(el, "Period") == 0)
+        {
+            td.tariffConf.period = Tariff::parsePeriod(attr[1]);
+            return 0;
+        }
+
+        if (strcasecmp(el, "ChangePolicy") == 0)
+        {
+            td.tariffConf.changePolicy = Tariff::parseChangePolicy(attr[1]);
+            return 0;
+        }
+
+        if (strcasecmp(el, "ChangePolicyTimeout") == 0)
+        {
+            int64_t policyTime = 0;
+            if (str2x(attr[1], policyTime) == 0)
+                td.tariffConf.changePolicyTimeout = (time_t)policyTime;
+            return 0;
+        }
+    }
+    return -1;
+}
+
+void CHG_TARIFF::CreateAnswer()
+{
+    if (!td.tariffConf.name.data().empty())
+    {
+        auto tariffData = td.get({});
+        if (m_tariffs.Chg(tariffData, &m_currAdmin) == 0)
+            m_answer = "<" + m_tag + " Result=\"ok\"/>";
+        else
+            m_answer = "<" + m_tag + " Result=\"Change tariff error! " + m_tariffs.GetStrError() + "\"/>";
+    }
+    else
+        m_answer = "<" + m_tag + " Result=\"Change tariff error!\"/>";
+}
diff --git a/projects/stargazer/plugins/configuration/sgconfig/parser_tariffs.h b/projects/stargazer/plugins/configuration/sgconfig/parser_tariffs.h
new file mode 100644 (file)
index 0000000..9f9c503
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#pragma once
+
+#include "parser.h"
+
+#include "stg/tariff_conf.h"
+#include "stg/common.h"
+
+#include <string>
+
+namespace STG
+{
+
+struct Tariffs;
+struct Users;
+struct Admin;
+
+namespace PARSER
+{
+
+class GET_TARIFFS: public BASE_PARSER
+{
+    public:
+        class FACTORY : public BASE_PARSER::FACTORY
+        {
+            public:
+                explicit FACTORY(const Tariffs & tariffs) : m_tariffs(tariffs) {}
+                virtual BASE_PARSER * create(const Admin & admin) { return new GET_TARIFFS(admin, m_tariffs); }
+                static void Register(REGISTRY & registry, const Tariffs & tariffs)
+                { registry[ToLower(tag)] = new FACTORY(tariffs); }
+            private:
+                const Tariffs & m_tariffs;
+        };
+
+        static const char * tag;
+
+        GET_TARIFFS(const Admin & admin, const Tariffs & tariffs)
+            : BASE_PARSER(admin, tag), m_tariffs(tariffs) {}
+
+    private:
+        const Tariffs & m_tariffs;
+
+        void CreateAnswer();
+};
+
+class ADD_TARIFF: public BASE_PARSER
+{
+    public:
+        class FACTORY : public BASE_PARSER::FACTORY
+        {
+            public:
+                explicit FACTORY(Tariffs & tariffs) : m_tariffs(tariffs) {}
+                virtual BASE_PARSER * create(const Admin & admin) { return new ADD_TARIFF(admin, m_tariffs); }
+                static void Register(REGISTRY & registry, Tariffs & tariffs)
+                { registry[ToLower(tag)] = new FACTORY(tariffs); }
+            private:
+                Tariffs & m_tariffs;
+        };
+
+        static const char * tag;
+
+        ADD_TARIFF(const Admin & admin, Tariffs & tariffs)
+            : BASE_PARSER(admin, tag), m_tariffs(tariffs) {}
+        int Start(void * data, const char * el, const char ** attr);
+
+    private:
+        std::string tariff;
+        Tariffs & m_tariffs;
+
+        void CreateAnswer();
+};
+
+class DEL_TARIFF: public BASE_PARSER
+{
+    public:
+        class FACTORY : public BASE_PARSER::FACTORY
+        {
+            public:
+                FACTORY(Tariffs & tariffs, const Users & users) : m_tariffs(tariffs), m_users(users) {}
+                virtual BASE_PARSER * create(const Admin & admin) { return new DEL_TARIFF(admin, m_users, m_tariffs); }
+                static void Register(REGISTRY & registry, Tariffs & tariffs, const Users & users)
+                { registry[ToLower(tag)] = new FACTORY(tariffs, users); }
+            private:
+                Tariffs & m_tariffs;
+                const Users & m_users;
+        };
+
+        static const char * tag;
+
+        DEL_TARIFF(const Admin & admin, const Users & users, Tariffs & tariffs)
+            : BASE_PARSER(admin, tag), m_users(users), m_tariffs(tariffs) {}
+        int Start(void * data, const char * el, const char ** attr);
+
+    private:
+        std::string tariff;
+        const Users & m_users;
+        Tariffs & m_tariffs;
+
+        void CreateAnswer();
+};
+
+class CHG_TARIFF: public BASE_PARSER
+{
+    public:
+        class FACTORY : public BASE_PARSER::FACTORY
+        {
+            public:
+                explicit FACTORY(Tariffs & tariffs) : m_tariffs(tariffs) {}
+                virtual BASE_PARSER * create(const Admin & admin) { return new CHG_TARIFF(admin, m_tariffs); }
+                static void Register(REGISTRY & registry, Tariffs & tariffs)
+                { registry[ToLower(tag)] = new FACTORY(tariffs); }
+            private:
+                Tariffs & m_tariffs;
+        };
+
+        static const char * tag;
+
+        CHG_TARIFF(const Admin & admin, Tariffs & tariffs)
+            : BASE_PARSER(admin, tag), m_tariffs(tariffs) {}
+        int Start(void * data, const char * el, const char ** attr);
+
+    private:
+        TariffDataOpt td;
+        Tariffs & m_tariffs;
+
+        int CheckTariffData();
+        void CreateAnswer();
+};
+
+} // namespace PARSER
+} // namespace STG
diff --git a/projects/stargazer/plugins/configuration/sgconfig/parser_user_info.cpp b/projects/stargazer/plugins/configuration/sgconfig/parser_user_info.cpp
new file mode 100644 (file)
index 0000000..ccc86d8
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#include "parser_user_info.h"
+
+#include "stg/users.h"
+#include "stg/user.h"
+
+#include <strings.h> // strcasecmp
+
+using STG::PARSER::USER_INFO;
+
+const char * USER_INFO::tag = "GetUserInfo";
+
+int USER_INFO::Start(void * /*data*/, const char *el, const char **attr)
+{
+    if (strcasecmp(el, m_tag.c_str()) != 0)
+        return -1;
+
+    if (!attr[1])
+        return -1;
+
+    m_login = attr[1];
+    return 0;
+}
+
+void USER_INFO::CreateAnswer()
+{
+    using ConstUserPtr = const User*;
+    ConstUserPtr u;
+    if (m_users.FindByName(m_login, &u))
+    {
+        m_answer = "<UserInfo result=\"error\"/>";
+        return;
+    }
+
+    m_answer = "<UserInfo lastAuthTime=\"" + std::to_string(u->GetAuthorizedModificationTime()) + "\"" +
+             " lastDisconnectTime=\"" + std::to_string(u->GetConnectedModificationTime()) + "\"" +
+             " connected=\"" + (u->GetConnected() ? "true" : "false") + "\"" +
+             " lastDisconnectReason=\"" + u->GetLastDisconnectReason() + "\">";
+    std::vector<std::string> list(u->GetAuthorizers());
+    for (std::vector<std::string>::const_iterator it = list.begin(); it != list.end(); ++it)
+        m_answer += "<Auth name=\"" + *it + "\"/>";
+    m_answer += "</UserInfo>";
+}
diff --git a/projects/stargazer/plugins/configuration/sgconfig/parser_user_info.h b/projects/stargazer/plugins/configuration/sgconfig/parser_user_info.h
new file mode 100644 (file)
index 0000000..50f3101
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#pragma once
+
+#include "parser.h"
+
+#include "stg/common.h"
+
+#include <string>
+
+namespace STG
+{
+
+struct Users;
+
+namespace PARSER
+{
+
+class USER_INFO : public BASE_PARSER
+{
+    public:
+        class FACTORY : public BASE_PARSER::FACTORY
+        {
+            public:
+                FACTORY(const Users & users) : m_users(users) {}
+                virtual BASE_PARSER * create(const Admin & admin) { return new USER_INFO(admin, m_users); }
+                static void Register(REGISTRY & registry, const Users & users)
+                { registry[ToLower(tag)] = new FACTORY(users); }
+            private:
+                const Users & m_users;
+        };
+
+        static const char * tag;
+
+        USER_INFO(const Admin & admin, const Users & users)
+            : BASE_PARSER(admin, tag), m_users(users) {}
+        int Start(void * data, const char * el, const char ** attr);
+
+    private:
+        const Users & m_users;
+        std::string m_login;
+
+        void CreateAnswer();
+};
+
+} // namespace PARSER
+} // namespace STG
diff --git a/projects/stargazer/plugins/configuration/sgconfig/parser_users.cpp b/projects/stargazer/plugins/configuration/sgconfig/parser_users.cpp
new file mode 100644 (file)
index 0000000..bd7dd4e
--- /dev/null
@@ -0,0 +1,761 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#include "parser_users.h"
+
+#include "stg/users.h"
+#include "stg/user.h"
+#include "stg/user_conf.h"
+#include "stg/user_stat.h"
+#include "stg/tariffs.h"
+#include "stg/tariff.h"
+#include "stg/user_property.h"
+
+#include <cstdio>
+#include <cassert>
+
+using STG::PARSER::GET_USERS;
+using STG::PARSER::GET_USER;
+using STG::PARSER::ADD_USER;
+using STG::PARSER::DEL_USER;
+using STG::PARSER::CHG_USER;
+using STG::PARSER::CHECK_USER;
+
+const char * GET_USERS::tag  = "GetUsers";
+const char * GET_USER::tag   = "GetUser";
+const char * ADD_USER::tag   = "AddUser";
+const char * CHG_USER::tag   = "SetUser";
+const char * DEL_USER::tag   = "DelUser";
+const char * CHECK_USER::tag = "CheckUser";
+
+using UserPtr = STG::User*;
+using ConstUserPtr = const STG::User*;
+
+namespace
+{
+
+std::string UserToXML(const STG::User & user, bool loginInStart, bool showPass, time_t lastTime = 0)
+{
+    std::string answer;
+
+    if (loginInStart)
+        answer += "<User login=\"" + user.GetLogin() + "\" result=\"ok\">";
+    else
+        answer += "<User result=\"ok\">";
+
+    answer += "<Login value=\"" + user.GetLogin() + "\"/>";
+
+    if (user.GetProperties().password.ModificationTime() > lastTime)
+    {
+        if (showPass)
+            answer += "<Password value=\"" + user.GetProperties().password.Get() + "\" />";
+        else
+            answer += "<Password value=\"++++++\"/>";
+    }
+
+    if (user.GetProperties().cash.ModificationTime() > lastTime)
+        answer += "<Cash value=\"" + std::to_string(user.GetProperties().cash.Get()) + "\"/>";
+    if (user.GetProperties().freeMb.ModificationTime() > lastTime)
+        answer += "<FreeMb value=\"" + std::to_string(user.GetProperties().freeMb.Get()) + "\"/>";
+    if (user.GetProperties().credit.ModificationTime() > lastTime)
+        answer += "<Credit value=\"" + std::to_string(user.GetProperties().credit.Get()) + "\"/>";
+
+    if (user.GetProperties().nextTariff.Get() != "")
+    {
+        if (user.GetProperties().tariffName.ModificationTime() > lastTime ||
+            user.GetProperties().nextTariff.ModificationTime() > lastTime)
+            answer += "<Tariff value=\"" + user.GetProperties().tariffName.Get() + "/" + user.GetProperties().nextTariff.Get() + "\"/>";
+    }
+    else
+    {
+        if (user.GetProperties().tariffName.ModificationTime() > lastTime)
+            answer += "<Tariff value=\"" + user.GetProperties().tariffName.Get() + "\"/>";
+    }
+
+    if (user.GetProperties().note.ModificationTime() > lastTime)
+        answer += "<Note value=\"" + Encode12str(user.GetProperties().note) + "\"/>";
+    if (user.GetProperties().phone.ModificationTime() > lastTime)
+        answer += "<Phone value=\"" + Encode12str(user.GetProperties().phone) + "\"/>";
+    if (user.GetProperties().address.ModificationTime() > lastTime)
+        answer += "<Address value=\"" + Encode12str(user.GetProperties().address) + "\"/>";
+    if (user.GetProperties().email.ModificationTime() > lastTime)
+        answer += "<Email value=\"" + Encode12str(user.GetProperties().email) + "\"/>";
+
+    std::vector<const STG::UserPropertyLogged<std::string> *> userdata;
+    userdata.push_back(user.GetProperties().userdata0.GetPointer());
+    userdata.push_back(user.GetProperties().userdata1.GetPointer());
+    userdata.push_back(user.GetProperties().userdata2.GetPointer());
+    userdata.push_back(user.GetProperties().userdata3.GetPointer());
+    userdata.push_back(user.GetProperties().userdata4.GetPointer());
+    userdata.push_back(user.GetProperties().userdata5.GetPointer());
+    userdata.push_back(user.GetProperties().userdata6.GetPointer());
+    userdata.push_back(user.GetProperties().userdata7.GetPointer());
+    userdata.push_back(user.GetProperties().userdata8.GetPointer());
+    userdata.push_back(user.GetProperties().userdata9.GetPointer());
+
+    for (size_t i = 0; i < userdata.size(); i++)
+        if (userdata[i]->ModificationTime() > lastTime)
+            answer += "<UserData" + std::to_string(i) + " value=\"" + Encode12str(userdata[i]->Get()) + "\" />";
+
+    if (user.GetProperties().realName.ModificationTime() > lastTime)
+        answer += "<Name value=\"" + Encode12str(user.GetProperties().realName) + "\"/>";
+    if (user.GetProperties().group.ModificationTime() > lastTime)
+        answer += "<Group value=\"" + Encode12str(user.GetProperties().group) + "\"/>";
+    if (user.GetConnectedModificationTime() > lastTime)
+        answer += std::string("<Status value=\"") + (user.GetConnected() ? "1" : "0") + "\"/>";
+    if (user.GetProperties().alwaysOnline.ModificationTime() > lastTime)
+        answer += std::string("<AOnline value=\"") + (user.GetProperties().alwaysOnline.Get() ? "1" : "0") + "\"/>";
+    if (user.GetCurrIPModificationTime() > lastTime)
+        answer += "<CurrIP value=\"" + inet_ntostring(user.GetCurrIP()) + "\"/>";
+    if (user.GetPingTime() > lastTime)
+        answer += "<PingTime value=\"" + std::to_string(user.GetPingTime()) + "\"/>";
+    if (user.GetProperties().ips.ModificationTime() > lastTime)
+        answer += "<IP value=\"" + user.GetProperties().ips.Get().toString() + "\"/>";
+
+    answer += "<Traff";
+    const auto & upload(user.GetProperties().up.Get());
+    const auto & download(user.GetProperties().down.Get());
+    if (user.GetProperties().up.ModificationTime() > lastTime)
+        for (size_t j = 0; j < DIR_NUM; j++)
+            answer += " MU" + std::to_string(j) + "=\"" + std::to_string(upload[j]) + "\"";
+    if (user.GetProperties().down.ModificationTime() > lastTime)
+        for (size_t j = 0; j < DIR_NUM; j++)
+            answer += " MD" + std::to_string(j) + "=\"" + std::to_string(download[j]) + "\"";
+    if (user.GetSessionUploadModificationTime() > lastTime)
+        for (size_t j = 0; j < DIR_NUM; j++)
+            answer += " SU" + std::to_string(j) + "=\"" + std::to_string(user.GetSessionUpload()[j]) + "\"";
+    if (user.GetSessionDownloadModificationTime() > lastTime)
+        for (size_t j = 0; j < DIR_NUM; j++)
+            answer += " SD" + std::to_string(j) + "=\"" + std::to_string(user.GetSessionDownload()[j]) + "\"";
+    answer += "/>";
+
+    if (user.GetProperties().disabled.ModificationTime() > lastTime)
+        answer += std::string("<Down value=\"") + (user.GetProperties().disabled.Get() ? "1" : "0") + "\"/>";
+    if (user.GetProperties().disabledDetailStat.ModificationTime() > lastTime)
+        answer += std::string("<DisableDetailStat value=\"") + (user.GetProperties().disabledDetailStat.Get() ? "1" : "0") + "\"/>";
+    if (user.GetProperties().passive.ModificationTime() > lastTime)
+        answer += std::string("<Passive value=\"") + (user.GetProperties().passive.Get() ? "1" : "0") + "\"/>";
+    if (user.GetProperties().lastCashAdd.ModificationTime() > lastTime)
+        answer += "<LastCash value=\"" + std::to_string(user.GetProperties().lastCashAdd.Get()) + "\"/>";
+    if (user.GetProperties().lastCashAddTime.ModificationTime() > lastTime)
+        answer += "<LastTimeCash value=\"" + std::to_string(user.GetProperties().lastCashAddTime.Get()) + "\"/>";
+    if (user.GetProperties().lastActivityTime.ModificationTime() > lastTime)
+        answer += "<LastActivityTime value=\"" + std::to_string(user.GetProperties().lastActivityTime.Get()) + "\"/>";
+    if (user.GetProperties().creditExpire.ModificationTime() > lastTime)
+        answer += "<CreditExpire value=\"" + std::to_string(user.GetProperties().creditExpire.Get()) + "\"/>";
+
+    if (lastTime == 0)
+    {
+        answer += "<AuthorizedBy>";
+        std::vector<std::string> list(user.GetAuthorizers());
+        for (std::vector<std::string>::const_iterator it = list.begin(); it != list.end(); ++it)
+            answer += "<Auth name=\"" + *it + "\"/>";
+        answer += "</AuthorizedBy>";
+    }
+
+    answer += "</User>";
+
+    return answer;
+}
+
+} // namespace anonymous
+
+int GET_USERS::Start(void *, const char * el, const char ** attr)
+{
+    if (strcasecmp(el, m_tag.c_str()) != 0)
+    {
+        printfd(__FILE__, "Got wrong tag: '%s' instead of '%s'\n", el, m_tag.c_str());
+        return -1;
+    }
+
+    while (attr && *attr && *(attr + 1))
+    {
+        if (strcasecmp(*attr, "LastUpdate") == 0)
+            str2x(*(attr + 1), m_lastUserUpdateTime);
+        ++attr;
+    }
+
+    return 0;
+}
+
+void GET_USERS::CreateAnswer()
+{
+    int h = m_users.OpenSearch();
+    assert(h);
+
+    if (m_lastUserUpdateTime > 0)
+        m_answer = "<Users LastUpdate=\"" + std::to_string(time(NULL)) + "\">";
+    else
+        m_answer = "<Users>";
+
+    UserPtr u;
+
+    while (m_users.SearchNext(h, &u) == 0)
+        m_answer += UserToXML(*u, true, m_currAdmin.priv().userConf || m_currAdmin.priv().userPasswd, m_lastUserUpdateTime);
+
+    m_users.CloseSearch(h);
+
+    m_answer += "</Users>";
+}
+
+int GET_USER::Start(void *, const char * el, const char ** attr)
+{
+    if (strcasecmp(el, m_tag.c_str()) != 0)
+        return -1;
+
+    if (attr[1] == NULL)
+        return -1;
+
+    m_login = attr[1];
+    return 0;
+}
+
+void GET_USER::CreateAnswer()
+{
+    ConstUserPtr u;
+
+    if (m_users.FindByName(m_login, &u))
+        m_answer = "<User result=\"error\" reason=\"User not found.\"/>";
+    else
+        m_answer = UserToXML(*u, false, m_currAdmin.priv().userConf || m_currAdmin.priv().userPasswd);
+}
+
+int ADD_USER::Start(void *, const char * el, const char ** attr)
+{
+    m_depth++;
+
+    if (m_depth == 1)
+    {
+        if (strcasecmp(el, m_tag.c_str()) == 0)
+            return 0;
+    }
+    else
+    {
+        if (strcasecmp(el, "login") == 0)
+        {
+            m_login = attr[1];
+            return 0;
+        }
+    }
+    return -1;
+}
+
+void ADD_USER::CreateAnswer()
+{
+    if (m_users.Exists(m_login))
+        m_answer = "<" + m_tag + " result=\"error\" reason=\"User '" + m_login + "' exists.\"/>";
+    else if (m_users.Add(m_login, &m_currAdmin) == 0)
+        m_answer = "<" + m_tag + " result=\"ok\"/>";
+    else
+        m_answer = "<" + m_tag + " result=\"error\" reason=\"Access denied\"/>";
+}
+
+int CHG_USER::Start(void *, const char * el, const char ** attr)
+{
+    m_depth++;
+
+    if (m_depth == 1)
+    {
+        if (strcasecmp(el, m_tag.c_str()) == 0)
+            return 0;
+    }
+    else
+    {
+        if (strcasecmp(el, "login") == 0)
+        {
+            m_login = attr[1];
+            return 0;
+        }
+
+        if (strcasecmp(el, "ip") == 0)
+        {
+            m_ucr.ips = UserIPs::parse(attr[1]);
+            return 0;
+        }
+
+        if (strcasecmp(el, "password") == 0)
+        {
+            m_ucr.password = attr[1];
+            return 0;
+        }
+
+        if (strcasecmp(el, "address") == 0)
+        {
+            m_ucr.address = Decode21str(attr[1]);
+            return 0;
+        }
+
+        if (strcasecmp(el, "aonline") == 0)
+        {
+            m_ucr.alwaysOnline = (*(attr[1]) != '0');
+            return 0;
+        }
+
+        if (strcasecmp(el, "cash") == 0)
+        {
+            if (attr[2] && (strcasecmp(attr[2], "msg") == 0))
+                m_cashMsg = Decode21str(attr[3]);
+
+            double cash = 0;
+            if (strtodouble2(attr[1], cash) == 0)
+                m_usr.cash = cash;
+
+            m_cashMustBeAdded = (strcasecmp(attr[0], "add") == 0);
+
+            return 0;
+        }
+
+        if (strcasecmp(el, "CreditExpire") == 0)
+        {
+            long int creditExpire = 0;
+            if (str2x(attr[1], creditExpire) == 0)
+                m_ucr.creditExpire = (time_t)creditExpire;
+
+            return 0;
+        }
+
+        if (strcasecmp(el, "credit") == 0)
+        {
+            double credit = 0;
+            if (strtodouble2(attr[1], credit) == 0)
+                m_ucr.credit = credit;
+            return 0;
+        }
+
+        if (strcasecmp(el, "freemb") == 0)
+        {
+            double freeMb = 0;
+            if (strtodouble2(attr[1], freeMb) == 0)
+                m_usr.freeMb = freeMb;
+            return 0;
+        }
+
+        if (strcasecmp(el, "down") == 0)
+        {
+            int down = 0;
+            if (str2x(attr[1], down) == 0)
+                m_ucr.disabled = down;
+            return 0;
+        }
+
+        if (strcasecmp(el, "DisableDetailStat") == 0)
+        {
+            int disabledDetailStat = 0;
+            if (str2x(attr[1], disabledDetailStat) == 0)
+                m_ucr.disabledDetailStat = disabledDetailStat;
+            return 0;
+        }
+
+        if (strcasecmp(el, "email") == 0)
+        {
+            m_ucr.email = Decode21str(attr[1]);
+            return 0;
+        }
+
+        for (int i = 0; i < USERDATA_NUM; i++)
+        {
+            char name[15];
+            sprintf(name, "userdata%d", i);
+            if (strcasecmp(el, name) == 0)
+            {
+                m_ucr.userdata[i] = Decode21str(attr[1]);
+                return 0;
+            }
+        }
+
+        if (strcasecmp(el, "group") == 0)
+        {
+            m_ucr.group = Decode21str(attr[1]);
+            return 0;
+        }
+
+        if (strcasecmp(el, "note") == 0)
+        {
+            m_ucr.note = Decode21str(attr[1]);
+            return 0;
+        }
+
+        if (strcasecmp(el, "passive") == 0)
+        {
+            int passive = 0;
+            if (str2x(attr[1], passive) == 0)
+                m_ucr.passive = passive;
+            return 0;
+        }
+
+        if (strcasecmp(el, "phone") == 0)
+        {
+            m_ucr.phone = Decode21str(attr[1]);
+            return 0;
+        }
+
+        if (strcasecmp(el, "Name") == 0)
+        {
+            m_ucr.realName = Decode21str(attr[1]);
+            return 0;
+        }
+
+        if (strcasecmp(el, "traff") == 0)
+        {
+            int j = 0;
+            while (attr[j])
+            {
+                int dir = attr[j][2] - '0';
+
+                if (strncasecmp(attr[j], "md", 2) == 0)
+                {
+                    uint64_t t = 0;
+                    str2x(attr[j + 1], t);
+                    m_downr[dir] = t;
+                }
+                if (strncasecmp(attr[j], "mu", 2) == 0)
+                {
+                    uint64_t t = 0;
+                    str2x(attr[j + 1], t);
+                    m_upr[dir] = t;
+                }
+                j += 2;
+            }
+            return 0;
+        }
+
+        if (strcasecmp(el, "tariff") == 0)
+        {
+            if (strcasecmp(attr[0], "now") == 0)
+                m_ucr.tariffName = attr[1];
+
+            if (strcasecmp(attr[0], "delayed") == 0)
+                m_ucr.nextTariff = attr[1];
+
+            return 0;
+        }
+    }
+    return -1;
+}
+
+void CHG_USER::CreateAnswer()
+{
+    if (ApplyChanges() == 0)
+        m_answer = "<" + m_tag + " result=\"ok\"/>";
+    else
+        m_answer = "<" + m_tag + " result=\"error\"/>";
+}
+
+int CHG_USER::ApplyChanges()
+{
+    printfd(__FILE__, "PARSER_CHG_USER::ApplyChanges()\n");
+    UserPtr u;
+
+    if (m_users.FindByName(m_login, &u))
+        return -1;
+
+    bool check = false;
+    bool alwaysOnline = u->GetProperties().alwaysOnline;
+    if (!m_ucr.alwaysOnline.empty())
+    {
+        check = true;
+        alwaysOnline = m_ucr.alwaysOnline.const_data();
+    }
+    bool onlyOneIP = u->GetProperties().ips.ConstData().onlyOneIP();
+    if (!m_ucr.ips.empty())
+    {
+        check = true;
+        onlyOneIP = m_ucr.ips.const_data().onlyOneIP();
+    }
+
+    if (check && alwaysOnline && !onlyOneIP)
+    {
+        printfd(__FILE__, "Requested change leads to a forbidden state: AlwaysOnline with multiple IP's\n");
+        PluginLogger::get("conf_sg")("%s Requested change leads to a forbidden state: AlwaysOnline with multiple IP's", m_currAdmin.logStr().c_str());
+        return -1;
+    }
+
+    for (size_t i = 0; i < m_ucr.ips.const_data().count(); ++i)
+    {
+        ConstUserPtr user;
+        uint32_t ip = m_ucr.ips.const_data().operator[](i).ip;
+        if (m_users.IsIPInUse(ip, m_login, &user))
+        {
+            printfd(__FILE__, "Trying to assign an IP %s to '%s' that is already in use by '%s'\n", inet_ntostring(ip).c_str(), m_login.c_str(), user->GetLogin().c_str());
+            PluginLogger::get("conf_sg")("%s trying to assign an IP %s to '%s' that is currently in use by '%s'", m_currAdmin.logStr().c_str(), inet_ntostring(ip).c_str(), m_login.c_str(), user->GetLogin().c_str());
+            return -1;
+        }
+    }
+
+    if (!m_ucr.ips.empty())
+        if (!u->GetProperties().ips.Set(m_ucr.ips.const_data(), m_currAdmin, m_login, m_store))
+            return -1;
+
+    if (!m_ucr.alwaysOnline.empty())
+        if (!u->GetProperties().alwaysOnline.Set(m_ucr.alwaysOnline.const_data(),
+                                                 m_currAdmin, m_login, m_store))
+            return -1;
+
+    if (!m_ucr.address.empty())
+        if (!u->GetProperties().address.Set(m_ucr.address.const_data(), m_currAdmin, m_login, m_store))
+            return -1;
+
+    if (!m_ucr.creditExpire.empty())
+        if (!u->GetProperties().creditExpire.Set(m_ucr.creditExpire.const_data(),
+                                                 m_currAdmin, m_login, m_store))
+            return -1;
+
+    if (!m_ucr.credit.empty())
+        if (!u->GetProperties().credit.Set(m_ucr.credit.const_data(), m_currAdmin, m_login, m_store))
+            return -1;
+
+    if (!m_usr.freeMb.empty())
+        if (!u->GetProperties().freeMb.Set(m_usr.freeMb.const_data(), m_currAdmin, m_login, m_store))
+            return -1;
+
+    if (!m_ucr.disabled.empty())
+        if (!u->GetProperties().disabled.Set(m_ucr.disabled.const_data(), m_currAdmin, m_login, m_store))
+            return -1;
+
+    if (!m_ucr.disabledDetailStat.empty())
+        if (!u->GetProperties().disabledDetailStat.Set(m_ucr.disabledDetailStat.const_data(), m_currAdmin, m_login, m_store))
+            return -1;
+
+    if (!m_ucr.email.empty())
+        if (!u->GetProperties().email.Set(m_ucr.email.const_data(), m_currAdmin, m_login, m_store))
+            return -1;
+
+    if (!m_ucr.group.empty())
+        if (!u->GetProperties().group.Set(m_ucr.group.const_data(), m_currAdmin, m_login, m_store))
+            return -1;
+
+    if (!m_ucr.note.empty())
+        if (!u->GetProperties().note.Set(m_ucr.note.const_data(), m_currAdmin, m_login, m_store))
+            return -1;
+
+    std::vector<STG::UserPropertyLogged<std::string> *> userdata;
+    userdata.push_back(u->GetProperties().userdata0.GetPointer());
+    userdata.push_back(u->GetProperties().userdata1.GetPointer());
+    userdata.push_back(u->GetProperties().userdata2.GetPointer());
+    userdata.push_back(u->GetProperties().userdata3.GetPointer());
+    userdata.push_back(u->GetProperties().userdata4.GetPointer());
+    userdata.push_back(u->GetProperties().userdata5.GetPointer());
+    userdata.push_back(u->GetProperties().userdata6.GetPointer());
+    userdata.push_back(u->GetProperties().userdata7.GetPointer());
+    userdata.push_back(u->GetProperties().userdata8.GetPointer());
+    userdata.push_back(u->GetProperties().userdata9.GetPointer());
+
+    for (int i = 0; i < (int)userdata.size(); i++)
+        if (!m_ucr.userdata[i].empty())
+            if(!userdata[i]->Set(m_ucr.userdata[i].const_data(), m_currAdmin, m_login, m_store))
+                return -1;
+
+    if (!m_ucr.passive.empty())
+        if (!u->GetProperties().passive.Set(m_ucr.passive.const_data(), m_currAdmin, m_login, m_store))
+            return -1;
+
+    if (!m_ucr.password.empty())
+        if (!u->GetProperties().password.Set(m_ucr.password.const_data(), m_currAdmin, m_login, m_store))
+            return -1;
+
+    if (!m_ucr.phone.empty())
+        if (!u->GetProperties().phone.Set(m_ucr.phone.const_data(), m_currAdmin, m_login, m_store))
+            return -1;
+
+    if (!m_ucr.realName.empty())
+        if (!u->GetProperties().realName.Set(m_ucr.realName.const_data(), m_currAdmin, m_login, m_store))
+            return -1;
+
+    if (!m_usr.cash.empty())
+    {
+        if (m_cashMustBeAdded)
+        {
+            if (!u->GetProperties().cash.Set(m_usr.cash.const_data() + u->GetProperties().cash,
+                                             m_currAdmin,
+                                             m_login,
+                                             m_store,
+                                             m_cashMsg))
+                return -1;
+        }
+        else
+        {
+            if (!u->GetProperties().cash.Set(m_usr.cash.const_data(), m_currAdmin, m_login, m_store, m_cashMsg))
+                return -1;
+        }
+    }
+
+    if (!m_ucr.tariffName.empty())
+    {
+        const auto newTariff = m_tariffs.FindByName(m_ucr.tariffName.const_data());
+        if (newTariff)
+        {
+            const auto tariff = u->GetTariff();
+            std::string message = tariff->TariffChangeIsAllowed(*newTariff, stgTime);
+            if (message.empty())
+            {
+                if (!u->GetProperties().tariffName.Set(m_ucr.tariffName.const_data(), m_currAdmin, m_login, m_store))
+                    return -1;
+                u->ResetNextTariff();
+            }
+            else
+            {
+                PluginLogger::get("conf_sg")("Tariff change is prohibited for user %s. %s", u->GetLogin().c_str(), message.c_str());
+            }
+        }
+        else
+        {
+            //WriteServLog("SetUser: Tariff %s not found", ud.conf.tariffName.c_str());
+            return -1;
+        }
+    }
+
+    if (!m_ucr.nextTariff.empty())
+    {
+        if (m_tariffs.FindByName(m_ucr.nextTariff.const_data()))
+        {
+            if (!u->GetProperties().nextTariff.Set(m_ucr.nextTariff.const_data(), m_currAdmin, m_login, m_store))
+                return -1;
+        }
+        else
+        {
+            //WriteServLog("SetUser: Tariff %s not found", ud.conf.tariffName.c_str());
+            return -1;
+        }
+    }
+
+    auto up = u->GetProperties().up.get();
+    auto down = u->GetProperties().down.get();
+    int upCount = 0;
+    int downCount = 0;
+    for (int i = 0; i < DIR_NUM; i++)
+    {
+        if (!m_upr[i].empty())
+        {
+            up[i] = m_upr[i].data();
+            upCount++;
+        }
+        if (!m_downr[i].empty())
+        {
+            down[i] = m_downr[i].data();
+            downCount++;
+        }
+    }
+
+    if (upCount)
+        if (!u->GetProperties().up.Set(up, m_currAdmin, m_login, m_store))
+            return -1;
+
+    if (downCount)
+        if (!u->GetProperties().down.Set(down, m_currAdmin, m_login, m_store))
+            return -1;
+
+    u->WriteConf();
+    u->WriteStat();
+
+    return 0;
+}
+
+int DEL_USER::Start(void *, const char *el, const char **attr)
+{
+    res = 0;
+    if (strcasecmp(el, m_tag.c_str()) == 0)
+    {
+        if (attr[0] == NULL || attr[1] == NULL)
+        {
+            //CreateAnswer("Parameters error!");
+            CreateAnswer();
+            return 0;
+        }
+
+        if (m_users.FindByName(attr[1], &u))
+        {
+            res = 1;
+            CreateAnswer();
+            return 0;
+        }
+        CreateAnswer();
+        return 0;
+    }
+    return -1;
+}
+
+int DEL_USER::End(void *, const char *el)
+{
+    if (strcasecmp(el, m_tag.c_str()) == 0)
+    {
+        if (!res)
+            m_users.Del(u->GetLogin(), &m_currAdmin);
+
+        return 0;
+    }
+    return -1;
+}
+
+void DEL_USER::CreateAnswer()
+{
+    if (res)
+        m_answer = "<" + m_tag + " value=\"error\" reason=\"User not found\"/>";
+    else
+        m_answer = "<" + m_tag + " value=\"ok\"/>";
+}
+
+int CHECK_USER::Start(void *, const char *el, const char **attr)
+{
+    if (strcasecmp(el, m_tag.c_str()) == 0)
+    {
+        if (attr[0] == NULL || attr[1] == NULL ||
+            attr[2] == NULL || attr[3] == NULL)
+        {
+            CreateAnswer("Invalid parameters.");
+            printfd(__FILE__, "PARSER_CHECK_USER - attr err\n");
+            return 0;
+        }
+
+        ConstUserPtr user;
+        if (m_users.FindByName(attr[1], &user))
+        {
+            CreateAnswer("User not found.");
+            printfd(__FILE__, "PARSER_CHECK_USER - login err\n");
+            return 0;
+        }
+
+        if (strcmp(user->GetProperties().password.Get().c_str(), attr[3]))
+        {
+            CreateAnswer("Wrong password.");
+            printfd(__FILE__, "PARSER_CHECK_USER - passwd err\n");
+            return 0;
+        }
+
+        CreateAnswer(NULL);
+        return 0;
+    }
+    return -1;
+}
+
+int CHECK_USER::End(void *, const char *el)
+{
+    if (strcasecmp(el, m_tag.c_str()) == 0)
+        return 0;
+    return -1;
+}
+
+void CHECK_USER::CreateAnswer(const char * error)
+{
+    if (error)
+        m_answer = "<" + m_tag + " value=\"Err\" reason=\"" + error + "\"/>";
+    else
+        m_answer = "<" + m_tag + " value=\"Ok\"/>";
+}
diff --git a/projects/stargazer/plugins/configuration/sgconfig/parser_users.h b/projects/stargazer/plugins/configuration/sgconfig/parser_users.h
new file mode 100644 (file)
index 0000000..cdef451
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#pragma once
+
+#include "parser.h"
+
+#include "stg/user_conf.h"
+#include "stg/user_stat.h"
+#include "stg/common.h"
+#include "stg/optional.h"
+
+#include <string>
+
+namespace STG
+{
+
+struct Users;
+struct User;
+struct Tariffs;
+struct Admin;
+struct Store;
+
+namespace PARSER
+{
+
+class GET_USERS: public BASE_PARSER
+{
+    public:
+        class FACTORY : public BASE_PARSER::FACTORY
+        {
+            public:
+                explicit FACTORY(Users & users) : m_users(users) {}
+                virtual BASE_PARSER * create(const Admin & admin) { return new GET_USERS(admin, m_users); }
+                static void Register(REGISTRY & registry, Users & users)
+                { registry[ToLower(tag)] = new FACTORY(users); }
+            private:
+                Users & m_users;
+        };
+
+        static const char * tag;
+
+        GET_USERS(const Admin & admin, Users & users)
+            : BASE_PARSER(admin, tag), m_users(users),
+              m_lastUserUpdateTime(0) {}
+        int Start(void * data, const char * el, const char ** attr);
+
+    private:
+        Users & m_users;
+        time_t m_lastUserUpdateTime;
+
+        void CreateAnswer();
+};
+
+class GET_USER: public BASE_PARSER
+{
+    public:
+        class FACTORY : public BASE_PARSER::FACTORY
+        {
+            public:
+                explicit FACTORY(const Users & users) : m_users(users) {}
+                virtual BASE_PARSER * create(const Admin & admin) { return new GET_USER(admin, m_users); }
+                static void Register(REGISTRY & registry, const Users & users)
+                { registry[ToLower(tag)] = new FACTORY(users); }
+            private:
+                const Users & m_users;
+        };
+
+        static const char * tag;
+
+        GET_USER(const Admin & admin, const Users & users)
+            : BASE_PARSER(admin, tag), m_users(users) {}
+        int Start(void * data, const char * el, const char ** attr);
+
+    private:
+        const Users & m_users;
+        std::string m_login;
+
+        void CreateAnswer();
+};
+
+class ADD_USER: public BASE_PARSER
+{
+    public:
+        class FACTORY : public BASE_PARSER::FACTORY
+        {
+            public:
+                explicit FACTORY(Users & users) : m_users(users) {}
+                virtual BASE_PARSER * create(const Admin & admin) { return new ADD_USER(admin, m_users); }
+                static void Register(REGISTRY & registry, Users & users)
+                { registry[ToLower(tag)] = new FACTORY(users); }
+            private:
+                Users & m_users;
+        };
+
+        static const char * tag;
+
+        ADD_USER(const Admin & admin, Users & users)
+            : BASE_PARSER(admin, tag), m_users(users) {}
+        int Start(void * data, const char * el, const char ** attr);
+
+    private:
+        Users & m_users;
+        std::string m_login;
+
+        void CreateAnswer();
+};
+
+class CHG_USER: public BASE_PARSER
+{
+    public:
+        class FACTORY : public BASE_PARSER::FACTORY
+        {
+            public:
+                FACTORY(Users & users, Store & store, const Tariffs & tariffs)
+                    : m_users(users), m_store(store), m_tariffs(tariffs)
+                {}
+                virtual BASE_PARSER * create(const Admin & admin) { return new CHG_USER(admin, m_users, m_store, m_tariffs); }
+                static void Register(REGISTRY & registry, Users & users, Store & store, const Tariffs & tariffs)
+                { registry[ToLower(tag)] = new FACTORY(users, store, tariffs); }
+            private:
+                Users & m_users;
+                Store & m_store;
+                const Tariffs & m_tariffs;
+        };
+
+        static const char * tag;
+
+        CHG_USER(const Admin & admin, Users & users,
+                 Store & store, const Tariffs & tariffs)
+            : BASE_PARSER(admin, tag),
+              m_users(users),
+              m_store(store),
+              m_tariffs(tariffs),
+              m_cashMustBeAdded(false) {}
+
+        int Start(void * data, const char * el, const char ** attr);
+
+    private:
+        Users & m_users;
+        Store & m_store;
+        const Tariffs & m_tariffs;
+        UserStatOpt m_usr;
+        UserConfOpt m_ucr;
+        Optional<uint64_t> m_upr[DIR_NUM];
+        Optional<uint64_t> m_downr[DIR_NUM];
+        std::string m_cashMsg;
+        std::string m_login;
+        bool m_cashMustBeAdded;
+
+        int ApplyChanges();
+        void CreateAnswer();
+};
+
+class DEL_USER: public BASE_PARSER
+{
+    public:
+        class FACTORY : public BASE_PARSER::FACTORY
+        {
+            public:
+                explicit FACTORY(Users & users) : m_users(users) {}
+                virtual BASE_PARSER * create(const Admin & admin) { return new DEL_USER(admin, m_users); }
+                static void Register(REGISTRY & registry, Users & users)
+                { registry[ToLower(tag)] = new FACTORY(users); }
+            private:
+                Users & m_users;
+        };
+
+        static const char * tag;
+
+        DEL_USER(const Admin & admin, Users & users)
+            : BASE_PARSER(admin, tag), m_users(users), res(0), u(NULL) {}
+        int Start(void * data, const char * el, const char ** attr);
+        int End(void * data, const char * el);
+
+    private:
+        Users & m_users;
+        int res;
+        User * u;
+
+        void CreateAnswer();
+};
+
+class CHECK_USER: public BASE_PARSER
+{
+    public:
+        class FACTORY : public BASE_PARSER::FACTORY
+        {
+            public:
+                explicit FACTORY(const Users & users) : m_users(users) {}
+                virtual BASE_PARSER * create(const Admin & admin) { return new CHECK_USER(admin, m_users); }
+                static void Register(REGISTRY & registry, const Users & users)
+                { registry[ToLower(tag)] = new FACTORY(users); }
+            private:
+                const Users & m_users;
+        };
+
+        static const char * tag;
+
+        CHECK_USER(const Admin & admin, const Users & users)
+            : BASE_PARSER(admin, tag), m_users(users) {}
+        int Start(void * data, const char * el, const char ** attr);
+        int End(void * data, const char * el);
+
+    private:
+        const Users & m_users;
+
+        void CreateAnswer(const char * error);
+        void CreateAnswer() {} // dummy
+};
+
+} // namespace PARSER
+} // namespace STG
diff --git a/projects/stargazer/plugins/configuration/sgconfig/stgconfig.cpp b/projects/stargazer/plugins/configuration/sgconfig/stgconfig.cpp
new file mode 100644 (file)
index 0000000..3f47f24
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+#include "stgconfig.h"
+
+#include "stg/common.h"
+
+#include <algorithm>
+#include <csignal>
+#include <cstring>
+#include <cerrno>
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+bool STG_CONFIG_SETTINGS::ParseSettings(const STG::ModuleSettings & s)
+{
+    STG::ParamValue pv;
+    std::vector<STG::ParamValue>::const_iterator pvi;
+    ///////////////////////////
+    pv.param = "Port";
+    pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+    if (pvi == s.moduleParams.end() || pvi->value.empty())
+        {
+        errorStr = "Parameter \'Port\' is not found.";
+        printfd(__FILE__, "%s\n", errorStr.c_str());
+        return false;
+        }
+    int p;
+    if (ParseIntInRange(pvi->value[0], 2, 65535, &p))
+        {
+        errorStr = "Parameter \'Port\' should be an integral value in range (2, 65535). Actual value: '" + pvi->value[0] + "'.";
+        printfd(__FILE__, "%s\n", errorStr.c_str());
+        return false;
+        }
+    m_port = static_cast<uint16_t>(p);
+
+    pv.param = "BindAddress";
+    pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+    if (pvi != s.moduleParams.end() && !pvi->value.empty())
+        m_bindAddress = pvi->value[0];
+
+    return true;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+extern "C" STG::Plugin * GetPlugin()
+{
+    static STG_CONFIG plugin;
+    return &plugin;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+STG_CONFIG::STG_CONFIG()
+    : nonstop(false),
+      isRunning(false),
+      logger(STG::PluginLogger::get("conf_sg")),
+      config(logger)
+{
+}
+//-----------------------------------------------------------------------------
+int STG_CONFIG::ParseSettings()
+{
+    if (stgConfigSettings.ParseSettings(settings))
+        return 0;
+    errorStr = stgConfigSettings.GetStrError();
+    return -1;
+}
+//-----------------------------------------------------------------------------
+int STG_CONFIG::Start()
+{
+    if (isRunning)
+        return 0;
+
+    nonstop = true;
+
+    config.SetPort(stgConfigSettings.GetPort());
+    config.SetBindAddress(stgConfigSettings.GetBindAddress());
+
+    if (config.Prepare())
+    {
+        errorStr = config.GetStrError();
+        return -1;
+    }
+
+    if (pthread_create(&thread, NULL, Run, this))
+    {
+        errorStr = std::string("Cannot create thread: '") + strerror(errno) + "'.";
+        printfd(__FILE__, "%s\n", errorStr.c_str());
+        logger(errorStr);
+        return -1;
+    }
+
+    return 0;
+}
+//-----------------------------------------------------------------------------
+int STG_CONFIG::Stop()
+{
+    if (!isRunning)
+        return 0;
+
+    config.Stop();
+
+    //5 seconds to thread stops itself
+    for (size_t i = 0; i < 25; ++i)
+    {
+        if (!isRunning)
+            break;
+
+        struct timespec ts = {0, 200000000};
+        nanosleep(&ts, NULL);
+    }
+
+    if (isRunning)
+        return -1;
+
+    return 0;
+}
+//-----------------------------------------------------------------------------
+void * STG_CONFIG::Run(void * d)
+{
+    sigset_t signalSet;
+    sigfillset(&signalSet);
+    pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+    STG_CONFIG & stgConf = *static_cast<STG_CONFIG *>(d);
+    stgConf.isRunning = true;
+
+    stgConf.config.Run();
+
+    stgConf.isRunning = false;
+
+    return NULL;
+}
diff --git a/projects/stargazer/plugins/configuration/sgconfig/stgconfig.h b/projects/stargazer/plugins/configuration/sgconfig/stgconfig.h
new file mode 100644 (file)
index 0000000..b7684e3
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+#pragma once
+
+#include "configproto.h"
+
+#include "stg/plugin.h"
+#include "stg/logger.h"
+
+#include <string>
+
+#include <pthread.h>
+
+class STG_CONFIG_SETTINGS
+{
+    public:
+        STG_CONFIG_SETTINGS() : m_port(0), m_bindAddress("0.0.0.0") {}
+        const std::string & GetStrError() const { return errorStr; }
+        bool ParseSettings(const STG::ModuleSettings & s);
+        uint16_t GetPort() const { return m_port; }
+        const std::string & GetBindAddress() const { return m_bindAddress; }
+    private:
+        std::string errorStr;
+        uint16_t m_port;
+        std::string m_bindAddress;
+};
+
+class STG_CONFIG : public STG::Plugin
+{
+    public:
+        STG_CONFIG();
+
+        void                SetUsers(STG::Users * users) override { config.SetUsers(users); }
+        void                SetTariffs(STG::Tariffs * tariffs) override { config.SetTariffs(tariffs); }
+        void                SetAdmins(STG::Admins * admins) override { config.SetAdmins(admins); }
+        void                SetServices(STG::Services * services) override { config.SetServices(services); }
+        void                SetCorporations(STG::Corporations * corporations) override { config.SetCorporations( corporations); }
+        void                SetStore(STG::Store * store) override { config.SetStore(store); }
+        void                SetStgSettings(const STG::Settings * s) override { config.SetSettings(s); }
+        void                SetSettings(const STG::ModuleSettings & s) override { settings = s; }
+        int                 ParseSettings() override;
+
+        int                 Start() override;
+        int                 Stop() override;
+        int                 Reload(const STG::ModuleSettings & /*ms*/) override { return 0; }
+        bool                IsRunning() override { return isRunning; }
+
+        const std::string & GetStrError() const override { return errorStr; }
+        std::string         GetVersion() const override { return "Stg Configurator v. 2.0"; }
+        uint16_t            GetStartPosition() const override { return 20; }
+        uint16_t            GetStopPosition() const override { return 20; }
+
+    private:
+        STG_CONFIG(const STG_CONFIG & rvalue);
+        STG_CONFIG & operator=(const STG_CONFIG & rvalue);
+
+        static void *       Run(void *);
+
+        mutable std::string errorStr;
+        STG_CONFIG_SETTINGS stgConfigSettings;
+        pthread_t           thread;
+        bool                nonstop;
+        bool                isRunning;
+        STG::PluginLogger   logger;
+        CONFIGPROTO         config;
+        STG::ModuleSettings settings;
+};
diff --git a/projects/stargazer/plugins/other/ping/ping.cpp b/projects/stargazer/plugins/other/ping/ping.cpp
new file mode 100644 (file)
index 0000000..147ef68
--- /dev/null
@@ -0,0 +1,334 @@
+#include "ping.h"
+
+#include "stg/user.h"
+#include "stg/locker.h"
+#include "stg/user_property.h"
+
+#include <cstdio>
+#include <cassert>
+#include <csignal>
+#include <ctime>
+#include <algorithm>
+
+namespace
+{
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template <typename varType>
+class HAS_USER: public std::binary_function<varType, UserPtr, bool>
+{
+public:
+    explicit HAS_USER(const UserPtr & u) : user(u) {}
+    bool operator()(varType notifier) const
+        {
+        return notifier.GetUser() == user;
+        }
+private:
+    const UserPtr & user;
+};
+}
+
+extern "C" STG::Plugin* GetPlugin()
+{
+    static PING plugin;
+    return &plugin;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+int PING_SETTINGS::ParseSettings(const STG::ModuleSettings & s)
+{
+STG::ParamValue pv;
+std::vector<STG::ParamValue>::const_iterator pvi;
+
+pv.param = "PingDelay";
+pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end() || pvi->value.empty())
+    {
+    errorStr = "Parameter \'PingDelay\' not found.";
+    printfd(__FILE__, "Parameter 'PingDelay' not found\n");
+    return -1;
+    }
+if (ParseIntInRange(pvi->value[0], 5, 3600, &pingDelay))
+    {
+    errorStr = "Cannot parse parameter \'PingDelay\': " + errorStr;
+    printfd(__FILE__, "Canot parse parameter 'PingDelay'\n");
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+PING::PING()
+    : users(NULL),
+      nonstop(false),
+      isRunning(false),
+      onAddUserNotifier(*this),
+      onDelUserNotifier(*this),
+      logger(STG::PluginLogger::get("ping"))
+{
+pthread_mutex_init(&mutex, NULL);
+}
+//-----------------------------------------------------------------------------
+PING::~PING()
+{
+pthread_mutex_destroy(&mutex);
+}
+//-----------------------------------------------------------------------------
+int PING::ParseSettings()
+{
+int ret = pingSettings.ParseSettings(settings);
+if (ret)
+    errorStr = pingSettings.GetStrError();
+return ret;
+}
+//-----------------------------------------------------------------------------
+int PING::Start()
+{
+GetUsers();
+
+users->AddNotifierUserAdd(&onAddUserNotifier);
+users->AddNotifierUserDel(&onDelUserNotifier);
+
+nonstop = true;
+
+pinger.SetDelayTime(pingSettings.GetPingDelay());
+pinger.Start();
+
+if (pthread_create(&thread, NULL, Run, this))
+    {
+    errorStr = "Cannot start thread.";
+    logger("Cannot create thread.");
+    printfd(__FILE__, "Cannot start thread\n");
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int PING::Stop()
+{
+STG_LOCKER lock(&mutex);
+
+if (!isRunning)
+    return 0;
+
+pinger.Stop();
+nonstop = false;
+//5 seconds to thread stops itself
+struct timespec ts = {0, 200000000};
+for (int i = 0; i < 25; i++)
+    {
+    if (!isRunning)
+        break;
+
+    nanosleep(&ts, NULL);
+    }
+
+users->DelNotifierUserAdd(&onAddUserNotifier);
+users->DelNotifierUserDel(&onDelUserNotifier);
+
+std::list<UserPtr>::iterator users_iter;
+users_iter = usersList.begin();
+while (users_iter != usersList.end())
+    {
+    UnSetUserNotifiers(*users_iter);
+    ++users_iter;
+    }
+
+if (isRunning)
+    return -1;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+bool PING::IsRunning()
+{
+return isRunning;
+}
+//-----------------------------------------------------------------------------
+void * PING::Run(void * d)
+{
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+PING * ping = static_cast<PING *>(d);
+ping->isRunning = true;
+
+long delay = (10000000 * ping->pingSettings.GetPingDelay()) / 3 + 50000000;
+
+while (ping->nonstop)
+    {
+    std::list<UserPtr>::iterator iter = ping->usersList.begin();
+        {
+        STG_LOCKER lock(&ping->mutex);
+        while (iter != ping->usersList.end())
+            {
+            if ((*iter)->GetProperties().ips.ConstData().onlyOneIP())
+                {
+                uint32_t ip = (*iter)->GetProperties().ips.ConstData()[0].ip;
+                time_t t;
+                if (ping->pinger.GetIPTime(ip, &t) == 0)
+                    {
+                    if (t)
+                        (*iter)->UpdatePingTime(t);
+                    }
+                }
+            else
+                {
+                uint32_t ip = (*iter)->GetCurrIP();
+                if (ip)
+                    {
+                    time_t t;
+                    if (ping->pinger.GetIPTime(ip, &t) == 0)
+                        {
+                        if (t)
+                            (*iter)->UpdatePingTime(t);
+                        }
+                    }
+                }
+            ++iter;
+            }
+        }
+    struct timespec ts = {delay / 1000000000, delay % 1000000000};
+    for (int i = 0; i < 100; i++)
+        {
+        if (ping->nonstop)
+            {
+            nanosleep(&ts, NULL);
+            }
+        }
+    }
+
+ping->isRunning = false;
+return NULL;
+}
+//-----------------------------------------------------------------------------
+void PING::SetUserNotifiers(UserPtr u)
+{
+CHG_CURRIP_NOTIFIER_PING ChgCurrIPNotifier(*this, u);
+CHG_IPS_NOTIFIER_PING ChgIPNotifier(*this, u);
+
+ChgCurrIPNotifierList.push_front(ChgCurrIPNotifier);
+ChgIPNotifierList.push_front(ChgIPNotifier);
+
+u->AddCurrIPAfterNotifier(&(*ChgCurrIPNotifierList.begin()));
+u->GetProperties().ips.AddAfterNotifier(&(*ChgIPNotifierList.begin()));
+}
+//-----------------------------------------------------------------------------
+void PING::UnSetUserNotifiers(UserPtr u)
+{
+// ---          CurrIP              ---
+HAS_USER<CHG_CURRIP_NOTIFIER_PING> IsContainsUserCurrIP(u);
+HAS_USER<CHG_IPS_NOTIFIER_PING> IsContainsUserIP(u);
+
+std::list<CHG_CURRIP_NOTIFIER_PING>::iterator currIPter;
+std::list<CHG_IPS_NOTIFIER_PING>::iterator IPIter;
+
+currIPter = find_if(ChgCurrIPNotifierList.begin(),
+                    ChgCurrIPNotifierList.end(),
+                    IsContainsUserCurrIP);
+
+if (currIPter != ChgCurrIPNotifierList.end())
+    {
+    currIPter->GetUser()->DelCurrIPAfterNotifier(&(*currIPter));
+    ChgCurrIPNotifierList.erase(currIPter);
+    }
+// ---         CurrIP end          ---
+
+// ---          IP              ---
+IPIter = find_if(ChgIPNotifierList.begin(),
+                 ChgIPNotifierList.end(),
+                 IsContainsUserIP);
+
+if (IPIter != ChgIPNotifierList.end())
+    {
+    IPIter->GetUser()->GetProperties().ips.DelAfterNotifier(&(*IPIter));
+    ChgIPNotifierList.erase(IPIter);
+    }
+// ---          IP end          ---
+}
+//-----------------------------------------------------------------------------
+void PING::GetUsers()
+{
+STG_LOCKER lock(&mutex);
+
+UserPtr u;
+int h = users->OpenSearch();
+assert(h && "USERS::OpenSearch is always correct");
+
+while (users->SearchNext(h, &u) == 0)
+    {
+    usersList.push_back(u);
+    SetUserNotifiers(u);
+    if (u->GetProperties().ips.ConstData().onlyOneIP())
+        {
+        pinger.AddIP(u->GetProperties().ips.ConstData()[0].ip);
+        }
+    else
+        {
+        uint32_t ip = u->GetCurrIP();
+        if (ip)
+            pinger.AddIP(ip);
+        }
+    }
+
+users->CloseSearch(h);
+}
+//-----------------------------------------------------------------------------
+void PING::AddUser(UserPtr u)
+{
+STG_LOCKER lock(&mutex);
+
+SetUserNotifiers(u);
+usersList.push_back(u);
+}
+//-----------------------------------------------------------------------------
+void PING::DelUser(UserPtr u)
+{
+STG_LOCKER lock(&mutex);
+
+UnSetUserNotifiers(u);
+
+std::list<UserPtr>::iterator users_iter;
+users_iter = usersList.begin();
+
+while (users_iter != usersList.end())
+    {
+    if (u == *users_iter)
+        {
+        usersList.erase(users_iter);
+        break;
+        }
+    ++users_iter;
+    }
+}
+//-----------------------------------------------------------------------------
+void CHG_CURRIP_NOTIFIER_PING::Notify(const uint32_t & oldIP, const uint32_t & newIP)
+{
+ping.pinger.DelIP(oldIP);
+if (newIP)
+    ping.pinger.AddIP(newIP);
+}
+//-----------------------------------------------------------------------------
+void CHG_IPS_NOTIFIER_PING::Notify(const STG::UserIPs & oldIPS, const STG::UserIPs & newIPS)
+{
+if (oldIPS.onlyOneIP())
+    ping.pinger.DelIP(oldIPS[0].ip);
+
+if (newIPS.onlyOneIP())
+    ping.pinger.AddIP(newIPS[0].ip);
+}
+//-----------------------------------------------------------------------------
+void ADD_USER_NONIFIER_PING::Notify(const UserPtr & user)
+{
+ping.AddUser(user);
+}
+//-----------------------------------------------------------------------------
+void DEL_USER_NONIFIER_PING::Notify(const UserPtr & user)
+{
+ping.DelUser(user);
+}
+//-----------------------------------------------------------------------------
diff --git a/projects/stargazer/plugins/other/ping/ping.h b/projects/stargazer/plugins/other/ping/ping.h
new file mode 100644 (file)
index 0000000..9986be3
--- /dev/null
@@ -0,0 +1,142 @@
+#pragma once
+
+#include "stg/plugin.h"
+#include "stg/module_settings.h"
+#include "stg/notifer.h"
+#include "stg/user_ips.h"
+#include "stg/pinger.h"
+#include "stg/users.h"
+#include "stg/logger.h"
+
+#include <string>
+#include <list>
+#include <cstdint>
+
+#include <pthread.h>
+
+class PING;
+
+namespace STG
+{
+struct USER;
+struct SETTINGS;
+}
+
+using UserPtr = STG::User*;
+//-----------------------------------------------------------------------------*/
+class CHG_CURRIP_NOTIFIER_PING: public STG::PropertyNotifierBase<uint32_t> {
+public:
+    CHG_CURRIP_NOTIFIER_PING(const PING & p, UserPtr u)
+        : user(u), ping(p) {}
+    void Notify(const uint32_t & oldIP, const uint32_t & newIP);
+    UserPtr GetUser() const { return user; }
+
+private:
+    CHG_CURRIP_NOTIFIER_PING & operator=(const CHG_CURRIP_NOTIFIER_PING &);
+
+    UserPtr user;
+    const PING & ping;
+};
+//-----------------------------------------------------------------------------
+class CHG_IPS_NOTIFIER_PING: public STG::PropertyNotifierBase<STG::UserIPs> {
+public:
+    CHG_IPS_NOTIFIER_PING(const PING & p, UserPtr u)
+        : user(u), ping(p) {}
+    void Notify(const STG::UserIPs & oldIPS, const STG::UserIPs & newIPS);
+    UserPtr GetUser() const { return user; }
+
+private:
+    CHG_IPS_NOTIFIER_PING & operator=(const CHG_IPS_NOTIFIER_PING &);
+
+    UserPtr user;
+    const PING & ping;
+};
+//-----------------------------------------------------------------------------
+class ADD_USER_NONIFIER_PING: public STG::NotifierBase<UserPtr> {
+public:
+    explicit ADD_USER_NONIFIER_PING(PING & p) : ping(p) {}
+    void Notify(const UserPtr & user);
+
+private:
+    ADD_USER_NONIFIER_PING(const ADD_USER_NONIFIER_PING &);
+    ADD_USER_NONIFIER_PING & operator=(const ADD_USER_NONIFIER_PING &);
+
+    PING & ping;
+};
+//-----------------------------------------------------------------------------
+class DEL_USER_NONIFIER_PING: public STG::NotifierBase<UserPtr> {
+public:
+    explicit DEL_USER_NONIFIER_PING(PING & p) : ping(p) {}
+    void Notify(const UserPtr & user);
+
+private:
+    DEL_USER_NONIFIER_PING(const DEL_USER_NONIFIER_PING &);
+    DEL_USER_NONIFIER_PING & operator=(const DEL_USER_NONIFIER_PING &);
+
+    PING & ping;
+};
+//-----------------------------------------------------------------------------
+class PING_SETTINGS {
+public:
+    PING_SETTINGS() : pingDelay(0) {}
+    const std::string & GetStrError() const { return errorStr; }
+    int ParseSettings(const STG::ModuleSettings & s);
+    int GetPingDelay() const { return pingDelay; }
+private:
+    int pingDelay;
+    mutable std::string errorStr;
+};
+//-----------------------------------------------------------------------------
+class PING : public STG::Plugin {
+friend class CHG_CURRIP_NOTIFIER_PING;
+friend class CHG_IPS_NOTIFIER_PING;
+public:
+    PING();
+    ~PING() override;
+
+    void SetUsers(STG::Users * u) override { users = u; }
+    void SetSettings(const STG::ModuleSettings & s) override { settings = s; }
+    int ParseSettings() override;
+
+    int Start() override;
+    int Stop() override;
+    int Reload(const STG::ModuleSettings & /*ms*/) override { return 0; }
+    bool IsRunning() override;
+
+    const std::string & GetStrError() const override { return errorStr; }
+    std::string GetVersion() const override { return "Pinger v.1.01"; }
+    uint16_t GetStartPosition() const override { return 10; }
+    uint16_t GetStopPosition() const override { return 10; }
+
+    void AddUser(UserPtr u);
+    void DelUser(UserPtr u);
+
+private:
+    explicit PING(const PING & rvalue);
+    PING & operator=(const PING & rvalue);
+
+    void GetUsers();
+    void SetUserNotifiers(UserPtr u);
+    void UnSetUserNotifiers(UserPtr u);
+    static void * Run(void * d);
+
+    mutable std::string errorStr;
+    PING_SETTINGS pingSettings;
+    STG::ModuleSettings settings;
+    STG::Users * users;
+    std::list<UserPtr> usersList;
+
+    pthread_t thread;
+    pthread_mutex_t mutex;
+    bool nonstop;
+    bool isRunning;
+    mutable STG_PINGER pinger;
+
+    std::list<CHG_CURRIP_NOTIFIER_PING> ChgCurrIPNotifierList;
+    std::list<CHG_IPS_NOTIFIER_PING> ChgIPNotifierList;
+
+    ADD_USER_NONIFIER_PING onAddUserNotifier;
+    DEL_USER_NONIFIER_PING onDelUserNotifier;
+
+    STG::PluginLogger logger;
+};
diff --git a/projects/stargazer/plugins/other/rscript/nrmap_parser.cpp b/projects/stargazer/plugins/other/rscript/nrmap_parser.cpp
new file mode 100644 (file)
index 0000000..308d5d0
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+ /*
+ $Revision: 1.8 $
+ $Author: faust $
+ $Date: 2009/10/22 09:58:53 $
+ */
+
+#include <fstream>
+#include <cerrno>
+#include <cstring>
+#include <algorithm>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+#include "stg/common.h"
+#include "nrmap_parser.h"
+
+bool NRMapParser::ReadFile(const std::string & fileName)
+{
+std::ifstream source(fileName.c_str());
+
+if (!source)
+    {
+    errorStr = "Error opening file ";
+    errorStr += fileName;
+    printfd(__FILE__, "NRMapParser::ReadFile(): %s\n", errorStr.c_str());
+    return true;
+    }
+
+int lineNumber = 0;
+std::string line;
+std::vector<NET_ROUTER> _nrmap;
+
+while (getline(source, line))
+    {
+    ++lineNumber;
+    NET_ROUTER nr;
+
+    if (Trim(line) == "")
+        {
+        continue;
+        }
+
+    if (ParseLine(line, nr))
+        {
+        printfd(__FILE__, "NRMapParser::ReadFile(): Error parsing line %d: '%s'\n", lineNumber, errorStr.c_str());
+        return true;
+        }
+
+    _nrmap.push_back(nr);
+    }
+
+nrmap = _nrmap;
+
+return false;
+}
+
+bool NRMapParser::ParseLine(const std::string & line, NET_ROUTER & nr) const
+{
+// xxx.xxx.xxx.xxx/yy zzz.zzz.zzz.zzz
+size_t pos = line.find_first_of(" \t");
+
+if (pos == std::string::npos)
+    {
+    errorStr = "No space between subnet and router";
+    return true;
+    }
+
+std::string subnet(line.substr(0, pos)); // xxx.xxx.xxx.xxx/yy
+
+uint32_t ip = 0;
+uint32_t mask = 0;
+
+if (ParseNet(subnet, ip, mask))
+    {
+    return true;
+    }
+
+nr.subnetIP = ip;
+nr.subnetMask = mask;
+
+pos = line.find_first_not_of(" \t", pos);
+
+if (pos == std::string::npos)
+    {
+    errorStr = "No router address found";
+    return true;
+    }
+
+size_t pos2 = line.find_first_of(" \t", pos);
+
+std::string router(line.substr(pos, pos2 == std::string::npos ? line.length() - pos2 - 1 : pos2 - pos)); //zzz.zzz.zzz.zzz
+
+uint32_t routerIP;
+
+if (ParseRouter(router, routerIP))
+    {
+    return true;
+    }
+
+std::vector<uint32_t>::iterator it;
+
+it = std::lower_bound(
+        nr.routers.begin(),
+        nr.routers.end(),
+        routerIP
+        );
+nr.routers.insert(it, routerIP);
+
+//nr.routers.push_back(routerIP);
+
+while (pos2 != std::string::npos)
+    {
+    pos = line.find_first_not_of(" \t", pos2);
+
+    if (pos == std::string::npos)
+        {
+        return false;
+        }
+
+    pos2 = line.find_first_of(" \t", pos);
+
+    if (ParseRouter(line.substr(
+                        pos,
+                        pos2 == std::string::npos ? line.length() - pos2 - 1 : pos2 - pos),
+                    routerIP))
+        {
+        return true;
+        }
+
+    it = std::lower_bound(
+            nr.routers.begin(),
+            nr.routers.end(),
+            routerIP
+            );
+    nr.routers.insert(it, routerIP);
+
+    //nr.routers.push_back(routerIP);
+
+    }
+
+return false;
+}
+
+bool NRMapParser::ParseNet(const std::string & line, uint32_t & ip, uint32_t & mask) const
+{
+// xxx.xxx.xxx.xxx/yy
+
+size_t pos = line.find_first_of('/');
+
+if (pos == std::string::npos)
+    {
+    errorStr = "Subnet is not in CIDR notation";
+    return true;
+    }
+
+int res = inet_pton(AF_INET, line.substr(0, pos).c_str(), &ip); //xxx.xxx.xxx.xxx
+
+if (res < 0)
+    {
+    errorStr = strerror(errno);
+    return true;
+    }
+else if (res == 0)
+    {
+    errorStr = "Invalid subnet address";
+    return true;
+    }
+
+if (str2x(line.substr(pos + 1, line.length() - pos - 1), mask)) //yy
+    {
+    errorStr = "Invalid subnet mask";
+    return true;
+    }
+if (mask > 32)
+    {
+    errorStr = "Subnet mask is out of range [0..32]";
+    return true;
+    }
+mask = htonl(0xffFFffFF << (32 - mask)); //bitmask
+
+return false;
+}
+
+bool NRMapParser::ParseRouter(const std::string & line, uint32_t & ip) const
+{
+int res = inet_pton(AF_INET, line.c_str(), &ip); //zzz.zzz.zzz.zzz
+
+if (res < 0)
+    {
+    errorStr = strerror(errno);
+    return true;
+    }
+else if (res == 0)
+    {
+    printfd(__FILE__, "NRMapParser::ParseRouter(): IP '%s' is invalid\n", line.c_str());
+    errorStr = "Invalid router address";
+    return true;
+    }
+return false;
+}
diff --git a/projects/stargazer/plugins/other/rscript/nrmap_parser.h b/projects/stargazer/plugins/other/rscript/nrmap_parser.h
new file mode 100644 (file)
index 0000000..82e7edb
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+ /*
+ $Revision: 1.2 $
+ $Author: faust $
+ $Date: 2009/09/23 12:51:42 $
+ */
+
+#ifndef __NRMAP_PARSER_H__
+#define __NRMAP_PARSER_H__
+
+#include <string>
+#include <vector>
+#include <cstdint>
+
+struct NET_ROUTER
+{
+    NET_ROUTER() : subnetIP(0), subnetMask(0), routers() {}
+    NET_ROUTER(const NET_ROUTER & rvalue)
+        : subnetIP(rvalue.subnetIP),
+          subnetMask(rvalue.subnetMask),
+          routers(rvalue.routers)
+    {}
+
+    uint32_t              subnetIP;
+    uint32_t              subnetMask;
+    std::vector<uint32_t> routers;
+
+    NET_ROUTER & operator=(const NET_ROUTER & rvalue)
+    {
+    subnetIP = rvalue.subnetIP;
+    subnetMask = rvalue.subnetMask;
+    routers = rvalue.routers;
+    return *this;
+    }
+};
+
+class NRMapParser {
+public:
+    NRMapParser() : nrmap(), errorStr() {}
+    ~NRMapParser() {}
+
+    bool ReadFile(const std::string & fileName);
+    const std::vector<NET_ROUTER> & GetMap() const { return nrmap; }
+    const std::string & GetErrorStr() const { return errorStr; }
+
+private:
+    NRMapParser(const NRMapParser & rvalue);
+    NRMapParser & operator=(const NRMapParser & rvalue);
+
+    std::vector<NET_ROUTER> nrmap;
+    mutable std::string errorStr;
+
+    bool ParseLine(const std::string & line, NET_ROUTER & nr) const;
+    bool ParseNet(const std::string & line, uint32_t & ip, uint32_t & mask) const;
+    bool ParseRouter(const std::string & line, uint32_t & ip) const;
+};
+
+#endif
diff --git a/projects/stargazer/plugins/other/rscript/rscript.cpp b/projects/stargazer/plugins/other/rscript/rscript.cpp
new file mode 100644 (file)
index 0000000..764e536
--- /dev/null
@@ -0,0 +1,590 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#include "rscript.h"
+
+#include "ur_functor.h"
+#include "send_functor.h"
+
+#include "stg/common.h"
+#include "stg/locker.h"
+#include "stg/users.h"
+#include "stg/user_property.h"
+#include "stg/logger.h"
+
+#include <algorithm>
+
+#include <csignal>
+#include <cassert>
+#include <cstdlib>
+#include <cerrno>
+#include <cstring>
+
+#include <sys/time.h>
+#include <netinet/ip.h>
+
+#define RS_DEBUG (1)
+#define MAX_SHORT_PCKT  (3)
+
+extern volatile time_t stgTime;
+
+using RS::REMOTE_SCRIPT;
+
+namespace {
+
+template<typename T>
+struct USER_IS
+{
+    explicit USER_IS(RS::UserPtr u) : user(u) {}
+    bool operator()(const T & notifier) { return notifier.GetUser() == user; }
+
+    RS::UserPtr user;
+};
+
+} // namespace anonymous
+
+extern "C" STG::Plugin* GetPlugin()
+{
+    static REMOTE_SCRIPT plugin;
+    return &plugin;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+RS::SETTINGS::SETTINGS()
+    : sendPeriod(0),
+      port(0)
+{
+}
+//-----------------------------------------------------------------------------
+int RS::SETTINGS::ParseSettings(const STG::ModuleSettings & s)
+{
+int p;
+STG::ParamValue pv;
+std::vector<STG::ParamValue>::const_iterator pvi;
+netRouters.clear();
+///////////////////////////
+pv.param = "Port";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end() || pvi->value.empty())
+    {
+    errorStr = "Parameter \'Port\' not found.";
+    printfd(__FILE__, "Parameter 'Port' not found\n");
+    return -1;
+    }
+if (ParseIntInRange(pvi->value[0], 2, 65535, &p))
+    {
+    errorStr = "Cannot parse parameter \'Port\': " + errorStr;
+    printfd(__FILE__, "Cannot parse parameter 'Port'\n");
+    return -1;
+    }
+port = static_cast<uint16_t>(p);
+///////////////////////////
+pv.param = "SendPeriod";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end() || pvi->value.empty())
+    {
+    errorStr = "Parameter \'SendPeriod\' not found.";
+    printfd(__FILE__, "Parameter 'SendPeriod' not found\n");
+    return -1;
+    }
+
+if (ParseIntInRange(pvi->value[0], 5, 600, &sendPeriod))
+    {
+    errorStr = "Cannot parse parameter \'SendPeriod\': " + errorStr;
+    printfd(__FILE__, "Cannot parse parameter 'SendPeriod'\n");
+    return -1;
+    }
+///////////////////////////
+pv.param = "UserParams";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end() || pvi->value.empty())
+    {
+    errorStr = "Parameter \'UserParams\' not found.";
+    printfd(__FILE__, "Parameter 'UserParams' not found\n");
+    return -1;
+    }
+userParams = pvi->value;
+///////////////////////////
+pv.param = "Password";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end() || pvi->value.empty())
+    {
+    errorStr = "Parameter \'Password\' not found.";
+    printfd(__FILE__, "Parameter 'Password' not found\n");
+    return -1;
+    }
+password = pvi->value[0];
+///////////////////////////
+pv.param = "SubnetFile";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end() || pvi->value.empty())
+    {
+    errorStr = "Parameter \'SubnetFile\' not found.";
+    printfd(__FILE__, "Parameter 'SubnetFile' not found\n");
+    return -1;
+    }
+subnetFile = pvi->value[0];
+
+NRMapParser nrMapParser;
+
+if (!nrMapParser.ReadFile(subnetFile))
+    {
+    netRouters = nrMapParser.GetMap();
+    }
+else
+    {
+        STG::PluginLogger::get("rscript")("mod_rscript: error opening subnets file '%s'", subnetFile.c_str());
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+REMOTE_SCRIPT::REMOTE_SCRIPT()
+    : sendPeriod(15),
+      halfPeriod(8),
+      nonstop(false),
+      isRunning(false),
+      users(NULL),
+      sock(0),
+      onAddUserNotifier(*this),
+      onDelUserNotifier(*this),
+      logger(STG::PluginLogger::get("rscript"))
+{
+pthread_mutex_init(&mutex, NULL);
+}
+//-----------------------------------------------------------------------------
+REMOTE_SCRIPT::~REMOTE_SCRIPT()
+{
+pthread_mutex_destroy(&mutex);
+}
+//-----------------------------------------------------------------------------
+void * REMOTE_SCRIPT::Run(void * d)
+{
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+REMOTE_SCRIPT * rs = static_cast<REMOTE_SCRIPT *>(d);
+
+rs->isRunning = true;
+
+while (rs->nonstop)
+    {
+    rs->PeriodicSend();
+    sleep(2);
+    }
+
+rs->isRunning = false;
+return NULL;
+}
+//-----------------------------------------------------------------------------
+int REMOTE_SCRIPT::ParseSettings()
+{
+int ret = rsSettings.ParseSettings(settings);
+if (ret)
+    errorStr = rsSettings.GetStrError();
+
+sendPeriod = rsSettings.GetSendPeriod();
+halfPeriod = sendPeriod / 2;
+
+return ret;
+}
+//-----------------------------------------------------------------------------
+int REMOTE_SCRIPT::Start()
+{
+netRouters = rsSettings.GetSubnetsMap();
+
+InitEncrypt(&ctx, rsSettings.GetPassword());
+
+users->AddNotifierUserAdd(&onAddUserNotifier);
+users->AddNotifierUserDel(&onDelUserNotifier);
+
+nonstop = true;
+
+if (GetUsers())
+    {
+    return -1;
+    }
+
+if (PrepareNet())
+    {
+    return -1;
+    }
+
+if (!isRunning)
+    {
+    if (pthread_create(&thread, NULL, Run, this))
+        {
+        errorStr = "Cannot create thread.";
+        logger("Cannot create thread.");
+        printfd(__FILE__, "Cannot create thread\n");
+        return -1;
+        }
+    }
+
+errorStr = "";
+return 0;
+}
+//-----------------------------------------------------------------------------
+int REMOTE_SCRIPT::Stop()
+{
+if (!IsRunning())
+    return 0;
+
+nonstop = false;
+
+std::for_each(
+        authorizedUsers.begin(),
+        authorizedUsers.end(),
+        DisconnectUser(*this)
+        );
+
+FinalizeNet();
+
+if (isRunning)
+    {
+    //5 seconds to thread stops itself
+    for (int i = 0; i < 25 && isRunning; i++)
+        {
+        struct timespec ts = {0, 200000000};
+        nanosleep(&ts, NULL);
+        }
+    }
+
+users->DelNotifierUserDel(&onDelUserNotifier);
+users->DelNotifierUserAdd(&onAddUserNotifier);
+
+if (isRunning)
+    {
+    logger("Cannot stop thread.");
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int REMOTE_SCRIPT::Reload(const STG::ModuleSettings & /*ms*/)
+{
+NRMapParser nrMapParser;
+
+if (nrMapParser.ReadFile(rsSettings.GetMapFileName()))
+    {
+    errorStr = nrMapParser.GetErrorStr();
+    logger("Map file reading error: %s", errorStr.c_str());
+    return -1;
+    }
+
+    {
+    STG_LOCKER lock(&mutex);
+
+    printfd(__FILE__, "REMOTE_SCRIPT::Reload()\n");
+
+    netRouters = nrMapParser.GetMap();
+    }
+
+std::for_each(authorizedUsers.begin(),
+              authorizedUsers.end(),
+              UpdateRouter(*this));
+
+logger("%s reloaded successfully.", rsSettings.GetMapFileName().c_str());
+printfd(__FILE__, "REMOTE_SCRIPT::Reload() %s reloaded successfully.\n");
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+bool REMOTE_SCRIPT::PrepareNet()
+{
+sock = socket(AF_INET, SOCK_DGRAM, 0);
+
+if (sock < 0)
+    {
+    errorStr = "Cannot create socket.";
+    logger("Canot create a socket: %s", strerror(errno));
+    printfd(__FILE__, "Cannot create socket\n");
+    return true;
+    }
+
+return false;
+}
+//-----------------------------------------------------------------------------
+bool REMOTE_SCRIPT::FinalizeNet()
+{
+close(sock);
+return false;
+}
+//-----------------------------------------------------------------------------
+void REMOTE_SCRIPT::PeriodicSend()
+{
+STG_LOCKER lock(&mutex);
+
+std::map<uint32_t, RS::USER>::iterator it(authorizedUsers.begin());
+while (it != authorizedUsers.end())
+    {
+    if (difftime(stgTime, it->second.lastSentTime) - (rand() % halfPeriod) > sendPeriod)
+        {
+        Send(it->second);
+        }
+    ++it;
+    }
+}
+//-----------------------------------------------------------------------------
+#ifdef NDEBUG
+bool REMOTE_SCRIPT::PreparePacket(char * buf, size_t, RS::USER & rsu, bool forceDisconnect) const
+#else
+bool REMOTE_SCRIPT::PreparePacket(char * buf, size_t bufSize, RS::USER & rsu, bool forceDisconnect) const
+#endif
+{
+RS::PACKET_HEADER packetHead;
+
+memset(packetHead.padding, 0, sizeof(packetHead.padding));
+strcpy((char*)packetHead.magic, RS_ID);
+packetHead.protoVer[0] = '0';
+packetHead.protoVer[1] = '2';
+if (forceDisconnect)
+    {
+    packetHead.packetType = RS_DISCONNECT_PACKET;
+    printfd(__FILE__, "RSCRIPT: force disconnect for '%s'\n", rsu.user->GetLogin().c_str());
+    }
+else
+    {
+    if (rsu.shortPacketsCount % MAX_SHORT_PCKT == 0)
+        {
+        //SendLong
+        packetHead.packetType = rsu.user->IsInetable() ? RS_CONNECT_PACKET : RS_DISCONNECT_PACKET;
+        if (rsu.user->IsInetable())
+            printfd(__FILE__, "RSCRIPT: connect for '%s'\n", rsu.user->GetLogin().c_str());
+        else
+            printfd(__FILE__, "RSCRIPT: disconnect for '%s'\n", rsu.user->GetLogin().c_str());
+        }
+    else
+        {
+        //SendShort
+        packetHead.packetType = rsu.user->IsInetable() ? RS_ALIVE_PACKET : RS_DISCONNECT_PACKET;
+        if (rsu.user->IsInetable())
+            printfd(__FILE__, "RSCRIPT: alive for '%s'\n", rsu.user->GetLogin().c_str());
+        else
+            printfd(__FILE__, "RSCRIPT: disconnect for '%s'\n", rsu.user->GetLogin().c_str());
+        }
+    }
+rsu.shortPacketsCount++;
+rsu.lastSentTime = stgTime;
+
+packetHead.ip = htonl(rsu.ip);
+packetHead.id = htonl(rsu.user->GetID());
+strncpy((char*)packetHead.login, rsu.user->GetLogin().c_str(), RS_LOGIN_LEN);
+packetHead.login[RS_LOGIN_LEN - 1] = 0;
+
+memcpy(buf, &packetHead, sizeof(packetHead));
+
+if (packetHead.packetType == RS_ALIVE_PACKET)
+    {
+    return false;
+    }
+
+RS::PACKET_TAIL packetTail;
+
+memset(packetTail.padding, 0, sizeof(packetTail.padding));
+strcpy((char*)packetTail.magic, RS_ID);
+std::vector<std::string>::const_iterator it;
+std::string params;
+for(it = rsSettings.GetUserParams().begin();
+    it != rsSettings.GetUserParams().end();
+    ++it)
+    {
+    std::string parameter(rsu.user->GetParamValue(it->c_str()));
+    if (params.length() + parameter.length() > RS_PARAMS_LEN - 1)
+    {
+        logger("Script params string length %d exceeds the limit of %d symbols.", params.length() + parameter.length(), RS_PARAMS_LEN);
+        break;
+    }
+    params += parameter + " ";
+    }
+strncpy((char *)packetTail.params, params.c_str(), RS_PARAMS_LEN);
+packetTail.params[RS_PARAMS_LEN - 1] = 0;
+
+assert(sizeof(packetHead) + sizeof(packetTail) <= bufSize && "Insufficient buffer space");
+
+Encrypt(&ctx, buf + sizeof(packetHead), (char *)&packetTail, sizeof(packetTail) / 8);
+
+return false;
+}
+//-----------------------------------------------------------------------------
+bool REMOTE_SCRIPT::Send(RS::USER & rsu, bool forceDisconnect) const
+{
+char buffer[RS_MAX_PACKET_LEN];
+
+memset(buffer, 0, sizeof(buffer));
+
+if (PreparePacket(buffer, sizeof(buffer), rsu, forceDisconnect))
+    {
+    printfd(__FILE__, "REMOTE_SCRIPT::Send() - Invalid packet length!\n");
+    return true;
+    }
+
+std::for_each(
+        rsu.routers.begin(),
+        rsu.routers.end(),
+        PacketSender(sock, buffer, sizeof(buffer), static_cast<uint16_t>(htons(rsSettings.GetPort())))
+        );
+
+return false;
+}
+//-----------------------------------------------------------------------------
+bool REMOTE_SCRIPT::SendDirect(RS::USER & rsu, uint32_t routerIP, bool forceDisconnect) const
+{
+char buffer[RS_MAX_PACKET_LEN];
+
+if (PreparePacket(buffer, sizeof(buffer), rsu, forceDisconnect))
+    {
+    printfd(__FILE__, "REMOTE_SCRIPT::SendDirect() - Invalid packet length!\n");
+    return true;
+    }
+
+struct sockaddr_in sendAddr;
+
+sendAddr.sin_family = AF_INET;
+sendAddr.sin_port = static_cast<uint16_t>(htons(rsSettings.GetPort()));
+sendAddr.sin_addr.s_addr = routerIP;
+
+ssize_t res = sendto(sock, buffer, sizeof(buffer), 0, (struct sockaddr *)&sendAddr, sizeof(sendAddr));
+
+if (res < 0)
+    logger("sendto error: %s", strerror(errno));
+
+return (res != sizeof(buffer));
+}
+//-----------------------------------------------------------------------------
+bool REMOTE_SCRIPT::GetUsers()
+{
+UserPtr u;
+
+int h = users->OpenSearch();
+assert(h && "USERS::OpenSearch is always correct");
+
+while (!users->SearchNext(h, &u))
+    {
+    SetUserNotifiers(u);
+    }
+
+users->CloseSearch(h);
+return false;
+}
+//-----------------------------------------------------------------------------
+std::vector<uint32_t> REMOTE_SCRIPT::IP2Routers(uint32_t ip)
+{
+STG_LOCKER lock(&mutex);
+for (size_t i = 0; i < netRouters.size(); ++i)
+    {
+    if ((ip & netRouters[i].subnetMask) == (netRouters[i].subnetIP & netRouters[i].subnetMask))
+        {
+        return netRouters[i].routers;
+        }
+    }
+return std::vector<uint32_t>();
+}
+//-----------------------------------------------------------------------------
+void REMOTE_SCRIPT::SetUserNotifiers(UserPtr u)
+{
+ipNotifierList.push_front(RS::IP_NOTIFIER(*this, u));
+connNotifierList.push_front(RS::CONNECTED_NOTIFIER(*this, u));
+}
+//-----------------------------------------------------------------------------
+void REMOTE_SCRIPT::UnSetUserNotifiers(UserPtr u)
+{
+ipNotifierList.erase(std::remove_if(ipNotifierList.begin(),
+                                    ipNotifierList.end(),
+                                    USER_IS<IP_NOTIFIER>(u)),
+                     ipNotifierList.end());
+connNotifierList.erase(std::remove_if(connNotifierList.begin(),
+                                      connNotifierList.end(),
+                                      USER_IS<CONNECTED_NOTIFIER>(u)),
+                       connNotifierList.end());
+
+}
+//-----------------------------------------------------------------------------
+void REMOTE_SCRIPT::AddRSU(UserPtr user)
+{
+RS::USER rsu(IP2Routers(user->GetCurrIP()), user);
+Send(rsu);
+
+STG_LOCKER lock(&mutex);
+authorizedUsers.insert(std::make_pair(user->GetCurrIP(), rsu));
+}
+//-----------------------------------------------------------------------------
+void REMOTE_SCRIPT::DelRSU(UserPtr user)
+{
+STG_LOCKER lock(&mutex);
+std::map<uint32_t, RS::USER>::iterator it(authorizedUsers.begin());
+while (it != authorizedUsers.end())
+    {
+    if (it->second.user == user)
+        {
+        Send(it->second, true);
+        authorizedUsers.erase(it);
+        return;
+        }
+    ++it;
+    }
+/*const std::map<uint32_t, RS::USER>::iterator it(
+        authorizedUsers.find(user->GetCurrIP())
+        );
+if (it != authorizedUsers.end())
+    {
+    Send(it->second, true);
+    authorizedUsers.erase(it);
+    }*/
+}
+//-----------------------------------------------------------------------------
+void RS::IP_NOTIFIER::Notify(const uint32_t & /*oldValue*/, const uint32_t & newValue)
+{
+if (newValue)
+    rs.AddRSU(user);
+else
+    rs.DelRSU(user);
+}
+//-----------------------------------------------------------------------------
+void RS::CONNECTED_NOTIFIER::Notify(const bool & /*oldValue*/, const bool & newValue)
+{
+if (newValue)
+    rs.AddRSU(user);
+else
+    rs.DelRSU(user);
+}
+//-----------------------------------------------------------------------------
+void REMOTE_SCRIPT::InitEncrypt(BLOWFISH_CTX * ctx, const std::string & password) const
+{
+unsigned char keyL[PASSWD_LEN];  // Пароль для шифровки
+memset(keyL, 0, PASSWD_LEN);
+strncpy((char *)keyL, password.c_str(), PASSWD_LEN);
+Blowfish_Init(ctx, keyL, PASSWD_LEN);
+}
+//-----------------------------------------------------------------------------
+void REMOTE_SCRIPT::Encrypt(BLOWFISH_CTX * ctx, void * dst, const void * src, size_t len8) const
+{
+if (dst != src)
+    memcpy(dst, src, len8 * 8);
+for (size_t i = 0; i < len8; ++i)
+    Blowfish_Encrypt(ctx, static_cast<uint32_t *>(dst) + i * 2, static_cast<uint32_t *>(dst) + i * 2 + 1);
+}
+//-----------------------------------------------------------------------------
diff --git a/projects/stargazer/plugins/other/rscript/rscript.h b/projects/stargazer/plugins/other/rscript/rscript.h
new file mode 100644 (file)
index 0000000..e734227
--- /dev/null
@@ -0,0 +1,277 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#pragma once
+
+#include "stg/plugin.h"
+#include "stg/module_settings.h"
+#include "stg/notifer.h"
+#include "stg/user.h"
+#include "stg/blowfish.h"
+#include "stg/rs_packets.h"
+#include "stg/logger.h"
+
+#include "nrmap_parser.h"
+
+#include <string>
+#include <list>
+#include <map>
+#include <functional>
+#include <utility>
+#include <cstdint>
+
+#include <pthread.h>
+
+namespace STG
+{
+struct Settings;
+struct Settings;
+}
+
+namespace RS
+{
+
+class REMOTE_SCRIPT;
+class UpdateRouter;
+class DisconnectUser;
+
+using UserPtr = STG::User*;
+
+//-----------------------------------------------------------------------------
+class ADD_USER_NONIFIER: public STG::NotifierBase<UserPtr> {
+public:
+    explicit ADD_USER_NONIFIER(REMOTE_SCRIPT & r)
+        : rs(r) {}
+    void Notify(const UserPtr & user);
+
+private:
+    ADD_USER_NONIFIER(const ADD_USER_NONIFIER & rhs);
+    ADD_USER_NONIFIER & operator=(const ADD_USER_NONIFIER);
+
+    REMOTE_SCRIPT & rs;
+};
+//-----------------------------------------------------------------------------
+class DEL_USER_NONIFIER: public STG::NotifierBase<UserPtr> {
+public:
+    explicit DEL_USER_NONIFIER(REMOTE_SCRIPT & r)
+        : rs(r) {}
+    void Notify(const UserPtr & user);
+
+private:
+    DEL_USER_NONIFIER(const DEL_USER_NONIFIER & rhs);
+    DEL_USER_NONIFIER & operator=(const DEL_USER_NONIFIER);
+
+    REMOTE_SCRIPT & rs;
+};
+//-----------------------------------------------------------------------------
+class IP_NOTIFIER: public STG::PropertyNotifierBase<uint32_t> {
+public:
+    IP_NOTIFIER(REMOTE_SCRIPT & r, UserPtr u)
+        : user(u), rs(r) { user->AddCurrIPAfterNotifier(this); }
+    IP_NOTIFIER(const IP_NOTIFIER & rhs)
+        : user(rhs.user), rs(rhs.rs) { user->AddCurrIPAfterNotifier(this); }
+    ~IP_NOTIFIER() { user->DelCurrIPAfterNotifier(this); }
+
+    IP_NOTIFIER & operator=(const IP_NOTIFIER & rhs)
+    {
+        user->DelCurrIPAfterNotifier(this);
+        user = rhs.user;
+        user->AddCurrIPAfterNotifier(this);
+        return *this;
+    }
+
+    void Notify(const uint32_t & oldValue, const uint32_t & newValue);
+    UserPtr GetUser() const { return user; }
+
+private:
+
+    UserPtr user;
+    REMOTE_SCRIPT & rs;
+};
+//-----------------------------------------------------------------------------
+class CONNECTED_NOTIFIER: public STG::PropertyNotifierBase<bool> {
+public:
+    CONNECTED_NOTIFIER(REMOTE_SCRIPT & r, UserPtr u)
+        : user(u), rs(r) { user->AddConnectedAfterNotifier(this); }
+    CONNECTED_NOTIFIER(const CONNECTED_NOTIFIER & rhs)
+        : user(rhs.user), rs(rhs.rs) { user->AddConnectedAfterNotifier(this); }
+    ~CONNECTED_NOTIFIER() { user->DelConnectedAfterNotifier(this); }
+
+    CONNECTED_NOTIFIER & operator=(const CONNECTED_NOTIFIER & rhs)
+    {
+        user->DelConnectedAfterNotifier(this);
+        user = rhs.user;
+        user->AddConnectedAfterNotifier(this);
+        return *this;
+    }
+
+    void Notify(const bool & oldValue, const bool & newValue);
+    UserPtr GetUser() const { return user; }
+
+private:
+
+    UserPtr user;
+    REMOTE_SCRIPT & rs;
+};
+//-----------------------------------------------------------------------------
+struct USER {
+    USER(const std::vector<uint32_t> & r, UserPtr it)
+        : lastSentTime(0),
+          user(it),
+          routers(r),
+          shortPacketsCount(0),
+          ip(user->GetCurrIP())
+    {}
+
+    time_t lastSentTime;
+    UserPtr user;
+    std::vector<uint32_t> routers;
+    int shortPacketsCount;
+    uint32_t ip;
+};
+//-----------------------------------------------------------------------------
+class SETTINGS {
+public:
+                        SETTINGS();
+    virtual             ~SETTINGS() {}
+    const std::string & GetStrError() const { return errorStr; }
+    int                 ParseSettings(const STG::ModuleSettings & s);
+    int                 GetSendPeriod() const { return sendPeriod; }
+    uint16_t            GetPort() const { return port; }
+    const std::vector<NET_ROUTER> & GetSubnetsMap() const { return netRouters; }
+    const std::vector<std::string> & GetUserParams() const { return userParams; }
+    const std::string & GetPassword() const { return password; }
+    const std::string & GetMapFileName() const { return subnetFile; }
+
+private:
+    int                 sendPeriod;
+    uint16_t            port;
+    std::string         errorStr;
+    std::vector<NET_ROUTER> netRouters;
+    std::vector<std::string> userParams;
+    std::string         password;
+    std::string         subnetFile;
+};
+//-----------------------------------------------------------------------------
+class REMOTE_SCRIPT : public STG::Plugin {
+public:
+                        REMOTE_SCRIPT();
+                        ~REMOTE_SCRIPT() override;
+
+    void                SetUsers(STG::Users * u) override { users = u; }
+    void                SetSettings(const STG::ModuleSettings & s) override { settings = s; }
+    int                 ParseSettings() override;
+
+    int                 Start() override;
+    int                 Stop() override;
+    int                 Reload(const STG::ModuleSettings & ms) override;
+    bool                IsRunning() override { return isRunning; }
+
+    const std::string & GetStrError() const override { return errorStr; }
+    std::string         GetVersion() const override { return "Remote script v 0.3"; }
+    uint16_t            GetStartPosition() const override { return 10; }
+    uint16_t            GetStopPosition() const override { return 10; }
+
+    void                DelUser(UserPtr u) { UnSetUserNotifiers(u); }
+    void                AddUser(UserPtr u) { SetUserNotifiers(u); }
+
+    void                AddRSU(UserPtr user);
+    void                DelRSU(UserPtr user);
+
+private:
+    REMOTE_SCRIPT(const REMOTE_SCRIPT & rhs);
+    REMOTE_SCRIPT & operator=(const REMOTE_SCRIPT & rhs);
+
+    static void *       Run(void *);
+    bool                PrepareNet();
+    bool                FinalizeNet();
+
+    bool                Send(USER & rsu, bool forceDisconnect = false) const;
+    bool                SendDirect(USER & rsu, uint32_t routerIP, bool forceDisconnect = false) const;
+    bool                PreparePacket(char * buf, size_t bufSize, USER &rsu, bool forceDisconnect = false) const;
+    void                PeriodicSend();
+
+    std::vector<uint32_t> IP2Routers(uint32_t ip);
+    bool                GetUsers();
+
+    void                SetUserNotifiers(UserPtr u);
+    void                UnSetUserNotifiers(UserPtr u);
+
+    void                InitEncrypt(BLOWFISH_CTX * ctx, const std::string & password) const;
+    void                Encrypt(BLOWFISH_CTX * ctx, void * dst, const void * src, size_t len8) const;
+
+    mutable BLOWFISH_CTX ctx;
+
+    std::list<IP_NOTIFIER> ipNotifierList;
+    std::list<CONNECTED_NOTIFIER> connNotifierList;
+    std::map<uint32_t, USER> authorizedUsers;
+
+    mutable std::string errorStr;
+    SETTINGS         rsSettings;
+    STG::ModuleSettings     settings;
+    int                 sendPeriod;
+    int                 halfPeriod;
+
+    bool                nonstop;
+    bool                isRunning;
+
+    STG::Users *             users;
+
+    std::vector<NET_ROUTER> netRouters;
+
+    pthread_t           thread;
+    pthread_mutex_t     mutex;
+
+    int                 sock;
+
+    ADD_USER_NONIFIER onAddUserNotifier;
+    DEL_USER_NONIFIER onDelUserNotifier;
+
+    STG::PluginLogger       logger;
+
+    friend class RS::UpdateRouter;
+    friend class RS::DisconnectUser;
+    friend class RS::CONNECTED_NOTIFIER;
+};
+//-----------------------------------------------------------------------------
+class DisconnectUser : public std::unary_function<std::pair<const uint32_t, USER> &, void> {
+    public:
+        explicit DisconnectUser(REMOTE_SCRIPT & rs) : rscript(rs) {}
+        void operator()(std::pair<const uint32_t, USER> & p)
+        {
+            rscript.Send(p.second, true);
+        }
+    private:
+        REMOTE_SCRIPT & rscript;
+};
+//-----------------------------------------------------------------------------
+inline void ADD_USER_NONIFIER::Notify(const UserPtr & user)
+{
+rs.AddUser(user);
+}
+//-----------------------------------------------------------------------------
+inline void DEL_USER_NONIFIER::Notify(const UserPtr & user)
+{
+rs.DelUser(user);
+}
+//-----------------------------------------------------------------------------
+
+} // namespace RS
diff --git a/projects/stargazer/plugins/other/rscript/send_functor.h b/projects/stargazer/plugins/other/rscript/send_functor.h
new file mode 100644 (file)
index 0000000..fbe6d3b
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+/*
+ $Revision: 1.2 $
+ $Date: 2010/03/04 12:11:09 $
+ $Author: faust $
+*/
+
+#ifndef __SEND_FUNCTOR_H__
+#define __SEND_FUNCTOR_H__
+
+#include <functional>
+#include <cstdint>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+
+class PacketSender : public std::unary_function<uint32_t, ssize_t> {
+    public:
+        PacketSender(int s, char * b, size_t l, uint16_t p)
+            : sock(s),
+              buffer(b),
+              length(l),
+              port(p) {}
+        ssize_t operator() (uint32_t ip)
+        {
+        struct sockaddr_in sendAddr;
+
+        sendAddr.sin_family = AF_INET;
+        sendAddr.sin_port = port;
+        sendAddr.sin_addr.s_addr = ip;
+
+        return sendto(sock, buffer, length, 0, (struct sockaddr*)&sendAddr, sizeof(sendAddr));
+        }
+    private:
+        int sock;
+        char * buffer;
+        size_t length;
+        uint16_t port;
+};
+
+#endif
diff --git a/projects/stargazer/plugins/other/rscript/ur_functor.h b/projects/stargazer/plugins/other/rscript/ur_functor.h
new file mode 100644 (file)
index 0000000..95b03ea
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#ifndef __UR_FUNCTOR_H__
+#define __UR_FUNCTOR_H__
+
+#include "rscript.h"
+
+#include "stg/common.h"
+
+#include <functional>
+#include <algorithm>
+#include <utility>
+#include <cstdint>
+
+namespace RS
+{
+
+class UpdateRouter : public std::unary_function<std::pair<const uint32_t, RS::USER>, void>
+{
+public:
+    explicit UpdateRouter(REMOTE_SCRIPT & t)
+        : obj(t) {}
+
+    void operator() (std::pair<const uint32_t, USER> & val)
+        {
+        std::vector<uint32_t> newRouters = obj.IP2Routers(val.second.ip);
+        std::vector<uint32_t>::const_iterator oldIt(val.second.routers.begin());
+        std::vector<uint32_t>::const_iterator newIt(newRouters.begin());
+        val.second.shortPacketsCount = 0;
+        while (oldIt != val.second.routers.end() ||
+               newIt != newRouters.end())
+            {
+            if (oldIt == val.second.routers.end())
+                {
+                if (newIt != newRouters.end())
+                    {
+                    obj.SendDirect(val.second, *newIt); // Connect on new router
+                    ++newIt;
+                    }
+                }
+            else if (newIt == newRouters.end())
+                {
+                obj.SendDirect(val.second, *oldIt, true); // Disconnect on old router
+                ++oldIt;
+                }
+            else if (*oldIt < *newIt)
+                {
+                obj.SendDirect(val.second, *oldIt, true); // Disconnect on old router
+                ++oldIt;
+                }
+            else if (*oldIt > *newIt)
+                {
+                obj.SendDirect(val.second, *newIt); // Connect on new router
+                ++newIt;
+                }
+            else
+                {
+                ++oldIt;
+                if (newIt != newRouters.end())
+                    ++newIt;
+                }
+            }
+        val.second.routers = newRouters;
+        }
+private:
+    REMOTE_SCRIPT & obj;
+};
+
+} // namespace RS
+
+#endif
diff --git a/projects/stargazer/plugins/other/smux/STG-MIB.mib b/projects/stargazer/plugins/other/smux/STG-MIB.mib
new file mode 100644 (file)
index 0000000..bccf5a2
--- /dev/null
@@ -0,0 +1,231 @@
+STG-MIB DEFINITIONS ::= BEGIN
+
+IMPORTS
+    enterprises,
+    MODULE-IDENTITY, OBJECT-TYPE,
+    Integer32                       FROM SNMPv2-SMI
+    DisplayString                   FROM SNMPv2-TC;
+
+stgMIB MODULE-IDENTITY
+    LAST-UPDATED "201101060000Z"
+    ORGANIZATION "STG"
+    CONTACT-INFO    
+        "Primary Contact: Maxim Mamontov
+         email:     faust@stg.dp.ua"
+    DESCRIPTION
+        "This MIB module defines objects for Stargazer data."
+    REVISION     "201101060000Z"
+    DESCRIPTION "Initial revision"
+    ::= { enterprises 38313 }
+
+stg24 OBJECT IDENTIFIER ::= { stgMIB 1 }
+
+users OBJECT IDENTIFIER ::= { stg24 1 }
+tariffs OBJECT IDENTIFIER ::= { stg24 2 }
+admins OBJECT IDENTIFIER ::= { stg24 3 }
+services OBJECT IDENTIFIER ::= { stg24 4 }
+corporations OBJECT IDENTIFIER ::= { stg24 5 }
+traffcounter OBJECT IDENTIFIER ::= { stg24 6 }
+
+totalUsers OBJECT-TYPE
+    SYNTAX      Integer32
+    MAX-ACCESS  read-only
+    STATUS      current
+    DESCRIPTION
+       "Total users registered in the billing"
+    DEFVAL { 0 }
+    ::= { users 1 }
+
+onlineUsers OBJECT-TYPE
+    SYNTAX      Integer32
+    MAX-ACCESS  read-only
+    STATUS      current
+    DESCRIPTION
+       "The number of currently online users"
+    DEFVAL { 0 }
+    ::= { users 2 }
+
+authorizedUsers OBJECT-TYPE
+    SYNTAX      Integer32
+    MAX-ACCESS  read-only
+    STATUS      current
+    DESCRIPTION
+       "The number of currently authorized users"
+    DEFVAL { 0 }
+    ::= { users 3 }
+
+alwaysOnlineUsers OBJECT-TYPE
+    SYNTAX      Integer32
+    MAX-ACCESS  read-only
+    STATUS      current
+    DESCRIPTION
+       "The number of users with 'always online' option"
+    DEFVAL { 0 }
+    ::= { users 4 }
+
+noCashUsers OBJECT-TYPE
+    SYNTAX      Integer32
+    MAX-ACCESS  read-only
+    STATUS      current
+    DESCRIPTION
+       "The number of users with negative cash"
+    DEFVAL { 0 }
+    ::= { users 5 }
+
+disabledDetailStatsUsers OBJECT-TYPE
+    SYNTAX      Integer32
+    MAX-ACCESS  read-only
+    STATUS      current
+    DESCRIPTION
+       "The number of users with disabled detail stats"
+    DEFVAL { 0 }
+    ::= { users 6 }
+
+disabledUsers OBJECT-TYPE
+    SYNTAX      Integer32
+    MAX-ACCESS  read-only
+    STATUS      current
+    DESCRIPTION
+       "The number of disabled users"
+    DEFVAL { 0 }
+    ::= { users 7 }
+
+passiveUsers OBJECT-TYPE
+    SYNTAX      Integer32
+    MAX-ACCESS  read-only
+    STATUS      current
+    DESCRIPTION
+       "The number of passive users"
+    DEFVAL { 0 }
+    ::= { users 8 }
+
+creditUsers OBJECT-TYPE
+    SYNTAX      Integer32
+    MAX-ACCESS  read-only
+    STATUS      current
+    DESCRIPTION
+       "The number of users with positive credit"
+    DEFVAL { 0 }
+    ::= { users 9 }
+
+freeMbUsers OBJECT-TYPE
+    SYNTAX      Integer32
+    MAX-ACCESS  read-only
+    STATUS      current
+    DESCRIPTION
+       "The number of users with positive freeMb"
+    DEFVAL { 0 }
+    ::= { users 10 }
+
+tariffChangeUsers OBJECT-TYPE
+    SYNTAX      Integer32
+    MAX-ACCESS  read-only
+    STATUS      current
+    DESCRIPTION
+       "The number of users changing tariff next month"
+    DEFVAL { 0 }
+    ::= { users 11 }
+
+activeUsers OBJECT-TYPE
+    SYNTAX      Integer32
+    MAX-ACCESS  read-only
+    STATUS      current
+    DESCRIPTION
+        "The number of online users with traffic during session"
+    DEFVAL {0}
+    ::= { users 12 }
+
+totalTariffs OBJECT-TYPE
+    SYNTAX      Integer32
+    MAX-ACCESS  read-only
+    STATUS      current
+    DESCRIPTION
+       "Total tariffs registered in the billing"
+    DEFVAL { 0 }
+    ::= { tariffs 1 }
+
+tariffUsageTable OBJECT-TYPE
+    SYNTAX      SEQUENCE OF TariffUsageTable
+    MAX-ACCESS  not-accessible
+    STATUS      current
+    DESCRIPTION
+       "The number of users by each tariff"
+    DEFVAL { 0 }
+    ::= { tariffs 2 }
+
+tariffUsageTableEntry OBJECT-TYPE
+    SYNTAX      TariffUsageTable
+    MAX-ACCESS  not-accessible
+    STATUS      current
+    DESCRIPTION
+        "A row describing a given tariff"
+    INDEX   { tariffIndex }
+    ::= {tariffUsageTable 1 }
+
+TariffUsageTable ::= SEQUENCE {
+    tariffIndex Integer32,
+    tariffName DisplayString,
+    userCount Integer32
+}
+
+tariffIndex OBJECT-TYPE
+    SYNTAX      Integer32 (0..255)
+    MAX-ACCESS  not-accessible
+    STATUS      current
+    DESCRIPTION
+        "The id of the tariff this table describes."
+    ::= { tariffUsageTableEntry 1 }
+
+tariffName OBJECT-TYPE
+    SYNTAX      DisplayString
+    MAX-ACCESS  read-only
+    STATUS      current
+    DESCRIPTION
+        "The name of the tariff this table describes."
+    ::= { tariffUsageTableEntry 2 }
+
+userCount OBJECT-TYPE
+    SYNTAX      Integer32
+    MAX-ACCESS  read-only
+    STATUS      current
+    DESCRIPTION
+        "The count fo users of the tariff this table describes."
+    ::= { tariffUsageTableEntry 3 }
+
+totalAdmins OBJECT-TYPE
+    SYNTAX      Integer32
+    MAX-ACCESS  read-only
+    STATUS      current
+    DESCRIPTION
+       "Total admins registered in the billing"
+    DEFVAL { 0 }
+    ::= { admins 1 }
+
+totalServices OBJECT-TYPE
+    SYNTAX      Integer32
+    MAX-ACCESS  read-only
+    STATUS      current
+    DESCRIPTION
+       "Total services registered in the billing"
+    DEFVAL { 0 }
+    ::= { services 1 }
+
+totalCorporations OBJECT-TYPE
+    SYNTAX      Integer32
+    MAX-ACCESS  read-only
+    STATUS      current
+    DESCRIPTION
+       "Total corporations registered in the billing"
+    DEFVAL { 0 }
+    ::= { corporations 1 }
+
+totalRules OBJECT-TYPE
+    SYNTAX      Integer32
+    MAX-ACCESS  read-only
+    STATUS      current
+    DESCRIPTION
+        "Total traffic classification rules described by rules file"
+    DEFVAL { 0 }
+    ::= { traffcounter 1 }
+
+END
diff --git a/projects/stargazer/plugins/other/smux/TODO b/projects/stargazer/plugins/other/smux/TODO
new file mode 100644 (file)
index 0000000..03dc09d
--- /dev/null
@@ -0,0 +1,14 @@
+Количество пользователей всего в биллинге
+Количество пользователей онлайн
+Количество пользователей с отрицательный балансом
+Количество пользователей с всегда онлайн
+Количество пользователей по отношению к каждому из тарифов
+Количество пользователей по отношению к каждому UserData полю - ?
+Количество пользователей с отключенной детальной статистикой
+Количество отключенных пользователей
+Количество замороженных пользователей
+Количество пользователей, у которых есть кредит
+Количество пользователей, у которых есть предоплаченный трафик
+
+Количество тарифов
+Количество направлений
diff --git a/projects/stargazer/plugins/other/smux/handlers.cpp b/projects/stargazer/plugins/other/smux/handlers.cpp
new file mode 100644 (file)
index 0000000..ac179da
--- /dev/null
@@ -0,0 +1,191 @@
+#include <cassert>
+
+#include "stg/GetRequest-PDU.h"
+#include "stg/GetResponse-PDU.h"
+#include "stg/VarBindList.h"
+#include "stg/VarBind.h"
+
+#include "stg/common.h"
+
+#include "utils.h"
+#include "smux.h"
+
+#ifdef SMUX_DEBUG
+bool SMUX::CloseHandler(const SMUX_PDUs_t * pdus)
+{
+printfd(__FILE__, "SMUX::CloseHandler()\n");
+asn_fprint(stderr, &asn_DEF_SMUX_PDUs, pdus);
+return true;
+}
+#else
+bool SMUX::CloseHandler(const SMUX_PDUs_t *)
+{
+return true;
+}
+#endif
+
+#ifdef SMUX_DEBUG
+bool SMUX::RegisterResponseHandler(const SMUX_PDUs_t * pdus)
+{
+printfd(__FILE__, "SMUX::RegisterResponseHandler()\n");
+asn_fprint(stderr, &asn_DEF_SMUX_PDUs, pdus);
+return true;
+}
+#else
+bool SMUX::RegisterResponseHandler(const SMUX_PDUs_t *)
+{
+return true;
+}
+#endif
+
+bool SMUX::PDUsRequestHandler(const SMUX_PDUs_t * pdus)
+{
+#ifdef SMUX_DEBUG
+printfd(__FILE__, "SMUX::PDUsRequestHandler()\n");
+asn_fprint(stderr, &asn_DEF_SMUX_PDUs, pdus);
+#endif
+PDUsHandlers::iterator it(pdusHandlers.find(pdus->choice.pdus.present));
+if (it != pdusHandlers.end())
+    {
+    return (this->*(it->second))(&pdus->choice.pdus);
+    }
+#ifdef SMUX_DEBUG
+else
+    {
+    switch (pdus->present)
+        {
+        case PDUs_PR_NOTHING:
+            printfd(__FILE__, "SMUX::PDUsRequestHandler() - nothing\n");
+            break;
+        case PDUs_PR_get_response:
+            printfd(__FILE__, "SMUX::PDUsRequestHandler() - get response\n");
+            break;
+        case PDUs_PR_trap:
+            printfd(__FILE__, "SMUX::PDUsRequestHandler() - trap\n");
+            break;
+        default:
+            printfd(__FILE__, "SMUX::PDUsRequestHandler() - undefined\n");
+        }
+    }
+#endif
+return true;
+}
+
+#ifdef SMUX_DEBUG
+bool SMUX::CommitOrRollbackHandler(const SMUX_PDUs_t * pdus)
+{
+printfd(__FILE__, "SMUX::CommitOrRollbackHandler()\n");
+asn_fprint(stderr, &asn_DEF_SMUX_PDUs, pdus);
+return true;
+}
+#else
+bool SMUX::CommitOrRollbackHandler(const SMUX_PDUs_t *)
+{
+return true;
+}
+#endif
+
+bool SMUX::GetRequestHandler(const PDUs_t * pdus)
+{
+#ifdef SMUX_DEBUG
+printfd(__FILE__, "SMUX::GetRequestHandler()\n");
+asn_fprint(stderr, &asn_DEF_PDUs, pdus);
+#endif
+const GetRequest_PDU_t * getRequest = &pdus->choice.get_request;
+GetResponse_PDU_t * msg = static_cast<GetResponse_PDU_t *>(calloc(1, sizeof(GetResponse_PDU_t)));
+assert(msg && "Enought mempry to allocate GetResponse_PDU_t");
+VarBindList_t * varBindList = &msg->variable_bindings;
+
+long id = 0;
+asn_INTEGER2long(&getRequest->request_id, &id);
+asn_long2INTEGER(&msg->request_id, id);
+asn_long2INTEGER(&msg->error_status, 0);
+asn_long2INTEGER(&msg->error_index, 0);
+
+const VarBindList_t * vbl = &getRequest->variable_bindings; 
+for (int i = 0; i < vbl->list.count; ++i)
+    {
+    VarBind_t * vb = getRequest->variable_bindings.list.array[i];
+    Sensors::iterator it;
+    it = sensors.find(OID(&vb->name));
+    if (it == sensors.end())
+        {
+        return SendGetResponseErrorPDU(sock, getRequest,
+                                       PDU__error_status_noSuchName, i);
+        }
+
+    VarBind_t * newVb = static_cast<VarBind_t *>(calloc(1, sizeof(VarBind_t)));
+    assert(newVb && "Enought mempry to allocate VarBind_t");
+
+    it->first.ToOID(&newVb->name);
+    it->second->GetValue(&newVb->value);
+
+    ASN_SEQUENCE_ADD(varBindList, newVb);
+    }
+
+bool res = SendGetResponsePDU(sock, msg);
+#ifdef SMUX_DEBUG
+asn_fprint(stderr, &asn_DEF_GetResponse_PDU, msg);
+#endif
+ASN_STRUCT_FREE(asn_DEF_GetResponse_PDU, msg);
+return res;
+}
+
+bool SMUX::GetNextRequestHandler(const PDUs_t * pdus)
+{
+#ifdef SMUX_DEBUG
+printfd(__FILE__, "SMUX::GetNextRequestHandler()\n");
+asn_fprint(stderr, &asn_DEF_PDUs, pdus);
+#endif
+const GetRequest_PDU_t * getRequest = &pdus->choice.get_request;
+GetResponse_PDU_t * msg = static_cast<GetResponse_PDU_t *>(calloc(1, sizeof(GetResponse_PDU_t)));
+assert(msg && "Enought mempry to allocate GetResponse_PDU_t");
+VarBindList_t * varBindList = &msg->variable_bindings;
+
+long id = 0;
+asn_INTEGER2long(&getRequest->request_id, &id);
+asn_long2INTEGER(&msg->request_id, id);
+asn_long2INTEGER(&msg->error_status, 0);
+asn_long2INTEGER(&msg->error_index, 0);
+
+const VarBindList_t * vbl = &getRequest->variable_bindings; 
+for (int i = 0; i < vbl->list.count; ++i)
+    {
+    VarBind_t * vb = getRequest->variable_bindings.list.array[i];
+    Sensors::iterator it;
+    it = sensors.upper_bound(OID(&vb->name));
+    if (it == sensors.end())
+        {
+#ifdef SMUX_DEBUG
+        printfd(__FILE__, "SMUX::GetNextRequestHandler() - '%s' not found\n", OID(&vb->name).ToString().c_str());
+#endif
+        return SendGetResponseErrorPDU(sock, getRequest,
+                                       PDU__error_status_noSuchName, i);
+        }
+
+    VarBind_t * newVb = static_cast<VarBind_t *>(calloc(1, sizeof(VarBind_t)));
+    assert(newVb && "Enought mempry to allocate VarBind_t");
+
+    it->first.ToOID(&newVb->name);
+    it->second->GetValue(&newVb->value);
+
+    ASN_SEQUENCE_ADD(varBindList, newVb);
+    }
+
+bool res = SendGetResponsePDU(sock, msg);
+#ifdef SMUX_DEBUG
+asn_fprint(stderr, &asn_DEF_PDU, msg);
+#endif
+ASN_STRUCT_FREE(asn_DEF_GetResponse_PDU, msg);
+return res;
+}
+
+bool SMUX::SetRequestHandler(const PDUs_t * pdus)
+{
+#ifdef SMUX_DEBUG
+printfd(__FILE__, "SMUX::SetRequestHandler()\n");
+asn_fprint(stderr, &asn_DEF_PDUs, pdus);
+#endif
+return SendGetResponseErrorPDU(sock, &pdus->choice.set_request,
+                               PDU__error_status_readOnly, 0);
+}
diff --git a/projects/stargazer/plugins/other/smux/pen.h b/projects/stargazer/plugins/other/smux/pen.h
new file mode 100644 (file)
index 0000000..45989bd
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __PEN_H__
+#define __PEN_H__
+
+#define PEN_PREFIX ".1.3.6.1.4.1.38313"
+
+#endif
diff --git a/projects/stargazer/plugins/other/smux/sensors.cpp b/projects/stargazer/plugins/other/smux/sensors.cpp
new file mode 100644 (file)
index 0000000..9a87cbd
--- /dev/null
@@ -0,0 +1,59 @@
+#include <cassert>
+
+#include "stg/INTEGER.h"
+
+#include "stg/user.h"
+
+#include "sensors.h"
+
+bool UsersSensor::GetValue(ObjectSyntax_t * objectSyntax) const
+{
+int handle = users.OpenSearch();
+assert(handle && "USERS::OpenSearch is always correct");
+
+STG::User* user;
+size_t count = 0;
+while (!users.SearchNext(handle, &user))
+    {
+    if (UserPredicate(user))
+        ++count;
+    }
+
+users.CloseSearch(handle);
+
+ValueToOS(count, objectSyntax);
+return true;
+}
+
+#ifdef DEBUG
+std::string UsersSensor::ToString() const
+{
+int handle = users.OpenSearch();
+assert(handle && "USERS::OpenSearch is always correct");
+
+STG::User* user;
+size_t count = 0;
+while (!users.SearchNext(handle, &user))
+    {
+    if (UserPredicate(user))
+        ++count;
+    }
+
+users.CloseSearch(handle);
+
+return std::to_string(count);
+}
+#endif
+
+bool ActiveUsersSensor::UserPredicate(STG::User* userPtr) const
+{
+if (!userPtr->GetConnected())
+    return false;
+for (size_t i = 0; i < DIR_NUM; ++i)
+    {
+    if (userPtr->GetSessionUpload()[i] > 0 ||
+        userPtr->GetSessionDownload()[i] > 0)
+        return true;
+    }
+return false;
+}
diff --git a/projects/stargazer/plugins/other/smux/sensors.h b/projects/stargazer/plugins/other/smux/sensors.h
new file mode 100644 (file)
index 0000000..9215180
--- /dev/null
@@ -0,0 +1,284 @@
+#ifndef __SENSORS_H__
+#define __SENSORS_H__
+
+#include <map>
+
+#include "stg/users.h"
+#include "stg/user.h"
+#include "stg/tariffs.h"
+#include "stg/admins.h"
+#include "stg/services.h"
+#include "stg/corporations.h"
+#include "stg/traffcounter.h"
+#include "stg/user_property.h"
+
+#include "stg/ObjectSyntax.h"
+
+#include "value2os.h"
+#include "types.h"
+
+class Sensor {
+    public:
+        virtual ~Sensor() = default;
+        virtual bool GetValue(ObjectSyntax_t * objectSyntax) const = 0;
+#ifdef DEBUG
+        virtual std::string ToString() const = 0;
+#endif
+};
+
+typedef std::map<OID, Sensor *> Sensors;
+
+class TotalUsersSensor : public Sensor {
+    public:
+        explicit TotalUsersSensor(const STG::Users & u) : users(u) {}
+
+        bool GetValue(ObjectSyntax_t * objectSyntax) const override
+        {
+        ValueToOS(users.Count(), objectSyntax);
+        return true;
+        }
+
+#ifdef DEBUG
+        std::string ToString() const override
+        { std::string res; std::to_string(users.Count(), res); return res; }
+#endif
+
+    private:
+        const STG::Users & users;
+};
+
+class UsersSensor : public Sensor {
+    public:
+        explicit UsersSensor(STG::Users & u) : users(u) {}
+
+        bool GetValue(ObjectSyntax_t * objectSyntax) const override;
+#ifdef DEBUG
+        std::string ToString() const override;
+#endif
+
+    private:
+        STG::Users & users;
+
+        virtual bool UserPredicate(STG::User* userPtr) const = 0;
+};
+
+class ConnectedUsersSensor : public UsersSensor {
+    public:
+        explicit ConnectedUsersSensor(STG::Users & u) : UsersSensor(u) {}
+
+    private:
+        bool UserPredicate(STG::User* userPtr) const override
+        { return userPtr->GetConnected(); }
+};
+
+class AuthorizedUsersSensor : public UsersSensor {
+    public:
+        explicit AuthorizedUsersSensor(STG::Users & u) : UsersSensor(u) {}
+
+    private:
+        bool UserPredicate(STG::User* userPtr) const override
+        { return userPtr->GetAuthorized(); }
+};
+
+class AlwaysOnlineUsersSensor : public UsersSensor {
+    public:
+        explicit AlwaysOnlineUsersSensor(STG::Users & u) : UsersSensor(u) {}
+
+    private:
+        bool UserPredicate(STG::User* userPtr) const override
+        { return userPtr->GetProperties().alwaysOnline; }
+};
+
+class NoCashUsersSensor : public UsersSensor {
+    public:
+        explicit NoCashUsersSensor(STG::Users & u) : UsersSensor(u) {}
+
+    private:
+        bool UserPredicate(STG::User* userPtr) const override
+        { return userPtr->GetProperties().cash < 0; }
+};
+
+class DisabledDetailStatsUsersSensor : public UsersSensor {
+    public:
+        explicit DisabledDetailStatsUsersSensor(STG::Users & u) : UsersSensor(u) {}
+
+    private:
+        bool UserPredicate(STG::User* userPtr) const override
+        { return userPtr->GetProperties().disabledDetailStat; }
+};
+
+class DisabledUsersSensor : public UsersSensor {
+    public:
+        explicit DisabledUsersSensor(STG::Users & u) : UsersSensor(u) {}
+
+    private:
+        bool UserPredicate(STG::User* userPtr) const override
+        { return userPtr->GetProperties().disabled; }
+};
+
+class PassiveUsersSensor : public UsersSensor {
+    public:
+        explicit PassiveUsersSensor(STG::Users & u) : UsersSensor(u) {}
+
+    private:
+        bool UserPredicate(STG::User* userPtr) const override
+        { return userPtr->GetProperties().passive; }
+};
+
+class CreditUsersSensor : public UsersSensor {
+    public:
+        explicit CreditUsersSensor(STG::Users & u) : UsersSensor(u) {}
+
+    private:
+        bool UserPredicate(STG::User* userPtr) const override
+        { return userPtr->GetProperties().credit > 0; }
+};
+
+class FreeMbUsersSensor : public UsersSensor {
+    public:
+        explicit FreeMbUsersSensor(STG::Users & u) : UsersSensor(u) {}
+
+    private:
+        bool UserPredicate(STG::User* userPtr) const override
+        { return userPtr->GetProperties().freeMb > 0; }
+};
+
+class TariffChangeUsersSensor : public UsersSensor {
+    public:
+        explicit TariffChangeUsersSensor(STG::Users & u) : UsersSensor(u) {}
+
+    private:
+        bool UserPredicate(STG::User* userPtr) const override
+        { return !userPtr->GetProperties().nextTariff.ConstData().empty(); }
+};
+
+class ActiveUsersSensor : public UsersSensor {
+    public:
+        explicit ActiveUsersSensor(STG::Users & u) : UsersSensor(u) {}
+
+    private:
+        bool UserPredicate(STG::User* userPtr) const override;
+};
+
+class TotalTariffsSensor : public Sensor {
+    public:
+        explicit TotalTariffsSensor(const STG::Tariffs & t) : tariffs(t) {}
+
+        bool GetValue(ObjectSyntax_t * objectSyntax) const override
+        {
+        ValueToOS(tariffs.Count(), objectSyntax);
+        return true;
+        }
+
+#ifdef DEBUG
+        std::string ToString() const override
+        { std::string res; std::to_string(tariffs.Count(), res); return res; }
+#endif
+
+    private:
+        const STG::Tariffs & tariffs;
+};
+
+class TotalAdminsSensor : public Sensor {
+    public:
+        explicit TotalAdminsSensor(const STG::Admins & a) : admins(a) {}
+
+        bool GetValue(ObjectSyntax_t * objectSyntax) const override
+        {
+        ValueToOS(admins.count(), objectSyntax);
+        return true;
+        }
+
+#ifdef DEBUG
+        std::string ToString() const override
+        { std::string res; std::to_string(admins.Count(), res); return res; }
+#endif
+
+    private:
+        const STG::Admins & admins;
+};
+
+class TotalServicesSensor : public Sensor {
+    public:
+        explicit TotalServicesSensor(const STG::Services & s) : services(s) {}
+
+        bool GetValue(ObjectSyntax_t * objectSyntax) const override
+        {
+        ValueToOS(services.Count(), objectSyntax);
+        return true;
+        }
+
+#ifdef DEBUG
+        std::string ToString() const override
+        { std::string res; std::to_string(services.Count(), res); return res; }
+#endif
+
+    private:
+        const STG::Services & services;
+};
+
+class TotalCorporationsSensor : public Sensor {
+    public:
+        explicit TotalCorporationsSensor(const STG::Corporations & c) : corporations(c) {}
+
+        bool GetValue(ObjectSyntax_t * objectSyntax) const override
+        {
+        ValueToOS(corporations.Count(), objectSyntax);
+        return true;
+        }
+
+#ifdef DEBUG
+        std::string ToString() const override
+        { std::string res; std::to_string(corporations.Count(), res); return res; }
+#endif
+
+    private:
+        const STG::Corporations & corporations;
+};
+
+class TotalRulesSensor : public Sensor {
+    public:
+        explicit TotalRulesSensor(const STG::TraffCounter & t) : traffcounter(t) {}
+
+        bool GetValue(ObjectSyntax_t * objectSyntax) const override
+        {
+        ValueToOS(traffcounter.rulesCount(), objectSyntax);
+        return true;
+        }
+
+#ifdef DEBUG
+        std::string ToString() const override
+        { std::string res; std::to_string(traffcounter.rulesCount(), res); return res; }
+#endif
+
+    private:
+        const STG::TraffCounter & traffcounter;
+};
+
+template <typename T>
+class ConstSensor : public Sensor {
+    public:
+        explicit ConstSensor(const T & v) : value(v) {}
+
+        bool GetValue(ObjectSyntax * objectSyntax) const override
+        { return ValueToOS(value, objectSyntax); }
+
+#ifdef DEBUG
+        std::string ToString() const override
+        { std::string res; std::to_string(value, res); return res; }
+#endif
+
+    private:
+        T value;
+};
+
+#ifdef DEBUG
+template <>
+inline
+std::string ConstSensor<std::string>::ToString() const
+{
+return value;
+}
+#endif
+
+#endif
diff --git a/projects/stargazer/plugins/other/smux/smux.cpp b/projects/stargazer/plugins/other/smux/smux.cpp
new file mode 100644 (file)
index 0000000..c74aeae
--- /dev/null
@@ -0,0 +1,512 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+#include <cstring>
+#include <cerrno>
+#include <ctime>
+#include <csignal>
+#include <cassert>
+
+#include <vector>
+#include <algorithm>
+#include <iterator>
+#include <stdexcept>
+#include <utility>
+
+#include "stg/common.h"
+
+#include "smux.h"
+#include "utils.h"
+
+namespace
+{
+
+bool SPrefixLess(const Sensors::value_type & a,
+                 const Sensors::value_type & b)
+{
+return a.first.PrefixLess(b.first);
+}
+
+}
+
+extern "C" STG::Plugin* GetPlugin()
+{
+    static SMUX plugin;
+    return &plugin;
+}
+
+SMUX_SETTINGS::SMUX_SETTINGS()
+    : errorStr(),
+      ip(0),
+      port(0),
+      password()
+{}
+
+int SMUX_SETTINGS::ParseSettings(const STG::ModuleSettings & s)
+{
+STG::ParamValue pv;
+std::vector<STG::ParamValue>::const_iterator pvi;
+int p;
+
+pv.param = "Port";
+pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end() || pvi->value.empty())
+    {
+    errorStr = "Parameter \'Port\' not found.";
+    printfd(__FILE__, "Parameter 'Port' not found\n");
+    return -1;
+    }
+if (ParseIntInRange(pvi->value[0], 2, 65535, &p))
+    {
+    errorStr = "Cannot parse parameter \'Port\': " + errorStr;
+    printfd(__FILE__, "Cannot parse parameter 'Port'\n");
+    return -1;
+    }
+port = static_cast<uint16_t>(p);
+
+pv.param = "Password";
+pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end() || pvi->value.empty())
+    {
+    errorStr = "Parameter \'Password\' not found.";
+    printfd(__FILE__, "Parameter 'Password' not found\n");
+    password = "";
+    }
+else
+    {
+    password = pvi->value[0];
+    }
+
+pv.param = "Server";
+pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end() || pvi->value.empty())
+    {
+    errorStr = "Parameter \'Server\' not found.";
+    printfd(__FILE__, "Parameter 'Server' not found\n");
+    return -1;
+    }
+ip = inet_strington(pvi->value[0]);
+
+return 0;
+}
+
+SMUX::SMUX()
+    : users(NULL),
+      tariffs(NULL),
+      admins(NULL),
+      services(NULL),
+      corporations(NULL),
+      traffcounter(NULL),
+      running(false),
+      stopped(true),
+      needReconnect(false),
+      lastReconnectTry(0),
+      reconnectTimeout(1),
+      sock(-1),
+      addUserNotifier(*this),
+      delUserNotifier(*this),
+      addDelTariffNotifier(*this),
+      logger(STG::PluginLogger::get("smux"))
+{
+pthread_mutex_init(&mutex, NULL);
+
+smuxHandlers[SMUX_PDUs_PR_close] = &SMUX::CloseHandler;
+smuxHandlers[SMUX_PDUs_PR_registerResponse] = &SMUX::RegisterResponseHandler;
+smuxHandlers[SMUX_PDUs_PR_pdus] = &SMUX::PDUsRequestHandler;
+smuxHandlers[SMUX_PDUs_PR_commitOrRollback] = &SMUX::CommitOrRollbackHandler;
+
+pdusHandlers[PDUs_PR_get_request] = &SMUX::GetRequestHandler;
+pdusHandlers[PDUs_PR_get_next_request] = &SMUX::GetNextRequestHandler;
+pdusHandlers[PDUs_PR_set_request] = &SMUX::SetRequestHandler;
+}
+
+SMUX::~SMUX()
+{
+    {
+    Sensors::iterator it;
+    for (it = sensors.begin(); it != sensors.end(); ++it)
+        delete it->second;
+    }
+    {
+    Tables::iterator it;
+    for (it = tables.begin(); it != tables.end(); ++it)
+        delete it->second;
+    }
+printfd(__FILE__, "SMUX::~SMUX()\n");
+pthread_mutex_destroy(&mutex);
+}
+
+int SMUX::ParseSettings()
+{
+return smuxSettings.ParseSettings(settings);
+}
+
+int SMUX::Start()
+{
+assert(users != NULL && "users must not be NULL");
+assert(tariffs != NULL && "tariffs must not be NULL");
+assert(admins != NULL && "admins must not be NULL");
+assert(services != NULL && "services must not be NULL");
+assert(corporations != NULL && "corporations must not be NULL");
+assert(traffcounter != NULL && "traffcounter must not be NULL");
+
+if (PrepareNet())
+    needReconnect = true;
+
+// Users
+sensors[OID(".1.3.6.1.4.1.38313.1.1.1")] = new TotalUsersSensor(*users);
+sensors[OID(".1.3.6.1.4.1.38313.1.1.2")] = new ConnectedUsersSensor(*users);
+sensors[OID(".1.3.6.1.4.1.38313.1.1.3")] = new AuthorizedUsersSensor(*users);
+sensors[OID(".1.3.6.1.4.1.38313.1.1.4")] = new AlwaysOnlineUsersSensor(*users);
+sensors[OID(".1.3.6.1.4.1.38313.1.1.5")] = new NoCashUsersSensor(*users);
+sensors[OID(".1.3.6.1.4.1.38313.1.1.6")] = new DisabledDetailStatsUsersSensor(*users);
+sensors[OID(".1.3.6.1.4.1.38313.1.1.7")] = new DisabledUsersSensor(*users);
+sensors[OID(".1.3.6.1.4.1.38313.1.1.8")] = new PassiveUsersSensor(*users);
+sensors[OID(".1.3.6.1.4.1.38313.1.1.9")] = new CreditUsersSensor(*users);
+sensors[OID(".1.3.6.1.4.1.38313.1.1.10")] = new FreeMbUsersSensor(*users);
+sensors[OID(".1.3.6.1.4.1.38313.1.1.11")] = new TariffChangeUsersSensor(*users);
+sensors[OID(".1.3.6.1.4.1.38313.1.1.12")] = new ActiveUsersSensor(*users);
+// Tariffs
+sensors[OID(".1.3.6.1.4.1.38313.1.2.1")] = new TotalTariffsSensor(*tariffs);
+// Admins
+sensors[OID(".1.3.6.1.4.1.38313.1.3.1")] = new TotalAdminsSensor(*admins);
+// Services
+sensors[OID(".1.3.6.1.4.1.38313.1.4.1")] = new TotalServicesSensor(*services);
+// Corporations
+sensors[OID(".1.3.6.1.4.1.38313.1.5.1")] = new TotalCorporationsSensor(*corporations);
+// Traffcounter
+sensors[OID(".1.3.6.1.4.1.38313.1.6.1")] = new TotalRulesSensor(*traffcounter);
+
+// Table data
+tables[".1.3.6.1.4.1.38313.1.2.2"] = new TariffUsersTable(".1.3.6.1.4.1.38313.1.2.2", *tariffs, *users);
+
+UpdateTables();
+SetNotifiers();
+
+#ifdef SMUX_DEBUG
+Sensors::const_iterator it(sensors.begin());
+while (it != sensors.end())
+    {
+    printfd(__FILE__, "%s = %s\n",
+            it->first.ToString().c_str(),
+            it->second->ToString().c_str());
+    ++it;
+    }
+#endif
+
+if (!running)
+    {
+    if (pthread_create(&thread, NULL, Runner, this))
+        {
+        errorStr = "Cannot create thread.";
+       logger("Cannot create thread.");
+        printfd(__FILE__, "Cannot create thread\n");
+        return -1;
+        }
+    }
+
+return 0;
+}
+
+int SMUX::Stop()
+{
+printfd(__FILE__, "SMUX::Stop() - Before\n");
+running = false;
+
+if (!stopped)
+    {
+    //5 seconds to thread stops itself
+    for (int i = 0; i < 25 && !stopped; i++)
+        {
+        struct timespec ts = {0, 200000000};
+        nanosleep(&ts, NULL);
+        }
+    }
+
+if (stopped)
+    pthread_join(thread, NULL);
+
+ResetNotifiers();
+
+    {
+    Tables::iterator it;
+    for (it = tables.begin(); it != tables.end(); ++it)
+        delete it->second;
+    }
+    {
+    Sensors::iterator it;
+    for (it = sensors.begin(); it != sensors.end(); ++it)
+        delete it->second;
+    }
+
+tables.erase(tables.begin(), tables.end());
+sensors.erase(sensors.begin(), sensors.end());
+
+close(sock);
+
+if (!stopped)
+    {
+    running = true;
+    return -1;
+    }
+
+printfd(__FILE__, "SMUX::Stop() - After\n");
+return 0;
+}
+
+int SMUX::Reload(const STG::ModuleSettings & /*ms*/)
+{
+if (Stop())
+    return -1;
+if (Start())
+    return -1;
+if (!needReconnect)
+    {
+    printfd(__FILE__, "SMUX reconnected succesfully.\n");
+    logger("Reconnected successfully.");
+    }
+return 0;
+}
+
+void * SMUX::Runner(void * d)
+{
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+SMUX * smux = static_cast<SMUX *>(d);
+
+smux->Run();
+
+return NULL;
+}
+
+void SMUX::Run()
+{
+stopped = true;
+if (!SendOpenPDU(sock))
+    needReconnect = true;
+if (!SendRReqPDU(sock))
+    needReconnect = true;
+running = true;
+stopped = false;
+
+while(running)
+    {
+    if (WaitPackets(sock) && !needReconnect)
+        {
+        SMUX_PDUs_t * pdus = RecvSMUXPDUs(sock);
+        if (pdus)
+            {
+            DispatchPDUs(pdus);
+            ASN_STRUCT_FREE(asn_DEF_SMUX_PDUs, pdus);
+            }
+        else if (running)
+            Reconnect();
+        }
+    else if (running && needReconnect)
+        Reconnect();
+    if (!running)
+        break;
+    }
+SendClosePDU(sock);
+stopped = true;
+}
+
+bool SMUX::PrepareNet()
+{
+sock = socket(AF_INET, SOCK_STREAM, 0);
+
+if (sock < 0)
+    {
+    errorStr = "Cannot create socket.";
+    logger("Cannot create a socket: %s", strerror(errno));
+    printfd(__FILE__, "Cannot create socket\n");
+    return true;
+    }
+
+struct sockaddr_in addr;
+
+addr.sin_family = AF_INET;
+addr.sin_port = htons(smuxSettings.GetPort());
+addr.sin_addr.s_addr = smuxSettings.GetIP();
+
+if (connect(sock, reinterpret_cast<struct sockaddr *>(&addr), sizeof(addr)))
+    {
+    errorStr = "Cannot connect.";
+    logger("Cannot connect the socket: %s", strerror(errno));
+    printfd(__FILE__, "Cannot connect. Message: '%s'\n", strerror(errno));
+    return true;
+    }
+
+return false;
+}
+
+bool SMUX::Reconnect()
+{
+if (needReconnect && difftime(time(NULL), lastReconnectTry) < reconnectTimeout)
+    return true;
+
+time(&lastReconnectTry);
+SendClosePDU(sock);
+close(sock);
+if (!PrepareNet())
+    if (SendOpenPDU(sock))
+        if (SendRReqPDU(sock))
+            {
+            reconnectTimeout = 1;
+            needReconnect = false;
+            logger("Connected successfully");
+            printfd(__FILE__, "Connected successfully\n");
+            return false;
+            }
+
+if (needReconnect)
+    if (reconnectTimeout < 60)
+        reconnectTimeout *= 2;
+
+needReconnect = true;
+return true;
+}
+
+bool SMUX::DispatchPDUs(const SMUX_PDUs_t * pdus)
+{
+SMUXHandlers::iterator it(smuxHandlers.find(pdus->present));
+if (it != smuxHandlers.end())
+    {
+    return (this->*(it->second))(pdus);
+    }
+#ifdef SMUX_DEBUG
+else
+    {
+    switch (pdus->present)
+        {
+        case SMUX_PDUs_PR_NOTHING:
+            printfd(__FILE__, "PDUs: nothing\n");
+            break;
+        case SMUX_PDUs_PR_open:
+            printfd(__FILE__, "PDUs: open\n");
+            break;
+        case SMUX_PDUs_PR_registerRequest:
+            printfd(__FILE__, "PDUs: registerRequest\n");
+            break;
+        default:
+            printfd(__FILE__, "PDUs: undefined\n");
+        }
+    asn_fprint(stderr, &asn_DEF_SMUX_PDUs, pdus);
+    }
+#endif
+return false;
+}
+
+bool SMUX::UpdateTables()
+{
+Sensors newSensors;
+bool done = true;
+Tables::iterator it(tables.begin());
+while (it != tables.end())
+    {
+    try
+        {
+        it->second->UpdateSensors(newSensors);
+        }
+    catch (const std::runtime_error & ex)
+        {
+        printfd(__FILE__,
+                "SMUX::UpdateTables - failed to update table '%s': '%s'\n",
+                it->first.c_str(), ex.what());
+        done = false;
+        break;
+        }
+    ++it;
+    }
+if (!done)
+    {
+    Sensors::iterator it(newSensors.begin());
+    while (it != newSensors.end())
+        {
+        delete it->second;
+        ++it;
+        }
+    return false;
+    }
+
+it = tables.begin();
+while (it != tables.end())
+    {
+    std::pair<Sensors::iterator, Sensors::iterator> res;
+    res = std::equal_range(sensors.begin(),
+                           sensors.end(),
+                           std::pair<OID, Sensor *>(OID(it->first), NULL),
+                           SPrefixLess);
+    Sensors::iterator sit(res.first);
+    while (sit != res.second)
+        {
+        delete sit->second;
+        ++sit;
+        }
+    sensors.erase(res.first, res.second);
+    ++it;
+    }
+
+sensors.insert(newSensors.begin(), newSensors.end());
+
+return true;
+}
+
+void SMUX::SetNotifier(UserPtr userPtr)
+{
+notifiers.push_back(CHG_AFTER_NOTIFIER(*this, userPtr));
+userPtr->GetProperties().tariffName.AddAfterNotifier(&notifiers.back());
+}
+
+void SMUX::UnsetNotifier(UserPtr userPtr)
+{
+std::list<CHG_AFTER_NOTIFIER>::iterator it = notifiers.begin();
+while (it != notifiers.end())
+    {
+    if (it->GetUserPtr() == userPtr)
+        {
+        userPtr->GetProperties().tariffName.DelAfterNotifier(&(*it));
+        notifiers.erase(it);
+        break;
+        }
+    ++it;
+    }
+}
+
+void SMUX::SetNotifiers()
+{
+int h = users->OpenSearch();
+assert(h && "USERS::OpenSearch is always correct");
+
+UserPtr u;
+while (!users->SearchNext(h, &u))
+    SetNotifier(u);
+
+users->CloseSearch(h);
+
+users->AddNotifierUserAdd(&addUserNotifier);
+users->AddNotifierUserDel(&delUserNotifier);
+
+tariffs->AddNotifierAdd(&addDelTariffNotifier);
+tariffs->AddNotifierDel(&addDelTariffNotifier);
+}
+
+void SMUX::ResetNotifiers()
+{
+tariffs->DelNotifierDel(&addDelTariffNotifier);
+tariffs->DelNotifierAdd(&addDelTariffNotifier);
+
+users->DelNotifierUserDel(&delUserNotifier);
+users->DelNotifierUserAdd(&addUserNotifier);
+
+std::list<CHG_AFTER_NOTIFIER>::iterator it(notifiers.begin());
+while (it != notifiers.end())
+    {
+    it->GetUserPtr()->GetProperties().tariffName.DelAfterNotifier(&(*it));
+    ++it;
+    }
+notifiers.clear();
+}
diff --git a/projects/stargazer/plugins/other/smux/smux.h b/projects/stargazer/plugins/other/smux/smux.h
new file mode 100644 (file)
index 0000000..4954bd0
--- /dev/null
@@ -0,0 +1,223 @@
+#ifndef __SMUX_H__
+#define __SMUX_H__
+
+#include <pthread.h>
+
+#include <string>
+#include <map>
+#include <list>
+#include <cstdint>
+
+#include "stg/SMUX-PDUs.h"
+#include "stg/ObjectSyntax.h"
+
+#include "stg/plugin.h"
+#include "stg/module_settings.h"
+#include "stg/notifer.h"
+#include "stg/noncopyable.h"
+#include "stg/logger.h"
+
+#include "sensors.h"
+#include "tables.h"
+#include "types.h"
+
+namespace STG
+{
+struct User;
+struct Settings;
+struct Users;
+struct Tariffs;
+struct Services;
+struct Corporations;
+struct TraffCounter;
+}
+
+class SMUX;
+
+typedef bool (SMUX::*SMUXPacketHandler)(const SMUX_PDUs_t * pdus);
+typedef bool (SMUX::*PDUsHandler)(const PDUs_t * pdus);
+typedef std::map<SMUX_PDUs_PR, SMUXPacketHandler> SMUXHandlers;
+typedef std::map<PDUs_PR, PDUsHandler> PDUsHandlers;
+
+using UserPtr = STG::User*;
+//-----------------------------------------------------------------------------
+class SMUX_SETTINGS {
+public:
+    SMUX_SETTINGS();
+    virtual ~SMUX_SETTINGS() {}
+    const std::string & GetStrError() const { return errorStr; }
+    int ParseSettings(const STG::ModuleSettings & s);
+
+    uint32_t GetIP() const { return ip; }
+    uint16_t GetPort() const { return port; }
+    const std::string GetPassword() const { return password; }
+
+private:
+    mutable std::string errorStr;
+
+    uint32_t ip;
+    uint16_t port;
+    std::string password;
+};
+//-----------------------------------------------------------------------------
+class CHG_AFTER_NOTIFIER : public STG::PropertyNotifierBase<std::string> {
+public:
+             CHG_AFTER_NOTIFIER(SMUX & s, const UserPtr & u)
+                 : STG::PropertyNotifierBase<std::string>(),
+                   smux(s), userPtr(u) {}
+             CHG_AFTER_NOTIFIER(const CHG_AFTER_NOTIFIER & rvalue)
+                 : STG::PropertyNotifierBase<std::string>(),
+                   smux(rvalue.smux), userPtr(rvalue.userPtr) {}
+    void     Notify(const std::string &, const std::string &);
+
+    UserPtr GetUserPtr() const { return userPtr; }
+
+private:
+    CHG_AFTER_NOTIFIER & operator=(const CHG_AFTER_NOTIFIER & rvalue);
+    SMUX & smux;
+    UserPtr userPtr;
+};
+//-----------------------------------------------------------------------------
+class ADD_DEL_TARIFF_NOTIFIER : public STG::NotifierBase<STG::TariffData> {
+public:
+    explicit ADD_DEL_TARIFF_NOTIFIER(SMUX & s)
+             : STG::NotifierBase<STG::TariffData>(), smux(s) {}
+    void Notify(const STG::TariffData &);
+
+private:
+    SMUX & smux;
+};
+//-----------------------------------------------------------------------------
+class ADD_USER_NOTIFIER : public STG::NotifierBase<UserPtr> {
+public:
+    explicit ADD_USER_NOTIFIER(SMUX & s) : STG::NotifierBase<STG::User*>(), smux(s) {}
+    void Notify(const UserPtr &);
+
+private:
+    SMUX & smux;
+};
+//-----------------------------------------------------------------------------
+class DEL_USER_NOTIFIER : public STG::NotifierBase<UserPtr> {
+public:
+    explicit DEL_USER_NOTIFIER(SMUX & s) : STG::NotifierBase<UserPtr>(), smux(s) {}
+    void Notify(const UserPtr &);
+
+private:
+    SMUX & smux;
+};
+//-----------------------------------------------------------------------------
+class SMUX : public STG::Plugin {
+public:
+    SMUX();
+    virtual ~SMUX();
+
+    void SetUsers(STG::Users * u) { users = u; }
+    void SetTariffs(STG::Tariffs * t) { tariffs = t; }
+    void SetAdmins(STG::Admins * a) { admins = a; }
+    void SetServices(STG::Services * s) { services = s; }
+    void SetTraffcounter(STG::TraffCounter * tc) { traffcounter = tc; }
+    void SetCorporations(STG::Corporations * c) { corporations = c; }
+    void SetSettings(const STG::ModuleSettings & s) { settings = s; }
+    int ParseSettings();
+
+    int Start();
+    int Stop();
+    int Reload(const STG::ModuleSettings & ms);
+    bool IsRunning() { return running && !stopped; }
+
+    const std::string & GetStrError() const { return errorStr; }
+    std::string GetVersion() const { return "Stg SMUX Plugin 1.1"; }
+    uint16_t GetStartPosition() const { return 10; }
+    uint16_t GetStopPosition() const { return 10; }
+
+    bool UpdateTables();
+
+    void SetNotifier(UserPtr userPtr);
+    void UnsetNotifier(UserPtr userPtr);
+
+private:
+    SMUX(const SMUX & rvalue);
+    SMUX & operator=(const SMUX & rvalue);
+
+    static void * Runner(void * d);
+    void Run();
+    bool PrepareNet();
+    bool Reconnect();
+
+    bool DispatchPDUs(const SMUX_PDUs_t * pdus);
+
+    bool CloseHandler(const SMUX_PDUs_t * pdus);
+    bool RegisterResponseHandler(const SMUX_PDUs_t * pdus);
+    bool PDUsRequestHandler(const SMUX_PDUs_t * pdus);
+    bool CommitOrRollbackHandler(const SMUX_PDUs_t * pdus);
+
+    bool GetRequestHandler(const PDUs_t * pdus);
+    bool GetNextRequestHandler(const PDUs_t * pdus);
+    bool SetRequestHandler(const PDUs_t * pdus);
+
+    void SetNotifiers();
+    void ResetNotifiers();
+
+    STG::Users * users;
+    STG::Tariffs * tariffs;
+    STG::Admins * admins;
+    STG::Services * services;
+    STG::Corporations * corporations;
+    STG::TraffCounter * traffcounter;
+
+    mutable std::string errorStr;
+    SMUX_SETTINGS smuxSettings;
+    STG::ModuleSettings settings;
+
+    pthread_t thread;
+    pthread_mutex_t mutex;
+    bool running;
+    bool stopped;
+    bool needReconnect;
+
+    time_t lastReconnectTry;
+    unsigned reconnectTimeout;
+
+    int sock;
+
+    SMUXHandlers smuxHandlers;
+    PDUsHandlers pdusHandlers;
+    Sensors sensors;
+    Tables tables;
+
+    std::list<CHG_AFTER_NOTIFIER> notifiers;
+    ADD_USER_NOTIFIER addUserNotifier;
+    DEL_USER_NOTIFIER delUserNotifier;
+    ADD_DEL_TARIFF_NOTIFIER addDelTariffNotifier;
+
+    STG::PluginLogger logger;
+};
+//-----------------------------------------------------------------------------
+
+inline
+void CHG_AFTER_NOTIFIER::Notify(const std::string &, const std::string &)
+{
+smux.UpdateTables();
+}
+
+inline
+void ADD_DEL_TARIFF_NOTIFIER::Notify(const STG::TariffData &)
+{
+smux.UpdateTables();
+}
+
+inline
+void ADD_USER_NOTIFIER::Notify(const UserPtr & userPtr)
+{
+smux.SetNotifier(userPtr);
+smux.UpdateTables();
+}
+
+inline
+void DEL_USER_NOTIFIER::Notify(const UserPtr & userPtr)
+{
+smux.UnsetNotifier(userPtr);
+smux.UpdateTables();
+}
+
+#endif
diff --git a/projects/stargazer/plugins/other/smux/tables.cpp b/projects/stargazer/plugins/other/smux/tables.cpp
new file mode 100644 (file)
index 0000000..21173b7
--- /dev/null
@@ -0,0 +1,65 @@
+#include <cassert>
+#include <utility>
+#include <iterator>
+#include <algorithm>
+
+#include "stg/user_property.h"
+#include "stg/tariffs.h"
+#include "stg/tariff_conf.h"
+#include "stg/users.h"
+
+#include "tables.h"
+
+std::pair<std::string, size_t> TD2Info(const STG::TariffData & td);
+
+void TariffUsersTable::UpdateSensors(Sensors & sensors) const
+{
+std::map<std::string, size_t> data;
+
+std::vector<STG::TariffData> tdl;
+tariffs.GetTariffsData(&tdl);
+std::transform(tdl.begin(),
+               tdl.end(),
+               std::inserter(data, data.begin()),
+               TD2Info);
+
+int handle = users.OpenSearch();
+assert(handle && "USERS::OpenSearch is always correct");
+
+STG::User* user;
+while (!users.SearchNext(handle, &user))
+    {
+    if (user->GetDeleted())
+        continue;
+    std::string tariffName(user->GetProperties().tariffName.ConstData());
+    std::map<std::string, size_t>::iterator it(data.lower_bound(tariffName));
+    if (it == data.end() ||
+        it->first != tariffName)
+        {
+        data.insert(it, std::make_pair(tariffName, 1));
+        }
+    else
+        {
+        ++it->second;
+        }
+    }
+
+users.CloseSearch(handle);
+
+size_t idx = 1;
+OID prefixOid(prefix);
+
+std::map<std::string, size_t>::const_iterator it(data.begin());
+while (it != data.end())
+    {
+    sensors[prefixOid.copyWithSuffix(2, static_cast<unsigned int>(idx))] = new ConstSensor<std::string>(it->first);
+    sensors[prefixOid.copyWithSuffix(3, static_cast<unsigned int>(idx))] = new ConstSensor<unsigned long>(it->second);
+    ++idx;
+    ++it;
+    }
+}
+
+std::pair<std::string, size_t> TD2Info(const STG::TariffData & td)
+{
+return std::make_pair(td.tariffConf.name, 0);
+}
diff --git a/projects/stargazer/plugins/other/smux/tables.h b/projects/stargazer/plugins/other/smux/tables.h
new file mode 100644 (file)
index 0000000..edfe437
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef __TABLES_H__
+#define __TABLES_H__
+
+#include <string>
+#include <map>
+
+#include "sensors.h"
+
+namespace STG
+{
+struct Tariffs;
+struct Users;
+}
+
+class TableSensor {
+    public:
+        explicit TableSensor(const std::string & p) : prefix(p) {}
+        virtual ~TableSensor() {}
+
+        const std::string & GetPrefix() const { return prefix; }
+        virtual void UpdateSensors(Sensors & sensors) const = 0;
+
+    protected:
+        std::string prefix;
+};
+
+class TariffUsersTable : public TableSensor {
+    public:
+        TariffUsersTable(const std::string & p,
+                         STG::Tariffs & t,
+                         STG::Users & u)
+            : TableSensor(p),
+              tariffs(t),
+              users(u)
+        {}
+        virtual ~TariffUsersTable() {}
+
+        void UpdateSensors(Sensors & sensors) const;
+
+    private:
+        STG::Tariffs & tariffs;
+        STG::Users & users;
+};
+
+typedef std::map<std::string, TableSensor *> Tables;
+
+#endif
diff --git a/projects/stargazer/plugins/other/smux/types.cpp b/projects/stargazer/plugins/other/smux/types.cpp
new file mode 100644 (file)
index 0000000..4e54749
--- /dev/null
@@ -0,0 +1,252 @@
+#include <stdexcept>
+#include <algorithm>
+#include <iterator>
+#include <sstream>
+
+#include "types.h"
+
+namespace
+{
+
+bool ParseArcs(const char * str, ptrdiff_t length, unsigned * a, size_t * pos);
+bool StringToArcs(const char * str, size_t length, std::vector<unsigned> & arcs);
+bool AppendToArcs(const char * str, size_t length, std::vector<unsigned> & arcs);
+
+bool ParseArcs(const char * str, ptrdiff_t length, unsigned * a, size_t * pos)
+{
+if (length == 0)
+    return false;
+const char * left = str;
+if (*left == '.')
+    ++left;
+size_t arcPos = 0;
+while ((left - str) < length)
+    {
+    char * pos = NULL;
+    unsigned arc = static_cast<unsigned int>(strtoul(left, &pos, 10));
+    if (pos == left)
+        return false;
+    a[arcPos++] = arc;
+    if (arcPos >= 1024)
+        return false;
+    left = pos + 1;
+    }
+*pos = arcPos;
+return true;
+}
+
+bool StringToArcs(const char * str, size_t length, std::vector<unsigned> & arcs)
+{
+unsigned a[1024];
+size_t pos = 0;
+
+if (!ParseArcs(str, length, a, &pos))
+    return false;
+
+arcs.assign(a, a + pos);
+return true;
+}
+
+bool AppendToArcs(const char * str, size_t length, std::vector<unsigned> & arcs)
+{
+unsigned a[1024];
+size_t pos = 0;
+
+if (!ParseArcs(str, length, a, &pos))
+    return false;
+
+std::copy(&a[0], &a[pos], std::back_inserter(arcs));
+return true;
+}
+
+}
+
+OID::OID(const std::string & str)
+    : arcs()
+{
+if (!StringToArcs(str.c_str(), str.length(), arcs))
+    throw std::runtime_error("Invalid oid");
+}
+
+OID::OID(const char * str, size_t length)
+    : arcs()
+{
+if (!StringToArcs(str, length, arcs))
+    throw std::runtime_error("Invalid oid");
+}
+
+OID::OID(const std::vector<unsigned> & a)
+    : arcs(a)
+{
+}
+
+OID::OID(const unsigned * a, size_t length)
+    : arcs()
+{
+std::vector<unsigned> newArcs(a, a + length);
+arcs.swap(newArcs);
+}
+
+OID::OID(OBJECT_IDENTIFIER_t * oid)
+    : arcs()
+{
+unsigned a[1024];
+int count = OBJECT_IDENTIFIER_get_arcs(oid, a, sizeof(a[0]), 1024);
+
+if (count > 1024)
+    throw std::runtime_error("OID is too long");
+
+std::vector<unsigned> newArcs(a, a + count);
+arcs.swap(newArcs);
+}
+
+OID::OID(const OID & rvalue)
+    : arcs(rvalue.arcs)
+{
+}
+
+OID::~OID()
+{
+}
+
+bool OID::addSuffix(const char * suffix, size_t length)
+{
+if (!AppendToArcs(suffix, length, arcs))
+    return false;
+return true;
+}
+
+bool OID::addSuffix(const std::string & suffix)
+{
+if (!AppendToArcs(suffix.c_str(), suffix.length(), arcs))
+    return false;
+return true;
+}
+
+bool OID::addSuffix(const unsigned * suffix, size_t length)
+{
+std::copy(suffix, suffix + length, std::back_inserter(arcs));
+return true;
+}
+
+bool OID::addSuffix(const std::vector<unsigned> & suffix)
+{
+std::copy(suffix.begin(), suffix.end(), std::back_inserter(arcs));
+return true;
+}
+
+bool OID::addSuffix(unsigned a, unsigned b)
+{
+arcs.push_back(a);
+arcs.push_back(b);
+return true;
+}
+
+OID OID::copyWithSuffix(const char * suffix, size_t length) const
+{
+OID oid(*this);
+if (!oid.addSuffix(suffix, length))
+    throw std::runtime_error("Invalid suffix");
+return oid;
+}
+
+OID OID::copyWithSuffix(const std::string & suffix) const
+{
+OID oid(*this);
+if (!oid.addSuffix(suffix))
+    throw std::runtime_error("Invalid suffix");
+return oid;
+}
+
+OID OID::copyWithSuffix(const unsigned * suffix, size_t length) const
+{
+OID oid(*this);
+if (!oid.addSuffix(suffix, length))
+    throw std::runtime_error("Invalid suffix");
+return oid;
+}
+
+OID OID::copyWithSuffix(const std::vector<unsigned> & suffix) const
+{
+OID oid(*this);
+if (!oid.addSuffix(suffix))
+    throw std::runtime_error("Invalid suffix");
+return oid;
+}
+
+OID OID::copyWithSuffix(unsigned a, unsigned b) const
+{
+OID oid(*this);
+oid.addSuffix(a, b);
+return oid;
+}
+
+std::string OID::ToString() const
+{
+std::stringstream stream;
+for (size_t i = 0; i < arcs.size(); ++i)
+    stream << "." << arcs[i];
+return stream.str();
+}
+
+void OID::ToOID(OBJECT_IDENTIFIER_t * oid) const
+{
+OBJECT_IDENTIFIER_set_arcs(oid, &arcs.front(), sizeof(unsigned), static_cast<unsigned int>(arcs.size()));
+}
+
+OID & OID::operator=(const OID & rvalue)
+{
+arcs = rvalue.arcs;
+return *this;
+}
+
+bool OID::operator==(const OID & rvalue) const
+{
+if (arcs.size() != rvalue.arcs.size())
+    return false;
+for (size_t i = 0; i < arcs.size(); ++i)
+    if (arcs[i] != rvalue.arcs[i])
+        return false;
+return true;
+}
+
+bool OID::operator<(const OID & rvalue) const
+{
+size_t i = 0;
+size_t min = std::min(arcs.size(), rvalue.arcs.size());
+while (i < min &&
+       arcs[i] == rvalue.arcs[i])
+    ++i;
+if (i == min)
+    {
+    if (rvalue.arcs.size() > arcs.size())
+        return true;
+    return false;
+    }
+
+if (arcs[i] < rvalue.arcs[i])
+    return true;
+
+return false;
+}
+
+bool OID::PrefixLess(const OID & rvalue) const
+{
+size_t i = 0;
+size_t min = std::min(arcs.size(), rvalue.arcs.size());
+while (i < min &&
+       arcs[i] == rvalue.arcs[i])
+    ++i;
+if (i == min)
+    return false;
+if (arcs[i] < rvalue.arcs[i])
+    return true;
+return false;
+}
+
+std::ostream & operator<<(std::ostream & stream, const OID & oid)
+{
+for (size_t i = 0; i < oid.arcs.size(); ++i)
+    stream << "." << oid.arcs[i];
+return stream;
+}
diff --git a/projects/stargazer/plugins/other/smux/types.h b/projects/stargazer/plugins/other/smux/types.h
new file mode 100644 (file)
index 0000000..2b54f2a
--- /dev/null
@@ -0,0 +1,57 @@
+#ifndef __TYPES_H__
+#define __TYPES_H__
+
+#include <string>
+#include <vector>
+#include <iostream>
+
+#include "stg/OBJECT_IDENTIFIER.h"
+
+class OID {
+    public:
+        explicit OID(const std::string & str);
+        OID(const char * str, size_t length);
+        explicit OID(const std::vector<unsigned> & arcs);
+        OID(const unsigned * arcs, size_t length);
+        explicit OID(OBJECT_IDENTIFIER_t * oid);
+        OID(const OID & rvalue);
+        ~OID();
+
+        bool addSuffix(const char * suffix, size_t length);
+        bool addSuffix(const std::string & suffix);
+        bool addSuffix(const unsigned * suffix, size_t length);
+        bool addSuffix(const std::vector<unsigned> & suffix);
+        bool addSuffix(unsigned a, unsigned b);
+
+        OID copyWithSuffix(const char * suffix, size_t length) const;
+        OID copyWithSuffix(const std::string & suffix) const;
+        OID copyWithSuffix(const unsigned * suffix, size_t length) const;
+        OID copyWithSuffix(const std::vector<unsigned> & suffix) const;
+        OID copyWithSuffix(unsigned a, unsigned b) const;
+
+        std::string ToString() const;
+        const std::vector<unsigned> & ToVector() const { return arcs; }
+        void ToOID(OBJECT_IDENTIFIER_t * oid) const;
+
+        OID & operator=(const OID & rvalue);
+        bool operator==(const OID & rvalue) const;
+        bool operator!=(const OID & rvalue) const { return !operator==(rvalue); }
+        bool operator<(const OID & rvalue) const;
+        bool operator>(const OID & rvalue) const
+        { return !operator==(rvalue) && !operator<(rvalue); }
+
+        bool PrefixLess(const OID & rvalue) const;
+
+        friend std::ostream & operator<<(std::ostream & stream, const OID & oid);
+
+    private:
+        std::vector<unsigned> arcs;
+};
+
+inline
+bool PrefixLess(const OID & a, const OID & b)
+{
+return a.PrefixLess(b);
+}
+
+#endif
diff --git a/projects/stargazer/plugins/other/smux/utils.cpp b/projects/stargazer/plugins/other/smux/utils.cpp
new file mode 100644 (file)
index 0000000..0ea39bb
--- /dev/null
@@ -0,0 +1,244 @@
+#include <unistd.h> // write
+
+#include <cstring> // memset
+#include <cerrno>
+
+#include "stg/common.h"
+
+#include "stg/OpenPDU.h"
+#include "stg/ClosePDU.h"
+#include "stg/RReqPDU.h"
+#include "stg/ber_decoder.h"
+#include "stg/der_encoder.h"
+
+#include "pen.h"
+#include "utils.h"
+
+bool String2OI(const std::string & str, OBJECT_IDENTIFIER_t * oi)
+{
+size_t left = 0, pos = 0, arcPos = 0;
+int arcs[1024];
+pos = str.find_first_of('.', left);
+if (pos == 0)
+    {
+    left = 1;
+    pos = str.find_first_of('.', left);
+    }
+while (pos != std::string::npos)
+    {
+    int arc = 0;
+    if (str2x(str.substr(left, left - pos), arc))
+        {
+        return false;
+        }
+    arcs[arcPos++] = arc;
+    left = pos + 1;
+    pos = str.find_first_of('.', left);
+    }
+if (left < str.length())
+    {
+    int arc = 0;
+    if (str2x(str.substr(left, left - pos), arc))
+        {
+        return false;
+        }
+    arcs[arcPos++] = arc;
+    }
+OBJECT_IDENTIFIER_set_arcs(oi, arcs, sizeof(arcs[0]), static_cast<unsigned int>(arcPos));
+return true;
+}
+
+bool SendOpenPDU(int fd)
+{
+const char * description = "Stg SMUX Plugin";
+asn_enc_rval_t error;
+OpenPDU_t msg;
+
+memset(&msg, 0, sizeof(msg));
+
+msg.present = OpenPDU_PR_simple;
+asn_long2INTEGER(&msg.choice.simple.version, SimpleOpen__version_version_1);
+if (!String2OI(PEN_PREFIX, &msg.choice.simple.identity))
+    {
+    printfd(__FILE__,
+            "SendOpenPDU() - failed to convert string to OBJECT_IDENTIFIER\n");
+    return false;
+    }
+OCTET_STRING_fromString(&msg.choice.simple.description, description);
+OCTET_STRING_fromString(&msg.choice.simple.password, "");
+
+char buffer[1024];
+error = der_encode_to_buffer(&asn_DEF_OpenPDU, &msg, buffer, sizeof(buffer));
+
+ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_OpenPDU, &msg);
+
+if (error.encoded == -1)
+    {
+    printfd(__FILE__, "Could not encode OpenPDU (at %s)\n",
+            error.failed_type ? error.failed_type->name : "unknown");
+    return false;
+    }
+else
+    {
+    if (write(fd, buffer, error.encoded) < 0)
+        {
+        printfd(__FILE__, "Failed to send OpenPDU: %s\n", strerror(errno));
+        return false;
+        }
+    }
+return true;
+}
+
+bool SendClosePDU(int fd)
+{
+ClosePDU_t msg;
+
+memset(&msg, 0, sizeof(msg));
+
+asn_long2INTEGER(&msg, ClosePDU_goingDown);
+
+char buffer[1024];
+asn_enc_rval_t error;
+error = der_encode_to_buffer(&asn_DEF_ClosePDU, &msg, buffer, sizeof(buffer));
+
+ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_ClosePDU, &msg);
+
+if (error.encoded == -1)
+    {
+    printfd(__FILE__, "Could not encode ClosePDU (at %s)\n",
+            error.failed_type ? error.failed_type->name : "unknown");
+    return false;
+    }
+else
+    {
+    if (write(fd, buffer, error.encoded) < 0)
+        {
+        printfd(__FILE__, "Failed to send ClosePDU: %s\n", strerror(errno));
+        return false;
+        }
+    }
+return true;
+}
+
+bool SendRReqPDU(int fd)
+{
+int oid[] = {1, 3, 6, 1, 4, 1, 38313, 1};
+asn_enc_rval_t error;
+RReqPDU_t msg;
+
+memset(&msg, 0, sizeof(msg));
+
+msg.priority = 0;
+asn_long2INTEGER(&msg.operation, RReqPDU__operation_readOnly);
+OBJECT_IDENTIFIER_set_arcs(&msg.subtree,
+                           oid,
+                           sizeof(oid[0]),
+                           8);
+
+char buffer[1024];
+error = der_encode_to_buffer(&asn_DEF_RReqPDU, &msg, buffer, sizeof(buffer));
+
+ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RReqPDU, &msg);
+
+if (error.encoded == -1)
+    {
+    printfd(__FILE__, "Could not encode RReqPDU (at %s)\n",
+            error.failed_type ? error.failed_type->name : "unknown");
+    return false;
+    }
+else
+    {
+    if (write(fd, buffer, error.encoded) < 0)
+        {
+        printfd(__FILE__, "Failed to send RReqPDU: %s\n", strerror(errno));
+        return false;
+        }
+    }
+return true;
+}
+
+SMUX_PDUs_t * RecvSMUXPDUs(int fd)
+{
+char buffer[1024];
+SMUX_PDUs_t * pdus = NULL;
+
+memset(buffer, 0, sizeof(buffer));
+
+size_t length = read(fd, buffer, sizeof(buffer));
+if (length < 1)
+    return NULL;
+asn_dec_rval_t error;
+error = ber_decode(0, &asn_DEF_SMUX_PDUs, (void **)&pdus, buffer, length);
+
+if(error.code != RC_OK)
+    {
+    printfd(__FILE__, "Failed to decode PDUs at byte %ld\n",
+            (long)error.consumed);
+    return NULL;
+    }
+return pdus;
+}
+
+bool SendGetResponsePDU(int fd, GetResponse_PDU_t * getResponse)
+{
+asn_enc_rval_t error;
+
+char buffer[1024];
+error = der_encode_to_buffer(&asn_DEF_GetResponse_PDU, getResponse, buffer,
+                             sizeof(buffer));
+
+if (error.encoded == -1)
+    {
+    printfd(__FILE__, "Could not encode GetResponsePDU (at %s)\n",
+            error.failed_type ? error.failed_type->name : "unknown");
+    return false;
+    }
+else
+    {
+    if (write(fd, buffer, error.encoded) < 0)
+        {
+        printfd(__FILE__, "Failed to send GetResponsePDU: %s\n", strerror(errno));
+        return false;
+        }
+    }
+return true;
+}
+
+bool SendGetResponseErrorPDU(int fd,
+                             const PDU_t * getRequest,
+                             int errorStatus,
+                             int errorIndex)
+{
+asn_enc_rval_t error;
+GetResponse_PDU_t msg;
+
+memset(&msg, 0, sizeof(msg));
+
+long id = 0;
+asn_INTEGER2long(&getRequest->request_id, &id);
+asn_long2INTEGER(&msg.request_id, id);
+asn_long2INTEGER(&msg.error_status, errorStatus);
+asn_long2INTEGER(&msg.error_index, errorIndex);
+
+char buffer[1024];
+error = der_encode_to_buffer(&asn_DEF_GetResponse_PDU, &msg, buffer,
+                             sizeof(buffer));
+
+ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_GetResponse_PDU, &msg);
+
+if (error.encoded == -1)
+    {
+    printfd(__FILE__, "Could not encode GetResponsePDU for error (at %s)\n",
+            error.failed_type ? error.failed_type->name : "unknown");
+    return false;
+    }
+else
+    {
+    if (write(fd, buffer, error.encoded) < 0)
+        {
+        printfd(__FILE__, "Failed to send GetResponseErrorPDU: %s\n", strerror(errno));
+        return false;
+        }
+    }
+return true;
+}
diff --git a/projects/stargazer/plugins/other/smux/utils.h b/projects/stargazer/plugins/other/smux/utils.h
new file mode 100644 (file)
index 0000000..52a3988
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef __UTILS_H__
+#define __UTILS_H__
+
+#include <string>
+
+#include "stg/OBJECT_IDENTIFIER.h"
+#include "stg/SMUX-PDUs.h"
+#include "stg/GetResponse-PDU.h"
+
+bool String2OI(const std::string & str, OBJECT_IDENTIFIER_t * oi);
+bool SendOpenPDU(int fd);
+bool SendClosePDU(int fd);
+bool SendRReqPDU(int fd);
+SMUX_PDUs_t * RecvSMUXPDUs(int fd);
+bool SendGetResponsePDU(int fd, GetResponse_PDU_t * getResponse);
+bool SendGetResponseErrorPDU(int fd,
+                             const PDU_t * getRequest,
+                             int errorStatus,
+                             int errorIndex);
+
+#endif
diff --git a/projects/stargazer/plugins/other/smux/value2os.h b/projects/stargazer/plugins/other/smux/value2os.h
new file mode 100644 (file)
index 0000000..c069aff
--- /dev/null
@@ -0,0 +1,64 @@
+#ifndef __VALUE_2_OS_H__
+#define __VALUE_2_OS_H__
+
+#include "stg/ObjectSyntax.h"
+
+template <typename T>
+bool ValueToOS(const T & value, ObjectSyntax * objectSyntax);
+
+template <>
+inline
+bool ValueToOS<int>(const int & value, ObjectSyntax * objectSyntax)
+{
+objectSyntax->present = ObjectSyntax_PR_simple;
+SimpleSyntax_t * simpleSyntax = &objectSyntax->choice.simple;
+simpleSyntax->present = SimpleSyntax_PR_number;
+asn_long2INTEGER(&simpleSyntax->choice.number, value);
+return true;
+}
+
+template <>
+inline
+bool ValueToOS<unsigned int>(const unsigned int & value, ObjectSyntax * objectSyntax)
+{
+objectSyntax->present = ObjectSyntax_PR_simple;
+SimpleSyntax_t * simpleSyntax = &objectSyntax->choice.simple;
+simpleSyntax->present = SimpleSyntax_PR_number;
+asn_long2INTEGER(&simpleSyntax->choice.number, value);
+return true;
+}
+
+template <>
+inline
+bool ValueToOS<long>(const long & value, ObjectSyntax * objectSyntax)
+{
+objectSyntax->present = ObjectSyntax_PR_simple;
+SimpleSyntax_t * simpleSyntax = &objectSyntax->choice.simple;
+simpleSyntax->present = SimpleSyntax_PR_number;
+asn_long2INTEGER(&simpleSyntax->choice.number, value);
+return true;
+}
+
+template <>
+inline
+bool ValueToOS<unsigned long>(const unsigned long & value, ObjectSyntax * objectSyntax)
+{
+objectSyntax->present = ObjectSyntax_PR_simple;
+SimpleSyntax_t * simpleSyntax = &objectSyntax->choice.simple;
+simpleSyntax->present = SimpleSyntax_PR_number;
+asn_long2INTEGER(&simpleSyntax->choice.number, value);
+return true;
+}
+
+template <>
+inline
+bool ValueToOS<std::string>(const std::string & value, ObjectSyntax * objectSyntax)
+{
+objectSyntax->present = ObjectSyntax_PR_simple;
+SimpleSyntax_t * simpleSyntax = &objectSyntax->choice.simple;
+simpleSyntax->present = SimpleSyntax_PR_string;
+OCTET_STRING_fromBuf(&simpleSyntax->choice.string, value.c_str(), static_cast<int>(value.length()));
+return true;
+}
+
+#endif
diff --git a/projects/stargazer/plugins/store/files/file_store.cpp b/projects/stargazer/plugins/store/files/file_store.cpp
new file mode 100644 (file)
index 0000000..3fd9e6d
--- /dev/null
@@ -0,0 +1,2208 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+/*
+ $Revision: 1.67 $
+ $Date: 2010/10/07 19:53:11 $
+ $Author: faust $
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include "file_store.h"
+
+#include "stg/common.h"
+#include "stg/user_ips.h"
+#include "stg/user_conf.h"
+#include "stg/user_stat.h"
+#include "stg/const.h"
+#include "stg/blowfish.h"
+#include "stg/logger.h"
+#include "stg/locker.h"
+#include "stg/admin_conf.h"
+#include "stg/tariff.h"
+#include "stg/tariff_conf.h"
+#include "stg/service_conf.h"
+
+#include <sstream>
+#include <algorithm>
+#include <cstdio>
+#include <ctime>
+#include <cerrno>
+#include <cstring>
+
+#include <pwd.h>
+#include <grp.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <fcntl.h>
+#include <dirent.h>
+
+#define DELETED_USERS_DIR   "deleted_users"
+
+#define adm_enc_passwd "cjeifY8m3"
+
+int GetFileList(std::vector<std::string> * fileList, const std::string & directory, mode_t mode, const std::string & ext);
+
+const int pt_mega = 1024 * 1024;
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+namespace
+{
+
+bool CheckAndCreate(const std::string & dir, mode_t mode)
+{
+if (access(dir.c_str(), F_OK) == 0)
+    return true;
+if (mkdir(dir.c_str(), mode) == 0)
+    return true;
+return false;
+}
+
+}
+
+extern "C" STG::Store* GetStore()
+{
+    static FILES_STORE plugin;
+    return &plugin;
+}
+//-----------------------------------------------------------------------------
+FILES_STORE_SETTINGS::FILES_STORE_SETTINGS()
+    : settings(NULL),
+      statMode(0),
+      statUID(0),
+      statGID(0),
+      confMode(0),
+      confUID(0),
+      confGID(0),
+      userLogMode(0),
+      userLogUID(0),
+      userLogGID(0),
+      removeBak(true),
+      readBak(true)
+{
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE_SETTINGS::ParseOwner(const std::vector<STG::ParamValue> & moduleParams, const std::string & owner, uid_t * uid)
+{
+STG::ParamValue pv;
+pv.param = owner;
+std::vector<STG::ParamValue>::const_iterator pvi;
+pvi = find(moduleParams.begin(), moduleParams.end(), pv);
+if (pvi == moduleParams.end() || pvi->value.empty())
+    {
+    errorStr = "Parameter \'" + owner + "\' not found.";
+    printfd(__FILE__, "%s\n", errorStr.c_str());
+    return -1;
+    }
+if (User2UID(pvi->value[0].c_str(), uid) < 0)
+    {
+    errorStr = "Parameter \'" + owner + "\': Unknown user \'" + pvi->value[0] + "\'";
+    printfd(__FILE__, "%s\n", errorStr.c_str());
+    return -1;
+    }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE_SETTINGS::ParseGroup(const std::vector<STG::ParamValue> & moduleParams, const std::string & group, gid_t * gid)
+{
+STG::ParamValue pv;
+pv.param = group;
+std::vector<STG::ParamValue>::const_iterator pvi;
+pvi = find(moduleParams.begin(), moduleParams.end(), pv);
+if (pvi == moduleParams.end() || pvi->value.empty())
+    {
+    errorStr = "Parameter \'" + group + "\' not found.";
+    printfd(__FILE__, "%s\n", errorStr.c_str());
+    return -1;
+    }
+if (Group2GID(pvi->value[0].c_str(), gid) < 0)
+    {
+    errorStr = "Parameter \'" + group + "\': Unknown group \'" + pvi->value[0] + "\'";
+    printfd(__FILE__, "%s\n", errorStr.c_str());
+    return -1;
+    }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE_SETTINGS::ParseYesNo(const std::string & value, bool * val)
+{
+if (0 == strcasecmp(value.c_str(), "yes"))
+    {
+    *val = true;
+    return 0;
+    }
+if (0 == strcasecmp(value.c_str(), "no"))
+    {
+    *val = false;
+    return 0;
+    }
+
+errorStr = "Incorrect value \'" + value + "\'.";
+return -1;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE_SETTINGS::ParseMode(const std::vector<STG::ParamValue> & moduleParams, const std::string & modeStr, mode_t * mode)
+{
+STG::ParamValue pv;
+pv.param = modeStr;
+std::vector<STG::ParamValue>::const_iterator pvi;
+pvi = find(moduleParams.begin(), moduleParams.end(), pv);
+if (pvi == moduleParams.end() || pvi->value.empty())
+    {
+    errorStr = "Parameter \'" + modeStr + "\' not found.";
+    printfd(__FILE__, "%s\n", errorStr.c_str());
+    return -1;
+    }
+if (Str2Mode(pvi->value[0].c_str(), mode) < 0)
+    {
+    errorStr = "Parameter \'" + modeStr + "\': Incorrect mode \'" + pvi->value[0] + "\'";
+    printfd(__FILE__, "%s\n", errorStr.c_str());
+    return -1;
+    }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE_SETTINGS::ParseSettings(const STG::ModuleSettings & s)
+{
+if (ParseOwner(s.moduleParams, "StatOwner", &statUID) < 0)
+    return -1;
+if (ParseGroup(s.moduleParams, "StatGroup", &statGID) < 0)
+    return -1;
+if (ParseMode(s.moduleParams, "StatMode", &statMode) < 0)
+    return -1;
+
+if (ParseOwner(s.moduleParams, "ConfOwner", &confUID) < 0)
+    return -1;
+if (ParseGroup(s.moduleParams, "ConfGroup", &confGID) < 0)
+    return -1;
+if (ParseMode(s.moduleParams, "ConfMode", &confMode) < 0)
+    return -1;
+
+if (ParseOwner(s.moduleParams, "UserLogOwner", &userLogUID) < 0)
+    return -1;
+if (ParseGroup(s.moduleParams, "UserLogGroup", &userLogGID) < 0)
+    return -1;
+if (ParseMode(s.moduleParams, "UserLogMode", &userLogMode) < 0)
+    return -1;
+
+std::vector<STG::ParamValue>::const_iterator pvi;
+STG::ParamValue pv;
+pv.param = "RemoveBak";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end() || pvi->value.empty())
+    {
+    removeBak = true;
+    }
+else
+    {
+    if (ParseYesNo(pvi->value[0], &removeBak))
+        {
+        printfd(__FILE__, "Cannot parse parameter 'RemoveBak'\n");
+        return -1;
+        }
+    }
+
+pv.param = "ReadBak";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end() || pvi->value.empty())
+    {
+    readBak = false;
+    }
+else
+    {
+    if (ParseYesNo(pvi->value[0], &readBak))
+        {
+        printfd(__FILE__, "Cannot parse parameter 'ReadBak'\n");
+        return -1;
+        }
+    }
+
+pv.param = "WorkDir";
+pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
+if (pvi == s.moduleParams.end() || pvi->value.empty())
+    {
+    errorStr = "Parameter \'WorkDir\' not found.";
+    printfd(__FILE__, "Parameter 'WorkDir' not found\n");
+    return -1;
+    }
+
+workDir = pvi->value[0];
+if (workDir.size() && workDir[workDir.size() - 1] == '/')
+    {
+    workDir.resize(workDir.size() - 1);
+    }
+usersDir = workDir + "/users/";
+if (!CheckAndCreate(usersDir, GetConfModeDir()))
+    {
+    errorStr = usersDir + " doesn't exist. Failed to create.";
+    printfd(__FILE__, "%s\n", errorStr.c_str());
+    return -1;
+    }
+tariffsDir = workDir + "/tariffs/";
+if (!CheckAndCreate(tariffsDir, GetConfModeDir()))
+    {
+    errorStr = tariffsDir + " doesn't exist. Failed to create.";
+    printfd(__FILE__, "%s\n", errorStr.c_str());
+    return -1;
+    }
+adminsDir = workDir + "/admins/";
+if (!CheckAndCreate(adminsDir, GetConfModeDir()))
+    {
+    errorStr = adminsDir + " doesn't exist. Failed to create.";
+    printfd(__FILE__, "%s\n", errorStr.c_str());
+    return -1;
+    }
+servicesDir = workDir + "/services/";
+if (!CheckAndCreate(servicesDir, GetConfModeDir()))
+    {
+    errorStr = servicesDir + " doesn't exist. Failed to create.";
+    printfd(__FILE__, "%s\n", errorStr.c_str());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+const std::string & FILES_STORE_SETTINGS::GetStrError() const
+{
+return errorStr;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE_SETTINGS::User2UID(const char * user, uid_t * uid)
+{
+struct passwd * pw;
+pw = getpwnam(user);
+if (!pw)
+    {
+    errorStr = std::string("User \'") + std::string(user) + std::string("\' not found in system.");
+    printfd(__FILE__, "%s\n", errorStr.c_str());
+    return -1;
+    }
+
+*uid = pw->pw_uid;
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE_SETTINGS::Group2GID(const char * gr, gid_t * gid)
+{
+struct group * grp;
+grp = getgrnam(gr);
+if (!grp)
+    {
+    errorStr = std::string("Group \'") + std::string(gr) + std::string("\' not found in system.");
+    printfd(__FILE__, "%s\n", errorStr.c_str());
+    return -1;
+    }
+
+*gid = grp->gr_gid;
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE_SETTINGS::Str2Mode(const char * str, mode_t * mode)
+{
+char a;
+char b;
+char c;
+if (strlen(str) > 3)
+    {
+    errorStr = std::string("Error parsing mode \'") + str + std::string("\'");
+    printfd(__FILE__, "%s\n", errorStr.c_str());
+    return -1;
+    }
+
+for (int i = 0; i < 3; i++)
+    if (str[i] > '7' || str[i] < '0')
+        {
+        errorStr = std::string("Error parsing mode \'") + str + std::string("\'");
+        printfd(__FILE__, "%s\n", errorStr.c_str());
+        return -1;
+        }
+
+a = str[0] - '0';
+b = str[1] - '0';
+c = str[2] - '0';
+
+*mode = ((mode_t)c) + ((mode_t)b << 3) + ((mode_t)a << 6);
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+mode_t FILES_STORE_SETTINGS::GetStatModeDir() const
+{
+mode_t mode = statMode;
+if (statMode & S_IRUSR) mode |= S_IXUSR;
+if (statMode & S_IRGRP) mode |= S_IXGRP;
+if (statMode & S_IROTH) mode |= S_IXOTH;
+return mode;
+}
+//-----------------------------------------------------------------------------
+mode_t FILES_STORE_SETTINGS::GetConfModeDir() const
+{
+mode_t mode = confMode;
+if (confMode & S_IRUSR) mode |= S_IXUSR;
+if (confMode & S_IRGRP) mode |= S_IXGRP;
+if (confMode & S_IROTH) mode |= S_IXOTH;
+return mode;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+FILES_STORE::FILES_STORE()
+    : version("file_store v.1.04"),
+      logger(STG::PluginLogger::get("store_files"))
+{
+pthread_mutexattr_t attr;
+pthread_mutexattr_init(&attr);
+pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+pthread_mutex_init(&mutex, &attr);
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::ParseSettings()
+{
+int ret = storeSettings.ParseSettings(settings);
+if (ret)
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = storeSettings.GetStrError();
+    }
+return ret;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::GetUsersList(std::vector<std::string> * userList) const
+{
+std::vector<std::string> files;
+
+if (GetFileList(&files, storeSettings.GetUsersDir(), S_IFDIR, ""))
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "Failed to open '" + storeSettings.GetUsersDir() + "': " + std::string(strerror(errno));
+    return -1;
+    }
+
+STG_LOCKER lock(&mutex);
+
+userList->swap(files);
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::GetAdminsList(std::vector<std::string> * adminList) const
+{
+std::vector<std::string> files;
+
+if (GetFileList(&files, storeSettings.GetAdminsDir(), S_IFREG, ".adm"))
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "Failed to open '" + storeSettings.GetAdminsDir() + "': " + std::string(strerror(errno));
+    return -1;
+    }
+
+STG_LOCKER lock(&mutex);
+
+adminList->swap(files);
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::GetTariffsList(std::vector<std::string> * tariffList) const
+{
+std::vector<std::string> files;
+
+if (GetFileList(&files, storeSettings.GetTariffsDir(), S_IFREG, ".tf"))
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "Failed to open '" + storeSettings.GetTariffsDir() + "': " + std::string(strerror(errno));
+    return -1;
+    }
+
+STG_LOCKER lock(&mutex);
+
+tariffList->swap(files);
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::GetServicesList(std::vector<std::string> * list) const
+{
+std::vector<std::string> files;
+
+if (GetFileList(&files, storeSettings.GetServicesDir(), S_IFREG, ".serv"))
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "Failed to open '" + storeSettings.GetServicesDir() + "': " + std::string(strerror(errno));
+    return -1;
+    }
+
+STG_LOCKER lock(&mutex);
+
+list->swap(files);
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::RemoveDir(const char * path) const
+{
+DIR * d = opendir(path);
+
+if (!d)
+    {
+    errorStr = "failed to open dir. Message: '";
+    errorStr += strerror(errno);
+    errorStr += "'";
+    printfd(__FILE__, "FILE_STORE::RemoveDir() - Failed to open dir '%s': '%s'\n", path, strerror(errno));
+    return -1;
+    }
+
+dirent * entry;
+while ((entry = readdir(d)))
+    {
+    if (!(strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..")))
+        continue;
+
+    std::string str = path;
+    str += "/" + std::string(entry->d_name);
+
+    struct stat st;
+    if (stat(str.c_str(), &st))
+        continue;
+
+    if ((st.st_mode & S_IFREG))
+        {
+        if (unlink(str.c_str()))
+            {
+            STG_LOCKER lock(&mutex);
+            errorStr = "unlink failed. Message: '";
+            errorStr += strerror(errno);
+            errorStr += "'";
+            printfd(__FILE__, "FILES_STORE::RemoveDir() - unlink failed. Message: '%s'\n", strerror(errno));
+            closedir(d);
+            return -1;
+            }
+        }
+
+    if (!(st.st_mode & S_IFDIR))
+        {
+        if (RemoveDir(str.c_str()))
+            {
+            closedir(d);
+            return -1;
+            }
+
+        }
+    }
+
+closedir(d);
+
+if (rmdir(path))
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "rmdir failed. Message: '";
+    errorStr += strerror(errno);
+    errorStr += "'";
+    printfd(__FILE__, "FILES_STORE::RemoveDir() - rmdir failed. Message: '%s'\n", strerror(errno));
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::AddUser(const std::string & login) const
+{
+std::string fileName;
+
+strprintf(&fileName, "%s%s", storeSettings.GetUsersDir().c_str(), login.c_str());
+
+if (mkdir(fileName.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == -1)
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = std::string("mkdir failed. Message: '") + strerror(errno) + "'";
+    printfd(__FILE__, "FILES_STORE::AddUser - mkdir failed. Message: '%s'\n", strerror(errno));
+    return -1;
+    }
+
+strprintf(&fileName, "%s%s/conf", storeSettings.GetUsersDir().c_str(), login.c_str());
+if (Touch(fileName))
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "Cannot create file \"" + fileName + "\'";
+    printfd(__FILE__, "FILES_STORE::AddUser - fopen failed. Message: '%s'\n", strerror(errno));
+    return -1;
+    }
+
+strprintf(&fileName, "%s%s/stat", storeSettings.GetUsersDir().c_str(), login.c_str());
+if (Touch(fileName))
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "Cannot create file \"" + fileName + "\'";
+    printfd(__FILE__, "FILES_STORE::AddUser - fopen failed. Message: '%s'\n", strerror(errno));
+    return -1;
+    }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::DelUser(const std::string & login) const
+{
+std::string dirName;
+std::string dirName1;
+
+strprintf(&dirName, "%s/%s", storeSettings.GetWorkDir().c_str(), DELETED_USERS_DIR);
+if (access(dirName.c_str(), F_OK) != 0)
+    {
+    if (mkdir(dirName.c_str(), 0700) != 0)
+        {
+        STG_LOCKER lock(&mutex);
+        errorStr = "Directory '" + dirName + "' cannot be created.";
+        printfd(__FILE__, "FILES_STORE::DelUser - mkdir failed. Message: '%s'\n", strerror(errno));
+        return -1;
+        }
+    }
+
+if (access(dirName.c_str(), F_OK) == 0)
+    {
+    strprintf(&dirName, "%s/%s/%s.%lu", storeSettings.GetWorkDir().c_str(), DELETED_USERS_DIR, login.c_str(), time(NULL));
+    strprintf(&dirName1, "%s/%s", storeSettings.GetUsersDir().c_str(), login.c_str());
+    if (rename(dirName1.c_str(), dirName.c_str()))
+        {
+        STG_LOCKER lock(&mutex);
+        errorStr = "Error moving dir from " + dirName1 + " to " + dirName;
+        printfd(__FILE__, "FILES_STORE::DelUser - rename failed. Message: '%s'\n", strerror(errno));
+        return -1;
+        }
+    }
+else
+    {
+    strprintf(&dirName, "%s/%s", storeSettings.GetUsersDir().c_str(), login.c_str());
+    if (RemoveDir(dirName.c_str()))
+        {
+        return -1;
+        }
+    }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::RestoreUserConf(STG::UserConf * conf, const std::string & login) const
+{
+std::string fileName;
+fileName = storeSettings.GetUsersDir() + "/" + login + "/conf";
+if (RestoreUserConf(conf, login, fileName))
+    {
+    if (!storeSettings.GetReadBak())
+        {
+        return -1;
+        }
+    return RestoreUserConf(conf, login, fileName + ".bak");
+    }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::RestoreUserConf(STG::UserConf * conf, const std::string & login, const std::string & fileName) const
+{
+CONFIGFILE cf(fileName);
+int e = cf.Error();
+
+if (e)
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "User \'" + login + "\' data not read.";
+    printfd(__FILE__, "FILES_STORE::RestoreUserConf - conf read failed for user '%s'\n", login.c_str());
+    return -1;
+    }
+
+if (cf.ReadString("Password", &conf->password, "") < 0)
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "User \'" + login + "\' data not read. Parameter Password.";
+    printfd(__FILE__, "FILES_STORE::RestoreUserConf - password read failed for user '%s'\n", login.c_str());
+    return -1;
+    }
+if (conf->password.empty())
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "User \'" + login + "\' password is blank.";
+    printfd(__FILE__, "FILES_STORE::RestoreUserConf - password is blank for user '%s'\n", login.c_str());
+    return -1;
+    }
+
+if (cf.ReadString("tariff", &conf->tariffName, "") < 0)
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "User \'" + login + "\' data not read. Parameter Tariff.";
+    printfd(__FILE__, "FILES_STORE::RestoreUserConf - tariff read failed for user '%s'\n", login.c_str());
+    return -1;
+    }
+if (conf->tariffName.empty())
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "User \'" + login + "\' tariff is blank.";
+    printfd(__FILE__, "FILES_STORE::RestoreUserConf - tariff is blank for user '%s'\n", login.c_str());
+    return -1;
+    }
+
+std::string ipStr;
+cf.ReadString("IP", &ipStr, "?");
+try
+    {
+    conf->ips = STG::UserIPs::parse(ipStr);
+    }
+catch (const std::string & s)
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "User \'" + login + "\' data not read. Parameter IP address. " + s;
+    printfd(__FILE__, "FILES_STORE::RestoreUserConf - ip read failed for user '%s'\n", login.c_str());
+    return -1;
+    }
+
+if (cf.ReadInt("alwaysOnline", &conf->alwaysOnline, 0) != 0)
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "User \'" + login + "\' data not read. Parameter AlwaysOnline.";
+    printfd(__FILE__, "FILES_STORE::RestoreUserConf - alwaysonline read failed for user '%s'\n", login.c_str());
+    return -1;
+    }
+
+if (cf.ReadInt("down", &conf->disabled, 0) != 0)
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "User \'" + login + "\' data not read. Parameter Down.";
+    printfd(__FILE__, "FILES_STORE::RestoreUserConf - down read failed for user '%s'\n", login.c_str());
+    return -1;
+    }
+
+if (cf.ReadInt("passive", &conf->passive, 0) != 0)
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "User \'" + login + "\' data not read. Parameter Passive.";
+    printfd(__FILE__, "FILES_STORE::RestoreUserConf - passive read failed for user '%s'\n", login.c_str());
+    return -1;
+    }
+
+cf.ReadInt("DisabledDetailStat", &conf->disabledDetailStat, 0);
+cf.ReadTime("CreditExpire", &conf->creditExpire, 0);
+cf.ReadString("TariffChange", &conf->nextTariff, "");
+cf.ReadString("Group", &conf->group, "");
+cf.ReadString("RealName", &conf->realName, "");
+cf.ReadString("Address", &conf->address, "");
+cf.ReadString("Phone", &conf->phone, "");
+cf.ReadString("Note", &conf->note, "");
+cf.ReadString("email", &conf->email, "");
+
+char userdataName[12];
+for (int i = 0; i < USERDATA_NUM; i++)
+    {
+    snprintf(userdataName, 12, "Userdata%d", i);
+    cf.ReadString(userdataName, &conf->userdata[i], "");
+    }
+
+if (cf.ReadDouble("Credit", &conf->credit, 0) != 0)
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "User \'" + login + "\' data not read. Parameter Credit.";
+    printfd(__FILE__, "FILES_STORE::RestoreUserConf - credit read failed for user '%s'\n", login.c_str());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::RestoreUserStat(STG::UserStat * stat, const std::string & login) const
+{
+std::string fileName;
+fileName = storeSettings.GetUsersDir() + "/" + login + "/stat";
+
+if (RestoreUserStat(stat, login, fileName))
+    {
+    if (!storeSettings.GetReadBak())
+        {
+        return -1;
+        }
+    return RestoreUserStat(stat, login, fileName + ".bak");
+    }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::RestoreUserStat(STG::UserStat * stat, const std::string & login, const std::string & fileName) const
+{
+CONFIGFILE cf(fileName);
+
+int e = cf.Error();
+
+if (e)
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "User \'" + login + "\' stat not read. Cannot open file " + fileName + ".";
+    printfd(__FILE__, "FILES_STORE::RestoreUserStat - stat read failed for user '%s'\n", login.c_str());
+    return -1;
+    }
+
+char s[22];
+
+for (int i = 0; i < DIR_NUM; i++)
+    {
+    uint64_t traff;
+    snprintf(s, 22, "D%d", i);
+    if (cf.ReadULongLongInt(s, &traff, 0) != 0)
+        {
+        STG_LOCKER lock(&mutex);
+        errorStr = "User \'" + login + "\' stat not read. Parameter " + std::string(s);
+        printfd(__FILE__, "FILES_STORE::RestoreUserStat - download stat read failed for user '%s'\n", login.c_str());
+        return -1;
+        }
+    stat->monthDown[i] = traff;
+
+    snprintf(s, 22, "U%d", i);
+    if (cf.ReadULongLongInt(s, &traff, 0) != 0)
+        {
+        STG_LOCKER lock(&mutex);
+        errorStr =   "User \'" + login + "\' stat not read. Parameter " + std::string(s);
+        printfd(__FILE__, "FILES_STORE::RestoreUserStat - upload stat read failed for user '%s'\n", login.c_str());
+        return -1;
+        }
+    stat->monthUp[i] = traff;
+    }
+
+if (cf.ReadDouble("Cash", &stat->cash, 0) != 0)
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr =   "User \'" + login + "\' stat not read. Parameter Cash";
+    printfd(__FILE__, "FILES_STORE::RestoreUserStat - cash read failed for user '%s'\n", login.c_str());
+    return -1;
+    }
+
+if (cf.ReadDouble("FreeMb", &stat->freeMb, 0) != 0)
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr =   "User \'" + login + "\' stat not read. Parameter FreeMb";
+    printfd(__FILE__, "FILES_STORE::RestoreUserStat - freemb read failed for user '%s'\n", login.c_str());
+    return -1;
+    }
+
+if (cf.ReadTime("LastCashAddTime", &stat->lastCashAddTime, 0) != 0)
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr =   "User \'" + login + "\' stat not read. Parameter LastCashAddTime";
+    printfd(__FILE__, "FILES_STORE::RestoreUserStat - lastcashaddtime read failed for user '%s'\n", login.c_str());
+    return -1;
+    }
+
+if (cf.ReadTime("PassiveTime", &stat->passiveTime, 0) != 0)
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr =   "User \'" + login + "\' stat not read. Parameter PassiveTime";
+    printfd(__FILE__, "FILES_STORE::RestoreUserStat - passivetime read failed for user '%s'\n", login.c_str());
+    return -1;
+    }
+
+if (cf.ReadDouble("LastCashAdd", &stat->lastCashAdd, 0) != 0)
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr =   "User \'" + login + "\' stat not read. Parameter LastCashAdd";
+    printfd(__FILE__, "FILES_STORE::RestoreUserStat - lastcashadd read failed for user '%s'\n", login.c_str());
+    return -1;
+    }
+
+if (cf.ReadTime("LastActivityTime", &stat->lastActivityTime, 0) != 0)
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr =   "User \'" + login + "\' stat not read. Parameter LastActivityTime";
+    printfd(__FILE__, "FILES_STORE::RestoreUserStat - lastactivitytime read failed for user '%s'\n", login.c_str());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::SaveUserConf(const STG::UserConf & conf, const std::string & login) const
+{
+std::string fileName;
+fileName = storeSettings.GetUsersDir() + "/" + login + "/conf";
+
+CONFIGFILE cfstat(fileName, true);
+
+int e = cfstat.Error();
+
+if (e)
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = std::string("User \'") + login + "\' conf not written\n";
+    printfd(__FILE__, "FILES_STORE::SaveUserConf - conf write failed for user '%s'\n", login.c_str());
+    return -1;
+    }
+
+e = chmod(fileName.c_str(), storeSettings.GetConfMode());
+e += chown(fileName.c_str(), storeSettings.GetConfUID(), storeSettings.GetConfGID());
+
+if (e)
+    {
+    STG_LOCKER lock(&mutex);
+    printfd(__FILE__, "FILES_STORE::SaveUserConf - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
+    }
+
+cfstat.WriteString("Password",     conf.password);
+cfstat.WriteInt   ("Passive",      conf.passive);
+cfstat.WriteInt   ("Down",         conf.disabled);
+cfstat.WriteInt("DisabledDetailStat", conf.disabledDetailStat);
+cfstat.WriteInt   ("AlwaysOnline", conf.alwaysOnline);
+cfstat.WriteString("Tariff",       conf.tariffName);
+cfstat.WriteString("Address",      conf.address);
+cfstat.WriteString("Phone",        conf.phone);
+cfstat.WriteString("Email",        conf.email);
+cfstat.WriteString("Note",         conf.note);
+cfstat.WriteString("RealName",     conf.realName);
+cfstat.WriteString("Group",        conf.group);
+cfstat.WriteDouble("Credit",       conf.credit);
+cfstat.WriteString("TariffChange", conf.nextTariff);
+
+char userdataName[12];
+for (int i = 0; i < USERDATA_NUM; i++)
+    {
+    snprintf(userdataName, 12, "Userdata%d", i);
+    cfstat.WriteString(userdataName, conf.userdata[i]);
+    }
+cfstat.WriteInt("CreditExpire",    conf.creditExpire);
+
+std::ostringstream ipStr;
+ipStr << conf.ips;
+cfstat.WriteString("IP", ipStr.str());
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::SaveUserStat(const STG::UserStat & stat, const std::string & login) const
+{
+std::string fileName;
+fileName = storeSettings.GetUsersDir() + "/" + login + "/stat";
+
+    {
+    CONFIGFILE cfstat(fileName, true);
+    int e = cfstat.Error();
+
+    if (e)
+        {
+        STG_LOCKER lock(&mutex);
+        errorStr = std::string("User \'") + login + "\' stat not written\n";
+        printfd(__FILE__, "FILES_STORE::SaveUserStat - stat write failed for user '%s'\n", login.c_str());
+        return -1;
+        }
+
+    for (int i = 0; i < DIR_NUM; i++)
+        {
+        char s[22];
+        snprintf(s, 22, "D%d", i);
+        cfstat.WriteInt(s, stat.monthDown[i]);
+        snprintf(s, 22, "U%d", i);
+        cfstat.WriteInt(s, stat.monthUp[i]);
+        }
+
+    cfstat.WriteDouble("Cash", stat.cash);
+    cfstat.WriteDouble("FreeMb", stat.freeMb);
+    cfstat.WriteDouble("LastCashAdd", stat.lastCashAdd);
+    cfstat.WriteInt("LastCashAddTime", stat.lastCashAddTime);
+    cfstat.WriteInt("PassiveTime", stat.passiveTime);
+    cfstat.WriteInt("LastActivityTime", stat.lastActivityTime);
+    }
+
+int e = chmod(fileName.c_str(), storeSettings.GetStatMode());
+e += chown(fileName.c_str(), storeSettings.GetStatUID(), storeSettings.GetStatGID());
+
+if (e)
+    {
+    STG_LOCKER lock(&mutex);
+    printfd(__FILE__, "FILES_STORE::SaveUserStat - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::WriteLogString(const std::string & str, const std::string & login) const
+{
+FILE * f;
+time_t tm = time(NULL);
+std::string fileName;
+fileName = storeSettings.GetUsersDir() + "/" + login + "/log";
+f = fopen(fileName.c_str(), "at");
+
+if (f)
+    {
+    fprintf(f, "%s", LogDate(tm));
+    fprintf(f, " -- ");
+    fprintf(f, "%s", str.c_str());
+    fprintf(f, "\n");
+    fclose(f);
+    }
+else
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "Cannot open \'" + fileName + "\'";
+    printfd(__FILE__, "FILES_STORE::WriteLogString - log write failed for user '%s'\n", login.c_str());
+    return -1;
+    }
+
+int e = chmod(fileName.c_str(), storeSettings.GetLogMode());
+e += chown(fileName.c_str(), storeSettings.GetLogUID(), storeSettings.GetLogGID());
+
+if (e)
+    {
+    STG_LOCKER lock(&mutex);
+    printfd(__FILE__, "FILES_STORE::WriteLogString - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::WriteLog2String(const std::string & str, const std::string & login) const
+{
+FILE * f;
+time_t tm = time(NULL);
+std::string fileName;
+fileName = storeSettings.GetUsersDir() + "/" + login + "/log2";
+f = fopen(fileName.c_str(), "at");
+
+if (f)
+    {
+    fprintf(f, "%s", LogDate(tm));
+    fprintf(f, " -- ");
+    fprintf(f, "%s", str.c_str());
+    fprintf(f, "\n");
+    fclose(f);
+    }
+else
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "Cannot open \'" + fileName + "\'";
+    printfd(__FILE__, "FILES_STORE::WriteLogString - log write failed for user '%s'\n", login.c_str());
+    return -1;
+    }
+
+int e = chmod(fileName.c_str(), storeSettings.GetLogMode());
+e += chown(fileName.c_str(), storeSettings.GetLogUID(), storeSettings.GetLogGID());
+
+if (e)
+    {
+    STG_LOCKER lock(&mutex);
+    printfd(__FILE__, "FILES_STORE::WriteLogString - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::WriteUserChgLog(const std::string & login,
+                                 const std::string & admLogin,
+                                 uint32_t       admIP,
+                                 const std::string & paramName,
+                                 const std::string & oldValue,
+                                 const std::string & newValue,
+                                 const std::string & message) const
+{
+std::string userLogMsg = "Admin \'" + admLogin + "\', " + inet_ntostring(admIP) + ": \'"
+    + paramName + "\' parameter changed from \'" + oldValue +
+    "\' to \'" + newValue + "\'. " + message;
+
+return WriteLogString(userLogMsg, login);
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::WriteUserConnect(const std::string & login, uint32_t ip) const
+{
+std::string logStr = "Connect, " + inet_ntostring(ip);
+if (WriteLogString(logStr, login))
+    return -1;
+return WriteLog2String(logStr, login);
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::WriteUserDisconnect(const std::string & login,
+                                     const STG::DirTraff & monthUp,
+                                     const STG::DirTraff & monthDown,
+                                     const STG::DirTraff & sessionUp,
+                                     const STG::DirTraff & sessionDown,
+                                     double cash,
+                                     double freeMb,
+                                     const std::string & reason) const
+{
+std::ostringstream logStr;
+logStr << "Disconnect, "
+       << " session upload: \'"
+       << sessionUp
+       << "\' session download: \'"
+       << sessionDown
+       << "\' month upload: \'"
+       << monthUp
+       << "\' month download: \'"
+       << monthDown
+       << "\' cash: \'"
+       << cash
+       << "\'";
+
+if (WriteLogString(logStr.str(), login))
+    return -1;
+
+logStr << " freeMb: \'"
+       << freeMb
+       << "\'"
+       << " reason: \'"
+       << reason
+       << "\'";
+
+return WriteLog2String(logStr.str(), login);
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::SaveMonthStat(const STG::UserStat & stat, int month, int year, const std::string & login) const
+{
+// Classic stats
+std::string stat1;
+strprintf(&stat1,"%s/%s/stat.%d.%02d",
+        storeSettings.GetUsersDir().c_str(), login.c_str(), year + 1900, month + 1);
+
+CONFIGFILE s(stat1, true);
+
+if (s.Error())
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "Cannot create file '" + stat1 + "'";
+    printfd(__FILE__, "FILES_STORE::SaveMonthStat - month stat write failed for user '%s'\n", login.c_str());
+    return -1;
+    }
+
+// New stats
+std::string stat2;
+strprintf(&stat2,"%s/%s/stat2.%d.%02d",
+        storeSettings.GetUsersDir().c_str(), login.c_str(), year + 1900, month + 1);
+
+CONFIGFILE s2(stat2, true);
+
+if (s2.Error())
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "Cannot create file '" + stat2 + "'";
+    printfd(__FILE__, "FILES_STORE::SaveMonthStat - month stat write failed for user '%s'\n", login.c_str());
+    return -1;
+    }
+
+for (size_t i = 0; i < DIR_NUM; i++)
+    {
+    char dirName[3];
+    snprintf(dirName, 3, "U%llu", (unsigned long long)i);
+    s.WriteInt(dirName, stat.monthUp[i]); // Classic
+    s2.WriteInt(dirName, stat.monthUp[i]); // New
+    snprintf(dirName, 3, "D%llu", (unsigned long long)i);
+    s.WriteInt(dirName, stat.monthDown[i]); // Classic
+    s2.WriteInt(dirName, stat.monthDown[i]); // New
+    }
+
+// Classic
+s.WriteDouble("cash", stat.cash);
+
+// New
+s2.WriteDouble("Cash", stat.cash);
+s2.WriteDouble("FreeMb", stat.freeMb);
+s2.WriteDouble("LastCashAdd", stat.lastCashAdd);
+s2.WriteInt("LastCashAddTime", stat.lastCashAddTime);
+s2.WriteInt("PassiveTime", stat.passiveTime);
+s2.WriteInt("LastActivityTime", stat.lastActivityTime);
+
+return 0;
+}
+//-----------------------------------------------------------------------------*/
+int FILES_STORE::AddAdmin(const std::string & login) const
+{
+std::string fileName;
+strprintf(&fileName, "%s/%s.adm", storeSettings.GetAdminsDir().c_str(), login.c_str());
+
+if (Touch(fileName))
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "Cannot create file " + fileName;
+    printfd(__FILE__, "FILES_STORE::AddAdmin - failed to add admin '%s'\n", login.c_str());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------*/
+int FILES_STORE::DelAdmin(const std::string & login) const
+{
+std::string fileName;
+strprintf(&fileName, "%s/%s.adm", storeSettings.GetAdminsDir().c_str(), login.c_str());
+if (unlink(fileName.c_str()))
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "unlink failed. Message: '";
+    errorStr += strerror(errno);
+    errorStr += "'";
+    printfd(__FILE__, "FILES_STORE::DelAdmin - unlink failed. Message: '%s'\n", strerror(errno));
+    }
+return 0;
+}
+//-----------------------------------------------------------------------------*/
+int FILES_STORE::SaveAdmin(const STG::AdminConf & ac) const
+{
+std::string fileName;
+
+strprintf(&fileName, "%s/%s.adm", storeSettings.GetAdminsDir().c_str(), ac.login.c_str());
+
+    {
+    CONFIGFILE cf(fileName, true);
+
+    int e = cf.Error();
+
+    if (e)
+        {
+        STG_LOCKER lock(&mutex);
+        errorStr = "Cannot write admin " + ac.login + ". " + fileName;
+        printfd(__FILE__, "FILES_STORE::SaveAdmin - failed to save admin '%s'\n", ac.login.c_str());
+        return -1;
+        }
+
+    char pass[ADM_PASSWD_LEN + 1];
+    memset(pass, 0, sizeof(pass));
+
+    char adminPass[ADM_PASSWD_LEN + 1];
+    memset(adminPass, 0, sizeof(adminPass));
+
+    BLOWFISH_CTX ctx;
+    InitContext(adm_enc_passwd, strlen(adm_enc_passwd), &ctx);
+
+    strncpy(adminPass, ac.password.c_str(), ADM_PASSWD_LEN);
+    adminPass[ADM_PASSWD_LEN - 1] = 0;
+
+    for (int i = 0; i < ADM_PASSWD_LEN/8; i++)
+        {
+        EncryptBlock(pass + 8*i, adminPass + 8*i, &ctx);
+        }
+
+    pass[ADM_PASSWD_LEN - 1] = 0;
+    char passwordE[2 * ADM_PASSWD_LEN + 2];
+    Encode12(passwordE, pass, ADM_PASSWD_LEN);
+
+    cf.WriteString("password", passwordE);
+    cf.WriteInt("ChgConf",     ac.priv.userConf);
+    cf.WriteInt("ChgPassword", ac.priv.userPasswd);
+    cf.WriteInt("ChgStat",     ac.priv.userStat);
+    cf.WriteInt("ChgCash",     ac.priv.userCash);
+    cf.WriteInt("UsrAddDel",   ac.priv.userAddDel);
+    cf.WriteInt("ChgTariff",   ac.priv.tariffChg);
+    cf.WriteInt("ChgAdmin",    ac.priv.adminChg);
+    cf.WriteInt("ChgService",  ac.priv.serviceChg);
+    cf.WriteInt("ChgCorp",     ac.priv.corpChg);
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::RestoreAdmin(STG::AdminConf * ac, const std::string & login) const
+{
+std::string fileName;
+strprintf(&fileName, "%s/%s.adm", storeSettings.GetAdminsDir().c_str(), login.c_str());
+CONFIGFILE cf(fileName);
+char pass[ADM_PASSWD_LEN + 1];
+char password[ADM_PASSWD_LEN + 1];
+char passwordE[2 * ADM_PASSWD_LEN + 2];
+BLOWFISH_CTX ctx;
+
+std::string p;
+
+if (cf.Error())
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "Cannot open " + fileName;
+    printfd(__FILE__, "FILES_STORE::RestoreAdmin - failed to restore admin '%s'\n", ac->login.c_str());
+    return -1;
+    }
+
+if (cf.ReadString("password", &p, "*"))
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "Error in parameter password";
+    printfd(__FILE__, "FILES_STORE::RestoreAdmin - password read failed for admin '%s'\n", ac->login.c_str());
+    return -1;
+    }
+
+memset(passwordE, 0, sizeof(passwordE));
+strncpy(passwordE, p.c_str(), 2*ADM_PASSWD_LEN);
+
+memset(pass, 0, sizeof(pass));
+
+if (passwordE[0] != 0)
+    {
+    Decode21(pass, passwordE);
+    InitContext(adm_enc_passwd, strlen(adm_enc_passwd), &ctx);
+
+    for (int i = 0; i < ADM_PASSWD_LEN/8; i++)
+        {
+        DecryptBlock(password + 8*i, pass + 8*i, &ctx);
+        }
+    }
+else
+    {
+    password[0] = 0;
+    }
+
+ac->password = password;
+
+uint16_t a;
+
+if (cf.ReadUShortInt("ChgConf", &a, 0) == 0)
+    ac->priv.userConf = a;
+else
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "Error in parameter ChgConf";
+    printfd(__FILE__, "FILES_STORE::RestoreAdmin - chgconf read failed for admin '%s'\n", ac->login.c_str());
+    return -1;
+    }
+
+if (cf.ReadUShortInt("ChgPassword", &a, 0) == 0)
+    ac->priv.userPasswd = a;
+else
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "Error in parameter ChgPassword";
+    printfd(__FILE__, "FILES_STORE::RestoreAdmin - chgpassword read failed for admin '%s'\n", ac->login.c_str());
+    return -1;
+    }
+
+if (cf.ReadUShortInt("ChgStat", &a, 0) == 0)
+    ac->priv.userStat = a;
+else
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "Error in parameter ChgStat";
+    printfd(__FILE__, "FILES_STORE::RestoreAdmin - chgstat read failed for admin '%s'\n", ac->login.c_str());
+    return -1;
+    }
+
+if (cf.ReadUShortInt("ChgCash", &a, 0) == 0)
+    ac->priv.userCash = a;
+else
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "Error in parameter ChgCash";
+    printfd(__FILE__, "FILES_STORE::RestoreAdmin - chgcash read failed for admin '%s'\n", ac->login.c_str());
+    return -1;
+    }
+
+if (cf.ReadUShortInt("UsrAddDel", &a, 0) == 0)
+    ac->priv.userAddDel = a;
+else
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "Error in parameter UsrAddDel";
+    printfd(__FILE__, "FILES_STORE::RestoreAdmin - usradddel read failed for admin '%s'\n", ac->login.c_str());
+    return -1;
+    }
+
+if (cf.ReadUShortInt("ChgAdmin", &a, 0) == 0)
+    ac->priv.adminChg = a;
+else
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "Error in parameter ChgAdmin";
+    printfd(__FILE__, "FILES_STORE::RestoreAdmin - chgadmin read failed for admin '%s'\n", ac->login.c_str());
+    return -1;
+    }
+
+if (cf.ReadUShortInt("ChgTariff", &a, 0) == 0)
+    ac->priv.tariffChg = a;
+else
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "Error in parameter ChgTariff";
+    printfd(__FILE__, "FILES_STORE::RestoreAdmin - chgtariff read failed for admin '%s'\n", ac->login.c_str());
+    return -1;
+    }
+
+if (cf.ReadUShortInt("ChgService", &a, 0) == 0)
+    ac->priv.serviceChg = a;
+else
+    ac->priv.serviceChg = 0;
+
+if (cf.ReadUShortInt("ChgCorp", &a, 0) == 0)
+    ac->priv.corpChg = a;
+else
+    ac->priv.corpChg = 0;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::AddTariff(const std::string & name) const
+{
+std::string fileName;
+strprintf(&fileName, "%s/%s.tf", storeSettings.GetTariffsDir().c_str(), name.c_str());
+if (Touch(fileName))
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "Cannot create file " + fileName;
+    printfd(__FILE__, "FILES_STORE::AddTariff - failed to add tariff '%s'\n", name.c_str());
+    return -1;
+    }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::DelTariff(const std::string & name) const
+{
+std::string fileName;
+strprintf(&fileName, "%s/%s.tf", storeSettings.GetTariffsDir().c_str(), name.c_str());
+if (unlink(fileName.c_str()))
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "unlink failed. Message: '";
+    errorStr += strerror(errno);
+    errorStr += "'";
+    printfd(__FILE__, "FILES_STORE::DelTariff - unlink failed. Message: '%s'\n", strerror(errno));
+    }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::RestoreTariff(STG::TariffData * td, const std::string & tariffName) const
+{
+std::string fileName = storeSettings.GetTariffsDir() + "/" + tariffName + ".tf";
+CONFIGFILE conf(fileName);
+std::string str;
+td->tariffConf.name = tariffName;
+
+if (conf.Error() != 0)
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "Cannot read file " + fileName;
+    printfd(__FILE__, "FILES_STORE::RestoreTariff - failed to read tariff '%s'\n", tariffName.c_str());
+    return -1;
+    }
+
+std::string param;
+for (int i = 0; i<DIR_NUM; i++)
+    {
+    strprintf(&param, "Time%d", i);
+    if (conf.ReadString(param, &str, "00:00-00:00") < 0)
+        {
+        STG_LOCKER lock(&mutex);
+        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+        printfd(__FILE__, "FILES_STORE::RestoreTariff - time%d read failed for tariff '%s'\n", i, tariffName.c_str());
+        return -1;
+        }
+
+    ParseTariffTimeStr(str.c_str(),
+                       td->dirPrice[i].hDay,
+                       td->dirPrice[i].mDay,
+                       td->dirPrice[i].hNight,
+                       td->dirPrice[i].mNight);
+
+    strprintf(&param, "PriceDayA%d", i);
+    if (conf.ReadDouble(param, &td->dirPrice[i].priceDayA, 0.0) < 0)
+        {
+        STG_LOCKER lock(&mutex);
+        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+        printfd(__FILE__, "FILES_STORE::RestoreTariff - pricedaya read failed for tariff '%s'\n", tariffName.c_str());
+        return -1;
+        }
+    td->dirPrice[i].priceDayA /= (1024*1024);
+
+    strprintf(&param, "PriceDayB%d", i);
+    if (conf.ReadDouble(param, &td->dirPrice[i].priceDayB, 0.0) < 0)
+        {
+        STG_LOCKER lock(&mutex);
+        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+        printfd(__FILE__, "FILES_STORE::RestoreTariff - pricedayb read failed for tariff '%s'\n", tariffName.c_str());
+        return -1;
+        }
+    td->dirPrice[i].priceDayB /= (1024*1024);
+
+    strprintf(&param, "PriceNightA%d", i);
+    if (conf.ReadDouble(param, &td->dirPrice[i].priceNightA, 0.0) < 0)
+        {
+        STG_LOCKER lock(&mutex);
+        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+        printfd(__FILE__, "FILES_STORE::RestoreTariff - pricenighta read failed for tariff '%s'\n", tariffName.c_str());
+        return -1;
+        }
+    td->dirPrice[i].priceNightA /= (1024*1024);
+
+    strprintf(&param, "PriceNightB%d", i);
+    if (conf.ReadDouble(param, &td->dirPrice[i].priceNightB, 0.0) < 0)
+        {
+        STG_LOCKER lock(&mutex);
+        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+        printfd(__FILE__, "FILES_STORE::RestoreTariff - pricenightb read failed for tariff '%s'\n", tariffName.c_str());
+        return -1;
+        }
+    td->dirPrice[i].priceNightB /= (1024*1024);
+
+    strprintf(&param, "Threshold%d", i);
+    if (conf.ReadInt(param, &td->dirPrice[i].threshold, 0) < 0)
+        {
+        STG_LOCKER lock(&mutex);
+        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+        printfd(__FILE__, "FILES_STORE::RestoreTariff - threshold read failed for tariff '%s'\n", tariffName.c_str());
+        return -1;
+        }
+
+    strprintf(&param, "SinglePrice%d", i);
+    if (conf.ReadInt(param, &td->dirPrice[i].singlePrice, 0) < 0)
+        {
+        STG_LOCKER lock(&mutex);
+        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+        printfd(__FILE__, "FILES_STORE::RestoreTariff - singleprice read failed for tariff '%s'\n", tariffName.c_str());
+        return -1;
+        }
+
+    strprintf(&param, "NoDiscount%d", i);
+    if (conf.ReadInt(param, &td->dirPrice[i].noDiscount, 0) < 0)
+        {
+        STG_LOCKER lock(&mutex);
+        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+        printfd(__FILE__, "FILES_STORE::RestoreTariff - nodiscount read failed for tariff '%s'\n", tariffName.c_str());
+        return -1;
+        }
+    }
+
+if (conf.ReadDouble("Fee", &td->tariffConf.fee, 0) < 0)
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "Cannot read tariff " + tariffName + ". Parameter Fee";
+    printfd(__FILE__, "FILES_STORE::RestoreTariff - fee read failed for tariff '%s'\n", tariffName.c_str());
+    return -1;
+    }
+
+if (conf.ReadDouble("Free", &td->tariffConf.free, 0) < 0)
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "Cannot read tariff " + tariffName + ". Parameter Free";
+    printfd(__FILE__, "FILES_STORE::RestoreTariff - free read failed for tariff '%s'\n", tariffName.c_str());
+    return -1;
+    }
+
+if (conf.ReadDouble("PassiveCost", &td->tariffConf.passiveCost, 0) < 0)
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "Cannot read tariff " + tariffName + ". Parameter PassiveCost";
+    printfd(__FILE__, "FILES_STORE::RestoreTariff - passivecost read failed for tariff '%s'\n", tariffName.c_str());
+    return -1;
+    }
+
+if (conf.ReadString("TraffType", &str, "") < 0)
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "Cannot read tariff " + tariffName + ". Parameter TraffType";
+    printfd(__FILE__, "FILES_STORE::RestoreTariff - trafftype read failed for tariff '%s'\n", tariffName.c_str());
+    return -1;
+    }
+
+td->tariffConf.traffType = STG::Tariff::parseTraffType(str);
+
+if (conf.ReadString("Period", &str, "month") < 0)
+    td->tariffConf.period = STG::Tariff::MONTH;
+else
+    td->tariffConf.period = STG::Tariff::parsePeriod(str);
+
+if (conf.ReadString("ChangePolicy", &str, "allow") < 0)
+    td->tariffConf.changePolicy = STG::Tariff::ALLOW;
+else
+    td->tariffConf.changePolicy = STG::Tariff::parseChangePolicy(str);
+
+conf.ReadTime("ChangePolicyTimeout", &td->tariffConf.changePolicyTimeout, 0);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::SaveTariff(const STG::TariffData & td, const std::string & tariffName) const
+{
+std::string fileName = storeSettings.GetTariffsDir() + "/" + tariffName + ".tf";
+
+    {
+    CONFIGFILE cf(fileName, true);
+
+    int e = cf.Error();
+
+    if (e)
+        {
+        STG_LOCKER lock(&mutex);
+        errorStr = "Error writing tariff " + tariffName;
+        printfd(__FILE__, "FILES_STORE::RestoreTariff - failed to save tariff '%s'\n", tariffName.c_str());
+        return e;
+        }
+
+    std::string param;
+    for (int i = 0; i < DIR_NUM; i++)
+        {
+        strprintf(&param, "PriceDayA%d", i);
+        cf.WriteDouble(param, td.dirPrice[i].priceDayA * pt_mega);
+
+        strprintf(&param, "PriceDayB%d", i);
+        cf.WriteDouble(param, td.dirPrice[i].priceDayB * pt_mega);
+
+        strprintf(&param, "PriceNightA%d", i);
+        cf.WriteDouble(param, td.dirPrice[i].priceNightA * pt_mega);
+
+        strprintf(&param, "PriceNightB%d", i);
+        cf.WriteDouble(param, td.dirPrice[i].priceNightB * pt_mega);
+
+        strprintf(&param, "Threshold%d", i);
+        cf.WriteInt(param, td.dirPrice[i].threshold);
+
+        std::string s;
+        strprintf(&param, "Time%d", i);
+
+        strprintf(&s, "%0d:%0d-%0d:%0d",
+                td.dirPrice[i].hDay,
+                td.dirPrice[i].mDay,
+                td.dirPrice[i].hNight,
+                td.dirPrice[i].mNight);
+
+        cf.WriteString(param, s);
+
+        strprintf(&param, "NoDiscount%d", i);
+        cf.WriteInt(param, td.dirPrice[i].noDiscount);
+
+        strprintf(&param, "SinglePrice%d", i);
+        cf.WriteInt(param, td.dirPrice[i].singlePrice);
+        }
+
+    cf.WriteDouble("PassiveCost", td.tariffConf.passiveCost);
+    cf.WriteDouble("Fee", td.tariffConf.fee);
+    cf.WriteDouble("Free", td.tariffConf.free);
+    cf.WriteString("TraffType", STG::Tariff::toString(td.tariffConf.traffType));
+    cf.WriteString("Period", STG::Tariff::toString(td.tariffConf.period));
+    cf.WriteString("ChangePolicy", STG::Tariff::toString(td.tariffConf.changePolicy));
+    cf.WriteTime("ChangePolicyTimeout", td.tariffConf.changePolicyTimeout);
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------*/
+int FILES_STORE::AddService(const std::string & name) const
+{
+std::string fileName;
+strprintf(&fileName, "%s/%s.serv", storeSettings.GetServicesDir().c_str(), name.c_str());
+
+if (Touch(fileName))
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "Cannot create file " + fileName;
+    printfd(__FILE__, "FILES_STORE::AddService - failed to add service '%s'\n", name.c_str());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------*/
+int FILES_STORE::DelService(const std::string & name) const
+{
+std::string fileName;
+strprintf(&fileName, "%s/%s.serv", storeSettings.GetServicesDir().c_str(), name.c_str());
+if (unlink(fileName.c_str()))
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "unlink failed. Message: '";
+    errorStr += strerror(errno);
+    errorStr += "'";
+    printfd(__FILE__, "FILES_STORE::DelAdmin - unlink failed. Message: '%s'\n", strerror(errno));
+    }
+return 0;
+}
+//-----------------------------------------------------------------------------*/
+int FILES_STORE::SaveService(const STG::ServiceConf & conf) const
+{
+std::string fileName;
+
+strprintf(&fileName, "%s/%s.serv", storeSettings.GetServicesDir().c_str(), conf.name.c_str());
+
+    {
+    CONFIGFILE cf(fileName, true);
+
+    int e = cf.Error();
+
+    if (e)
+        {
+        STG_LOCKER lock(&mutex);
+        errorStr = "Cannot write service " + conf.name + ". " + fileName;
+        printfd(__FILE__, "FILES_STORE::SaveService - failed to save service '%s'\n", conf.name.c_str());
+        return -1;
+        }
+
+    cf.WriteString("name", conf.name);
+    cf.WriteString("comment", conf.comment);
+    cf.WriteDouble("cost", conf.cost);
+    cf.WriteInt("pay_day", conf.payDay);
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::RestoreService(STG::ServiceConf * conf, const std::string & name) const
+{
+std::string fileName;
+strprintf(&fileName, "%s/%s.serv", storeSettings.GetServicesDir().c_str(), name.c_str());
+CONFIGFILE cf(fileName);
+
+if (cf.Error())
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "Cannot open " + fileName;
+    printfd(__FILE__, "FILES_STORE::RestoreService - failed to restore service '%s'\n", name.c_str());
+    return -1;
+    }
+
+if (cf.ReadString("name", &conf->name, name))
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "Error in parameter 'name'";
+    printfd(__FILE__, "FILES_STORE::RestoreService - name read failed for service '%s'\n", name.c_str());
+    return -1;
+    }
+
+if (cf.ReadString("comment", &conf->comment, ""))
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "Error in parameter 'comment'";
+    printfd(__FILE__, "FILES_STORE::RestoreService - comment read failed for service '%s'\n", name.c_str());
+    return -1;
+    }
+
+if (cf.ReadDouble("cost", &conf->cost, 0.0))
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "Error in parameter 'cost'";
+    printfd(__FILE__, "FILES_STORE::RestoreService - cost read failed for service '%s'\n", name.c_str());
+    return -1;
+    }
+
+unsigned short value = 0;
+if (cf.ReadUShortInt("pay_day", &value, 0))
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "Error in parameter 'pay_day'";
+    printfd(__FILE__, "FILES_STORE::RestoreService - pay day read failed for service '%s'\n", name.c_str());
+    return -1;
+    }
+conf->payDay = value;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::WriteDetailedStat(const STG::TraffStat & statTree,
+                                   time_t lastStat,
+                                   const std::string & login) const
+{
+char fn[FN_STR_LEN];
+char dn[FN_STR_LEN];
+FILE * statFile;
+time_t t;
+tm * lt;
+
+t = time(NULL);
+
+snprintf(dn, FN_STR_LEN, "%s/%s/detail_stat", storeSettings.GetUsersDir().c_str(), login.c_str());
+if (access(dn, F_OK) != 0)
+    {
+    if (mkdir(dn, 0700) != 0)
+        {
+        STG_LOCKER lock(&mutex);
+        errorStr = "Directory \'" + std::string(dn) + "\' cannot be created.";
+        printfd(__FILE__, "FILES_STORE::WriteDetailStat - mkdir failed. Message: '%s'\n", strerror(errno));
+        return -1;
+        }
+    }
+
+int e = chown(dn, storeSettings.GetStatUID(), storeSettings.GetStatGID());
+e += chmod(dn, storeSettings.GetStatModeDir());
+
+if (e)
+    {
+    STG_LOCKER lock(&mutex);
+    printfd(__FILE__, "FILES_STORE::WriteDetailStat - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
+    }
+
+lt = localtime(&t);
+
+if (lt->tm_hour == 0 && lt->tm_min <= 5)
+    {
+    t -= 3600 * 24;
+    lt = localtime(&t);
+    }
+
+snprintf(dn, FN_STR_LEN, "%s/%s/detail_stat/%d",
+         storeSettings.GetUsersDir().c_str(),
+         login.c_str(),
+         lt->tm_year+1900);
+
+if (access(dn, F_OK) != 0)
+    {
+    if (mkdir(dn, 0700) != 0)
+        {
+        STG_LOCKER lock(&mutex);
+        errorStr = "Directory \'" + std::string(dn) + "\' cannot be created.";
+        printfd(__FILE__, "FILES_STORE::WriteDetailStat - mkdir failed. Message: '%s'\n", strerror(errno));
+        return -1;
+        }
+    }
+
+e = chown(dn, storeSettings.GetStatUID(), storeSettings.GetStatGID());
+e += chmod(dn, storeSettings.GetStatModeDir());
+
+if (e)
+    {
+    STG_LOCKER lock(&mutex);
+    printfd(__FILE__, "FILES_STORE::WriteDetailStat - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
+    }
+
+snprintf(dn, FN_STR_LEN, "%s/%s/detail_stat/%d/%s%d", 
+         storeSettings.GetUsersDir().c_str(),
+         login.c_str(),
+         lt->tm_year+1900,
+         lt->tm_mon+1 < 10 ? "0" : "",
+         lt->tm_mon+1);
+if (access(dn, F_OK) != 0)
+    {
+    if (mkdir(dn, 0700) != 0)
+        {
+        STG_LOCKER lock(&mutex);
+        errorStr = "Directory \'" + std::string(dn) + "\' cannot be created.";
+        printfd(__FILE__, "FILES_STORE::WriteDetailStat - mkdir failed. Message: '%s'\n", strerror(errno));
+        return -1;
+        }
+    }
+
+e = chown(dn, storeSettings.GetStatUID(), storeSettings.GetStatGID());
+e += chmod(dn, storeSettings.GetStatModeDir());
+
+if (e)
+    {
+    STG_LOCKER lock(&mutex);
+    printfd(__FILE__, "FILES_STORE::WriteDetailStat - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
+    }
+
+snprintf(fn, FN_STR_LEN, "%s/%s%d", dn, lt->tm_mday < 10 ? "0" : "", lt->tm_mday);
+
+statFile = fopen (fn, "at");
+
+if (!statFile)
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "File \'" + std::string(fn) + "\' cannot be written.";
+    printfd(__FILE__, "FILES_STORE::WriteDetailStat - fopen failed. Message: '%s'\n", strerror(errno));
+    return -1;
+    }
+
+struct tm * lt1;
+struct tm * lt2;
+
+lt1 = localtime(&lastStat);
+
+int h1, m1, s1;
+int h2, m2, s2;
+
+h1 = lt1->tm_hour;
+m1 = lt1->tm_min;
+s1 = lt1->tm_sec;
+
+lt2 = localtime(&t);
+
+h2 = lt2->tm_hour;
+m2 = lt2->tm_min;
+s2 = lt2->tm_sec;
+
+if (fprintf(statFile, "-> %02d.%02d.%02d - %02d.%02d.%02d\n",
+            h1, m1, s1, h2, m2, s2) < 0)
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = std::string("fprint failed. Message: '") + strerror(errno) + "'";
+    printfd(__FILE__, "FILES_STORE::WriteDetailStat - fprintf failed. Message: '%s'\n", strerror(errno));
+    fclose(statFile);
+    return -1;
+    }
+
+auto stIter = statTree.begin();
+
+while (stIter != statTree.end())
+    {
+    const auto u = std::to_string(stIter->second.up);
+    const auto d = std::to_string(stIter->second.down);
+    #ifdef TRAFF_STAT_WITH_PORTS
+    if (fprintf(statFile, "%17s:%hu\t%15d\t%15s\t%15s\t%f\n",
+                inet_ntostring(stIter->first.ip).c_str(),
+                stIter->first.port,
+                stIter->first.dir,
+                d.c_str(),
+                u.c_str(),
+                stIter->second.cash) < 0)
+        {
+        STG_LOCKER lock(&mutex);
+        errorStr = "fprint failed. Message: '";
+        errorStr += strerror(errno);
+        errorStr += "'";
+        printfd(__FILE__, "FILES_STORE::WriteDetailStat - fprintf failed. Message: '%s'\n", strerror(errno));
+        fclose(statFile);
+        return -1;
+        }
+    #else
+    if (fprintf(statFile, "%17s\t%15d\t%15s\t%15s\t%f\n",
+                inet_ntostring(stIter->first.ip).c_str(),
+                stIter->first.dir,
+                d.c_str(),
+                u.c_str(),
+                stIter->second.cash) < 0)
+        {
+        STG_LOCKER lock(&mutex);
+        errorStr = std::string("fprint failed. Message: '");
+        errorStr += strerror(errno);
+        errorStr += "'";
+        printfd(__FILE__, "FILES_STORE::WriteDetailStat - fprintf failed. Message: '%s'\n", strerror(errno));
+        fclose(statFile);
+        return -1;
+        }
+    #endif
+
+    ++stIter;
+    }
+
+fclose(statFile);
+
+e = chown(fn, storeSettings.GetStatUID(), storeSettings.GetStatGID());
+e += chmod(fn, storeSettings.GetStatMode());
+
+if (e)
+    {
+    STG_LOCKER lock(&mutex);
+    printfd(__FILE__, "FILES_STORE::WriteDetailStat - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::AddMessage(STG::Message * msg, const std::string & login) const
+{
+std::string fn;
+std::string dn;
+struct timeval tv;
+
+strprintf(&dn, "%s/%s/messages", storeSettings.GetUsersDir().c_str(), login.c_str());
+if (access(dn.c_str(), F_OK) != 0)
+    {
+    if (mkdir(dn.c_str(), 0700) != 0)
+        {
+        STG_LOCKER lock(&mutex);
+        errorStr = "Directory \'";
+        errorStr += dn;
+        errorStr += "\' cannot be created.";
+        printfd(__FILE__, "FILES_STORE::AddMessage - mkdir failed. Message: '%s'\n", strerror(errno));
+        return -1;
+        }
+    }
+
+chmod(dn.c_str(), storeSettings.GetConfModeDir());
+
+gettimeofday(&tv, NULL);
+
+msg->header.id = ((long long)tv.tv_sec) * 1000000 + ((long long)tv.tv_usec);
+strprintf(&fn, "%s/%lld", dn.c_str(), msg->header.id);
+
+if (Touch(fn))
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "File \'";
+    errorStr += fn;
+    errorStr += "\' cannot be writen.";
+    printfd(__FILE__, "FILES_STORE::AddMessage - fopen failed. Message: '%s'\n", strerror(errno));
+    return -1;
+    }
+
+return EditMessage(*msg, login);
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::EditMessage(const STG::Message & msg, const std::string & login) const
+{
+std::string fileName;
+
+FILE * msgFile;
+strprintf(&fileName, "%s/%s/messages/%lld", storeSettings.GetUsersDir().c_str(), login.c_str(), msg.header.id);
+
+if (access(fileName.c_str(), F_OK) != 0)
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "Message for user \'";
+    errorStr += login + "\' with ID \'";
+    errorStr += std::to_string(msg.header.id) + "\' does not exist.";
+    printfd(__FILE__, "FILES_STORE::EditMessage - %s\n", errorStr.c_str());
+    return -1;
+    }
+
+Touch(fileName + ".new");
+
+msgFile = fopen((fileName + ".new").c_str(), "wt");
+if (!msgFile)
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "File \'" + fileName + "\' cannot be writen.";
+    printfd(__FILE__, "FILES_STORE::EditMessage - fopen failed. Message: '%s'\n", strerror(errno));
+    return -1;
+    }
+
+bool res = true;
+res &= (fprintf(msgFile, "%u\n", msg.header.type) >= 0);
+res &= (fprintf(msgFile, "%u\n", msg.header.lastSendTime) >= 0);
+res &= (fprintf(msgFile, "%u\n", msg.header.creationTime) >= 0);
+res &= (fprintf(msgFile, "%u\n", msg.header.showTime) >= 0);
+res &= (fprintf(msgFile, "%d\n", msg.header.repeat) >= 0);
+res &= (fprintf(msgFile, "%u\n", msg.header.repeatPeriod) >= 0);
+res &= (fprintf(msgFile, "%s", msg.text.c_str()) >= 0);
+
+if (!res)
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = std::string("fprintf failed. Message: '") + strerror(errno) + "'";
+    printfd(__FILE__, "FILES_STORE::EditMessage - fprintf failed. Message: '%s'\n", strerror(errno));
+    fclose(msgFile);
+    return -1;
+    }
+
+fclose(msgFile);
+
+chmod((fileName + ".new").c_str(), storeSettings.GetConfMode());
+
+if (rename((fileName + ".new").c_str(), fileName.c_str()) < 0)
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "Error moving dir from " + fileName + ".new to " + fileName;
+    printfd(__FILE__, "FILES_STORE::EditMessage - rename failed. Message: '%s'\n", strerror(errno));
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::GetMessage(uint64_t id, STG::Message * msg, const std::string & login) const
+{
+std::string fn;
+strprintf(&fn, "%s/%s/messages/%lld", storeSettings.GetUsersDir().c_str(), login.c_str(), id);
+msg->header.id = id;
+return ReadMessage(fn, &msg->header, &msg->text);
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::DelMessage(uint64_t id, const std::string & login) const
+{
+std::string fn;
+strprintf(&fn, "%s/%s/messages/%lld", storeSettings.GetUsersDir().c_str(), login.c_str(), id);
+
+return unlink(fn.c_str());
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::GetMessageHdrs(std::vector<STG::Message::Header> * hdrsList, const std::string & login) const
+{
+std::string dn(storeSettings.GetUsersDir() + "/" + login + "/messages/");
+
+if (access(dn.c_str(), F_OK) != 0)
+    {
+    return 0;
+    }
+
+std::vector<std::string> messages;
+GetFileList(&messages, dn, S_IFREG, "");
+
+for (unsigned i = 0; i < messages.size(); i++)
+    {
+    unsigned long long id = 0;
+
+    if (str2x(messages[i].c_str(), id))
+        {
+        if (unlink((dn + messages[i]).c_str()))
+            {
+            STG_LOCKER lock(&mutex);
+            errorStr = std::string("unlink failed. Message: '") + strerror(errno) + "'";
+            printfd(__FILE__, "FILES_STORE::GetMessageHdrs - unlink failed. Message: '%s'\n", strerror(errno));
+            return -1;
+            }
+        continue;
+        }
+
+    STG::Message::Header hdr;
+    if (ReadMessage(dn + messages[i], &hdr, NULL))
+        {
+        return -1;
+        }
+
+    if (hdr.repeat < 0)
+        {
+        if (unlink((dn + messages[i]).c_str()))
+            {
+            STG_LOCKER lock(&mutex);
+            errorStr = std::string("unlink failed. Message: '") + strerror(errno) + "'";
+            printfd(__FILE__, "FILES_STORE::GetMessageHdrs - unlink failed. Message: '%s'\n", strerror(errno));
+            return -1;
+            }
+        continue;
+        }
+
+    hdr.id = id;
+    hdrsList->push_back(hdr);
+    }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::ReadMessage(const std::string & fileName,
+                             STG::Message::Header * hdr,
+                             std::string * text) const
+{
+FILE * msgFile;
+msgFile = fopen(fileName.c_str(), "rt");
+if (!msgFile)
+    {
+    STG_LOCKER lock(&mutex);
+    errorStr = "File \'";
+    errorStr += fileName;
+    errorStr += "\' cannot be openned.";
+    printfd(__FILE__, "FILES_STORE::ReadMessage - fopen failed. Message: '%s'\n", strerror(errno));
+    return -1;
+    }
+char p[20];
+unsigned * d[6];
+d[0] = &hdr->type;
+d[1] = &hdr->lastSendTime;
+d[2] = &hdr->creationTime;
+d[3] = &hdr->showTime;
+d[4] = (unsigned*)(&hdr->repeat);
+d[5] = &hdr->repeatPeriod;
+
+memset(p, 0, sizeof(p));
+
+for (int pos = 0; pos < 6; pos++)
+    {
+    if (fgets(p, sizeof(p) - 1, msgFile) == NULL) {
+        STG_LOCKER lock(&mutex);
+        errorStr = "Cannot read file \'";
+        errorStr += fileName;
+        errorStr += "\'. Missing data.";
+        printfd(__FILE__, "FILES_STORE::ReadMessage - cannot read file (missing data)\n");
+        printfd(__FILE__, "FILES_STORE::ReadMessage - position: %d\n", pos);
+        fclose(msgFile);
+        return -1;
+    }
+
+    char * ep;
+    ep = strrchr(p, '\r');
+    if (ep) *ep = 0;
+    ep = strrchr(p, '\n');
+    if (ep) *ep = 0;
+
+    if (feof(msgFile))
+        {
+        STG_LOCKER lock(&mutex);
+        errorStr = "Cannot read file \'";
+        errorStr += fileName;
+        errorStr += "\'. Missing data.";
+        printfd(__FILE__, "FILES_STORE::ReadMessage - cannot read file (feof)\n");
+        printfd(__FILE__, "FILES_STORE::ReadMessage - position: %d\n", pos);
+        fclose(msgFile);
+        return -1;
+        }
+
+    if (str2x(p, *(d[pos])))
+        {
+        STG_LOCKER lock(&mutex);
+        errorStr = "Cannot read file \'";
+        errorStr += fileName;
+        errorStr += "\'. Incorrect value. \'";
+        errorStr += p;
+        errorStr += "\'";
+        printfd(__FILE__, "FILES_STORE::ReadMessage - incorrect value\n");
+        fclose(msgFile);
+        return -1;
+        }
+    }
+
+char txt[2048];
+memset(txt, 0, sizeof(txt));
+if (text)
+    {
+    text->erase(text->begin(), text->end());
+    while (!feof(msgFile))
+        {
+        txt[0] = 0;
+        if (fgets(txt, sizeof(txt) - 1, msgFile) == NULL) {
+            break;
+        }
+
+        (*text) += txt;
+        }
+    }
+fclose(msgFile);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FILES_STORE::Touch(const std::string & path) const
+{
+FILE * f = fopen(path.c_str(), "wb");
+if (f)
+    {
+    fclose(f);
+    return 0;
+    }
+return -1;
+}
+//-----------------------------------------------------------------------------
+int GetFileList(std::vector<std::string> * fileList, const std::string & directory, mode_t mode, const std::string & ext)
+{
+DIR * d = opendir(directory.c_str());
+
+if (!d)
+    {
+    printfd(__FILE__, "GetFileList - Failed to open dir '%s': '%s'\n", directory.c_str(), strerror(errno));
+    return -1;
+    }
+
+dirent * entry;
+while ((entry = readdir(d)))
+    {
+    if (!(strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..")))
+        continue;
+
+    std::string str = directory + "/" + std::string(entry->d_name);
+
+    struct stat st;
+    if (stat(str.c_str(), &st))
+        continue;
+
+    if (!(st.st_mode & mode)) // Filter by mode
+        continue;
+
+    if (!ext.empty())
+        {
+        // Check extension
+        size_t d_nameLen = strlen(entry->d_name);
+        if (d_nameLen <= ext.size())
+            continue;
+
+        if (ext == entry->d_name + (d_nameLen - ext.size()))
+            {
+            entry->d_name[d_nameLen - ext.size()] = 0;
+            fileList->push_back(entry->d_name);
+            }
+        }
+    else
+        {
+        fileList->push_back(entry->d_name);
+        }
+    }
+
+closedir(d);
+
+return 0;
+}
+//-----------------------------------------------------------------------------
diff --git a/projects/stargazer/plugins/store/files/file_store.h b/projects/stargazer/plugins/store/files/file_store.h
new file mode 100644 (file)
index 0000000..8bc2ab3
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+#pragma once
+
+#include "stg/module_settings.h"
+#include "stg/store.h"
+#include "stg/conffiles.h"
+#include "stg/user_traff.h"
+#include "stg/logger.h"
+
+#include <string>
+
+#include <sys/types.h>
+#include <pthread.h>
+
+//-----------------------------------------------------------------------------
+class FILES_STORE_SETTINGS {
+public:
+    FILES_STORE_SETTINGS();
+    int ParseSettings(const STG::ModuleSettings & s);
+    const std::string & GetStrError() const;
+
+    std::string  GetWorkDir() const { return workDir; }
+    std::string  GetUsersDir() const { return usersDir; }
+    std::string  GetAdminsDir() const { return adminsDir; }
+    std::string  GetTariffsDir() const { return tariffsDir; }
+    std::string  GetServicesDir() const { return servicesDir; }
+
+    mode_t  GetStatMode() const { return statMode; }
+    mode_t  GetStatModeDir() const;
+    uid_t   GetStatUID() const { return statUID; }
+    gid_t   GetStatGID() const { return statGID; }
+
+    mode_t  GetConfMode() const { return confMode; }
+    mode_t  GetConfModeDir() const;
+    uid_t   GetConfUID() const { return confUID; }
+    gid_t   GetConfGID() const { return confGID; }
+
+    mode_t  GetLogMode() const { return userLogMode; }
+    uid_t   GetLogUID() const { return userLogUID; }
+    gid_t   GetLogGID() const { return userLogGID; }
+
+    bool    GetRemoveBak() const { return removeBak; }
+    bool    GetReadBak() const { return readBak; }
+
+private:
+    FILES_STORE_SETTINGS(const FILES_STORE_SETTINGS & rvalue);
+    FILES_STORE_SETTINGS & operator=(const FILES_STORE_SETTINGS & rvalue);
+
+    const STG::ModuleSettings * settings;
+
+    int     User2UID(const char * user, uid_t * uid);
+    int     Group2GID(const char * gr, gid_t * gid);
+    int     Str2Mode(const char * str, mode_t * mode);
+    int     ParseOwner(const std::vector<STG::ParamValue> & moduleParams, const std::string & owner, uid_t * uid);
+    int     ParseGroup(const std::vector<STG::ParamValue> & moduleParams, const std::string & group, uid_t * uid);
+    int     ParseMode(const std::vector<STG::ParamValue> & moduleParams, const std::string & modeStr, mode_t * mode);
+    int     ParseYesNo(const std::string & value, bool * val);
+
+    std::string  errorStr;
+
+    std::string  workDir;
+    std::string  usersDir;
+    std::string  adminsDir;
+    std::string  tariffsDir;
+    std::string  servicesDir;
+
+    mode_t  statMode;
+    uid_t   statUID;
+    gid_t   statGID;
+
+    mode_t  confMode;
+    uid_t   confUID;
+    gid_t   confGID;
+
+    mode_t  userLogMode;
+    uid_t   userLogUID;
+    gid_t   userLogGID;
+
+    bool    removeBak;
+    bool    readBak;
+};
+//-----------------------------------------------------------------------------
+class FILES_STORE: public STG::Store {
+public:
+    FILES_STORE();
+    const std::string & GetStrError() const override { return errorStr; }
+
+    //User
+    int GetUsersList(std::vector<std::string> * usersList) const override;
+    int AddUser(const std::string & login) const override;
+    int DelUser(const std::string & login) const override;
+    int SaveUserStat(const STG::UserStat & stat, const std::string & login) const override;
+    int SaveUserConf(const STG::UserConf & conf, const std::string & login) const override;
+
+    int RestoreUserStat(STG::UserStat * stat, const std::string & login) const override;
+    int RestoreUserConf(STG::UserConf * conf, const std::string & login) const override;
+
+    int WriteUserChgLog(const std::string & login,
+                        const std::string & admLogin,
+                        uint32_t admIP,
+                        const std::string & paramName,
+                        const std::string & oldValue,
+                        const std::string & newValue,
+                        const std::string & message = "") const override;
+    int WriteUserConnect(const std::string & login, uint32_t ip) const override;
+    int WriteUserDisconnect(const std::string & login,
+                            const STG::DirTraff & up,
+                            const STG::DirTraff & down,
+                            const STG::DirTraff & sessionUp,
+                            const STG::DirTraff & sessionDown,
+                            double cash,
+                            double freeMb,
+                            const std::string & reason) const override;
+
+    int WriteDetailedStat(const STG::TraffStat & statTree,
+                          time_t lastStat,
+                          const std::string & login) const override;
+
+    int AddMessage(STG::Message * msg, const std::string & login) const override;
+    int EditMessage(const STG::Message & msg, const std::string & login) const override;
+    int GetMessage(uint64_t id, STG::Message * msg, const std::string & login) const override;
+    int DelMessage(uint64_t id, const std::string & login) const override;
+    int GetMessageHdrs(std::vector<STG::Message::Header> * hdrsList, const std::string & login) const override;
+
+    int SaveMonthStat(const STG::UserStat & stat, int month, int year, const std::string & login) const override;
+
+    //Admin
+    int GetAdminsList(std::vector<std::string> * adminsList) const override;
+    int AddAdmin(const std::string & login) const override;
+    int DelAdmin(const std::string & login) const override;
+    int RestoreAdmin(STG::AdminConf * ac, const std::string & login) const override;
+    int SaveAdmin(const STG::AdminConf & ac) const override;
+
+    //Tariff
+    int GetTariffsList(std::vector<std::string> * tariffsList) const override;
+    int AddTariff(const std::string & name) const override;
+    int DelTariff(const std::string & name) const override;
+    int SaveTariff(const STG::TariffData & td, const std::string & tariffName) const override;
+    int RestoreTariff(STG::TariffData * td, const std::string & tariffName) const override;
+
+    //Corparation
+    int GetCorpsList(std::vector<std::string> *) const override { return 0; }
+    int SaveCorp(const STG::CorpConf &) const override { return 0; }
+    int RestoreCorp(STG::CorpConf *, const std::string &) const override { return 0; }
+    int AddCorp(const std::string &) const override { return 0; }
+    int DelCorp(const std::string &) const override { return 0; }
+
+    // Services
+    int GetServicesList(std::vector<std::string> *) const override;
+    int SaveService(const STG::ServiceConf &) const override;
+    int RestoreService(STG::ServiceConf *, const std::string &) const override;
+    int AddService(const std::string &) const override;
+    int DelService(const std::string &) const override;
+
+    void SetSettings(const STG::ModuleSettings & s) override { settings = s; }
+    int ParseSettings() override;
+    const std::string & GetVersion() const override { return version; }
+
+private:
+    FILES_STORE(const FILES_STORE & rvalue);
+    FILES_STORE & operator=(const FILES_STORE & rvalue);
+
+    int ReadMessage(const std::string & fileName,
+                    STG::Message::Header * hdr,
+                    std::string * text) const;
+
+    virtual int RestoreUserStat(STG::UserStat * stat, const std::string & login, const std::string & fileName) const;
+    virtual int RestoreUserConf(STG::UserConf * conf, const std::string & login, const std::string & fileName) const;
+
+    virtual int WriteLogString(const std::string & str, const std::string & login) const;
+    virtual int WriteLog2String(const std::string & str, const std::string & login) const;
+    int RemoveDir(const char * path) const;
+    int Touch(const std::string & path) const;
+
+    mutable std::string errorStr;
+    std::string version;
+    FILES_STORE_SETTINGS storeSettings;
+    STG::ModuleSettings settings;
+    mutable pthread_mutex_t mutex;
+
+    STG::PluginLogger logger;
+};
diff --git a/projects/stargazer/plugins/store/firebird/firebird_store.cpp b/projects/stargazer/plugins/store/firebird/firebird_store.cpp
new file mode 100644 (file)
index 0000000..c11b442
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+/*
+ *  This file contains a realization of a base firebird-storage plugin class
+ *
+ *  $Revision: 1.18 $
+ *  $Date: 2010/01/08 16:00:45 $
+ *
+ */
+
+#include "firebird_store.h"
+
+#include "stg/common.h"
+
+#include <string>
+#include <vector>
+
+extern "C" STG::Store* GetStore()
+{
+    static FIREBIRD_STORE plugin;
+    return &plugin;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+FIREBIRD_STORE::FIREBIRD_STORE()
+    : version("firebird_store v.1.4"),
+      db_server("localhost"),
+      db_database("/var/stg/stargazer.fdb"),
+      db_user("stg"),
+      db_password("123456"),
+      til(IBPP::ilConcurrency),
+      tlr(IBPP::lrWait),
+      schemaVersion(0),
+      logger(STG::PluginLogger::get("store_firebird"))
+{
+pthread_mutex_init(&mutex, NULL);
+}
+//-----------------------------------------------------------------------------
+FIREBIRD_STORE::~FIREBIRD_STORE()
+{
+db->Disconnect();
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::ParseSettings()
+{
+std::vector<STG::ParamValue>::iterator i;
+std::string s;
+
+for(i = settings.moduleParams.begin(); i != settings.moduleParams.end(); ++i)
+    {
+    if (i->value.empty())
+        continue;
+    s = ToLower(i->param);
+
+    if (s == "server")
+        db_server = i->value.front();
+
+    if (s == "database")
+        db_database = i->value.front();
+
+    if (s == "user")
+        db_user = i->value.front();
+
+    if (s == "password")
+        db_password = i->value.front();
+
+    // Advanced settings block
+
+    if (s == "isolationLevel")
+        {
+        if (i->value.front() == "Concurrency")
+            til = IBPP::ilConcurrency;
+        else if (i->value.front() == "DirtyRead")
+            til = IBPP::ilReadDirty;
+        else if (i->value.front() == "ReadCommitted")
+            til = IBPP::ilReadCommitted;
+        else if (i->value.front() == "Consistency")
+            til = IBPP::ilConsistency;
+        }
+
+    if (s == "lockResolution")
+        {
+        if (i->value.front() == "Wait")
+            tlr = IBPP::lrWait;
+        else if (i->value.front() == "NoWait")
+            tlr = IBPP::lrNoWait;
+        }
+    }
+
+try
+    {
+    db = IBPP::DatabaseFactory(db_server, db_database, db_user, db_password, "", "KOI8U", "");
+    db->Connect();
+    return CheckVersion();
+    }
+catch (IBPP::Exception & ex)
+    {
+    strError = "IBPP exception";
+    printfd(__FILE__, ex.what());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::CheckVersion()
+{
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+    {
+    tr->Start();
+    st->Execute("SELECT RDB$RELATION_NAME FROM RDB$RELATIONS WHERE RDB$SYSTEM_FLAG=0 AND RDB$RELATION_NAME = 'TB_INFO'");
+    if (!st->Fetch())
+        {
+        schemaVersion = 0;
+        }
+    else
+        {
+        st->Execute("SELECT version FROM tb_info");
+        while (st->Fetch())
+            st->Get(1, schemaVersion);
+        }
+    tr->Commit();
+    logger("FIREBIRD_STORE: Current DB schema version: %d", schemaVersion);
+    }
+
+catch (IBPP::Exception & ex)
+    {
+    tr->Rollback();
+    strError = "IBPP exception";
+    printfd(__FILE__, ex.what());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
diff --git a/projects/stargazer/plugins/store/firebird/firebird_store.h b/projects/stargazer/plugins/store/firebird/firebird_store.h
new file mode 100644 (file)
index 0000000..14f0b26
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#pragma once
+
+#include "stg/store.h"
+#include "stg/locker.h"
+#include "stg/ibpp.h"
+#include "stg/logger.h"
+#include "stg/module_settings.h"
+
+#include <ctime>
+#include <string>
+#include <vector>
+
+struct ToLower {
+    char operator() (char c) const  { return static_cast<char>(std::tolower(c)); }
+};
+
+class FIREBIRD_STORE : public STG::Store {
+public:
+    FIREBIRD_STORE();
+    ~FIREBIRD_STORE() override;
+
+    int GetUsersList(std::vector<std::string> * usersList) const override;
+    int AddUser(const std::string & login) const override;
+    int DelUser(const std::string & login) const override;
+    int SaveUserStat(const STG::UserStat & stat, const std::string & login) const override;
+    int SaveUserConf(const STG::UserConf & conf, const std::string & login) const override;
+    int RestoreUserStat(STG::UserStat * stat, const std::string & login) const override;
+    int RestoreUserConf(STG::UserConf * conf, const std::string & login) const override;
+    int WriteUserChgLog(const std::string & login,
+                        const std::string & admLogin,
+                        uint32_t admIP,
+                        const std::string & paramName,
+                        const std::string & oldValue,
+                        const std::string & newValue,
+                        const std::string & message) const override;
+    int WriteUserConnect(const std::string & login, uint32_t ip) const override;
+    int WriteUserDisconnect(const std::string & login,
+                            const STG::DirTraff & up,
+                            const STG::DirTraff & down,
+                            const STG::DirTraff & sessionUp,
+                            const STG::DirTraff & sessionDown,
+                            double cash,
+                            double freeMb,
+                            const std::string & reason) const override;
+    int WriteDetailedStat(const STG::TraffStat & statTree,
+                          time_t lastStat,
+                          const std::string & login) const override;
+
+    int AddMessage(STG::Message * msg, const std::string & login) const override;
+    int EditMessage(const STG::Message & msg, const std::string & login) const override;
+    int GetMessage(uint64_t id, STG::Message * msg, const std::string & login) const override;
+    int DelMessage(uint64_t id, const std::string & login) const override;
+    int GetMessageHdrs(std::vector<STG::Message::Header> * hdrsList, const std::string & login) const override;
+
+    int SaveMonthStat(const STG::UserStat & stat, int month, int year, const std::string  & login) const override;
+
+    int GetAdminsList(std::vector<std::string> * adminsList) const override;
+    int SaveAdmin(const STG::AdminConf & ac) const override;
+    int RestoreAdmin(STG::AdminConf * ac, const std::string & login) const override;
+    int AddAdmin(const std::string & login) const override;
+    int DelAdmin(const std::string & login) const override;
+
+    int GetTariffsList(std::vector<std::string> * tariffsList) const override;
+    int AddTariff(const std::string & name) const override;
+    int DelTariff(const std::string & name) const override;
+    int SaveTariff(const STG::TariffData & td, const std::string & tariffName) const override;
+    int RestoreTariff(STG::TariffData * td, const std::string & tariffName) const override;
+
+    int GetCorpsList(std::vector<std::string> * corpsList) const override;
+    int SaveCorp(const STG::CorpConf & cc) const override;
+    int RestoreCorp(STG::CorpConf * cc, const std::string & name) const override;
+    int AddCorp(const std::string & name) const override;
+    int DelCorp(const std::string & name) const override;
+
+    inline void SetSettings(const STG::ModuleSettings & s) override { settings = s; }
+    int ParseSettings() override;
+
+    inline const std::string & GetStrError() const override { return strError; }
+
+    inline const std::string & GetVersion() const override { return version; }
+
+    int GetServicesList(std::vector<std::string> * servicesList) const override;
+    int SaveService(const STG::ServiceConf & sc) const override;
+    int RestoreService(STG::ServiceConf * sc, const std::string & name) const override;
+    int AddService(const std::string & name) const override;
+    int DelService(const std::string & name) const override;
+
+private:
+    FIREBIRD_STORE(const FIREBIRD_STORE & rvalue);
+    FIREBIRD_STORE & operator=(const FIREBIRD_STORE & rvalue);
+
+    std::string version;
+    mutable std::string strError;
+    std::string db_server, db_database, db_user, db_password;
+    STG::ModuleSettings settings;
+    mutable IBPP::Database db;
+    mutable pthread_mutex_t mutex;
+    IBPP::TIL til;
+    IBPP::TLR tlr;
+    int schemaVersion;
+    STG::PluginLogger logger;
+
+    int SaveStat(const STG::UserStat & stat, const std::string & login, int year = 0, int month = 0) const;
+    int CheckVersion();
+};
+
+time_t ts2time_t(const IBPP::Timestamp & ts);
+void time_t2ts(time_t t, IBPP::Timestamp * ts);
+void ym2date(int year, int month, IBPP::Date * date);
+
+template <typename T>
+inline
+T Get(IBPP::Statement st, size_t pos)
+{
+    T value;
+    st->Get(pos, value);
+    return value;
+}
diff --git a/projects/stargazer/plugins/store/firebird/firebird_store_admins.cpp b/projects/stargazer/plugins/store/firebird/firebird_store_admins.cpp
new file mode 100644 (file)
index 0000000..bb0bc0f
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+/*
+ *  Administrators manipulation methods
+ *
+ *  $Revision: 1.11 $
+ *  $Date: 2008/12/04 17:10:06 $
+ *
+ */
+
+#include "firebird_store.h"
+
+#include "stg/ibpp.h"
+#include "stg/admin_conf.h"
+#include "stg/blowfish.h"
+#include "stg/common.h"
+
+#include <string>
+#include <vector>
+
+#define adm_enc_passwd "cjeifY8m3"
+
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::GetAdminsList(std::vector<std::string> * adminsList) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+std::string login;
+
+try
+    {
+    tr->Start();
+    st->Execute("select login from tb_admins");
+    while (st->Fetch())
+        {
+        st->Get(1, login);
+        adminsList->push_back(login);
+        }
+    tr->Commit();
+    }
+
+catch (IBPP::Exception & ex)
+    {
+    tr->Rollback();
+    strError = "IBPP exception";
+    printfd(__FILE__, ex.what());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::SaveAdmin(const STG::AdminConf & ac) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+char encodedPass[2 * ADM_PASSWD_LEN + 2];
+char cryptedPass[ADM_PASSWD_LEN + 1];
+char adminPass[ADM_PASSWD_LEN + 1];
+BLOWFISH_CTX ctx;
+
+memset(cryptedPass, 0, ADM_PASSWD_LEN + 1);
+strncpy(adminPass, ac.password.c_str(), ADM_PASSWD_LEN);
+InitContext(adm_enc_passwd, sizeof(adm_enc_passwd), &ctx);
+
+for (int i = 0; i < ADM_PASSWD_LEN / 8; i++)
+    EncryptBlock(cryptedPass + 8 * i, adminPass + 8 * i, &ctx);
+
+cryptedPass[ADM_PASSWD_LEN] = 0;
+Encode12(encodedPass, cryptedPass, ADM_PASSWD_LEN);
+
+try
+    {
+    tr->Start();
+    st->Prepare("update tb_admins set passwd=?, \
+               chg_conf=?, \
+               chg_password=?, \
+               chg_stat=?, \
+               chg_cash=?, \
+               usr_add_del=?, \
+               chg_tariff=?, \
+               chg_admin=? \
+               where login=?");
+    st->Set(1, encodedPass);
+    st->Set(2, static_cast<int16_t>(ac.priv.userConf));
+    st->Set(3, static_cast<int16_t>(ac.priv.userPasswd));
+    st->Set(4, static_cast<int16_t>(ac.priv.userStat));
+    st->Set(5, static_cast<int16_t>(ac.priv.userCash));
+    st->Set(6, static_cast<int16_t>(ac.priv.userAddDel));
+    st->Set(7, static_cast<int16_t>(ac.priv.tariffChg));
+    st->Set(8, static_cast<int16_t>(ac.priv.adminChg));
+    st->Set(9, ac.login);
+    st->Execute();
+    tr->Commit();
+    }
+
+catch (IBPP::Exception & ex)
+    {
+    tr->Rollback();
+    strError = "IBPP exception";
+    printfd(__FILE__, ex.what());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::RestoreAdmin(STG::AdminConf * ac, const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+char cryptedPass[ADM_PASSWD_LEN + 1];
+char adminPass[ADM_PASSWD_LEN + 1];
+BLOWFISH_CTX ctx;
+
+try
+    {
+    tr->Start();
+    st->Prepare("select * from tb_admins where login = ?");
+    st->Set(1, login);
+    st->Execute();
+    if (st->Fetch())
+        {
+        st->Get(2, ac->login);
+        st->Get(3, ac->password);
+        st->Get(4, (int16_t &)ac->priv.userConf);
+        st->Get(5, (int16_t &)ac->priv.userPasswd);
+        st->Get(6, (int16_t &)ac->priv.userStat);
+        st->Get(7, (int16_t &)ac->priv.userCash);
+        st->Get(8, (int16_t &)ac->priv.userAddDel);
+        st->Get(9, (int16_t &)ac->priv.tariffChg);
+        st->Get(10, (int16_t &)ac->priv.adminChg);
+        }
+    else
+        {
+        strError = "Admin \"" + login + "\" not found in database";
+    printfd(__FILE__, "Admin '%s' not found in database\n", login.c_str());
+    tr->Rollback();
+        return -1;
+        }
+    tr->Commit();
+    }
+
+catch (IBPP::Exception & ex)
+    {
+    tr->Rollback();
+    strError = "IBPP exception";
+    printfd(__FILE__, ex.what());
+    return -1;
+    }
+
+if (ac->password == "")
+    {
+    return 0;
+    }
+
+Decode21(cryptedPass, ac->password.c_str());
+InitContext(adm_enc_passwd, sizeof(adm_enc_passwd), &ctx);
+for (int i = 0; i < ADM_PASSWD_LEN / 8; i++)
+    {
+    DecryptBlock(adminPass + 8 * i, cryptedPass + 8 * i, &ctx);
+    }
+ac->password = adminPass;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::AddAdmin(const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+    {
+    tr->Start();
+    st->Prepare("insert into tb_admins(login, \
+                    passwd, \
+                    chg_conf, \
+                    chg_password, \
+                    chg_stat, \
+                    chg_cash, \
+                    usr_add_del, \
+                    chg_tariff, \
+                    chg_admin, \
+                    chg_service, \
+                    chg_corporation) \
+                 values (?, '', 0, 0, 0, 0, 0, 0, 0, 0, 0)");
+    st->Set(1, login);
+    st->Execute();
+    tr->Commit();
+    }
+
+catch (IBPP::Exception & ex)
+    {
+    tr->Rollback();
+    strError = "IBPP exception";
+    printfd(__FILE__, ex.what());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::DelAdmin(const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+    {
+    tr->Start();
+    st->Prepare("delete from tb_admins where login = ?");
+    st->Set(1, login);
+    st->Execute();
+    tr->Commit();
+    }
+
+catch (IBPP::Exception & ex)
+    {
+    strError = "IBPP exception";
+    printfd(__FILE__, ex.what());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+
diff --git a/projects/stargazer/plugins/store/firebird/firebird_store_corporations.cpp b/projects/stargazer/plugins/store/firebird/firebird_store_corporations.cpp
new file mode 100644 (file)
index 0000000..3b9ad78
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+/*
+ *  Corporations manipulation methods
+ *
+ *  $Revision: 1.5 $
+ *  $Date: 2007/12/23 13:39:59 $
+ *
+ */
+
+#include "firebird_store.h"
+
+#include "stg/ibpp.h"
+#include "stg/corp_conf.h"
+#include "stg/common.h"
+
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::GetCorpsList(std::vector<std::string> * corpsList) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+std::string name;
+
+try
+    {
+    tr->Start();
+    st->Execute("select name from tb_corporations");
+    while (st->Fetch())
+        {
+        st->Get(1, name);
+        corpsList->push_back(name);
+        }
+    tr->Commit();
+    }
+
+catch (IBPP::Exception & ex)
+    {
+    tr->Rollback();
+    strError = "IBPP exception";
+    printfd(__FILE__, ex.what());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::SaveCorp(const STG::CorpConf & cc) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+    {
+    tr->Start();
+    st->Execute("update tb_corporations set cash = ? where name = ?");
+    st->Set(1, cc.cash);
+    st->Set(2, cc.name);
+    st->Execute();
+    tr->Commit();
+    }
+
+catch (IBPP::Exception & ex)
+    {
+    tr->Rollback();
+    strError = "IBPP exception";
+    printfd(__FILE__, ex.what());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::RestoreCorp(STG::CorpConf * cc, const std::string & name) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+    {
+    tr->Start();
+    st->Prepare("select cash from tb_corporations where name = ?");
+    st->Set(1, name);
+    st->Execute();
+    if (st->Fetch())
+        {
+        st->Get(1, cc->cash);
+        }
+    else
+        {
+        strError = "Corporation \"" + name + "\" not found in database";
+        tr->Rollback();
+    printfd(__FILE__, "Corporation '%s' not found in database\n", name.c_str());
+        return -1;
+        }
+    tr->Commit();
+    }
+
+catch (IBPP::Exception & ex)
+    {
+    tr->Rollback();
+    strError = "IBPP exception";
+    printfd(__FILE__, ex.what());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::AddCorp(const std::string & name) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+    {
+    tr->Start();
+    st->Prepare("insert into tb_corporations (name, cash), values (?, 0)");
+    st->Set(1, name);
+    st->Execute();
+    tr->Commit();
+    }
+
+catch (IBPP::Exception & ex)
+    {
+    tr->Rollback();
+    strError = "IBPP exception";
+    printfd(__FILE__, ex.what());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::DelCorp(const std::string & name) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+    {
+    tr->Start();
+    st->Prepare("delete from tb_corporations where name = ?");
+    st->Set(1, name);
+    st->Execute();
+    tr->Commit();
+    }
+
+catch (IBPP::Exception & ex)
+    {
+    tr->Rollback();
+    strError = "IBPP exception";
+    printfd(__FILE__, ex.what());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+
diff --git a/projects/stargazer/plugins/store/firebird/firebird_store_messages.cpp b/projects/stargazer/plugins/store/firebird/firebird_store_messages.cpp
new file mode 100644 (file)
index 0000000..90c3e57
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+
+/*
+ *  Messages manipualtion methods
+ *
+ *  $Revision: 1.10 $
+ *  $Date: 2009/03/03 16:16:23 $
+ *
+ */
+
+#include "firebird_store.h"
+
+#include "stg/ibpp.h"
+#include "stg/message.h"
+#include "stg/common.h"
+
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::AddMessage(STG::Message * msg, const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+    {
+    tr->Start();
+    st->Prepare("execute procedure sp_add_message(NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
+    st->Set(1, login);
+    st->Set(2, (int32_t)msg->header.ver);
+    st->Set(3, (int32_t)msg->header.type);
+    st->Set(4, (int32_t)msg->header.lastSendTime);
+    st->Set(5, (int32_t)msg->header.creationTime);
+    st->Set(6, (int32_t)msg->header.showTime);
+    st->Set(7, msg->header.repeat);
+    st->Set(8, (int32_t)msg->header.repeatPeriod);
+    st->Set(9, msg->text);
+    st->Execute();
+    st->Get(1, (int64_t &)msg->header.id);
+    tr->Commit();
+    }
+
+catch (IBPP::Exception & ex)
+    {
+    tr->Rollback();
+    strError = "IBPP exception";
+    printfd(__FILE__, ex.what());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::EditMessage(const STG::Message & msg,
+                                const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+    {
+    tr->Start();
+    st->Prepare("execute procedure sp_add_message(?, ?, ?, ?, ?, ?, ?, ?, ?)");
+    st->Set(1, (int64_t)msg.header.id);
+    st->Set(2, login);
+    st->Set(3, (int32_t)msg.header.ver);
+    st->Set(4, (int32_t)msg.header.type);
+    st->Set(5, (int32_t)msg.header.lastSendTime);
+    st->Set(6, (int32_t)msg.header.creationTime);
+    st->Set(7, (int32_t)msg.header.showTime);
+    st->Set(8, msg.header.repeat);
+    st->Set(9, (int32_t)msg.header.repeatPeriod);
+    st->Set(10, msg.text.c_str());
+    st->Execute();
+    tr->Commit();
+    }
+
+catch (IBPP::Exception & ex)
+    {
+    tr->Rollback();
+    strError = "IBPP exception";
+    printfd(__FILE__, ex.what());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::GetMessage(uint64_t id,
+                               STG::Message * msg,
+                               const std::string &) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+    {
+    tr->Start();
+    st->Prepare("select * from tb_messages where pk_message = ?");
+    st->Set(1, (int64_t)id);
+    st->Execute();
+    if (st->Fetch())
+        {
+        st->Get(1, (int64_t &)msg->header.id);
+        st->Get(3, (int32_t &)msg->header.ver);
+        st->Get(4, (int32_t &)msg->header.type);
+        st->Get(5, (int32_t &)msg->header.lastSendTime);
+        st->Get(6, (int32_t &)msg->header.creationTime);
+        st->Get(7, (int32_t &)msg->header.showTime);
+        st->Get(8, msg->header.repeat);
+        st->Get(9, (int32_t &)msg->header.repeatPeriod);
+        st->Get(10, msg->text);
+        }
+    else
+        {
+        strprintf(&strError, "Message with id = %d not found in database", id);
+    printfd(__FILE__, "Message with id - %d not found in database\n", id);
+        tr->Rollback();
+        return -1;
+        }
+    tr->Commit();
+    }
+
+catch (IBPP::Exception & ex)
+    {
+    tr->Rollback();
+    strError = "IBPP exception";
+    printfd(__FILE__, ex.what());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::DelMessage(uint64_t id, const std::string &) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+    {
+    tr->Start();
+    st->Prepare("delete from tb_messages where pk_message = ?");
+    st->Set(1, (int64_t)id);
+    st->Execute();
+    tr->Commit();
+    }
+
+catch (IBPP::Exception & ex)
+    {
+    tr->Rollback();
+    strError = "IBPP exception";
+    printfd(__FILE__, ex.what());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::GetMessageHdrs(std::vector<STG::Message::Header> * hdrsList,
+                                   const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+STG::Message::Header header;
+
+try
+    {
+    tr->Start();
+    st->Prepare("select pk_message, ver, msg_type, \
+                        last_send_time, creation_time, \
+            show_time, repeat, repeat_period \
+         from tb_messages where \
+                fk_user = (select pk_user from tb_users where name = ?)");
+    st->Set(1, login);
+    st->Execute();
+    while (st->Fetch())
+        {
+        st->Get(1, (int64_t &)header.id);
+        st->Get(2, (int32_t &)header.ver);
+        st->Get(3, (int32_t &)header.type);
+        st->Get(4, (int32_t &)header.lastSendTime);
+        st->Get(5, (int32_t &)header.creationTime);
+        st->Get(6, (int32_t &)header.showTime);
+        st->Get(7, header.repeat);
+        st->Get(8, (int32_t &)header.repeatPeriod);
+        hdrsList->push_back(header);
+        }
+    tr->Commit();
+    }
+
+catch (IBPP::Exception & ex)
+    {
+    tr->Rollback();
+    strError = "IBPP exception";
+    printfd(__FILE__, ex.what());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+
diff --git a/projects/stargazer/plugins/store/firebird/firebird_store_services.cpp b/projects/stargazer/plugins/store/firebird/firebird_store_services.cpp
new file mode 100644 (file)
index 0000000..0056879
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+
+/*
+ *  Services manipulation methods
+ *
+ *  $Revision: 1.6 $
+ *  $Date: 2009/05/13 13:19:33 $
+ *
+ */
+
+#include "firebird_store.h"
+
+#include "stg/ibpp.h"
+#include "stg/service_conf.h"
+#include "stg/common.h"
+
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::GetServicesList(std::vector<std::string> * servicesList) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+std::string name;
+
+try
+    {
+    tr->Start();
+    st->Execute("select name from tb_services");
+    while (st->Fetch())
+        {
+        st->Get(1, name);
+        servicesList->push_back(name);
+        }
+    tr->Commit();
+    }
+
+catch (IBPP::Exception & ex)
+    {
+    tr->Rollback();
+    strError = "IBPP exception";
+    printfd(__FILE__, ex.what());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::SaveService(const STG::ServiceConf & sc) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+    {
+    tr->Start();
+    st->Prepare("update tb_services set \
+            comments = ?, \
+            cost = ?, \
+            pay_day = ? \
+         where name = ?");
+    st->Set(1, sc.comment);
+    st->Set(2, sc.cost);
+    st->Set(3, static_cast<int16_t>(sc.payDay));
+    st->Set(4, sc.name);
+    st->Execute();
+    tr->Commit();
+    }
+
+catch (IBPP::Exception & ex)
+    {
+    tr->Rollback();
+    strError = "IBPP exception";
+    printfd(__FILE__, ex.what());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::RestoreService(STG::ServiceConf * sc,
+                                   const std::string & name) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+    {
+    tr->Start();
+    st->Prepare("select * from tb_services where name = ?");
+    st->Set(1, name);
+    st->Execute();
+    if (st->Fetch())
+        {
+        st->Get(3, sc->comment);
+        st->Get(4, sc->cost);
+        int16_t pd;
+        st->Get(5, pd);
+        sc->payDay = static_cast<uint8_t>(pd);
+        }
+    else
+        {
+        strError = "Service \"" + name + "\" not found in database";
+    printfd(__FILE__, "Service '%s' not found in database\n", name.c_str());
+        tr->Rollback();
+        return -1;
+        }
+    tr->Commit();
+    }
+
+catch (IBPP::Exception & ex)
+    {
+    tr->Rollback();
+    strError = "IBPP exception";
+    printfd(__FILE__, ex.what());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::AddService(const std::string & name) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+    {
+    tr->Start();
+    st->Prepare("insert into tb_services (name, comment, cost, pay_day) \
+            values (?, '', 0, 0)");
+    st->Set(1, name);
+    st->Execute();
+    tr->Commit();
+    }
+
+catch (IBPP::Exception & ex)
+    {
+    tr->Rollback();
+    strError = "IBPP exception";
+    printfd(__FILE__, ex.what());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::DelService(const std::string & name) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+    {
+    tr->Start();
+    st->Prepare("execute procedure sp_delete_service(?)");
+    st->Set(1, name);
+    st->Execute();
+    tr->Commit();
+    }
+
+catch (IBPP::Exception & ex)
+    {
+    tr->Rollback();
+    strError = "IBPP exception";
+    printfd(__FILE__, ex.what());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+
diff --git a/projects/stargazer/plugins/store/firebird/firebird_store_tariffs.cpp b/projects/stargazer/plugins/store/firebird/firebird_store_tariffs.cpp
new file mode 100644 (file)
index 0000000..10c45ab
--- /dev/null
@@ -0,0 +1,375 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+/*
+ *  Tariffs manipulation methods
+ *
+ *  $Revision: 1.5 $
+ *  $Date: 2007/12/23 13:39:59 $
+ *
+ */
+
+#include "firebird_store.h"
+
+#include "stg/ibpp.h"
+#include "stg/tariff.h"
+#include "stg/tariff_conf.h"
+#include "stg/common.h"
+
+#include <cmath>
+
+namespace
+{
+
+const int pt_mega = 1024 * 1024;
+
+}
+
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::GetTariffsList(std::vector<std::string> * tariffsList) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+std::string name;
+
+try
+    {
+    tr->Start();
+    st->Execute("select name from tb_tariffs");
+    while (st->Fetch())
+        {
+        st->Get(1, name);
+        tariffsList->push_back(name);
+        }
+    tr->Commit();
+    }
+
+catch (IBPP::Exception & ex)
+    {
+    tr->Rollback();
+    strError = "IBPP exception";
+    printfd(__FILE__, ex.what());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::AddTariff(const std::string & name) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+    {
+    tr->Start();
+    st->Prepare("execute procedure sp_add_tariff(?, ?)");
+    st->Set(1, name);
+    st->Set(2, DIR_NUM);
+    st->Execute();
+    tr->Commit();
+    }
+
+catch (IBPP::Exception & ex)
+    {
+    tr->Rollback();
+    strError = "IBPP exception";
+    printfd(__FILE__, ex.what());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::DelTariff(const std::string & name) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+    {
+    tr->Start();
+    st->Prepare("execute procedure sp_delete_tariff(?)");
+    st->Set(1, name);
+    st->Execute();
+    tr->Commit();
+    }
+
+catch (IBPP::Exception & ex)
+    {
+    tr->Rollback();
+    strError = "IBPP exception";
+    printfd(__FILE__, ex.what());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::SaveTariff(const STG::TariffData & td,
+                               const std::string & tariffName) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+    {
+    tr->Start();
+    st->Prepare("select pk_tariff from tb_tariffs where name = ?");
+    st->Set(1, tariffName);
+    st->Execute();
+    if (!st->Fetch())
+    {
+    tr->Rollback();
+    strprintf(&strError, "Tariff \"%s\" not found in database", tariffName.c_str());
+    printfd(__FILE__, "Tariff '%s' not found in database\n", tariffName.c_str());
+    return -1;
+    }
+    int32_t id;
+    st->Get(1, id);
+    st->Close();
+
+    std::string query = "update tb_tariffs set \
+                            fee = ?, \
+                            free = ?, \
+                            passive_cost = ?, \
+                            traff_type = ?";
+
+    if (schemaVersion > 0)
+        query += ", period = ?";
+    if (schemaVersion > 1)
+        query += ", change_policy = ?, \
+                    change_policy_timeout = ?";
+
+    query += " where pk_tariff = ?";
+
+    unsigned num = 5;
+    st->Prepare(query);
+    st->Set(1, td.tariffConf.fee);
+    st->Set(2, td.tariffConf.free);
+    st->Set(3, td.tariffConf.passiveCost);
+    st->Set(4, td.tariffConf.traffType);
+
+    if (schemaVersion > 0)
+        {
+        st->Set(5, STG::Tariff::toString(td.tariffConf.period));
+        ++num;
+        }
+
+    if (schemaVersion > 1)
+        {
+        st->Set(6, STG::Tariff::toString(td.tariffConf.changePolicy));
+        IBPP::Timestamp policyTimeout;
+        time_t2ts(td.tariffConf.changePolicyTimeout, &policyTimeout);
+        st->Set(7, policyTimeout);
+        num += 2;
+        }
+
+    st->Set(num, id);
+    st->Execute();
+    st->Close();
+
+    IBPP::Time tb;
+    IBPP::Time te;
+
+    for(int i = 0; i < DIR_NUM; i++)
+        {
+
+        tb.SetTime(td.dirPrice[i].hDay, td.dirPrice[i].mDay, 0);
+        te.SetTime(td.dirPrice[i].hNight, td.dirPrice[i].mNight, 0);
+
+        double pda = td.dirPrice[i].priceDayA * 1024 * 1024;
+        double pdb = td.dirPrice[i].priceDayB * 1024 * 1024;
+        double pna = 0;
+        double pnb = 0;
+
+        if (td.dirPrice[i].singlePrice)
+            {
+            pna = pda;
+            pnb = pdb;
+            }
+        else
+            {
+            pna = td.dirPrice[i].priceNightA;
+            pnb = td.dirPrice[i].priceNightB;
+            }
+
+        int threshold = 0;
+        if (td.dirPrice[i].noDiscount)
+            {
+            threshold = 0xffFFffFF;
+            }
+        else
+            {
+            threshold = td.dirPrice[i].threshold;
+            }
+
+        st->Prepare("update tb_tariffs_params set \
+                price_day_a = ?, \
+                price_day_b = ?, \
+                price_night_a = ?, \
+                price_night_b = ?, \
+                threshold = ?, \
+                time_day_begins = ?, \
+                time_day_ends = ? \
+                where fk_tariff = ? and dir_num = ?");
+        st->Set(1, pda);
+        st->Set(2, pdb);
+        st->Set(3, pna);
+        st->Set(4, pnb);
+        st->Set(5, threshold);
+        st->Set(6, tb);
+        st->Set(7, te);
+        st->Set(8, id);
+        st->Set(9, i);
+        st->Execute();
+        st->Close();
+        }
+    tr->Commit();
+    }
+
+catch (IBPP::Exception & ex)
+    {
+    tr->Rollback();
+    strError = "IBPP exception";
+    printfd(__FILE__, ex.what());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::RestoreTariff(STG::TariffData * td,
+                                  const std::string & tariffName) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+
+td->tariffConf.name = tariffName;
+
+try
+    {
+    tr->Start();
+    st->Prepare("select * from tb_tariffs where name = ?"); // TODO: explicit field order!
+    st->Set(1, tariffName);
+    st->Execute();
+    if (!st->Fetch())
+        {
+        strError = "Tariff \"" + tariffName + "\" not found in database";
+    printfd(__FILE__, "Tariff '%s' not found in database\n", tariffName.c_str());
+        tr->Rollback();
+        return -1;
+        }
+    int32_t id;
+    st->Get(1, id);
+    st->Get(3, td->tariffConf.fee);
+    st->Get(4, td->tariffConf.free);
+    st->Get(5, td->tariffConf.passiveCost);
+    td->tariffConf.traffType = STG::Tariff::fromInt(Get<int>(st, 6));
+    if (schemaVersion > 0)
+        td->tariffConf.period = STG::Tariff::parsePeriod(Get<std::string>(st, 7));
+    if (schemaVersion > 1)
+        {
+        td->tariffConf.changePolicy = STG::Tariff::parseChangePolicy(Get<std::string>(st, 8));
+        td->tariffConf.changePolicyTimeout = ts2time_t(Get<IBPP::Timestamp>(st, 9));
+        }
+    st->Close();
+    st->Prepare("select * from tb_tariffs_params where fk_tariff = ?");
+    st->Set(1, id);
+    st->Execute();
+    int i = 0;
+    while (st->Fetch())
+    {
+    i++;
+    if (i > DIR_NUM)
+        {
+        strError = "Too mach params for tariff \"" + tariffName + "\"";
+        printfd(__FILE__, "Too mach params for tariff '%s'\n", tariffName.c_str());
+        tr->Rollback();
+        return -1;
+        }
+    int16_t dir;
+    st->Get(3, dir);
+    st->Get(4, td->dirPrice[dir].priceDayA);
+    td->dirPrice[dir].priceDayA /= 1024*1024;
+    st->Get(5, td->dirPrice[dir].priceDayB);
+    td->dirPrice[dir].priceDayB /= 1024*1024;
+    st->Get(6, td->dirPrice[dir].priceNightA);
+    td->dirPrice[dir].priceNightA /= 1024*1024;
+    st->Get(7, td->dirPrice[dir].priceNightB);
+    td->dirPrice[dir].priceNightB /= 1024*1024;
+    st->Get(8, td->dirPrice[dir].threshold);
+    if (std::fabs(td->dirPrice[dir].priceDayA - td->dirPrice[dir].priceNightA) < 1.0e-3 / pt_mega &&
+        std::fabs(td->dirPrice[dir].priceDayB - td->dirPrice[dir].priceNightB) < 1.0e-3 / pt_mega)
+        {
+        td->dirPrice[dir].singlePrice = true;
+        }
+    else
+        {
+        td->dirPrice[dir].singlePrice = false;
+        }
+    if (td->dirPrice[dir].threshold == (int)0xffFFffFF)
+        {
+        td->dirPrice[dir].noDiscount = true;
+        }
+    else
+        {
+
+        td->dirPrice[dir].noDiscount = false;
+        }
+    IBPP::Time tb;
+    st->Get(9, tb);
+    IBPP::Time te;
+    st->Get(10, te);
+    int h, m, s;
+    tb.GetTime(h, m, s);
+    td->dirPrice[dir].hDay = h;
+    td->dirPrice[dir].mDay = m;
+    te.GetTime(h, m, s);
+    td->dirPrice[dir].hNight = h;
+    td->dirPrice[dir].mNight = m;
+    }
+    tr->Commit();
+    }
+
+catch (IBPP::Exception & ex)
+    {
+    tr->Rollback();
+    strError = "IBPP exception";
+    printfd(__FILE__, ex.what());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+
diff --git a/projects/stargazer/plugins/store/firebird/firebird_store_users.cpp b/projects/stargazer/plugins/store/firebird/firebird_store_users.cpp
new file mode 100644 (file)
index 0000000..ad28af3
--- /dev/null
@@ -0,0 +1,826 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+/*
+ *  User manipulation methods
+ *
+ *  $Revision: 1.19 $
+ *  $Date: 2010/01/19 11:07:25 $
+ *
+ */
+
+#include "firebird_store.h"
+
+#include "stg/ibpp.h"
+#include "stg/user_conf.h"
+#include "stg/user_stat.h"
+#include "stg/user_traff.h"
+#include "stg/user_ips.h"
+#include "stg/const.h"
+#include "stg/common.h"
+
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::GetUsersList(std::vector<std::string> * usersList) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+std::string name;
+
+try
+    {
+    tr->Start();
+    st->Execute("select name from tb_users");
+    while (st->Fetch())
+        {
+        st->Get(1, name);
+        usersList->push_back(name);
+        }
+    tr->Commit();
+    }
+
+catch (IBPP::Exception & ex)
+    {
+    tr->Rollback();
+    strError = "IBPP exception";
+    printfd(__FILE__, ex.what());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::AddUser(const std::string & name) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+    {
+    tr->Start();
+    st->Prepare("execute procedure sp_add_user(?, ?)");
+    st->Set(1, name);
+    st->Set(2, DIR_NUM);
+    st->Execute();
+    tr->Commit();
+    }
+
+catch (IBPP::Exception & ex)
+    {
+    tr->Rollback();
+    strError = "IBPP exception";
+    printfd(__FILE__, ex.what());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::DelUser(const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+    {
+    tr->Start();
+    st->Prepare("execute procedure sp_delete_user(?)");
+    st->Set(1, login);
+    st->Execute();
+    tr->Commit();
+    }
+
+catch (IBPP::Exception & ex)
+    {
+    tr->Rollback();
+    strError = "IBPP exception";
+    printfd(__FILE__, ex.what());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::SaveUserStat(const STG::UserStat & stat,
+                                 const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+return SaveStat(stat, login);
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::SaveStat(const STG::UserStat & stat,
+                             const std::string & login,
+                             int year,
+                             int month) const
+{
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+    {
+    tr->Start();
+    st->Prepare("select pk_user from tb_users where name = ?");
+    st->Set(1, login);
+    st->Execute();
+    if (!st->Fetch())
+    {
+    strError = "User \"" + login + "\" not found in database";
+    printfd(__FILE__, "User '%s' not found in database\n", login.c_str());
+    tr->Rollback();
+    return -1;
+    }
+    int32_t uid = Get<int32_t>(st, 1);
+    st->Close();
+    st->Prepare("select first 1 pk_stat from tb_stats where fk_user = ? order by stats_date desc");
+    st->Set(1, uid);
+    st->Execute();
+    if (!st->Fetch())
+    {
+    tr->Rollback();
+    strError = "No stat info for user \"" + login + "\"";
+    printfd(__FILE__, "No stat info for user '%s'\n", login.c_str());
+    return -1;
+    }
+    int32_t sid;
+    st->Get(1, sid);
+    st->Close();
+
+    IBPP::Timestamp actTime;
+    time_t2ts(stat.lastActivityTime, &actTime);
+    IBPP::Timestamp addTime;
+    time_t2ts(stat.lastCashAddTime, &addTime);
+    IBPP::Date dt;
+    if (year != 0)
+        ym2date(year, month, &dt);
+    else
+        dt.Today();
+
+    st->Prepare("update tb_stats set \
+                    cash = ?, \
+                    free_mb = ?, \
+                    last_activity_time = ?, \
+                    last_cash_add = ?, \
+                    last_cash_add_time = ?, \
+                    passive_time = ?, \
+                    stats_date = ? \
+                 where pk_stat = ?");
+
+    st->Set(1, stat.cash);
+    st->Set(2, stat.freeMb);
+    st->Set(3, actTime);
+    st->Set(4, stat.lastCashAdd);
+    st->Set(5, addTime);
+    st->Set(6, (int32_t)stat.passiveTime);
+    st->Set(7, dt);
+    st->Set(8, sid);
+
+    st->Execute();
+    st->Close();
+
+    for(int i = 0; i < DIR_NUM; i++)
+        {
+        st->Prepare("update tb_stats_traffic set \
+                        upload = ?, \
+                        download = ? \
+                     where fk_stat = ? and dir_num = ?");
+        st->Set(1, (int64_t)stat.monthUp[i]);
+        st->Set(2, (int64_t)stat.monthDown[i]);
+        st->Set(3, sid);
+        st->Set(4, i);
+        st->Execute();
+        st->Close();
+        }
+
+    tr->Commit();
+    }
+
+catch (IBPP::Exception & ex)
+    {
+    tr->Rollback();
+    strError = "IBPP exception";
+    printfd(__FILE__, ex.what());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::SaveUserConf(const STG::UserConf & conf,
+                                 const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+    {
+    tr->Start();
+    st->Prepare("select pk_user from tb_users where name = ?");
+    st->Set(1, login);
+    st->Execute();
+    if (!st->Fetch())
+        {
+        strError = "User \"" + login + "\" not found in database";
+        printfd(__FILE__, "User '%s' not found in database\n", login.c_str());
+        tr->Rollback();
+        return -1;
+        }
+    int32_t uid;
+    st->Get(1, uid);
+    st->Close();
+
+    IBPP::Timestamp creditExpire;
+    time_t2ts(conf.creditExpire, &creditExpire);
+
+    st->Prepare("update tb_users set \
+                    address = ?, \
+                    always_online = ?, \
+                    credit = ?, \
+                    credit_expire = ?, \
+                    disabled = ?, \
+                    disabled_detail_stat = ?, \
+                    email = ?, \
+                    grp = ?, \
+                    note = ?, \
+                    passive = ?, \
+                    passwd = ?, \
+                    phone = ?, \
+                    fk_tariff = (select pk_tariff from tb_tariffs \
+                                 where name = ?), \
+                    fk_tariff_change = (select pk_tariff from tb_tariffs \
+                                        where name = ?), \
+                    fk_corporation = (select pk_corporation from tb_corporations \
+                                      where name = ?), \
+                    real_name = ? \
+                 where pk_user = ?");
+
+    st->Set(1, conf.address);
+    st->Set(2, (bool)conf.alwaysOnline);
+    st->Set(3, conf.credit);
+    st->Set(4, creditExpire);
+    st->Set(5, (bool)conf.disabled);
+    st->Set(6, (bool)conf.disabledDetailStat);
+    st->Set(7, conf.email);
+    st->Set(8, conf.group);
+    st->Set(9, conf.note);
+    st->Set(10, (bool)conf.passive);
+    st->Set(11, conf.password);
+    st->Set(12, conf.phone);
+    st->Set(13, conf.tariffName);
+    st->Set(14, conf.nextTariff);
+    st->Set(15, conf.corp);
+    st->Set(16, conf.realName);
+    st->Set(17, uid);
+
+    st->Execute();
+    st->Close();
+
+    st->Prepare("delete from tb_users_services where fk_user = ?");
+    st->Set(1, uid);
+    st->Execute();
+    st->Close();
+
+    st->Prepare("insert into tb_users_services (fk_user, fk_service) \
+                    values (?, (select pk_service from tb_services \
+                                where name = ?))");
+    for(std::vector<std::string>::const_iterator it = conf.services.begin(); it != conf.services.end(); ++it)
+        {
+        st->Set(1, uid);
+        st->Set(2, *it);
+        st->Execute();
+        }
+    st->Close();
+
+    st->Prepare("delete from tb_users_data where fk_user = ?");
+    st->Set(1, uid);
+    st->Execute();
+    st->Close();
+
+    int i = 0;
+    st->Prepare("insert into tb_users_data (fk_user, data, num) values (?, ?, ?)");
+    for (std::vector<std::string>::const_iterator it = conf.userdata.begin(); it != conf.userdata.end(); ++it)
+        {
+        st->Set(1, uid);
+        st->Set(2, *it);
+        st->Set(3, i++);
+        st->Execute();
+        }
+    st->Close();
+
+    st->Prepare("delete from tb_allowed_ip where fk_user = ?");
+    st->Set(1, uid);
+    st->Execute();
+
+    st->Prepare("insert into tb_allowed_ip (fk_user, ip, mask) values (?, ?, ?)");
+    for(size_t i = 0; i < conf.ips.count(); i++)
+        {
+        st->Set(1, uid);
+        st->Set(2, (int32_t)conf.ips[i].ip);
+        st->Set(3, (int32_t)conf.ips[i].mask);
+        st->Execute();
+        }
+    tr->Commit();
+    }
+catch (IBPP::Exception & ex)
+    {
+    tr->Rollback();
+    strError = "IBPP exception";
+    printfd(__FILE__, ex.what());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::RestoreUserStat(STG::UserStat * stat,
+                                    const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+    {
+    tr->Start();
+    st->Prepare("select pk_user from tb_users where name = ?");
+    st->Set(1, login);
+    st->Execute();
+    if (!st->Fetch())
+        {
+        strError = "User \"" + login + "\" not found in database";
+        printfd(__FILE__, "User '%s' not found in database\n", login.c_str());
+        return -1;
+        }
+    int32_t uid;
+    st->Get(1, uid);
+    st->Close();
+
+    st->Prepare("select first 1 pk_stat, cash, free_mb, last_activity_time, \
+                    last_cash_add, last_cash_add_time, passive_time from tb_stats \
+                 where fk_user = ? order by stats_date desc");
+    st->Set(1, uid);
+    st->Execute();
+    if (!st->Fetch())
+        {
+        strError = "No stat info for user \"" + login + "\"";
+        printfd(__FILE__, "No stat info for user '%s'\n", login.c_str());
+        tr->Rollback();
+        return -1;
+        }
+
+    int32_t sid;
+    st->Get(1, sid);
+    st->Get(2, stat->cash);
+    st->Get(3, stat->freeMb);
+    IBPP::Timestamp actTime;
+    st->Get(4, actTime);
+    st->Get(5, stat->lastCashAdd);
+    IBPP::Timestamp addTime;
+    st->Get(6, addTime);
+    int32_t passiveTime;
+    st->Get(7, passiveTime);
+
+    stat->passiveTime = passiveTime;
+
+    stat->lastActivityTime = ts2time_t(actTime);
+
+    stat->lastCashAddTime = ts2time_t(addTime);
+
+    st->Close();
+    st->Prepare("select * from tb_stats_traffic where fk_stat = ?");
+    st->Set(1, sid);
+    st->Execute();
+    for(int i = 0; i < DIR_NUM; i++)
+        {
+        if (st->Fetch())
+            {
+            int dir;
+            st->Get(3, dir);
+            st->Get(5, (int64_t &)stat->monthUp[dir]);
+            st->Get(4, (int64_t &)stat->monthDown[dir]);
+            }
+        else
+            {
+            break;
+            }
+        }
+    tr->Commit();
+    }
+
+catch (IBPP::Exception & ex)
+    {
+    tr->Rollback();
+    strError = "IBPP exception";
+    printfd(__FILE__, ex.what());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::RestoreUserConf(STG::UserConf * conf,
+                                    const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+try
+    {
+    tr->Start();
+    st->Prepare("select tb_users.pk_user, tb_users.address, tb_users.always_online, \
+                        tb_users.credit, tb_users.credit_expire, tb_users.disabled, \
+                        tb_users.disabled_detail_stat, tb_users.email, tb_users.grp, \
+                        tb_users.note, tb_users.passive, tb_users.passwd, tb_users.phone, \
+                        tb_users.real_name, tf1.name, tf2.name, tb_corporations.name \
+                 from tb_users left join tb_tariffs tf1 \
+                 on tf1.pk_tariff = tb_users.fk_tariff \
+                 left join tb_tariffs tf2 \
+                 on tf2.pk_tariff = tb_users.fk_tariff_change \
+                 left join tb_corporations \
+                 on tb_corporations.pk_corporation = tb_users.fk_corporation \
+                 where tb_users.name = ?");
+    st->Set(1, login);
+    st->Execute();
+    if (!st->Fetch())
+        {
+        strError = "User \"" + login + "\" not found in database";
+    printfd(__FILE__, "User '%s' not found in database", login.c_str());
+        tr->Rollback();
+        return -1;
+        }
+    int32_t uid;
+    st->Get(1, uid);
+    // Getting base config
+    st->Get(2, conf->address);
+    bool test;
+    st->Get(3, test);
+    conf->alwaysOnline = test;
+    st->Get(4, conf->credit);
+    IBPP::Timestamp timestamp;
+    st->Get(5, timestamp);
+
+    conf->creditExpire = ts2time_t(timestamp);
+
+    st->Get(6, test);
+    conf->disabled = test;
+    st->Get(7, test);
+    conf->disabledDetailStat = test;
+    st->Get(8, conf->email);
+    st->Get(9, conf->group);
+    st->Get(10, conf->note);
+    st->Get(11, test);
+    conf->passive = test;
+    st->Get(12, conf->password);
+    st->Get(13, conf->phone);
+    st->Get(14, conf->realName);
+    st->Get(15, conf->tariffName);
+    st->Get(16, conf->nextTariff);
+    st->Get(17, conf->corp);
+
+    if (conf->tariffName == "")
+        conf->tariffName = NO_TARIFF_NAME;
+    if (conf->corp == "")
+        conf->corp = NO_CORP_NAME;
+
+    // Services
+    st->Close();
+    st->Prepare("select name from tb_services \
+                 where pk_service in \
+                    (select fk_service from tb_users_services \
+                     where fk_user = ?)");
+    st->Set(1, uid);
+    st->Execute();
+    while (st->Fetch())
+        {
+        std::string name;
+        st->Get(1, name);
+        conf->services.push_back(name);
+        }
+
+    // User data
+    st->Close();
+    st->Prepare("select data, num from tb_users_data where fk_user = ? order by num");
+    st->Set(1, uid);
+    st->Execute();
+    while (st->Fetch())
+        {
+        int i;
+        st->Get(2, i);
+        st->Get(1, conf->userdata[i]);
+        }
+
+    // User IPs
+    st->Close();
+    st->Prepare("select ip, mask from tb_allowed_ip \
+                 where fk_user = ?");
+    st->Set(1, uid);
+    st->Execute();
+    STG::UserIPs ips;
+    while (st->Fetch())
+        {
+        STG::IPMask im;
+        st->Get(1, (int32_t &)im.ip);
+        st->Get(2, (int32_t &)im.mask);
+        ips.add(im);
+        }
+    conf->ips = ips;
+
+    tr->Commit();
+    }
+catch (IBPP::Exception & ex)
+    {
+    tr->Rollback();
+    strError = "IBPP exception";
+    printfd(__FILE__, ex.what());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::WriteUserChgLog(const std::string & login,
+                                    const std::string & admLogin,
+                                    uint32_t admIP,
+                                    const std::string & paramName,
+                                    const std::string & oldValue,
+                                    const std::string & newValue,
+                                    const std::string & message = "") const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+IBPP::Timestamp now;
+now.Now();
+
+std::string temp = ""; // Composed message for log
+
+try
+    {
+    tr->Start();
+    temp += "Admin \"" + admLogin + "\", ";
+    temp += inet_ntostring(admIP);
+    temp += ": ";
+    temp = temp + message;
+    //----------------------------------------------------------------------------------------
+    // Checking and inserting parameters in params table
+    st->Prepare("select pk_parameter from tb_parameters where name = ?");
+    st->Set(1, paramName);
+    st->Execute();
+    if (!st->Fetch())
+        {
+        st->Close();
+        st->Prepare("insert into tb_parameters (name) values (?)");
+        st->Set(1, paramName);
+        st->Execute();
+        }
+    st->Close();
+    //----------------------------------------------------------------------------------------
+    st->Prepare("insert into tb_params_log \
+                    (fk_user, fk_parameter, event_time, from_val, to_val, comment) \
+                 values ((select pk_user from tb_users \
+                          where name = ?), \
+                         (select pk_parameter from tb_parameters \
+                          where name = ?), \
+                         ?, ?, ?, ?)");
+    st->Set(1, login);
+    st->Set(2, paramName);
+    st->Set(3, now);
+    st->Set(4, oldValue);
+    st->Set(5, newValue);
+    st->Set(6, temp);
+    st->Execute();
+    tr->Commit();
+    }
+
+catch (IBPP::Exception & ex)
+    {
+    tr->Rollback();
+    strError = "IBPP exception";
+    printfd(__FILE__, ex.what());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::WriteUserConnect(const std::string & login, uint32_t ip) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+IBPP::Timestamp now;
+now.Now();
+
+try
+    {
+    tr->Start();
+    st->Prepare("execute procedure sp_append_session_log(?, ?, 'c', ?)");
+    st->Set(1, login);
+    st->Set(2, now);
+    st->Set(3, (int32_t)ip);
+    tr->Commit();
+    }
+
+catch (IBPP::Exception & ex)
+    {
+    tr->Rollback();
+    strError = "IBPP exception";
+    printfd(__FILE__, ex.what());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::WriteUserDisconnect(const std::string & login,
+                    const STG::DirTraff & up,
+                    const STG::DirTraff & down,
+                    const STG::DirTraff & sessionUp,
+                    const STG::DirTraff & sessionDown,
+                    double /*cash*/,
+                    double /*freeMb*/,
+                    const std::string & /*reason*/) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+IBPP::Timestamp now;
+now.Now();
+
+try
+    {
+    tr->Start();
+    st->Prepare("execute procedure sp_append_session_log(?, ?, 'd', 0)");
+    st->Set(1, login);
+    st->Set(2, now);
+    st->Execute();
+    int32_t id;
+    st->Get(1, id);
+    st->Prepare("insert into tb_sessions_data \
+                    (fk_session_log, dir_num, session_upload, \
+                     session_download, month_upload, month_download) \
+                 values (?, ?, ?, ?, ?, ?)");
+    for(int i = 0; i < DIR_NUM; i++)
+        {
+        st->Set(1, id);
+        st->Set(2, i);
+        st->Set(3, (int64_t)sessionUp[i]);
+        st->Set(4, (int64_t)sessionDown[i]);
+        st->Set(5, (int64_t)up[i]);
+        st->Set(6, (int64_t)down[i]);
+        st->Execute();
+        }
+    tr->Commit();
+    }
+
+catch (IBPP::Exception & ex)
+    {
+    tr->Rollback();
+    strError = "IBPP exception";
+    printfd(__FILE__, ex.what());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::WriteDetailedStat(const STG::TraffStat & statTree,
+                                      time_t lastStat,
+                                      const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+IBPP::Timestamp statTime, now;
+now.Now();
+
+time_t2ts(lastStat, &statTime);
+
+try
+    {
+    tr->Start();
+    STG::TraffStat::const_iterator it;
+    it = statTree.begin();
+    st->Prepare("insert into tb_detail_stats \
+                    (till_time, from_time, fk_user, dir_num, \
+                     ip, download, upload, cost) \
+                 values (?, ?, (select pk_user from tb_users \
+                                where name = ?), \
+                     ?, ?, ?, ?, ?)");
+    while (it != statTree.end())
+        {
+        st->Set(1, now);
+        st->Set(2, statTime);
+        st->Set(3, login);
+        st->Set(4, it->first.dir);
+        st->Set(5, (int32_t)it->first.ip);
+        st->Set(6, (int64_t)it->second.down);
+        st->Set(7, (int64_t)it->second.up);
+        st->Set(8, it->second.cash);
+        st->Execute();
+        ++it;
+        }
+    tr->Commit();
+    }
+
+catch (IBPP::Exception & ex)
+    {
+    tr->Rollback();
+    strError = "IBPP exception";
+    printfd(__FILE__, ex.what());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int FIREBIRD_STORE::SaveMonthStat(const STG::UserStat & stat, int month, int year, const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
+IBPP::Statement st = IBPP::StatementFactory(db, tr);
+
+IBPP::Timestamp now;
+IBPP::Date nowDate;
+nowDate.Today();
+now.Now();
+
+if (SaveStat(stat, login, year, month))
+    {
+    return -1;
+    }
+
+try
+    {
+    tr->Start();
+
+    st->Prepare("execute procedure sp_add_stat(?, 0, 0, ?, 0, ?, 0, ?)");
+    st->Set(1, login);
+    st->Set(2, now);
+    st->Set(3, now);
+    st->Set(4, nowDate);
+
+    st->Execute();
+    int32_t id;
+    st->Get(1, id);
+    st->Close();
+
+    st->Prepare("insert into tb_stats_traffic \
+                    (fk_stat, dir_num, upload, download) \
+                 values (?, ?, 0, 0)");
+
+    for(int i = 0; i < DIR_NUM; i++)
+        {
+        st->Set(1, id);
+        st->Set(2, i);
+        st->Execute();
+        }
+
+    tr->Commit();
+    }
+catch (IBPP::Exception & ex)
+    {
+    tr->Rollback();
+    strError = "IBPP exception";
+    printfd(__FILE__, ex.what());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+
diff --git a/projects/stargazer/plugins/store/firebird/firebird_store_utils.cpp b/projects/stargazer/plugins/store/firebird/firebird_store_utils.cpp
new file mode 100644 (file)
index 0000000..582c544
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+/*
+ *  Vairous utility methods
+ *
+ *  $Revision: 1.8 $
+ *  $Date: 2010/03/04 12:20:32 $
+ *
+ */
+
+#include "firebird_store.h"
+
+#include "stg/ibpp.h"
+#include "stg/common.h"
+
+#include <cstdio>
+
+//-----------------------------------------------------------------------------
+time_t ts2time_t(const IBPP::Timestamp & ts)
+{
+    char buf[32];
+    int year, month, day, hour, min, sec;
+    struct tm time_tm;
+
+    memset(&time_tm, 0, sizeof(time_tm));
+    ts.GetDate(year, month, day);
+    ts.GetTime(hour, min, sec);
+    if (year < 1990)
+        return 0;
+    sprintf(buf, "%d-%d-%d %d:%d:%d", year, month, day, hour, min, sec);
+    stg_strptime(buf, "%Y-%m-%d %H:%M:%S", &time_tm);
+
+    return mktime(&time_tm);
+}
+//-----------------------------------------------------------------------------
+void time_t2ts(time_t t, IBPP::Timestamp * ts)
+{
+    struct tm res;
+
+    localtime_r(&t, &res); // Reenterable
+
+    *ts = IBPP::Timestamp(res.tm_year + 1900, res.tm_mon + 1, res.tm_mday, res.tm_hour, res.tm_min, res.tm_sec);
+}
+//-----------------------------------------------------------------------------
+void ym2date(int year, int month, IBPP::Date * date)
+{
+    date->SetDate(year + 1900, month + 1, 1);
+    date->EndOfMonth();
+}
+//-----------------------------------------------------------------------------
diff --git a/projects/stargazer/plugins/store/mysql/mysql_store.cpp b/projects/stargazer/plugins/store/mysql/mysql_store.cpp
new file mode 100644 (file)
index 0000000..3ad79b3
--- /dev/null
@@ -0,0 +1,2153 @@
+#include "mysql_store.h"
+
+#include "stg/common.h"
+#include "stg/user_ips.h"
+#include "stg/user_conf.h"
+#include "stg/user_stat.h"
+#include "stg/admin_conf.h"
+#include "stg/tariff_conf.h"
+#include "stg/blowfish.h"
+#include "stg/logger.h"
+
+#include <algorithm>
+#include <sys/time.h>
+#include <cerrno>
+#include <cstdio>
+#include <cstdlib>
+
+#include <mysql/errmsg.h>
+
+#define adm_enc_passwd "cjeifY8m3"
+
+namespace
+{
+char qbuf[4096];
+
+const int pt_mega = 1024 * 1024;
+const std::string badSyms = "'`";
+const char repSym = '\"';
+const int RepitTimes = 3;
+
+template <typename T>
+int GetInt(const std::string & str, T * val, T defaultVal = T())
+{
+    char *res;
+    
+    *val = static_cast<T>(strtoll(str.c_str(), &res, 10));
+    
+    if (*res != 0) 
+    {
+        *val = defaultVal; //Error!
+        return EINVAL;
+    }
+
+    return 0;
+}
+
+int GetDouble(const std::string & str, double * val, double defaultVal)
+{
+    char *res;
+    
+    *val = strtod(str.c_str(), &res);
+    
+    if (*res != 0) 
+    {
+        *val = defaultVal; //Error!
+        return EINVAL;
+    }
+
+    return 0;
+}
+
+int GetTime(const std::string & str, time_t * val, time_t defaultVal)
+{
+    char *res;
+    
+    *val = strtol(str.c_str(), &res, 10);
+    
+    if (*res != 0) 
+    {
+        *val = defaultVal; //Error!
+        return EINVAL;
+    }
+
+    return 0;
+}
+
+//-----------------------------------------------------------------------------
+std::string ReplaceStr(std::string source, const std::string & symlist, const char chgsym)
+{
+    std::string::size_type pos=0;
+
+    while( (pos = source.find_first_of(symlist,pos)) != std::string::npos)
+        source.replace(pos, 1,1, chgsym);
+
+    return source;
+}
+
+int GetULongLongInt(const std::string & str, uint64_t * val, uint64_t defaultVal)
+{
+    char *res;
+    
+    *val = strtoull(str.c_str(), &res, 10);
+    
+    if (*res != 0) 
+    {
+        *val = defaultVal; //Error!
+        return EINVAL;
+    }
+
+    return 0;
+} 
+
+}
+
+extern "C" STG::Store* GetStore()
+{
+    static MYSQL_STORE plugin;
+    return &plugin;
+}
+//-----------------------------------------------------------------------------
+MYSQL_STORE_SETTINGS::MYSQL_STORE_SETTINGS()
+    : settings(NULL)
+{
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE_SETTINGS::ParseParam(const std::vector<STG::ParamValue> & moduleParams,
+                                     const std::string & name, std::string & result)
+{
+STG::ParamValue pv;
+pv.param = name;
+std::vector<STG::ParamValue>::const_iterator pvi;
+pvi = find(moduleParams.begin(), moduleParams.end(), pv);
+if (pvi == moduleParams.end() || pvi->value.empty())
+    {
+    errorStr = "Parameter \'" + name + "\' not found.";
+    return -1;
+    }
+
+result = pvi->value[0];
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE_SETTINGS::ParseSettings(const STG::ModuleSettings & s)
+{
+if (ParseParam(s.moduleParams, "user", dbUser) < 0 &&
+    ParseParam(s.moduleParams, "dbuser", dbUser) < 0)
+    return -1;
+if (ParseParam(s.moduleParams, "password", dbPass) < 0 &&
+    ParseParam(s.moduleParams, "rootdbpass", dbPass) < 0)
+    return -1;
+if (ParseParam(s.moduleParams, "database", dbName) < 0 &&
+    ParseParam(s.moduleParams, "dbname", dbName) < 0)
+    return -1;
+if (ParseParam(s.moduleParams, "server", dbHost) < 0 &&
+    ParseParam(s.moduleParams, "dbhost", dbHost) < 0)
+    return -1;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+MYSQL_STORE::MYSQL_STORE()
+    : version("mysql_store v.0.67"),
+      schemaVersion(0),
+      logger(STG::PluginLogger::get("store_mysql"))
+{
+}
+//-----------------------------------------------------------------------------
+int    MYSQL_STORE::MysqlQuery(const char* sQuery,MYSQL * sock) const
+{
+    int ret;
+
+    if( (ret = mysql_query(sock,sQuery)) )
+    {
+        for(int i=0; i<RepitTimes; i++)
+        {
+            if( (ret = mysql_query(sock,sQuery)) )
+                ;//need to send error result
+            else
+                return 0;
+        }
+    }
+    
+    return ret;
+}
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::ParseSettings()
+{
+int ret = storeSettings.ParseSettings(settings);
+MYSQL mysql;
+mysql_init(&mysql);
+if (ret)
+    errorStr = storeSettings.GetStrError();
+else
+{
+    if(storeSettings.GetDBPassword().length() == 0)
+    {
+        errorStr = "Database password must be not empty. Please read Manual.";
+        return -1;
+    }
+    MYSQL * sock;
+    if (!(sock = mysql_real_connect(&mysql,storeSettings.GetDBHost().c_str(),
+            storeSettings.GetDBUser().c_str(),storeSettings.GetDBPassword().c_str(),
+            0,0,NULL,0)))
+        {
+            errorStr = "Couldn't connect to mysql engine! With error:\n";
+            errorStr += mysql_error(&mysql);
+            mysql_close(sock);
+            ret = -1;
+        }
+    else
+    {
+         if(mysql_select_db(sock, storeSettings.GetDBName().c_str()))
+         {
+             std::string res = "CREATE DATABASE " + storeSettings.GetDBName();
+            
+            if(MysqlQuery(res.c_str(),sock))
+            {
+                errorStr = "Couldn't create database! With error:\n";
+                errorStr += mysql_error(sock);
+                mysql_close(sock);
+                ret = -1;
+            }
+            else
+            {
+                 if(mysql_select_db(sock, storeSettings.GetDBName().c_str()))
+                 {
+                     errorStr = "Couldn't select database! With error:\n";
+                     errorStr += mysql_error(sock);
+                     mysql_close(sock);
+                     ret = -1;
+                 }
+                 else
+                     ret = CheckAllTables(sock);
+            }
+        }
+        else
+        {
+            ret = CheckAllTables(sock);
+        }
+        if (!ret)
+        {
+            logger("MYSQL_STORE: Current DB schema version: %d", schemaVersion);
+            MakeUpdates(sock);
+        }
+        mysql_close(sock);
+    }
+}
+return ret;
+}
+//-----------------------------------------------------------------------------
+bool MYSQL_STORE::IsTablePresent(const std::string & str,MYSQL * sock)
+{
+MYSQL_RES* result;
+
+if (!(result=mysql_list_tables(sock,str.c_str() )))
+{
+    errorStr = "Couldn't get tables list With error:\n";
+    errorStr += mysql_error(sock);
+    mysql_close(sock);
+    return -1;
+}
+
+my_ulonglong num_rows =  mysql_num_rows(result);
+
+if(result)
+    mysql_free_result(result);
+
+return num_rows == 1;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::CheckAllTables(MYSQL * sock)
+{
+//info-------------------------------------------------------------------------
+if(!IsTablePresent("info",sock))
+{
+    sprintf(qbuf,"CREATE TABLE info (version INTEGER NOT NULL)");
+
+    if(MysqlQuery(qbuf,sock))
+        {
+        errorStr = "Couldn't create info table With error:\n";
+        errorStr += mysql_error(sock);
+        mysql_close(sock);
+        return -1;
+        }
+
+    sprintf(qbuf,"INSERT INTO info SET version=0");
+
+    if(MysqlQuery(qbuf,sock))
+        {
+        errorStr = "Couldn't write default version. With error:\n";
+        errorStr += mysql_error(sock);
+        mysql_close(sock);
+        return -1;
+        }
+    schemaVersion = 0;
+}
+else
+{
+    std::vector<std::string> info;
+    if (GetAllParams(&info, "info", "version"))
+        schemaVersion = 0;
+    else
+    {
+        if (info.empty())
+            schemaVersion = 0;
+        else
+            GetInt(info.front(), &schemaVersion, 0);
+    }
+}
+//admins-----------------------------------------------------------------------
+if(!IsTablePresent("admins",sock))
+{
+    sprintf(qbuf,"CREATE TABLE admins (login VARCHAR(40) DEFAULT '' PRIMARY KEY,"\
+        "password VARCHAR(150) DEFAULT '*',ChgConf TINYINT DEFAULT 0,"\
+        "ChgPassword TINYINT DEFAULT 0,ChgStat TINYINT DEFAULT 0,"\
+        "ChgCash TINYINT DEFAULT 0,UsrAddDel TINYINT DEFAULT 0,"\
+        "ChgTariff TINYINT DEFAULT 0,ChgAdmin TINYINT DEFAULT 0)");
+    
+    if(MysqlQuery(qbuf,sock))
+    {
+        errorStr = "Couldn't create admin table list With error:\n";
+        errorStr += mysql_error(sock);
+        mysql_close(sock);
+        return -1;
+    }
+
+    sprintf(qbuf,"INSERT INTO admins SET login='admin',"\
+        "password='geahonjehjfofnhammefahbbbfbmpkmkmmefahbbbfbmpkmkmmefahbbbfbmpkmkaa',"\
+        "ChgConf=1,ChgPassword=1,ChgStat=1,ChgCash=1,UsrAddDel=1,ChgTariff=1,ChgAdmin=1");
+    
+    if(MysqlQuery(qbuf,sock))
+    {
+        errorStr = "Couldn't create default admin. With error:\n";
+        errorStr += mysql_error(sock);
+        mysql_close(sock);
+        return -1;
+    }
+}
+
+//tariffs-----------------------------------------------------------------------
+std::string param, res;
+if(!IsTablePresent("tariffs",sock))
+{
+    res = "CREATE TABLE tariffs (name VARCHAR(40) DEFAULT '' PRIMARY KEY,";
+        
+    for (int i = 0; i < DIR_NUM; i++)
+        {
+        strprintf(&param, " PriceDayA%d DOUBLE DEFAULT 0.0,", i); 
+        res += param;
+    
+        strprintf(&param, " PriceDayB%d DOUBLE DEFAULT 0.0,", i);
+        res += param;
+            
+        strprintf(&param, " PriceNightA%d DOUBLE DEFAULT 0.0,", i);
+        res += param;
+    
+        strprintf(&param, " PriceNightB%d DOUBLE DEFAULT 0.0,", i);
+        res += param;
+            
+        strprintf(&param, " Threshold%d INT DEFAULT 0,", i);
+        res += param;
+    
+        strprintf(&param, " Time%d VARCHAR(15) DEFAULT '0:0-0:0',", i);
+        res += param;
+    
+        strprintf(&param, " NoDiscount%d INT DEFAULT 0,", i);
+        res += param;
+    
+        strprintf(&param, " SinglePrice%d INT DEFAULT 0,", i);
+        res += param;
+        }
+    
+    res += "PassiveCost DOUBLE DEFAULT 0.0, Fee DOUBLE DEFAULT 0.0,"
+        "Free DOUBLE DEFAULT 0.0, TraffType VARCHAR(10) DEFAULT '',"
+        "period VARCHAR(32) NOT NULL DEFAULT 'month',"
+        "change_policy VARCHAR(32) NOT NULL DEFAULT 'allow',"
+        "change_policy_timeout TIMESTAMP NOT NULL DEFAULT 0)";
+    
+    if(MysqlQuery(res.c_str(),sock))
+    {
+        errorStr = "Couldn't create tariffs table list With error:\n";
+        errorStr += mysql_error(sock);
+        mysql_close(sock);
+        return -1;
+    }
+
+    res = "INSERT INTO tariffs SET name='tariff',";
+        
+    for (int i = 0; i < DIR_NUM; i++)
+        {
+        strprintf(&param, " NoDiscount%d=1,", i);
+        res += param;
+    
+        strprintf(&param, " Threshold%d=0,", i);
+        res += param;
+    
+        strprintf(&param, " Time%d='0:0-0:0',", i);
+        res += param;
+    
+        if(i != 0 && i != 1)
+        {
+            strprintf(&param, " SinglePrice%d=0,", i);
+            res += param;        
+        }
+    
+        if(i != 1)
+        {
+            strprintf(&param, " PriceDayA%d=0.0,", i); 
+            res += param;        
+        }
+        if(i != 1)
+        {
+            strprintf(&param, " PriceDayB%d=0.0,", i);        
+            res += param;    
+        }
+    
+        if(i != 0)
+        {
+            strprintf(&param, " PriceNightA%d=0.0,", i); 
+            res += param;        
+        }
+        if(i != 0)
+        {
+            strprintf(&param, " PriceNightB%d=0.0,", i);        
+            res += param;    
+        }
+        }
+    
+    res += "PassiveCost=0.0, Fee=10.0, Free=0,"\
+        "SinglePrice0=1, SinglePrice1=1,PriceDayA1=0.75,PriceDayB1=0.75,"\
+        "PriceNightA0=1.0,PriceNightB0=1.0,TraffType='up+down',period='month',"\
+        "change_policy='allow', change_policy_timeout=0";
+    
+    if(MysqlQuery(res.c_str(),sock))
+    {
+        errorStr = "Couldn't create default tariff. With error:\n";
+        errorStr += mysql_error(sock);
+        mysql_close(sock);
+        return -1;
+    }
+
+    sprintf(qbuf,"UPDATE info SET version=1");
+
+    if(MysqlQuery(qbuf,sock))
+    {
+        errorStr = "Couldn't write default version. With error:\n";
+        errorStr += mysql_error(sock);
+        mysql_close(sock);
+        return -1;
+    }
+    schemaVersion = 2;
+}
+
+//users-----------------------------------------------------------------------
+if(!IsTablePresent("users",sock))
+{
+    res = "CREATE TABLE users (login VARCHAR(50) NOT NULL DEFAULT '' PRIMARY KEY, Password VARCHAR(150) NOT NULL DEFAULT '*',"\
+        "Passive INT(3) DEFAULT 0,Down INT(3) DEFAULT 0,DisabledDetailStat INT(3) DEFAULT 0,AlwaysOnline INT(3) DEFAULT 0,Tariff VARCHAR(40) NOT NULL DEFAULT '',"\
+        "Address VARCHAR(254) NOT NULL DEFAULT '',Phone VARCHAR(128) NOT NULL DEFAULT '',Email VARCHAR(50) NOT NULL DEFAULT '',"\
+        "Note TEXT NOT NULL,RealName VARCHAR(254) NOT NULL DEFAULT '',StgGroup VARCHAR(40) NOT NULL DEFAULT '',"\
+        "Credit DOUBLE DEFAULT 0, TariffChange VARCHAR(40) NOT NULL DEFAULT '',";
+    
+    for (int i = 0; i < USERDATA_NUM; i++)
+        {
+        strprintf(&param, " Userdata%d VARCHAR(254) NOT NULL,", i);
+        res += param;
+        }
+    
+    param = " CreditExpire INT(11) DEFAULT 0,";
+    res += param;
+    
+    strprintf(&param, " IP VARCHAR(254) DEFAULT '*',");
+    res += param;
+    
+    for (int i = 0; i < DIR_NUM; i++)
+        {
+        strprintf(&param, " D%d BIGINT(30) DEFAULT 0,", i);
+        res += param;
+    
+        strprintf(&param, " U%d BIGINT(30) DEFAULT 0,", i);
+        res += param;
+        }
+    
+    strprintf(&param, "Cash DOUBLE DEFAULT 0,FreeMb DOUBLE DEFAULT 0,LastCashAdd DOUBLE DEFAULT 0,"\
+        "LastCashAddTime INT(11) DEFAULT 0,PassiveTime INT(11) DEFAULT 0,LastActivityTime INT(11) DEFAULT 0,"\
+        "NAS VARCHAR(17) NOT NULL, INDEX (AlwaysOnline), INDEX (IP), INDEX (Address),"\
+        " INDEX (Tariff),INDEX (Phone),INDEX (Email),INDEX (RealName))");
+    res += param;
+        
+    if(MysqlQuery(res.c_str(),sock))
+    {
+        errorStr = "Couldn't create users table list With error:\n";
+        errorStr += mysql_error(sock);
+        errorStr += "\n\n" + res;
+        mysql_close(sock);
+        return -1;
+    }
+
+    res = "INSERT INTO users SET login='test',Address='',AlwaysOnline=0,"\
+        "Credit=0.0,CreditExpire=0,Down=0,Email='',DisabledDetailStat=0,"\
+        "StgGroup='',IP='192.168.1.1',Note='',Passive=0,Password='123456',"\
+        "Phone='', RealName='',Tariff='tariff',TariffChange='',NAS='',";
+    
+    for (int i = 0; i < USERDATA_NUM; i++)
+        {
+        strprintf(&param, " Userdata%d='',", i);
+        res += param;
+        }
+    
+    for (int i = 0; i < DIR_NUM; i++)
+        {
+        strprintf(&param, " D%d=0,", i);
+        res += param;
+    
+        strprintf(&param, " U%d=0,", i);
+        res += param;
+        }
+    
+    res += "Cash=10.0,FreeMb=0.0,LastActivityTime=0,LastCashAdd=0,"\
+        "LastCashAddTime=0, PassiveTime=0";
+        
+    if(MysqlQuery(res.c_str(),sock))
+    {
+        errorStr = "Couldn't create default user. With error:\n";
+        errorStr += mysql_error(sock);
+        mysql_close(sock);
+        return -1;
+    }
+}
+/*
+//logs-----------------------------------------------------------------------
+if(!IsTablePresent("logs"))
+{
+    sprintf(qbuf,"CREATE TABLE logs (unid INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, login VARCHAR(40),text TEXT)");
+    
+    if(MysqlQuery(qbuf))
+    {
+        errorStr = "Couldn't create admin table list With error:\n";
+        errorStr += mysql_error(sock);
+        return -1;
+    }
+}
+*/
+//messages---------------------------------------------------------------------
+if(!IsTablePresent("messages",sock))
+{
+    sprintf(qbuf,"CREATE TABLE messages (login VARCHAR(40) DEFAULT '', id BIGINT, "\
+            "type INT, lastSendTime INT, creationTime INT, showTime INT,"\
+            "stgRepeat INT, repeatPeriod INT, text TEXT)");
+    
+    if(MysqlQuery(qbuf,sock))
+    {
+        errorStr = "Couldn't create messages table. With error:\n";
+        errorStr += mysql_error(sock);
+        mysql_close(sock);
+        return -1;
+    }
+}
+
+//month_stat-------------------------------------------------------------------
+if(!IsTablePresent("stat",sock))
+{
+    res = "CREATE TABLE stat (login VARCHAR(50), month TINYINT, year SMALLINT,";
+    
+    for (int i = 0; i < DIR_NUM; i++)
+        {
+        strprintf(&param, " U%d BIGINT,", i); 
+        res += param;
+            
+        strprintf(&param, " D%d BIGINT,", i); 
+        res += param;
+        }
+        
+    res += " cash DOUBLE, INDEX (login))";
+    
+    if(MysqlQuery(res.c_str(),sock))
+    {
+        errorStr = "Couldn't create stat table. With error:\n";
+        errorStr += mysql_error(sock);
+        mysql_close(sock);
+        return -1;
+    }
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::MakeUpdates(MYSQL * sock)
+{
+if (schemaVersion  < 1)
+    {
+    if (MysqlQuery("ALTER TABLE tariffs ADD period VARCHAR(32) NOT NULL DEFAULT 'month'", sock))
+        {
+        errorStr = "Couldn't update tariffs table to version 1. With error:\n";
+        errorStr += mysql_error(sock);
+        mysql_close(sock);
+        return -1;
+        }
+    if (MysqlQuery("UPDATE info SET version = 1", sock))
+        {
+        errorStr = "Couldn't update DB schema version to 1. With error:\n";
+        errorStr += mysql_error(sock);
+        mysql_close(sock);
+        return -1;
+        }
+    schemaVersion = 1;
+    logger("MYSQL_STORE: Updated DB schema to version %d", schemaVersion);
+    }
+
+if (schemaVersion  < 2)
+    {
+    if (MysqlQuery("ALTER TABLE tariffs ADD change_policy VARCHAR(32) NOT NULL DEFAULT 'allow'", sock) ||
+        MysqlQuery("ALTER TABLE tariffs ADD change_policy_timeout TIMESTAMP NOT NULL DEFAULT 0", sock))
+        {
+        errorStr = "Couldn't update tariffs table to version 2. With error:\n";
+        errorStr += mysql_error(sock);
+        mysql_close(sock);
+        return -1;
+        }
+    if (MysqlQuery("UPDATE info SET version = 2", sock))
+        {
+        errorStr = "Couldn't update DB schema version to 2. With error:\n";
+        errorStr += mysql_error(sock);
+        mysql_close(sock);
+        return -1;
+        }
+    schemaVersion = 2;
+    logger("MYSQL_STORE: Updated DB schema to version %d", schemaVersion);
+    }
+return 0;
+}
+//-----------------------------------------------------------------------------
+
+int MYSQL_STORE::GetAllParams(std::vector<std::string> * ParamList, 
+                            const std::string & table, const std::string & name) const
+{
+MYSQL_RES *res;
+MYSQL_ROW row;
+MYSQL * sock=NULL;
+my_ulonglong num, i;
+    
+ParamList->clear();
+    
+sprintf(qbuf,"SELECT %s FROM %s", name.c_str(), table.c_str());
+    
+if(MysqlGetQuery(qbuf,sock))
+{
+    errorStr = "Couldn't GetAllParams Query for: ";
+    errorStr += name + " - " + table + "\n";
+    errorStr += mysql_error(sock);
+    mysql_close(sock);
+    return -1;
+}
+
+if (!(res=mysql_store_result(sock)))
+{
+    errorStr = "Couldn't GetAllParams Results for: ";
+    errorStr += name + " - " + table + "\n";
+    errorStr += mysql_error(sock);
+    return -1;
+}
+
+num = mysql_num_rows(res);
+
+for(i = 0; i < num; i++)
+{
+    row = mysql_fetch_row(res);    
+    ParamList->push_back(row[0]);
+}
+
+mysql_free_result(res);
+mysql_close(sock);
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::GetUsersList(std::vector<std::string> * usersList) const
+{
+if(GetAllParams(usersList, "users", "login"))
+    return -1;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::GetAdminsList(std::vector<std::string> * adminsList) const
+{
+if(GetAllParams(adminsList, "admins", "login"))
+    return -1;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::GetTariffsList(std::vector<std::string> * tariffsList) const
+{
+if(GetAllParams(tariffsList, "tariffs", "name"))
+    return -1;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::AddUser(const std::string & login) const
+{
+std::string query = "INSERT INTO users SET login='" + login + "',Note='',NAS=''";
+
+for (int i = 0; i < USERDATA_NUM; i++)
+    query += ",Userdata" + std::to_string(i) + "=''";
+
+if(MysqlSetQuery(query.c_str()))
+{
+    errorStr = "Couldn't add user:\n";
+    //errorStr += mysql_error(sock);
+    return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::DelUser(const std::string & login) const
+{
+sprintf(qbuf,"DELETE FROM users WHERE login='%s' LIMIT 1", login.c_str());
+    
+if(MysqlSetQuery(qbuf))
+{
+    errorStr = "Couldn't delete user:\n";
+    //errorStr += mysql_error(sock);
+    return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::RestoreUserConf(STG::UserConf * conf, const std::string & login) const
+{
+MYSQL_RES *res;
+MYSQL_ROW row;
+MYSQL * sock;
+std::string query;
+
+query = "SELECT login, Password, Passive, Down, DisabledDetailStat, \
+         AlwaysOnline, Tariff, Address, Phone, Email, Note, \
+         RealName, StgGroup, Credit, TariffChange, ";
+
+for (int i = 0; i < USERDATA_NUM; i++)
+{
+    sprintf(qbuf, "Userdata%d, ", i);
+    query += qbuf;
+}
+
+query += "CreditExpire, IP FROM users WHERE login='";
+query += login + "' LIMIT 1";
+
+//sprintf(qbuf,"SELECT * FROM users WHERE login='%s' LIMIT 1", login.c_str());
+    
+if(MysqlGetQuery(query.c_str(),sock))
+{
+    errorStr = "Couldn't restore Tariff(on query):\n";
+    errorStr += mysql_error(sock);
+    mysql_close(sock);
+    return -1;
+}
+
+if (!(res=mysql_store_result(sock)))
+{
+    errorStr = "Couldn't restore Tariff(on getting result):\n";
+    errorStr += mysql_error(sock);
+    mysql_close(sock);
+    return -1;
+}
+
+if (mysql_num_rows(res) != 1)
+{
+    errorStr = "User not found";
+    mysql_close(sock);
+    return -1;
+}
+
+row = mysql_fetch_row(res);
+
+conf->password = row[1];
+
+if (conf->password.empty())
+    {
+    mysql_free_result(res);
+    errorStr = "User \'" + login + "\' password is blank.";
+    mysql_close(sock);
+    return -1;
+    }
+
+if (GetInt(row[2],&conf->passive) != 0)
+    {
+    mysql_free_result(res);
+    errorStr = "User \'" + login + "\' data not read. Parameter Passive.";
+    mysql_close(sock);
+    return -1;
+    }
+
+if (GetInt(row[3], &conf->disabled) != 0)
+    {
+    mysql_free_result(res);
+    errorStr = "User \'" + login + "\' data not read. Parameter Down.";
+    mysql_close(sock);
+    return -1;
+    }
+
+if (GetInt(row[4], &conf->disabledDetailStat) != 0)
+    {
+    mysql_free_result(res);
+    errorStr = "User \'" + login + "\' data not read. Parameter DisabledDetailStat.";
+    mysql_close(sock);
+    return -1;
+    }
+
+if (GetInt(row[5], &conf->alwaysOnline) != 0)
+    {
+    mysql_free_result(res);
+    errorStr = "User \'" + login + "\' data not read. Parameter AlwaysOnline.";
+    mysql_close(sock);
+    return -1;
+    }
+
+conf->tariffName = row[6];
+
+if (conf->tariffName.empty()) 
+    {
+    mysql_free_result(res);
+    errorStr = "User \'" + login + "\' tariff is blank.";
+    mysql_close(sock);
+    return -1;
+    }
+
+conf->address = row[7];
+conf->phone = row[8];
+conf->email = row[9];
+conf->note = row[10];
+conf->realName = row[11];
+conf->group = row[12];
+
+if (GetDouble(row[13], &conf->credit, 0) != 0)
+    {
+    mysql_free_result(res);
+    errorStr = "User \'" + login + "\' data not read. Parameter Credit.";
+    mysql_close(sock);
+    return -1;
+    }
+
+conf->nextTariff = row[14];
+
+for (int i = 0; i < USERDATA_NUM; i++)
+    {
+    conf->userdata[i] = row[15+i];
+    }
+
+GetTime(row[15+USERDATA_NUM], &conf->creditExpire, 0);
+    
+std::string ipStr = row[16+USERDATA_NUM];
+STG::UserIPs i;
+try
+    {
+    i = STG::UserIPs::parse(ipStr);
+    }
+catch (const std::string & s)
+    {
+    mysql_free_result(res);
+    errorStr = "User \'" + login + "\' data not read. Parameter IP address. " + s;
+    mysql_close(sock);
+    return -1;
+    }
+conf->ips = i;
+
+mysql_free_result(res);
+mysql_close(sock);
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::RestoreUserStat(STG::UserStat * stat, const std::string & login) const
+{
+MYSQL_RES *res;
+MYSQL_ROW row;
+MYSQL * sock;
+
+std::string query;
+
+query = "SELECT ";
+
+for (int i = 0; i < DIR_NUM; i++)
+{
+    sprintf(qbuf, "D%d, U%d, ", i, i);
+    query += qbuf;
+}
+
+query += "Cash, FreeMb, LastCashAdd, LastCashAddTime, PassiveTime, LastActivityTime \
+          FROM users WHERE login = '";
+query += login + "'";
+
+//sprintf(qbuf,"SELECT * FROM users WHERE login='%s' LIMIT 1", login.c_str());
+    
+if(MysqlGetQuery(query.c_str() ,sock))
+{
+    errorStr = "Couldn't restore UserStat(on query):\n";
+    errorStr += mysql_error(sock);
+    mysql_close(sock);
+    return -1;
+}
+
+if (!(res=mysql_store_result(sock)))
+{
+    errorStr = "Couldn't restore UserStat(on getting result):\n";
+    errorStr += mysql_error(sock);
+    mysql_close(sock);
+    return -1;
+}
+
+row = mysql_fetch_row(res);
+
+unsigned int startPos=0;
+
+char s[22];
+
+for (int i = 0; i < DIR_NUM; i++)
+    {
+    uint64_t traff;
+    sprintf(s, "D%d", i);
+    if (GetULongLongInt(row[startPos+i*2], &traff, 0) != 0)
+        {
+        mysql_free_result(res);
+        errorStr = "User \'" + login + "\' stat not read. Parameter " + std::string(s);
+        mysql_close(sock);
+        return -1;
+        }
+    stat->monthDown[i] = traff;
+
+    sprintf(s, "U%d", i);
+    if (GetULongLongInt(row[startPos+i*2+1], &traff, 0) != 0)
+        {
+        mysql_free_result(res);
+        errorStr =   "User \'" + login + "\' stat not read. Parameter " + std::string(s);
+        mysql_close(sock);
+        return -1;
+        }
+    stat->monthUp[i] = traff;
+    }//for
+
+startPos += (2*DIR_NUM);
+
+if (GetDouble(row[startPos], &stat->cash, 0) != 0)
+    {
+    mysql_free_result(res);
+    errorStr =   "User \'" + login + "\' stat not read. Parameter Cash";
+    mysql_close(sock);
+    return -1;
+    }
+
+if (GetDouble(row[startPos+1],&stat->freeMb, 0) != 0)
+    {
+    mysql_free_result(res);
+    errorStr =   "User \'" + login + "\' stat not read. Parameter FreeMb";
+    mysql_close(sock);
+    return -1;
+    }
+
+if (GetDouble(row[startPos+2], &stat->lastCashAdd, 0) != 0)
+    {
+    mysql_free_result(res);
+    errorStr =   "User \'" + login + "\' stat not read. Parameter LastCashAdd";
+    mysql_close(sock);
+    return -1;
+    }
+
+if (GetTime(row[startPos+3], &stat->lastCashAddTime, 0) != 0)
+    {
+    mysql_free_result(res);
+    errorStr =   "User \'" + login + "\' stat not read. Parameter LastCashAddTime";
+    mysql_close(sock);
+    return -1;
+    }
+
+if (GetTime(row[startPos+4], &stat->passiveTime, 0) != 0)
+    {
+    mysql_free_result(res);
+    errorStr =   "User \'" + login + "\' stat not read. Parameter PassiveTime";
+    mysql_close(sock);
+    return -1;
+    }
+
+if (GetTime(row[startPos+5], &stat->lastActivityTime, 0) != 0)
+    {
+    mysql_free_result(res);
+    errorStr =   "User \'" + login + "\' stat not read. Parameter LastActivityTime";
+    mysql_close(sock);
+    return -1;
+    }
+
+mysql_free_result(res);
+mysql_close(sock);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::SaveUserConf(const STG::UserConf & conf, const std::string & login) const
+{
+std::string param;
+std::string res;
+
+strprintf(&res,"UPDATE users SET Password='%s', Passive=%d, Down=%d, DisabledDetailStat = %d, "\
+    "AlwaysOnline=%d, Tariff='%s', Address='%s', Phone='%s', Email='%s', "\
+    "Note='%s', RealName='%s', StgGroup='%s', Credit=%f, TariffChange='%s', ", 
+    conf.password.c_str(),
+    conf.passive,
+    conf.disabled,
+    conf.disabledDetailStat,
+    conf.alwaysOnline,
+    conf.tariffName.c_str(),
+    (ReplaceStr(conf.address,badSyms,repSym)).c_str(),
+    (ReplaceStr(conf.phone,badSyms,repSym)).c_str(),
+    (ReplaceStr(conf.email,badSyms,repSym)).c_str(),
+    (ReplaceStr(conf.note,badSyms,repSym)).c_str(),
+    (ReplaceStr(conf.realName,badSyms,repSym)).c_str(),
+    (ReplaceStr(conf.group,badSyms,repSym)).c_str(),
+    conf.credit,
+    conf.nextTariff.c_str()
+    );
+
+for (int i = 0; i < USERDATA_NUM; i++)
+    {
+    strprintf(&param, " Userdata%d='%s',", i, 
+        (ReplaceStr(conf.userdata[i],badSyms,repSym)).c_str());
+    res += param;
+    }
+    
+strprintf(&param, " CreditExpire=%d,", conf.creditExpire);
+res += param;
+
+std::ostringstream ipStr;
+ipStr << conf.ips;
+
+strprintf(&param, " IP='%s'", ipStr.str().c_str());
+res += param;
+
+strprintf(&param, " WHERE login='%s' LIMIT 1", login.c_str());
+res += param;
+
+if(MysqlSetQuery(res.c_str()))
+{
+    errorStr = "Couldn't save user conf:\n";
+    //errorStr += mysql_error(sock);
+    return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::SaveUserStat(const STG::UserStat & stat, const std::string & login) const
+{
+std::string param;
+std::string res;
+
+res = "UPDATE users SET";
+
+for (int i = 0; i < DIR_NUM; i++)
+    {
+    strprintf(&param, " D%d=%lld,", i, stat.monthDown[i]);
+    res += param;
+
+    strprintf(&param, " U%d=%lld,", i, stat.monthUp[i]);
+    res += param;
+    }
+
+strprintf(&param, " Cash=%f, FreeMb=%f, LastCashAdd=%f, LastCashAddTime=%d,"\
+    " PassiveTime=%d, LastActivityTime=%d", 
+    stat.cash,
+    stat.freeMb,
+    stat.lastCashAdd,
+    stat.lastCashAddTime,
+    stat.passiveTime,
+    stat.lastActivityTime
+    );
+res += param;
+
+strprintf(&param, " WHERE login='%s' LIMIT 1", login.c_str());
+res += param;
+
+if(MysqlSetQuery(res.c_str()))
+{
+    errorStr = "Couldn't save user stat:\n";
+//    errorStr += mysql_error(sock);
+    return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::WriteLogString(const std::string & str, const std::string & login) const
+{
+std::string res, tempStr;
+time_t t;
+tm * lt;
+
+t = time(NULL);
+lt = localtime(&t);
+
+MYSQL_RES* result;
+MYSQL * sock;
+strprintf(&tempStr, "logs_%02d_%4d", lt->tm_mon+1, lt->tm_year+1900);
+if (!(sock=MysqlConnect())){
+    errorStr = "Couldn't connect to Server";
+    return -1;
+}
+if (!(result=mysql_list_tables(sock,tempStr.c_str() )))
+{
+    errorStr = "Couldn't get table " + tempStr + ":\n";
+    errorStr += mysql_error(sock);
+    mysql_close(sock);
+    return -1;
+}
+
+my_ulonglong num_rows =  mysql_num_rows(result);
+
+mysql_free_result(result);
+
+if (num_rows < 1)
+{
+    sprintf(qbuf,"CREATE TABLE logs_%02d_%4d (unid INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, login VARCHAR(40),text TEXT)",
+    lt->tm_mon+1, lt->tm_year+1900);
+    
+    if(MysqlQuery(qbuf,sock))
+    {
+        errorStr = "Couldn't create WriteDetailedStat table:\n";
+        errorStr += mysql_error(sock);
+        mysql_close(sock);
+        return -1;
+    }
+}
+
+strprintf(&res, "%s -- %s",LogDate(t), str.c_str());
+
+std::string send;
+
+strprintf(&send,"INSERT INTO logs_%02d_%4d SET login='%s', text='%s'",
+        lt->tm_mon+1, lt->tm_year+1900,
+    login.c_str(), (ReplaceStr(res,badSyms,repSym)).c_str());
+
+if(MysqlQuery(send.c_str(),sock))
+{
+    errorStr = "Couldn't write log string:\n";
+    errorStr += mysql_error(sock);
+    mysql_close(sock);
+    return -1;
+}
+mysql_close(sock);
+return 0;
+
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::WriteUserChgLog(const std::string & login,
+                                 const std::string & admLogin,
+                                 uint32_t       admIP,
+                                 const std::string & paramName,
+                                 const std::string & oldValue,
+                                 const std::string & newValue,
+                                 const std::string & message) const
+{
+std::string userLogMsg = "Admin \'" + admLogin + "\', " + inet_ntostring(admIP) + ": \'"
+    + paramName + "\' parameter changed from \'" + oldValue +
+    "\' to \'" + newValue + "\'. " + message;
+
+return WriteLogString(userLogMsg, login);
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::WriteUserConnect(const std::string & login, uint32_t ip) const
+{
+std::string logStr = "Connect, " + inet_ntostring(ip);
+return WriteLogString(logStr, login);
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::WriteUserDisconnect(const std::string & login,
+                                     const STG::DirTraff & up,
+                                     const STG::DirTraff & down,
+                                     const STG::DirTraff & sessionUp,
+                                     const STG::DirTraff & sessionDown,
+                                     double cash,
+                                     double /*freeMb*/,
+                                     const std::string & /*reason*/) const
+{
+std::string logStr = "Disconnect, ";
+std::ostringstream sssu;
+std::ostringstream sssd;
+std::ostringstream ssmu;
+std::ostringstream ssmd;
+std::ostringstream sscash;
+
+ssmu << up;
+ssmd << down;
+
+sssu << sessionUp;
+sssd << sessionDown;
+
+sscash << cash;
+
+logStr += " session upload: \'";
+logStr += sssu.str();
+logStr += "\' session download: \'";
+logStr += sssd.str();
+logStr += "\' month upload: \'";
+logStr += ssmu.str();
+logStr += "\' month download: \'";
+logStr += ssmd.str();
+logStr += "\' cash: \'";
+logStr += sscash.str();
+logStr += "\'";
+
+return WriteLogString(logStr, login);
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::SaveMonthStat(const STG::UserStat & stat, int month, int year, 
+                                const std::string & login) const
+{
+std::string param, res;
+
+strprintf(&res, "INSERT INTO stat SET login='%s', month=%d, year=%d,", 
+    login.c_str(), month+1, year+1900);
+    
+for (int i = 0; i < DIR_NUM; i++)
+    {
+    strprintf(&param, " U%d=%lld,", i, stat.monthUp[i]); 
+    res += param;
+
+    strprintf(&param, " D%d=%lld,", i, stat.monthDown[i]);        
+    res += param;
+    }
+    
+strprintf(&param, " cash=%f", stat.cash);        
+res += param;
+
+if(MysqlSetQuery(res.c_str()))
+{
+    errorStr = "Couldn't SaveMonthStat:\n";
+    //errorStr += mysql_error(sock);
+    return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------*/
+int MYSQL_STORE::AddAdmin(const std::string & login) const
+{
+sprintf(qbuf,"INSERT INTO admins SET login='%s'", login.c_str());
+    
+if(MysqlSetQuery(qbuf))
+{
+    errorStr = "Couldn't add admin:\n";
+    //errorStr += mysql_error(sock);
+    return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------*/
+int MYSQL_STORE::DelAdmin(const std::string & login) const
+{
+sprintf(qbuf,"DELETE FROM admins where login='%s' LIMIT 1", login.c_str());
+    
+if(MysqlSetQuery(qbuf))
+{
+    errorStr = "Couldn't delete admin:\n";
+    //errorStr += mysql_error(sock);
+    return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------*/
+int MYSQL_STORE::SaveAdmin(const STG::AdminConf & ac) const
+{
+char passwordE[2 * ADM_PASSWD_LEN + 2];
+char pass[ADM_PASSWD_LEN + 1];
+char adminPass[ADM_PASSWD_LEN + 1];
+
+memset(pass, 0, sizeof(pass));
+memset(adminPass, 0, sizeof(adminPass));
+
+BLOWFISH_CTX ctx;
+InitContext(adm_enc_passwd, strlen(adm_enc_passwd), &ctx);
+
+strncpy(adminPass, ac.password.c_str(), ADM_PASSWD_LEN);
+adminPass[ADM_PASSWD_LEN - 1] = 0;
+
+for (int i = 0; i < ADM_PASSWD_LEN/8; i++)
+    {
+    EncryptBlock(pass + 8*i, adminPass + 8*i, &ctx);
+    }
+
+pass[ADM_PASSWD_LEN - 1] = 0;
+Encode12(passwordE, pass, ADM_PASSWD_LEN);
+
+sprintf(qbuf,"UPDATE admins SET password='%s', ChgConf=%d, ChgPassword=%d, "\
+    "ChgStat=%d, ChgCash=%d, UsrAddDel=%d, ChgTariff=%d, ChgAdmin=%d "\
+    "WHERE login='%s' LIMIT 1", 
+    passwordE,
+    ac.priv.userConf,
+    ac.priv.userPasswd,
+    ac.priv.userStat,
+    ac.priv.userCash,
+    ac.priv.userAddDel,
+    ac.priv.tariffChg,
+    ac.priv.adminChg,
+    ac.login.c_str()
+    );
+
+if(MysqlSetQuery(qbuf))
+{
+    errorStr = "Couldn't save admin:\n";
+    //errorStr += mysql_error(sock);
+    return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::RestoreAdmin(STG::AdminConf * ac, const std::string & login) const
+{
+char pass[ADM_PASSWD_LEN + 1];
+char password[ADM_PASSWD_LEN + 1];
+char passwordE[2*ADM_PASSWD_LEN + 2];
+BLOWFISH_CTX ctx;
+
+memset(password, 0, sizeof(password));
+
+std::string p;
+MYSQL_RES *res;
+MYSQL_ROW row;
+MYSQL * sock;
+sprintf(qbuf,"SELECT * FROM admins WHERE login='%s' LIMIT 1", login.c_str());
+    
+if(MysqlGetQuery(qbuf,sock))
+{
+    errorStr = "Couldn't restore admin:\n";
+    errorStr += mysql_error(sock);
+    mysql_close(sock);
+    return -1;
+}
+
+if (!(res=mysql_store_result(sock)))
+{
+    errorStr = "Couldn't restore admin:\n";
+    errorStr += mysql_error(sock);
+    mysql_close(sock);
+    return -1;
+}
+
+if ( mysql_num_rows(res) == 0)
+{
+    mysql_free_result(res);
+    errorStr = "Couldn't restore admin as couldn't found him in table.\n";
+    mysql_close(sock);
+    return -1;
+}
+  
+row = mysql_fetch_row(res);
+
+p = row[1];
+
+if(p.length() == 0)
+{
+    mysql_free_result(res);
+    errorStr = "Error in parameter password";
+    mysql_close(sock);
+    return -1;
+}
+
+memset(passwordE, 0, sizeof(passwordE));
+strncpy(passwordE, p.c_str(), 2*ADM_PASSWD_LEN);
+
+memset(pass, 0, sizeof(pass));
+
+if (passwordE[0] != 0)
+    {
+    Decode21(pass, passwordE);
+    InitContext(adm_enc_passwd, strlen(adm_enc_passwd), &ctx);
+
+    for (int i = 0; i < ADM_PASSWD_LEN/8; i++)
+        {
+        DecryptBlock(password + 8*i, pass + 8*i, &ctx);
+        }
+    }
+else
+    {
+    password[0] = 0;
+    }
+
+ac->password = password;
+
+uint16_t a;
+
+if (GetInt(row[2], &a) == 0) 
+    ac->priv.userConf = a;
+else
+    {
+    mysql_free_result(res);
+    errorStr = "Error in parameter ChgConf";
+    mysql_close(sock);
+    return -1;
+    }
+
+if (GetInt(row[3], &a) == 0) 
+    ac->priv.userPasswd = a;
+else
+    {
+    mysql_free_result(res);
+    errorStr = "Error in parameter ChgPassword";
+    mysql_close(sock);
+    return -1;
+    }
+
+if (GetInt(row[4], &a) == 0) 
+    ac->priv.userStat = a;
+else
+    {
+    mysql_free_result(res);
+    errorStr = "Error in parameter ChgStat";
+    mysql_close(sock);
+    return -1;
+    }
+
+if (GetInt(row[5], &a) == 0) 
+    ac->priv.userCash = a;
+else
+    {
+    mysql_free_result(res);
+    errorStr = "Error in parameter ChgCash";
+    mysql_close(sock);
+    return -1;
+    }
+
+if (GetInt(row[6], &a) == 0) 
+    ac->priv.userAddDel = a;
+else
+    {
+    mysql_free_result(res);
+    errorStr = "Error in parameter UsrAddDel";
+    mysql_close(sock);
+    return -1;
+    }
+
+if (GetInt(row[7], &a) == 0) 
+    ac->priv.tariffChg = a;
+else
+    {
+    mysql_free_result(res);
+    errorStr = "Error in parameter ChgTariff";
+    mysql_close(sock);
+    return -1;
+    }
+
+if (GetInt(row[8], &a) == 0) 
+    ac->priv.adminChg = a;
+else
+    {
+    mysql_free_result(res);
+    errorStr = "Error in parameter ChgAdmin";
+    mysql_close(sock);
+    return -1;
+    }
+
+mysql_free_result(res);
+mysql_close(sock);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::AddTariff(const std::string & name) const
+{
+sprintf(qbuf,"INSERT INTO tariffs SET name='%s'", name.c_str());
+    
+if(MysqlSetQuery(qbuf))
+{
+    errorStr = "Couldn't add tariff:\n";
+//    errorStr += mysql_error(sock);
+    return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::DelTariff(const std::string & name) const
+{
+sprintf(qbuf,"DELETE FROM tariffs WHERE name='%s' LIMIT 1", name.c_str());
+    
+if(MysqlSetQuery(qbuf))
+{
+    errorStr = "Couldn't delete tariff: ";
+//    errorStr += mysql_error(sock);
+    return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::RestoreTariff(STG::TariffData * td, const std::string & tariffName) const
+{
+MYSQL_RES *res;
+MYSQL_ROW row;
+MYSQL * sock;
+sprintf(qbuf,"SELECT * FROM tariffs WHERE name='%s' LIMIT 1", tariffName.c_str());
+    
+if(MysqlGetQuery(qbuf,sock))
+{
+    errorStr = "Couldn't restore Tariff:\n";
+    errorStr += mysql_error(sock);
+    mysql_close(sock);
+    return -1;
+}
+
+if (!(res=mysql_store_result(sock)))
+{
+    errorStr = "Couldn't restore Tariff:\n";
+    errorStr += mysql_error(sock);
+    mysql_close(sock);
+    return -1;
+}
+
+std::string str;
+td->tariffConf.name = tariffName;
+
+row = mysql_fetch_row(res);
+
+std::string param;
+for (int i = 0; i<DIR_NUM; i++)
+    {
+    strprintf(&param, "Time%d", i);
+    str = row[6+i*8];
+    if (str.length() == 0)
+        {
+        mysql_free_result(res);
+        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+        mysql_close(sock);
+        return -1;
+        }
+
+    ParseTariffTimeStr(str.c_str(), 
+                       td->dirPrice[i].hDay, 
+                       td->dirPrice[i].mDay, 
+                       td->dirPrice[i].hNight, 
+                       td->dirPrice[i].mNight);
+
+    strprintf(&param, "PriceDayA%d", i);
+    if (GetDouble(row[1+i*8], &td->dirPrice[i].priceDayA, 0.0) < 0)
+        {
+        mysql_free_result(res);
+        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+        mysql_close(sock);
+        return -1;
+        }
+    td->dirPrice[i].priceDayA /= (1024*1024);
+
+    strprintf(&param, "PriceDayB%d", i);
+    if (GetDouble(row[2+i*8], &td->dirPrice[i].priceDayB, 0.0) < 0)
+        {
+        mysql_free_result(res);
+        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+        mysql_close(sock);
+        return -1;
+        }
+    td->dirPrice[i].priceDayB /= (1024*1024);
+
+    strprintf(&param, "PriceNightA%d", i);
+    if (GetDouble(row[3+i*8], &td->dirPrice[i].priceNightA, 0.0) < 0)
+        {
+        mysql_free_result(res);
+        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+        mysql_close(sock);
+        return -1;
+        }
+    td->dirPrice[i].priceNightA /= (1024*1024);
+
+    strprintf(&param, "PriceNightB%d", i);
+    if (GetDouble(row[4+i*8], &td->dirPrice[i].priceNightB, 0.0) < 0)
+        {
+        mysql_free_result(res);
+        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+        mysql_close(sock);
+        return -1;
+        }
+    td->dirPrice[i].priceNightB /= (1024*1024);
+
+    strprintf(&param, "Threshold%d", i);
+    if (GetInt(row[5+i*8], &td->dirPrice[i].threshold) < 0)
+        {
+        mysql_free_result(res);
+        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+        mysql_close(sock);
+        return -1;
+        }
+
+    strprintf(&param, "SinglePrice%d", i);
+    if (GetInt(row[8+i*8], &td->dirPrice[i].singlePrice) < 0)
+        {
+        mysql_free_result(res);
+        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+        mysql_close(sock);
+        return -1;
+        }
+
+    strprintf(&param, "NoDiscount%d", i);
+    if (GetInt(row[7+i*8], &td->dirPrice[i].noDiscount) < 0)
+        {
+        mysql_free_result(res);
+        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+        mysql_close(sock);
+        return -1;
+        }
+    }//main for
+
+if (GetDouble(row[2+8*DIR_NUM], &td->tariffConf.fee, 0.0) < 0)
+    {
+    mysql_free_result(res);
+    errorStr = "Cannot read tariff " + tariffName + ". Parameter Fee";
+    mysql_close(sock);
+    return -1;
+    }
+
+if (GetDouble(row[3+8*DIR_NUM], &td->tariffConf.free, 0.0) < 0)
+    {
+    mysql_free_result(res);
+    errorStr = "Cannot read tariff " + tariffName + ". Parameter Free";
+    mysql_close(sock);
+    return -1;
+    }
+
+if (GetDouble(row[1+8*DIR_NUM], &td->tariffConf.passiveCost, 0.0) < 0)
+    {
+    mysql_free_result(res);
+    errorStr = "Cannot read tariff " + tariffName + ". Parameter PassiveCost";
+    mysql_close(sock);
+    return -1;
+    }
+
+    str = row[4+8*DIR_NUM];
+    param = "TraffType";
+    
+    if (str.length() == 0)
+        {
+        mysql_free_result(res);
+        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+        mysql_close(sock);
+        return -1;
+        }
+
+td->tariffConf.traffType = STG::Tariff::parseTraffType(str);
+
+if (schemaVersion > 0)
+{
+    str = row[5+8*DIR_NUM];
+    param = "Period";
+
+    if (str.length() == 0)
+        {
+        mysql_free_result(res);
+        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+        mysql_close(sock);
+        return -1;
+        }
+
+    td->tariffConf.period = STG::Tariff::parsePeriod(str);
+    }
+else
+    {
+    td->tariffConf.period = STG::Tariff::MONTH;
+    }
+
+if (schemaVersion > 1)
+    {
+    str = row[6+8*DIR_NUM];
+    param = "ChangePolicy";
+
+    if (str.length() == 0)
+        {
+        mysql_free_result(res);
+        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+        mysql_close(sock);
+        return -1;
+        }
+
+    td->tariffConf.changePolicy = STG::Tariff::parseChangePolicy(str);
+
+    str = row[7+8*DIR_NUM];
+    param = "ChangePolicyTimeout";
+
+    if (str.length() == 0)
+        {
+        mysql_free_result(res);
+        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
+        mysql_close(sock);
+        return -1;
+        }
+
+    td->tariffConf.changePolicyTimeout = readTime(str);
+    }
+else
+    {
+    td->tariffConf.changePolicy = STG::Tariff::ALLOW;
+    td->tariffConf.changePolicyTimeout = 0;
+    }
+
+mysql_free_result(res);
+mysql_close(sock);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::SaveTariff(const STG::TariffData & td, const std::string & tariffName) const
+{
+std::string param;
+
+std::string res="UPDATE tariffs SET";
+
+for (int i = 0; i < DIR_NUM; i++)
+    {
+    strprintf(&param, " PriceDayA%d=%f,", i, 
+        td.dirPrice[i].priceDayA * pt_mega);
+    res += param;
+
+    strprintf(&param, " PriceDayB%d=%f,", i, 
+        td.dirPrice[i].priceDayB * pt_mega);        
+    res += param;
+        
+    strprintf(&param, " PriceNightA%d=%f,", i,
+        td.dirPrice[i].priceNightA * pt_mega);
+    res += param;
+
+    strprintf(&param, " PriceNightB%d=%f,", i, 
+        td.dirPrice[i].priceNightB * pt_mega);
+    res += param;
+        
+    strprintf(&param, " Threshold%d=%d,", i, 
+        td.dirPrice[i].threshold);
+    res += param;
+
+    std::string s;
+    strprintf(&param, " Time%d", i);
+
+    strprintf(&s, "%0d:%0d-%0d:%0d", 
+            td.dirPrice[i].hDay,
+            td.dirPrice[i].mDay,
+            td.dirPrice[i].hNight,
+            td.dirPrice[i].mNight);
+
+    res += (param + "='" + s + "',");
+
+    strprintf(&param, " NoDiscount%d=%d,", i, 
+        td.dirPrice[i].noDiscount);
+    res += param;
+
+    strprintf(&param, " SinglePrice%d=%d,", i, 
+        td.dirPrice[i].singlePrice);
+    res += param;
+    }
+
+strprintf(&param, " PassiveCost=%f,", td.tariffConf.passiveCost);
+res += param;
+
+strprintf(&param, " Fee=%f,", td.tariffConf.fee);
+res += param;
+
+strprintf(&param, " Free=%f,", td.tariffConf.free);
+res += param;
+
+res += " TraffType='" + STG::Tariff::toString(td.tariffConf.traffType) + "'";
+
+if (schemaVersion > 0)
+    res += ", Period='" + STG::Tariff::toString(td.tariffConf.period) + "'";
+
+if (schemaVersion > 1)
+    res += ", change_policy='" + STG::Tariff::toString(td.tariffConf.changePolicy) + "'"\
+           ", change_policy_timeout='" + formatTime(td.tariffConf.changePolicy) + "'";
+
+strprintf(&param, " WHERE name='%s' LIMIT 1", tariffName.c_str());
+res += param;
+
+if(MysqlSetQuery(res.c_str()))
+{
+    errorStr = "Couldn't save tariff:\n";
+    //errorStr += mysql_error(sock);
+    return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::WriteDetailedStat(const STG::TraffStat & statTree, 
+                                   time_t lastStat, 
+                                   const std::string & login) const
+{
+std::string res, stTime, endTime, tempStr;
+time_t t;
+tm * lt;
+
+t = time(NULL);
+lt = localtime(&t);
+
+if (lt->tm_hour == 0 && lt->tm_min <= 5)
+    {
+        t -= 3600 * 24;
+        lt = localtime(&t);
+    }
+
+MYSQL_RES* result;
+MYSQL * sock;
+strprintf(&tempStr, "detailstat_%02d_%4d", lt->tm_mon+1, lt->tm_year+1900);
+
+if (!(sock=MysqlConnect())){
+    mysql_close(sock);
+    return -1;
+}
+
+if (!(result=mysql_list_tables(sock,tempStr.c_str() )))
+{
+    errorStr = "Couldn't get table " + tempStr + ":\n";
+    errorStr += mysql_error(sock);
+    mysql_close(sock);
+    return -1;
+}
+
+my_ulonglong num_rows =  mysql_num_rows(result);
+
+mysql_free_result(result);
+
+if (num_rows < 1)
+{
+    sprintf(qbuf,"CREATE TABLE detailstat_%02d_%4d (login VARCHAR(40) DEFAULT '',"\
+        "day TINYINT DEFAULT 0,startTime TIME,endTime TIME,"\
+        "IP VARCHAR(17) DEFAULT '',dir INT DEFAULT 0,"\
+        "down BIGINT DEFAULT 0,up BIGINT DEFAULT 0, cash DOUBLE DEFAULT 0.0, INDEX (login), INDEX(dir), INDEX(day), INDEX(IP))",
+    lt->tm_mon+1, lt->tm_year+1900);
+    
+    if(MysqlQuery(qbuf,sock))
+    {
+        errorStr = "Couldn't create WriteDetailedStat table:\n";
+        errorStr += mysql_error(sock);
+        mysql_close(sock);
+        return -1;
+    }
+}
+
+struct tm * lt1;
+struct tm * lt2;
+
+lt1 = localtime(&lastStat);
+
+int h1, m1, s1;
+int h2, m2, s2;
+
+h1 = lt1->tm_hour;
+m1 = lt1->tm_min;
+s1 = lt1->tm_sec;
+
+lt2 = localtime(&t);
+
+h2 = lt2->tm_hour;
+m2 = lt2->tm_min;
+s2 = lt2->tm_sec;
+    
+strprintf(&stTime, "%02d:%02d:%02d", h1, m1, s1);
+strprintf(&endTime, "%02d:%02d:%02d", h2, m2, s2);
+
+strprintf(&res,"INSERT INTO detailstat_%02d_%4d SET login='%s',"\
+    "day=%d,startTime='%s',endTime='%s',", 
+    lt->tm_mon+1, lt->tm_year+1900,
+    login.c_str(),
+    lt->tm_mday,
+    stTime.c_str(),
+    endTime.c_str()
+    );
+
+STG::TraffStat::const_iterator stIter;
+stIter = statTree.begin();
+
+while (stIter != statTree.end())
+    {
+        strprintf(&tempStr,"IP='%s', dir=%d, down=%lld, up=%lld, cash=%f", 
+                inet_ntostring(stIter->first.ip).c_str(),
+                stIter->first.dir, 
+                stIter->second.down, 
+                stIter->second.up, 
+                stIter->second.cash
+            );
+    
+        if( MysqlQuery((res+tempStr).c_str(),sock) )
+        {
+            errorStr = "Couldn't insert data in WriteDetailedStat:\n";
+            errorStr += mysql_error(sock);
+            mysql_close(sock);
+            return -1;
+        }
+
+        result=mysql_store_result(sock);
+        if(result)
+            mysql_free_result(result);
+
+        ++stIter;
+    }
+mysql_close(sock);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::AddMessage(STG::Message * msg, const std::string & login) const
+{
+struct timeval tv;
+
+gettimeofday(&tv, NULL);
+
+msg->header.id = static_cast<uint64_t>(tv.tv_sec) * 1000000 + static_cast<uint64_t>(tv.tv_usec);
+
+sprintf(qbuf,"INSERT INTO messages SET login='%s', id=%lld", 
+    login.c_str(),
+    static_cast<long long>(msg->header.id)
+    );
+    
+if(MysqlSetQuery(qbuf))
+{
+    errorStr = "Couldn't add message:\n";
+    //errorStr += mysql_error(sock);
+    return -1;
+}
+
+return EditMessage(*msg, login);
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::EditMessage(const STG::Message & msg, const std::string & login) const
+{
+std::string res;
+
+strprintf(&res,"UPDATE messages SET type=%d, lastSendTime=%u, creationTime=%u, "\
+    "showTime=%u, stgRepeat=%d, repeatPeriod=%u, text='%s' "\
+    "WHERE login='%s' AND id=%lld LIMIT 1", 
+    msg.header.type,
+    msg.header.lastSendTime,
+    msg.header.creationTime,
+    msg.header.showTime,
+    msg.header.repeat,
+    msg.header.repeatPeriod,
+    (ReplaceStr(msg.text,badSyms,repSym)).c_str(),
+    login.c_str(),
+    msg.header.id
+    );
+
+if(MysqlSetQuery(res.c_str()))
+{
+    errorStr = "Couldn't edit message:\n";
+    //errorStr += mysql_error(sock);
+    return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::GetMessage(uint64_t id, STG::Message * msg, const std::string & login) const
+{
+MYSQL_RES *res;
+MYSQL_ROW row;
+MYSQL * sock;
+
+sprintf(qbuf,"SELECT * FROM messages WHERE login='%s' AND id=%llu LIMIT 1",
+        login.c_str(), static_cast<unsigned long long>(id));
+    
+if(MysqlGetQuery(qbuf,sock))
+{
+    errorStr = "Couldn't GetMessage:\n";
+    errorStr += mysql_error(sock);
+    mysql_close(sock);
+    return -1;
+}
+
+if (!(res=mysql_store_result(sock)))
+{
+    errorStr = "Couldn't GetMessage:\n";
+    errorStr += mysql_error(sock);
+    mysql_close(sock);
+    return -1;
+}
+
+row = mysql_fetch_row(res);
+
+if(row[2]&&str2x(row[2], msg->header.type))
+{
+    mysql_free_result(res);
+    errorStr = "Invalid value in message header for user: " + login;
+    mysql_close(sock);
+    return -1;
+}
+
+if(row[3] && str2x(row[3], msg->header.lastSendTime))
+{
+    mysql_free_result(res);
+    errorStr = "Invalid value in message header for user: " + login;
+    mysql_close(sock);
+    return -1;
+}
+
+if(row[4] && str2x(row[4], msg->header.creationTime))
+{
+    mysql_free_result(res);
+    errorStr = "Invalid value in message header for user: " + login;
+    mysql_close(sock);
+    return -1;
+}
+
+if(row[5] && str2x(row[5], msg->header.showTime))
+{
+    mysql_free_result(res);
+    errorStr = "Invalid value in message header for user: " + login;
+    mysql_close(sock);
+    return -1;
+}
+
+if(row[6] && str2x(row[6], msg->header.repeat))
+{
+    mysql_free_result(res);
+    errorStr = "Invalid value in message header for user: " + login;
+    mysql_close(sock);
+    return -1;
+}
+
+if(row[7] && str2x(row[7], msg->header.repeatPeriod))
+{
+    mysql_free_result(res);
+    errorStr = "Invalid value in message header for user: " + login;
+    mysql_close(sock);
+    return -1;
+}
+
+msg->header.id = id;
+msg->text = row[8];
+
+mysql_free_result(res);
+mysql_close(sock);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::DelMessage(uint64_t id, const std::string & login) const
+{
+sprintf(qbuf,"DELETE FROM messages WHERE login='%s' AND id=%lld LIMIT 1", 
+        login.c_str(), static_cast<long long>(id));
+    
+if(MysqlSetQuery(qbuf))
+{
+    errorStr = "Couldn't delete Message:\n";
+    //errorStr += mysql_error(sock);
+    return -1;
+}
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int MYSQL_STORE::GetMessageHdrs(std::vector<STG::Message::Header> * hdrsList, const std::string & login) const
+{
+MYSQL_RES *res;
+MYSQL_ROW row;
+MYSQL * sock;
+sprintf(qbuf,"SELECT * FROM messages WHERE login='%s'", login.c_str());
+    
+if(MysqlGetQuery(qbuf,sock))
+{
+    errorStr = "Couldn't GetMessageHdrs:\n";
+    errorStr += mysql_error(sock);
+    mysql_close(sock);
+    return -1;
+}
+
+if (!(res=mysql_store_result(sock)))
+{
+    errorStr = "Couldn't GetMessageHdrs:\n";
+    errorStr += mysql_error(sock);
+    mysql_close(sock);
+    return -1;
+}
+
+unsigned int i;
+my_ulonglong num_rows = mysql_num_rows(res);
+uint64_t id = 0;
+
+for (i = 0; i < num_rows; i++)
+{
+    row = mysql_fetch_row(res);
+    if (str2x(row[1], id))
+        continue;
+    
+    STG::Message::Header hdr;
+    if (row[2]) 
+        if(str2x(row[2], hdr.type))
+            continue;
+
+    if (row[3])
+        if(str2x(row[3], hdr.lastSendTime))
+            continue;
+
+    if (row[4])
+        if(str2x(row[4], hdr.creationTime))
+            continue;
+
+    if (row[5])
+        if(str2x(row[5], hdr.showTime))
+            continue;
+
+    if (row[6])
+        if(str2x(row[6], hdr.repeat))
+            continue;
+
+    if (row[7])
+        if(str2x(row[7], hdr.repeatPeriod))
+            continue;
+
+    hdr.id = id;
+    hdrsList->push_back(hdr);
+}
+
+mysql_free_result(res);
+mysql_close(sock);
+return 0;
+}
+//-----------------------------------------------------------------------------
+
+int MYSQL_STORE::MysqlSetQuery(const char * Query) const {
+
+    MYSQL * sock;
+    int ret=MysqlGetQuery(Query,sock);
+    mysql_close(sock);
+    return ret;
+}
+//-----------------------------------------------------------------------------
+int  MYSQL_STORE::MysqlGetQuery(const char * Query,MYSQL * & sock) const {
+    if (!(sock=MysqlConnect())) {
+        return -1;
+    }
+    return   MysqlQuery(Query,sock);
+}
+//-----------------------------------------------------------------------------
+MYSQL *  MYSQL_STORE::MysqlConnect() const {
+    MYSQL * sock;
+    if ( !(sock=mysql_init(NULL)) ){
+        errorStr= "mysql init susck\n";
+        return NULL;
+    }
+    if (!(sock = mysql_real_connect(sock,storeSettings.GetDBHost().c_str(),
+            storeSettings.GetDBUser().c_str(),storeSettings.GetDBPassword().c_str(),
+            0,0,NULL,0)))
+        {
+            errorStr = "Couldn't connect to mysql engine! With error:\n";
+            errorStr += mysql_error(sock);
+            return NULL;
+        }
+    else{
+         if(mysql_select_db(sock, storeSettings.GetDBName().c_str())){
+             errorStr = "Database lost !\n";
+             return NULL;
+         }
+    }
+    return sock;
+}
+//-----------------------------------------------------------------------------
diff --git a/projects/stargazer/plugins/store/mysql/mysql_store.h b/projects/stargazer/plugins/store/mysql/mysql_store.h
new file mode 100644 (file)
index 0000000..6d09c47
--- /dev/null
@@ -0,0 +1,140 @@
+#pragma once
+
+#include "stg/store.h"
+#include "stg/module_settings.h"
+#include "stg/user_traff.h"
+#include "stg/logger.h"
+
+#include <string>
+#include <vector>
+#include <map>
+
+#include <mysql/mysql.h>
+
+//-----------------------------------------------------------------------------
+class MYSQL_STORE_SETTINGS
+{
+public:
+    MYSQL_STORE_SETTINGS();
+    virtual ~MYSQL_STORE_SETTINGS() {}
+    virtual int ParseSettings(const STG::ModuleSettings & s);
+    virtual const std::string & GetStrError() const { return errorStr; }
+
+    const std::string & GetDBUser() const { return dbUser; }
+    const std::string & GetDBPassword() const { return dbPass; }
+    const std::string & GetDBHost() const { return dbHost; }
+    const std::string & GetDBName() const { return dbName; }
+
+private:
+    MYSQL_STORE_SETTINGS(const MYSQL_STORE_SETTINGS & rvalue);
+    MYSQL_STORE_SETTINGS & operator=(const MYSQL_STORE_SETTINGS & rvalue);
+
+    const STG::ModuleSettings * settings;
+
+    int     ParseParam(const std::vector<STG::ParamValue> & moduleParams, 
+                       const std::string & name, std::string & result);
+
+    std::string  errorStr;
+
+    std::string  dbUser;
+    std::string  dbPass;
+    std::string  dbName;
+    std::string  dbHost;
+};
+//-----------------------------------------------------------------------------
+class MYSQL_STORE: public STG::Store
+{
+public:
+    MYSQL_STORE();
+    const std::string & GetStrError() const override { return errorStr; }
+
+    //User
+    int GetUsersList(std::vector<std::string> * usersList) const override;
+    int AddUser(const std::string & login) const override;
+    int DelUser(const std::string & login) const override;
+    int SaveUserStat(const STG::UserStat & stat, const std::string & login) const override;
+    int SaveUserConf(const STG::UserConf & conf, const std::string & login) const override;
+    int RestoreUserStat(STG::UserStat * stat, const std::string & login) const override;
+    int RestoreUserConf(STG::UserConf * conf, const std::string & login) const override;
+    int WriteUserChgLog(const std::string & login,
+                        const std::string & admLogin,
+                        uint32_t       admIP,
+                        const std::string & paramName,
+                        const std::string & oldValue,
+                        const std::string & newValue,
+                        const std::string & message = "") const override;
+    int WriteUserConnect(const std::string & login, uint32_t ip) const override;
+    int WriteUserDisconnect(const std::string & login,
+                            const STG::DirTraff & up,
+                            const STG::DirTraff & down,
+                            const STG::DirTraff & sessionUp,
+                            const STG::DirTraff & sessionDown,
+                            double cash,
+                            double freeMb,
+                            const std::string & reason) const override;
+
+    int WriteDetailedStat(const STG::TraffStat & statTree,
+                          time_t lastStat,
+                          const std::string & login) const override;
+
+    int AddMessage(STG::Message * msg, const std::string & login) const override;
+    int EditMessage(const STG::Message & msg, const std::string & login) const override;
+    int GetMessage(uint64_t id, STG::Message * msg, const std::string & login) const override;
+    int DelMessage(uint64_t id, const std::string & login) const override;
+    int GetMessageHdrs(std::vector<STG::Message::Header> * hdrsList, const std::string & login) const override;
+
+    int SaveMonthStat(const STG::UserStat & stat, int month, int year, const std::string & login) const override;
+
+    //Admin
+    int GetAdminsList(std::vector<std::string> * adminsList) const override;
+    int AddAdmin(const std::string & login) const override;
+    int DelAdmin(const std::string & login) const override;
+    int RestoreAdmin(STG::AdminConf * ac, const std::string & login) const override;
+    int SaveAdmin(const STG::AdminConf & ac) const override;
+
+    //Tariff
+    int GetTariffsList(std::vector<std::string> * tariffsList) const override;
+    int AddTariff(const std::string & name) const override;
+    int DelTariff(const std::string & name) const override;
+    int SaveTariff(const STG::TariffData & td, const std::string & tariffName) const override;
+    int RestoreTariff(STG::TariffData * td, const std::string & tariffName) const override;
+
+    //Corparation
+    int GetCorpsList(std::vector<std::string> *) const override {return 0;}
+    int SaveCorp(const STG::CorpConf &) const override {return 0;}
+    int RestoreCorp(STG::CorpConf *, const std::string &) const override {return 0;}
+    int AddCorp(const std::string &) const override {return 0;}
+    int DelCorp(const std::string &) const override {return 0;}
+
+    // Services
+    int GetServicesList(std::vector<std::string> *) const override {return 0;}
+    int SaveService(const STG::ServiceConf &) const override {return 0;}
+    int RestoreService(STG::ServiceConf *, const std::string &) const override {return 0;}
+    int AddService(const std::string &) const override {return 0;}
+    int DelService(const std::string &) const override {return 0;}
+
+    void            SetSettings(const STG::ModuleSettings & s) override { settings = s; }
+    int             ParseSettings() override;
+    const std::string &  GetVersion() const override { return version; }
+
+private:
+    MYSQL_STORE(const MYSQL_STORE & rvalue);
+    MYSQL_STORE & operator=(const MYSQL_STORE & rvalue);
+
+    virtual int WriteLogString(const std::string & str, const std::string & login) const;
+    int GetAllParams(std::vector<std::string> * ParamList, const std::string & table, const std::string & name) const;
+    int CheckAllTables(MYSQL * sock);
+    int MakeUpdates(MYSQL * sock);
+    bool IsTablePresent(const std::string & str,MYSQL * sock);
+    mutable std::string          errorStr;
+    int                        MysqlQuery(const char* sQuery,MYSQL * sock) const;
+    int                     MysqlGetQuery(const char * Query,MYSQL * & sock) const;
+    int                     MysqlSetQuery(const char * Query) const;
+    MYSQL  *                MysqlConnect() const ;
+    std::string                  version;
+    MYSQL_STORE_SETTINGS    storeSettings;
+    STG::ModuleSettings         settings;
+    int                     schemaVersion;
+
+    STG::PluginLogger           logger;
+};
diff --git a/projects/stargazer/plugins/store/postgresql/postgresql_store.cpp b/projects/stargazer/plugins/store/postgresql/postgresql_store.cpp
new file mode 100644 (file)
index 0000000..2146d66
--- /dev/null
@@ -0,0 +1,235 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+/*
+ *  This file contains a realization of a base postgresql-storage plugin class
+ *
+ *  v. 1.3
+ *  FreeMb logging on disconnects added
+ *
+ *  v. 1.2
+ *  Reconnection on faults added
+ *
+ *  v. 1.1
+ *  tb_stats removed
+ *
+ *  v. 1.0
+ *  Initial implementation
+ *
+ *  $Revision: 1.5 $
+ *  $Date: 2010/01/06 10:43:48 $
+ *
+ */
+
+#include "postgresql_store.h"
+
+#include "postgresql_store_utils.h"
+#include "postgresql_store.h"
+
+#include "stg/common.h" // str2x, printfd
+
+#include <string>
+#include <vector>
+
+#include <libpq-fe.h>
+
+extern "C" STG::Store* GetStore()
+{
+    static POSTGRESQL_STORE plugin;
+    return &plugin;
+}
+
+//-----------------------------------------------------------------------------
+POSTGRESQL_STORE::POSTGRESQL_STORE()
+    : versionString("postgresql_store v.1.3"),
+      server("localhost"),
+      database("stargazer"),
+      user("stg"),
+      password("123456"),
+      clientEncoding("KOI8"),
+      version(0),
+      retries(3),
+      connection(NULL),
+      logger(STG::PluginLogger::get("store_postgresql"))
+{
+pthread_mutex_init(&mutex, NULL);
+}
+//-----------------------------------------------------------------------------
+POSTGRESQL_STORE::~POSTGRESQL_STORE()
+{
+if (connection)
+    {
+    PQfinish(connection);
+    }
+pthread_mutex_destroy(&mutex);
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::ParseSettings()
+{
+std::vector<STG::ParamValue>::iterator i;
+
+for(i = settings.moduleParams.begin(); i != settings.moduleParams.end(); ++i)
+    {
+    if (i->value.empty())
+        continue;
+    std::string s = ToLower(i->param);
+    if (s == "server")
+        {
+        server = i->value.front();
+        }
+    if (s == "database")
+        {
+        database = i->value.front();
+        }
+    if (s == "user")
+        {
+        user = i->value.front();
+        }
+    if (s == "password")
+        {
+        password = i->value.front();
+        }
+    if (s == "retries")
+        {
+        if (str2x(i->value.front(), retries))
+            {
+            strError = "Invalid 'retries' value";
+            printfd(__FILE__, "POSTGRESQL_STORE::ParseSettings(): '%s'\n", strError.c_str());
+            return -1;
+            }
+        }
+    }
+
+clientEncoding = "KOI8";
+
+return Connect();
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::Connect()
+{
+std::string params;
+params = "host=" + server + " "
+       + "dbname=" + database + " "
+       + "user=" + user + " "
+       + "password=" + password;
+
+connection = PQconnectdb(params.c_str());
+
+if (PQstatus(connection) != CONNECTION_OK)
+    {
+    strError = PQerrorMessage(connection);
+    printfd(__FILE__, "POSTGRESQL_STORE::Connect(): '%s'\n", strError.c_str());
+    // Will try to connect later
+    return 0;
+    }
+
+if (PQsetClientEncoding(connection, clientEncoding.c_str()))
+    {
+    strError = PQerrorMessage(connection);
+    printfd(__FILE__, "POSTGRESQL_STORE::Connect(): '%s'\n", strError.c_str());
+    return 1;
+    }
+
+return CheckVersion();
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::Reset() const
+{
+for (int i = 0; i < retries && PQstatus(connection) != CONNECTION_OK; ++i)
+    {
+    struct timespec ts = {1, 0};
+    nanosleep(&ts, NULL);
+    PQreset(connection);
+    }
+
+if (PQstatus(connection) != CONNECTION_OK)
+    {
+    strError = PQerrorMessage(connection);
+    printfd(__FILE__, "POSTGRESQL_STORE::Reset(): '%s'\n", strError.c_str());
+    return 1;
+    }
+
+if (PQsetClientEncoding(connection, clientEncoding.c_str()))
+    {
+    strError = PQerrorMessage(connection);
+    printfd(__FILE__, "POSTGRESQL_STORE::Reset(): '%s'\n", strError.c_str());
+    return -1;
+    }
+
+return CheckVersion();
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::CheckVersion() const
+{
+
+if (StartTransaction())
+    {
+    strError = "Failed to start transaction";
+    printfd(__FILE__, "POSTGRESQL_STORE::CheckVersion(): '%s'\n", strError.c_str());
+    return -1;
+    }
+
+PGresult * result = PQexec(connection, "SELECT MAX(version) FROM tb_info");
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    PQclear(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::CheckVersion(): '%s'\n");
+    RollbackTransaction();
+    return -1;
+    }
+
+if (str2x(PQgetvalue(result, 0, 0), version))
+    {
+    strError = "Invalid DB version";
+    PQclear(result);
+    RollbackTransaction();
+    printfd(__FILE__, "POSTGRESQL_STORE::CheckVersion(): '%s'\n", strError.c_str());
+    return -1;
+    }
+
+PQclear(result);
+
+if (version < DB_MIN_VERSION)
+    {
+    strError = "DB version too old";
+    RollbackTransaction();
+    printfd(__FILE__, "POSTGRESQL_STORE::CheckVersion(): '%s'\n", strError.c_str());
+    return -1;
+    }
+
+if (version < 6)
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::CheckVersion(): I recommend you to upgrade your DB to higher version to support FreeMb logging on disconnect. Current version is %d\n", version);
+    }
+
+if (CommitTransaction())
+    {
+    strError = "Failed to commit transaction";
+    printfd(__FILE__, "POSTGRESQL_STORE::CheckVersion(): '%s'\n", strError.c_str());
+    return -1;
+    }
+
+logger("POSTGRESQL_STORE: Current DB schema version: %d", version);
+
+return 0;
+}
+//-----------------------------------------------------------------------------
diff --git a/projects/stargazer/plugins/store/postgresql/postgresql_store.h b/projects/stargazer/plugins/store/postgresql/postgresql_store.h
new file mode 100644 (file)
index 0000000..0e8b639
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#pragma once
+
+#include "stg/store.h"
+#include "stg/module_settings.h"
+#include "stg/logger.h"
+
+#include <string>
+#include <vector>
+
+#include <libpq-fe.h>
+
+// Minimal DB version is 5
+// Recommended DB version is 6 (support FreeMb logging on disconnects)
+#define DB_MIN_VERSION 5
+
+namespace STG
+{
+
+class UserIPs;
+
+}
+
+class POSTGRESQL_STORE : public STG::Store {
+public:
+    POSTGRESQL_STORE();
+    ~POSTGRESQL_STORE() override;
+
+    // Users
+    int GetUsersList(std::vector<std::string> * usersList) const override;
+    int AddUser(const std::string & login) const override;
+    int DelUser(const std::string & login) const override;
+    int SaveUserStat(const STG::UserStat & stat, const std::string & login) const override;
+    int SaveUserConf(const STG::UserConf & conf, const std::string & login) const override;
+    int RestoreUserStat(STG::UserStat * stat, const std::string & login) const override;
+    int RestoreUserConf(STG::UserConf * conf, const std::string & login) const override;
+    int WriteUserChgLog(const std::string & login,
+                        const std::string & admLogin,
+                        uint32_t admIP,
+                        const std::string & paramName,
+                        const std::string & oldValue,
+                        const std::string & newValue,
+                        const std::string & message) const override;
+    int WriteUserConnect(const std::string & login, uint32_t ip) const override;
+    int WriteUserDisconnect(const std::string & login,
+                            const STG::DirTraff & up,
+                            const STG::DirTraff & down,
+                            const STG::DirTraff & sessionUp,
+                            const STG::DirTraff & sessionDown,
+                            double cash,
+                            double freeMb,
+                            const std::string & reason) const override;
+    int WriteDetailedStat(const STG::TraffStat & statTree,
+                          time_t lastStat,
+                          const std::string & login) const override;
+
+    // Messages
+    int AddMessage(STG::Message * msg, const std::string & login) const override;
+    int EditMessage(const STG::Message & msg, const std::string & login) const override;
+    int GetMessage(uint64_t id, STG::Message * msg, const std::string & login) const override;
+    int DelMessage(uint64_t id, const std::string & login) const override;
+    int GetMessageHdrs(std::vector<STG::Message::Header> * hdrsList, const std::string & login) const override;
+
+    // Stats
+    int SaveMonthStat(const STG::UserStat & stat, int month, int year, const std::string  & login) const override;
+
+    // Admins
+    int GetAdminsList(std::vector<std::string> * adminsList) const override;
+    int SaveAdmin(const STG::AdminConf & ac) const override;
+    int RestoreAdmin(STG::AdminConf * ac, const std::string & login) const override;
+    int AddAdmin(const std::string & login) const override;
+    int DelAdmin(const std::string & login) const override;
+
+    // Tariffs
+    int GetTariffsList(std::vector<std::string> * tariffsList) const override;
+    int AddTariff(const std::string & name) const override;
+    int DelTariff(const std::string & name) const override;
+    int SaveTariff(const STG::TariffData & td, const std::string & tariffName) const override;
+    int RestoreTariff(STG::TariffData * td, const std::string & tariffName) const override;
+
+    // Corporations
+    int GetCorpsList(std::vector<std::string> * corpsList) const override;
+    int SaveCorp(const STG::CorpConf & cc) const override;
+    int RestoreCorp(STG::CorpConf * cc, const std::string & name) const override;
+    int AddCorp(const std::string & name) const override;
+    int DelCorp(const std::string & name) const override;
+
+    // Services
+    int GetServicesList(std::vector<std::string> * servicesList) const override;
+    int SaveService(const STG::ServiceConf & sc) const override;
+    int RestoreService(STG::ServiceConf * sc, const std::string & name) const override;
+    int AddService(const std::string & name) const override;
+    int DelService(const std::string & name) const override;
+
+    // Settings
+    void SetSettings(const STG::ModuleSettings & s) override { settings = s; }
+    int ParseSettings() override;
+
+    const std::string & GetStrError() const override { return strError; }
+    const std::string & GetVersion() const override { return versionString; }
+private:
+    POSTGRESQL_STORE(const POSTGRESQL_STORE & rvalue);
+    POSTGRESQL_STORE & operator=(const POSTGRESQL_STORE & rvalue);
+
+    int StartTransaction() const;
+    int CommitTransaction() const;
+    int RollbackTransaction() const;
+
+    int EscapeString(std::string & value) const;
+
+    int SaveStat(const STG::UserStat & stat, const std::string & login, int year = 0, int month = 0) const;
+
+    int SaveUserServices(uint32_t uid, const std::vector<std::string> & services) const;
+    int SaveUserData(uint32_t uid, const std::vector<std::string> & data) const;
+    int SaveUserIPs(uint32_t uid, const STG::UserIPs & ips) const;
+
+    void MakeDate(std::string & date, int year = 0, int month = 0) const;
+
+    int Connect();
+    int Reset() const;
+    int CheckVersion() const;
+
+    std::string versionString;
+    mutable std::string strError;
+    std::string server;
+    std::string database;
+    std::string user;
+    std::string password;
+    std::string clientEncoding;
+    STG::ModuleSettings settings;
+    mutable pthread_mutex_t mutex;
+    mutable int version;
+    int retries;
+
+    PGconn * connection;
+
+    STG::PluginLogger logger;
+};
diff --git a/projects/stargazer/plugins/store/postgresql/postgresql_store_admins.cpp b/projects/stargazer/plugins/store/postgresql/postgresql_store_admins.cpp
new file mode 100644 (file)
index 0000000..b1c1203
--- /dev/null
@@ -0,0 +1,454 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+/*
+ *  Administrators manipulation methods
+ *
+ *  $Revision: 1.3 $
+ *  $Date: 2010/11/08 10:10:24 $
+ *
+ */
+
+#include "postgresql_store.h"
+
+#include "stg/locker.h"
+#include "stg/common.h"
+#include "stg/admin_conf.h"
+#include "stg/blowfish.h"
+
+#include <string>
+#include <vector>
+#include <sstream>
+
+#include <libpq-fe.h>
+
+#define adm_enc_passwd "cjeifY8m3"
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::GetAdminsList(std::vector<std::string> * adminsList) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::GetAdminsList(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+    if (Reset())
+        {
+        strError = "Connection lost";
+        printfd(__FILE__, "POSTGRESQL_STORE::GetAdminsList(): '%s'\n", strError.c_str());
+        return -1;
+        }
+    }
+
+PGresult * result;
+
+if (StartTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::GetAdminsList(): 'Failed to start transaction'\n");
+    return -1;
+    }
+
+result = PQexec(connection, "SELECT login FROM tb_admins WHERE login <> '@stargazer'");
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    PQclear(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::GetAdminsList(): '%s'\n", strError.c_str());
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::GetAdminsList(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+int tuples = PQntuples(result);
+
+for (int i = 0; i < tuples; ++i)
+    {
+    adminsList->push_back(PQgetvalue(result, i, 0));
+    }
+
+PQclear(result);
+
+if (CommitTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::GetAdminsList(): 'Failed to commit transaction'\n");
+    return -1;
+    }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::SaveAdmin(const STG::AdminConf & ac) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+    if (Reset())
+        {
+        strError = "Connection lost";
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): '%s'\n", strError.c_str());
+        return -1;
+        }
+    }
+
+PGresult * result;
+
+if (StartTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): 'Failed to start transaction'\n");
+    return -1;
+    }
+
+char encodedPass[2 * ADM_PASSWD_LEN + 2];
+char cryptedPass[ADM_PASSWD_LEN + 1];
+char adminPass[ADM_PASSWD_LEN + 1];
+BLOWFISH_CTX ctx;
+
+memset(cryptedPass, 0, ADM_PASSWD_LEN + 1);
+strncpy(adminPass, ac.password.c_str(), ADM_PASSWD_LEN);
+InitContext(adm_enc_passwd, sizeof(adm_enc_passwd), &ctx);
+
+for (int i = 0; i < ADM_PASSWD_LEN / 8; i++)
+    EncryptBlock(cryptedPass + 8 * i, adminPass + 8 * i, &ctx);
+
+cryptedPass[ADM_PASSWD_LEN] = 0;
+Encode12(encodedPass, cryptedPass, ADM_PASSWD_LEN);
+
+std::string pass = encodedPass;
+std::string login = ac.login;
+
+if (EscapeString(pass))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): 'Failed to escape password'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+if (EscapeString(login))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): 'Failed to escape login'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+std::stringstream query;
+query << "UPDATE tb_admins SET "
+          << "passwd = '" << pass << "', "
+          << "chg_conf = " << ac.priv.userConf << ", "
+          << "chg_password = " << ac.priv.userPasswd << ", "
+          << "chg_stat = " << ac.priv.userStat << ", "
+          << "chg_cash = " << ac.priv.userCash << ", "
+          << "usr_add_del = " << ac.priv.userAddDel << ", "
+          << "chg_tariff = " << ac.priv.tariffChg << ", "
+          << "chg_admin = " << ac.priv.adminChg << " "
+      << "WHERE login = '" << login << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    PQclear(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): '%s'\n", strError.c_str());
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+PQclear(result);
+
+if (CommitTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): 'Failed to commit transaction'\n");
+    return -1;
+    }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::RestoreAdmin(STG::AdminConf * ac, const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+    if (Reset())
+        {
+        strError = "Connection lost";
+        printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): '%s'\n", strError.c_str());
+        return -1;
+        }
+    }
+
+PGresult * result;
+
+if (StartTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): 'Failed to start transaction'\n");
+    return -1;
+    }
+
+char cryptedPass[ADM_PASSWD_LEN + 1];
+char adminPass[ADM_PASSWD_LEN + 1];
+BLOWFISH_CTX ctx;
+
+std::string elogin = login;
+
+if (EscapeString(elogin))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): 'Failed to escape login'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+std::ostringstream query;
+query << "SELECT login, passwd, \
+                 chg_conf, chg_password, chg_stat, \
+                 chg_cash, usr_add_del, chg_tariff, \
+                 chg_admin, chg_service, chg_corporation \
+          FROM tb_admins \
+          WHERE login = '" << elogin << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): '%s'\n", strError.c_str());
+    PQclear(result);
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+int tuples = PQntuples(result);
+
+if (tuples != 1)
+    {
+    strError = "Failed to fetch admin's data";
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
+    PQclear(result);
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+ac->login = PQgetvalue(result, 0, 0);
+ac->password = PQgetvalue(result, 0, 1);
+
+std::stringstream tuple;
+tuple << PQgetvalue(result, 0, 2) << " "
+      << PQgetvalue(result, 0, 3) << " "
+      << PQgetvalue(result, 0, 4) << " "
+      << PQgetvalue(result, 0, 5) << " "
+      << PQgetvalue(result, 0, 6) << " "
+      << PQgetvalue(result, 0, 7) << " "
+      << PQgetvalue(result, 0, 8) << " "
+      << PQgetvalue(result, 0, 9) << " "
+      << PQgetvalue(result, 0, 10);
+
+PQclear(result);
+
+tuple >> ac->priv.userConf
+      >> ac->priv.userPasswd
+      >> ac->priv.userStat
+      >> ac->priv.userCash
+      >> ac->priv.userAddDel
+      >> ac->priv.tariffChg
+      >> ac->priv.adminChg;
+
+if (CommitTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): 'Failed to commit transacion'\n");
+    return -1;
+    }
+
+if (ac->password == "")
+    {
+    return 0;
+    }
+
+Decode21(cryptedPass, ac->password.c_str());
+InitContext(adm_enc_passwd, sizeof(adm_enc_passwd), &ctx);
+for (int i = 0; i < ADM_PASSWD_LEN / 8; i++)
+    {
+    DecryptBlock(adminPass + 8 * i, cryptedPass + 8 * i, &ctx);
+    }
+ac->password = adminPass;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::AddAdmin(const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::AddAdmin(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+    if (Reset())
+        {
+        strError = "Connection lost";
+        printfd(__FILE__, "POSTGRESQL_STORE::AddAdmin(): '%s'\n", strError.c_str());
+        return -1;
+        }
+    }
+
+PGresult * result;
+
+if (StartTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::AddAdmin(): 'Failed to start transaction'\n");
+    return -1;
+    }
+
+std::string elogin = login;
+
+if (EscapeString(elogin))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::AddAdmin(): 'Failed to escape login'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::AddAdmin(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+std::ostringstream query;
+query << "INSERT INTO tb_admins \
+              (login, passwd, \
+              chg_conf, chg_password, chg_stat, \
+              chg_cash, usr_add_del, chg_tariff, \
+              chg_admin, chg_service, chg_corporation) \
+          VALUES "
+          << "('" << elogin << "', \
+              '', 0, 0, 0, 0, 0, 0, 0, 0, 0)";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    PQclear(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::AddAdmin(): '%s'\n", strError.c_str());
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::AddAdmin(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+PQclear(result);
+
+if (CommitTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::AddAdmin(): 'Failed to commit transaction'\n");
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::DelAdmin(const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::DelAdmin(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+    if (Reset())
+        {
+        strError = "Connection lost";
+        printfd(__FILE__, "POSTGRESQL_STORE::DelAdmin(): '%s'\n", strError.c_str());
+        return -1;
+        }
+    }
+
+PGresult * result;
+
+if (StartTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::DelAdmin(): 'Failed to start transaction'\n");
+    return -1;
+    }
+
+std::string elogin = login;
+
+if (EscapeString(elogin))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::DelAdmin(): 'Failed to escape login'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::DelAdmin(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+std::ostringstream query;
+query << "DELETE FROM tb_admins WHERE login = '" << elogin << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    PQclear(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::DelAdmin(): '%s'\n", strError.c_str());
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::DelAdmin(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+PQclear(result);
+
+if (CommitTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::DelAdmin(): 'Failed to commit transaction'\n");
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+
diff --git a/projects/stargazer/plugins/store/postgresql/postgresql_store_corporations.cpp b/projects/stargazer/plugins/store/postgresql/postgresql_store_corporations.cpp
new file mode 100644 (file)
index 0000000..1387d41
--- /dev/null
@@ -0,0 +1,377 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+/*
+ *  Corporations manipulation methods
+ *
+ *  $Revision: 1.2 $
+ *  $Date: 2009/06/09 12:32:39 $
+ *
+ */
+
+#include "postgresql_store.h"
+
+#include "stg/corp_conf.h"
+#include "stg/locker.h"
+#include "stg/common.h"
+
+#include <string>
+#include <vector>
+#include <sstream>
+
+#include <libpq-fe.h>
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::GetCorpsList(std::vector<std::string> * corpsList) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::GetCorpsList(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+    if (Reset())
+        {
+        strError = "Connection lost";
+        printfd(__FILE__, "POSTGRESQL_STORE::GetCorpsList(): '%s'\n", strError.c_str());
+        return -1;
+        }
+    }
+
+PGresult * result;
+
+if (StartTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::GetCorpsList(): 'Failed to start transaction'\n");
+    return -1;
+    }
+
+result = PQexec(connection, "SELECT name FROM tb_corporations");
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    PQclear(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::GetCorpsList(): '%s'\n", strError.c_str());
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::GetCorpsList(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+int tuples = PQntuples(result);
+
+for (int i = 0; i < tuples; ++i)
+    {
+    corpsList->push_back(PQgetvalue(result, i, 0));
+    }
+
+PQclear(result);
+
+if (CommitTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::GetCorpsList(): 'Failed to commit transaction'\n");
+    return -1;
+    }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::SaveCorp(const STG::CorpConf & cc) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveCorp(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+    if (Reset())
+        {
+        strError = "Connection lost";
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveCorp(): '%s'\n", strError.c_str());
+        return -1;
+        }
+    }
+
+PGresult * result;
+
+if (StartTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveCorp(): 'Failed to start transaction'\n");
+    return -1;
+    }
+
+std::string ename = cc.name;
+
+if (EscapeString(ename))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveCorp(): 'Failed to escape name'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveCorp(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+std::ostringstream query;
+query << "UPDATE tb_corporations SET "
+          << "cash = " << cc.cash
+      << "WHERE name = '" << ename << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    PQclear(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveCorp(): '%s'\n", strError.c_str());
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveCorp(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+PQclear(result);
+
+if (CommitTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveCorp(): 'Failed to commit transaction'\n");
+    return -1;
+    }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::RestoreCorp(STG::CorpConf * cc, const std::string & name) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+    if (Reset())
+        {
+        strError = "Connection lost";
+        printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): '%s'\n", strError.c_str());
+        return -1;
+        }
+    }
+
+PGresult * result;
+
+if (StartTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): 'Failed to start transaction'\n");
+    return -1;
+    }
+
+std::string ename = name;
+
+if (EscapeString(ename))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): 'Failed to escape name'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+std::ostringstream query;
+query << "SELECT cash FROM tb_corporations WHERE name = '" << ename << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    PQclear(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): '%s'\n", strError.c_str());
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+int tuples = PQntuples(result);
+
+if (tuples != 1)
+    {
+    strError = "Failed to fetch corp's data";
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
+    PQclear(result);
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+std::stringstream tuple;
+tuple << PQgetvalue(result, 0, 0);
+
+PQclear(result);
+
+tuple >> cc->cash;
+
+if (CommitTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): 'Failed to commit transaction'\n");
+    return -1;
+    }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::AddCorp(const std::string & name) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::AddCorp(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+    if (Reset())
+        {
+        strError = "Connection lost";
+        printfd(__FILE__, "POSTGRESQL_STORE::AddCorp(): '%s'\n", strError.c_str());
+        return -1;
+        }
+    }
+
+PGresult * result;
+
+if (StartTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::AddCorp(): 'Failed to start transaction'\n");
+    return -1;
+    }
+
+std::string ename = name;
+
+if (EscapeString(ename))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::AddCorp(): 'Failed to escape name'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::AddCorp(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+std::ostringstream query;
+query << "INSERT INTO tb_corporations \
+              (name, cash) \
+          VALUES \
+              ('" << ename << "', 0)";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    PQclear(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::AddCorp(): '%s'\n", strError.c_str());
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::AddCorp(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+PQclear(result);
+
+if (CommitTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::AddCorp(): 'Failed to commit transaction'\n");
+    return -1;
+    }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::DelCorp(const std::string & name) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::DelCorp(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+    if (Reset())
+        {
+        strError = "Connection lost";
+        printfd(__FILE__, "POSTGRESQL_STORE::DelCorp(): '%s'\n", strError.c_str());
+        return -1;
+        }
+    }
+
+PGresult * result;
+
+if (StartTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::DelCorp(): 'Failed to start transaction'\n");
+    return -1;
+    }
+
+std::string ename = name;
+
+if (EscapeString(ename))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::DelCorp(): 'Failed to escape name'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::DelCorp(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+std::ostringstream query;
+query << "DELETE FROM tb_corporations WHERE name = '" << ename << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    PQclear(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::DelCorp(): '%s'\n", strError.c_str());
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::DelCorp(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+PQclear(result);
+
+if (CommitTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::DelCorp(): 'Failed to commit transaction'\n");
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+
diff --git a/projects/stargazer/plugins/store/postgresql/postgresql_store_messages.cpp b/projects/stargazer/plugins/store/postgresql/postgresql_store_messages.cpp
new file mode 100644 (file)
index 0000000..905b467
--- /dev/null
@@ -0,0 +1,455 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+
+/*
+ *  Messages manipualtion methods
+ *
+ *  $Revision: 1.6 $
+ *  $Date: 2009/07/15 11:19:42 $
+ *
+ */
+
+#include "postgresql_store.h"
+
+#include "stg/common.h"
+#include "stg/locker.h"
+#include "stg/message.h"
+
+#include <string>
+#include <vector>
+#include <sstream>
+
+#include <libpq-fe.h>
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::AddMessage(STG::Message * msg, const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+    if (Reset())
+        {
+        strError = "Connection lost";
+        printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): '%s'\n", strError.c_str());
+        return -1;
+        }
+    }
+
+PGresult * result;
+
+if (StartTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Failed to start transaction'\n");
+    return -1;
+    }
+
+std::string elogin = login;
+std::string etext = msg->text;
+
+if (EscapeString(elogin))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Failed to escape login'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+if (EscapeString(etext))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Failed to escape message text'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+std::ostringstream query;
+query << "SELECT sp_add_message("
+      << "'" << elogin << "', "
+      << "CAST(1 AS SMALLINT), " // Here need to be a version, but, it's uninitiated actually
+      << "CAST(" << msg->header.type << " AS SMALLINT), "
+      << "CAST('" << formatTime(msg->header.lastSendTime) << "' AS TIMESTAMP), "
+      << "CAST('" << formatTime(msg->header.creationTime) << "' AS TIMESTAMP), "
+      << msg->header.showTime << ", "
+      << "CAST(" << msg->header.repeat << " AS SMALLINT), "
+      << msg->header.repeatPeriod << ", "
+      << "'" << etext << "')";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    PQclear(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): '%s'\n", strError.c_str());
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+int tuples = PQntuples(result);
+
+if (tuples != 1)
+    {
+    strError = "Failed to fetch newlly added message ID";
+    printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
+    PQclear(result);
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+std::stringstream tuple;
+tuple << PQgetvalue(result, 0, 0);
+
+PQclear(result);
+
+tuple >> msg->header.id;
+
+if (CommitTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Failed to commit transaction'\n");
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::EditMessage(const STG::Message & msg,
+                                  const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+    if (Reset())
+        {
+        strError = "Connection lost";
+        printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): '%s'\n", strError.c_str());
+        return -1;
+        }
+    }
+
+PGresult * result;
+
+if (StartTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): 'Failed to start transaction'\n");
+    return -1;
+    }
+
+std::string elogin = login;
+std::string etext = msg.text;
+
+if (EscapeString(elogin))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): 'Failed to escape login'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+if (EscapeString(etext))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): 'Failed to escape message text'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+std::ostringstream query;
+query << "UPDATE tb_messages SET "
+          << "fk_user = (SELECT pk_user FROM tb_users WHERE name = '" << elogin << "'), "
+          << "ver = " << msg.header.ver << ", "
+          << "msg_type = " << msg.header.type << ", "
+          << "last_send_time = CAST('" << formatTime(msg.header.lastSendTime) << "' AS TIMESTAMP), "
+          << "creation_time = CAST('" << formatTime(msg.header.creationTime) << "' AS TIMESTAMP), "
+          << "show_time = " << msg.header.showTime << ", "
+          << "repeat = " << msg.header.repeat << ", "
+          << "repeat_period = " << msg.header.repeatPeriod << ", "
+          << "msg_text = '" << etext << "' "
+      << "WHERE pk_message = " << msg.header.id;
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    PQclear(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): '%s'\n", strError.c_str());
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+PQclear(result);
+
+if (CommitTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): 'Failed to commit transaction'\n");
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::GetMessage(uint64_t id,
+                                 STG::Message * msg,
+                                 const std::string &) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::GetMessage(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+    if (Reset())
+        {
+        strError = "Connection lost";
+        printfd(__FILE__, "POSTGRESQL_STORE::GetMessage(): '%s'\n", strError.c_str());
+        return -1;
+        }
+    }
+
+PGresult * result;
+
+if (StartTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::GetMessage(): 'Failed to start transaction'\n");
+    return -1;
+    }
+
+std::ostringstream query;
+query << "SELECT ver, msg_type, last_send_time, \
+                 creation_time, show_time, repeat, \
+                 repeat_period, msg_text \
+          FROM tb_messages \
+          WHERE pk_message = " << id;
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    PQclear(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::GetMessage(): '%s'\n", strError.c_str());
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::GetMessage(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+int tuples = PQntuples(result);
+
+if (tuples != 1)
+    {
+    strError = "Failed to fetch message data";
+    printfd(__FILE__, "POSTGRESQL_STORE::GetMessage(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
+    PQclear(result);
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::GetMessage(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+str2x(PQgetvalue(result, 0, 0), msg->header.ver);
+str2x(PQgetvalue(result, 0, 1), msg->header.type);
+msg->header.lastSendTime = static_cast<unsigned int>(readTime(PQgetvalue(result, 0, 2)));
+msg->header.creationTime = static_cast<unsigned int>(readTime(PQgetvalue(result, 0, 3)));
+str2x(PQgetvalue(result, 0, 4), msg->header.showTime);
+str2x(PQgetvalue(result, 0, 5), msg->header.repeat);
+str2x(PQgetvalue(result, 0, 6), msg->header.repeatPeriod);
+msg->text = PQgetvalue(result, 0, 7);
+
+PQclear(result);
+
+if (CommitTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::GetMessage(): 'Failed to commit transaction'\n");
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::DelMessage(uint64_t id, const std::string &) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::DelMessage(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+    if (Reset())
+        {
+        strError = "Connection lost";
+        printfd(__FILE__, "POSTGRESQL_STORE::DelMessage(): '%s'\n", strError.c_str());
+        return -1;
+        }
+    }
+
+PGresult * result;
+
+if (StartTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::DelMessage(): 'Failed to start transaction'\n");
+    return -1;
+    }
+
+std::ostringstream query;
+query << "DELETE FROM tb_messages WHERE pk_message = " << id;
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    PQclear(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::DelMessage(): '%s'\n", strError.c_str());
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::DelMessage(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+PQclear(result);
+
+if (CommitTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::DelMessage(): 'Failed to commit transaction'\n");
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::GetMessageHdrs(std::vector<STG::Message::Header> * hdrsList,
+                                   const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::GetMessageHdrs(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+    if (Reset())
+        {
+        strError = "Connection lost";
+        printfd(__FILE__, "POSTGRESQL_STORE::GetMessageHdrs(): '%s'\n", strError.c_str());
+        return -1;
+        }
+    }
+
+PGresult * result;
+
+if (StartTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::GetMessageHdrs(): 'Failed to start transaction'\n");
+    return -1;
+    }
+
+std::string elogin = login;
+
+if (EscapeString(elogin))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::GetMessageHdrs(): 'Failed to escape login'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::GetMessageHdrs(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+std::ostringstream query;
+query << "SELECT pk_message, ver, msg_type, \
+                 last_send_time, creation_time, show_time, \
+                 repeat, repeat_period \
+          FROM tb_messages \
+          WHERE fk_user IN \
+                (SELECT pk_user FROM tb_users \
+          WHERE name = '" << elogin << "')";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    PQclear(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::GetMessageHdrs(): '%s'\n", strError.c_str());
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::GetMessageHdrs(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+int tuples = PQntuples(result);
+
+for (int i = 0; i < tuples; ++i)
+    {
+    std::stringstream tuple;
+    STG::Message::Header header;
+    tuple << PQgetvalue(result, i, 0) << " ";
+    tuple << PQgetvalue(result, i, 1) << " ";
+    tuple << PQgetvalue(result, i, 2) << " ";
+    header.lastSendTime = static_cast<unsigned int>(readTime(PQgetvalue(result, i, 3)));
+    header.creationTime = static_cast<unsigned int>(readTime(PQgetvalue(result, i, 4)));
+    tuple << PQgetvalue(result, i, 5) << " ";
+    tuple << PQgetvalue(result, i, 6) << " ";
+    tuple << PQgetvalue(result, i, 7) << " ";
+
+    tuple >> header.id;
+    tuple >> header.ver;
+    tuple >> header.type;
+    tuple >> header.showTime;
+    tuple >> header.repeat;
+    tuple >> header.repeatPeriod;
+    hdrsList->push_back(header);
+    }
+
+PQclear(result);
+
+if (CommitTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::GetMessageHdrs(): 'Failed to commit transaction'\n");
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+
diff --git a/projects/stargazer/plugins/store/postgresql/postgresql_store_services.cpp b/projects/stargazer/plugins/store/postgresql/postgresql_store_services.cpp
new file mode 100644 (file)
index 0000000..3d09816
--- /dev/null
@@ -0,0 +1,396 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+
+/*
+ *  Services manipulation methods
+ *
+ *  $Revision: 1.2 $
+ *  $Date: 2009/06/09 12:32:40 $
+ *
+ */
+
+#include "postgresql_store.h"
+
+#include "stg/service_conf.h"
+#include "stg/common.h"
+#include "stg/locker.h"
+
+#include <string>
+#include <vector>
+#include <sstream>
+
+#include <libpq-fe.h>
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::GetServicesList(std::vector<std::string> * servicesList) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::GetServicesList(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+    if (Reset())
+        {
+        strError = "Connection lost";
+        printfd(__FILE__, "POSTGRESQL_STORE::GetServicesList(): '%s'\n", strError.c_str());
+        return -1;
+        }
+    }
+
+PGresult * result;
+
+if (StartTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::GetServicesList(): 'Failed to start transaction'\n");
+    return -1;
+    }
+
+result = PQexec(connection, "SELECT name FROM tb_services");
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    PQclear(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::GetServicesList(): '%s'\n", strError.c_str());
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::GetServicesList(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+int tuples = PQntuples(result);
+
+for (int i = 0; i < tuples; ++i)
+    {
+    servicesList->push_back(PQgetvalue(result, i, 0));
+    }
+
+PQclear(result);
+
+if (CommitTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::GetServicesList(): 'Failed to commit transaction'\n");
+    return -1;
+    }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::SaveService(const STG::ServiceConf & sc) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+    if (Reset())
+        {
+        strError = "Connection lost";
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): '%s'\n", strError.c_str());
+        return -1;
+        }
+    }
+
+PGresult * result;
+
+if (StartTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to start transaction'\n");
+    return -1;
+    }
+
+std::string ename = sc.name;
+std::string ecomment = sc.comment;
+
+if (EscapeString(ename))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to escape name'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+if (EscapeString(ecomment))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to escape comment'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+std::ostringstream query;
+query << "UPDATE tb_services SET "
+          << "comment = '" << ecomment << "', "
+          << "cost = " << sc.cost << ", "
+          << "pay_day = " << sc.payDay << " "
+      << "WHERE name = '" << ename << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    PQclear(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): '%s'\n", strError.c_str());
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+PQclear(result);
+
+if (CommitTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to commit transaction'\n");
+    return -1;
+    }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::RestoreService(STG::ServiceConf * sc,
+                                     const std::string & name) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+    if (Reset())
+        {
+        strError = "Connection lost";
+        printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): '%s'\n", strError.c_str());
+        return -1;
+        }
+    }
+
+PGresult * result;
+
+if (StartTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Failed to start transaction'\n");
+    return -1;
+    }
+
+std::string ename = name;
+
+if (EscapeString(ename))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Failed to escape name'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+std::ostringstream query;
+query << "SELECT comment, cost, pay_day FROM tb_services WHERE name = '" << ename << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    PQclear(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): '%s'\n", strError.c_str());
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+int tuples = PQntuples(result);
+
+if (tuples != 1)
+    {
+    strError = "Failed to fetch service's data";
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
+    PQclear(result);
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+std::stringstream tuple;
+tuple << PQgetvalue(result, 0, 0) << " "
+      << PQgetvalue(result, 0, 1) << " "
+      << PQgetvalue(result, 0, 2);
+
+PQclear(result);
+
+tuple >> sc->comment
+      >> sc->cost
+      >> sc->payDay;
+
+if (CommitTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Failed to commit transaction'\n");
+    return -1;
+    }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::AddService(const std::string & name) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::AddService(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+    if (Reset())
+        {
+        strError = "Connection lost";
+        printfd(__FILE__, "POSTGRESQL_STORE::AddService(): '%s'\n", strError.c_str());
+        return -1;
+        }
+    }
+
+PGresult * result;
+
+if (StartTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::AddService(): 'Failed to start transaction'\n");
+    return -1;
+    }
+
+std::string ename = name;
+
+if (EscapeString(ename))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::AddService(): 'Failed to escape name'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::AddService(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+std::ostringstream query;
+query << "INSERT INTO tb_services \
+              (name, comment, cost, pay_day) \
+          VALUES \
+              ('" << ename << "', '', 0, 0)";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    PQclear(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::AddService(): '%s'\n", strError.c_str());
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::AddService(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+PQclear(result);
+
+if (CommitTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::AddService(): 'Failed to commit transaction'\n");
+    return -1;
+    }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::DelService(const std::string & name) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::DelService(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+    if (Reset())
+        {
+        strError = "Connection lost";
+        printfd(__FILE__, "POSTGRESQL_STORE::DelService(): '%s'\n", strError.c_str());
+        return -1;
+        }
+    }
+
+PGresult * result;
+
+if (StartTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::DelService(): 'Failed to start transaction'\n");
+    return -1;
+    }
+
+std::string ename = name;
+
+if (EscapeString(ename))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::DelService(): 'Failed to escape name'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::DelService(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+std::ostringstream query;
+query << "DELETE FROM tb_services WHERE name = '" << ename << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    PQclear(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::DelService(): '%s'\n", strError.c_str());
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::DelService(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+PQclear(result);
+
+if (CommitTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::DelService(): 'Failed to commit transaction'\n");
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+
diff --git a/projects/stargazer/plugins/store/postgresql/postgresql_store_tariffs.cpp b/projects/stargazer/plugins/store/postgresql/postgresql_store_tariffs.cpp
new file mode 100644 (file)
index 0000000..6a67598
--- /dev/null
@@ -0,0 +1,629 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+/*
+ *  Tariffs manipulation methods
+ *
+ *  $Revision: 1.2 $
+ *  $Date: 2009/06/09 12:32:40 $
+ *
+ */
+
+#include "postgresql_store.h"
+
+#include "stg/tariff_conf.h"
+#include "stg/common.h"
+#include "stg/locker.h"
+
+#include <string>
+#include <vector>
+#include <sstream>
+#include <cmath>
+
+#include <libpq-fe.h>
+
+namespace
+{
+
+const int pt_mega = 1024 * 1024;
+
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::GetTariffsList(std::vector<std::string> * tariffsList) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+    if (Reset())
+        {
+        strError = "Connection lost";
+        printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): '%s'\n", strError.c_str());
+        return -1;
+        }
+    }
+
+PGresult * result;
+
+if (StartTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): 'Failed to start transaction'\n");
+    return -1;
+    }
+
+result = PQexec(connection, "SELECT name FROM tb_tariffs");
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    PQclear(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): '%s'\n", strError.c_str());
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+int tuples = PQntuples(result);
+
+for (int i = 0; i < tuples; ++i)
+    {
+    tariffsList->push_back(PQgetvalue(result, i, 0));
+    }
+
+PQclear(result);
+
+if (CommitTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): 'Failed to commit transaction'\n");
+    return -1;
+    }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::AddTariff(const std::string & name) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+    if (Reset())
+        {
+        strError = "Connection lost";
+        printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): '%s'\n", strError.c_str());
+        return -1;
+        }
+    }
+
+PGresult * result;
+
+if (StartTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to start transaction'\n");
+    return -1;
+    }
+
+std::string ename = name;
+
+if (EscapeString(ename))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to escape name'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+std::ostringstream query;
+query << "SELECT sp_add_tariff('" << ename << "', " << DIR_NUM << ")";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    PQclear(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): '%s'\n", strError.c_str());
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+PQclear(result);
+
+if (CommitTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to commit transaction'\n");
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::DelTariff(const std::string & name) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+    if (Reset())
+        {
+        strError = "Connection lost";
+        printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): '%s'\n", strError.c_str());
+        return -1;
+        }
+    }
+
+PGresult * result;
+
+if (StartTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): 'Failed to start transaction'\n");
+    return -1;
+    }
+
+std::string ename = name;
+
+if (EscapeString(ename))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to escape name'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+std::ostringstream query;
+query << "DELETE FROM tb_tariffs WHERE name = '" << ename << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    PQclear(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): '%s'\n", strError.c_str());
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+PQclear(result);
+
+if (CommitTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): 'Failed to commit transaction'\n");
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::SaveTariff(const STG::TariffData & td,
+                                 const std::string & tariffName) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+    if (Reset())
+        {
+        strError = "Connection lost";
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): '%s'\n", strError.c_str());
+        return -1;
+        }
+    }
+
+PGresult * result;
+
+if (StartTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to start transaction'\n");
+    return -1;
+    }
+
+std::string ename = tariffName;
+
+if (EscapeString(ename))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to escape name'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+    {
+    std::ostringstream query;
+    query << "SELECT pk_tariff FROM tb_tariffs WHERE name = '" << ename << "'";
+
+    result = PQexec(connection, query.str().c_str());
+    }
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    PQclear(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): '%s'\n", strError.c_str());
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+int tuples = PQntuples(result);
+
+if (tuples != 1)
+    {
+    strError = "Failed to fetch tariff ID";
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
+    PQclear(result);
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+int32_t id;
+
+    {
+    std::stringstream tuple;
+    tuple << PQgetvalue(result, 0, 0);
+
+    PQclear(result);
+
+    tuple >> id;
+    }
+
+    {
+    std::ostringstream query;
+    query << "UPDATE tb_tariffs SET \
+                  fee = " << td.tariffConf.fee << ", \
+                  free = " << td.tariffConf.free << ", \
+                  passive_cost = " << td.tariffConf.passiveCost << ", \
+                  traff_type = " << td.tariffConf.traffType;
+
+    if (version > 6)
+        query << ", period = '" << STG::Tariff::toString(td.tariffConf.period) << "'";
+
+    if (version > 7)
+        query << ", change_policy = '" << STG::Tariff::toString(td.tariffConf.changePolicy) << "', \
+                  change_policy_timeout = CAST('" << formatTime(td.tariffConf.changePolicyTimeout) << "' AS TIMESTAMP)";
+
+    query << " WHERE pk_tariff = " << id;
+
+    result = PQexec(connection, query.str().c_str());
+    }
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    PQclear(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): '%s'\n", strError.c_str());
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+PQclear(result);
+
+for(int i = 0; i < DIR_NUM; i++)
+    {
+    double pda = td.dirPrice[i].priceDayA * 1024 * 1024;
+    double pdb = td.dirPrice[i].priceDayB * 1024 * 1024;
+    double pna = 0;
+    double pnb = 0;
+
+    if (td.dirPrice[i].singlePrice)
+        {
+        pna = pda;
+        pnb = pdb;
+        }
+    else
+        {
+        pna = td.dirPrice[i].priceNightA * 1024 * 1024;
+        pnb = td.dirPrice[i].priceNightB * 1024 * 1024;
+        }
+
+    int threshold = 0;
+    if (td.dirPrice[i].noDiscount)
+        {
+        threshold = 0xffFFffFF;
+        }
+    else
+        {
+        threshold = td.dirPrice[i].threshold;
+        }
+
+        {
+        std::ostringstream query;
+        query << "UPDATE tb_tariffs_params SET \
+                      price_day_a = " << pda << ", \
+                      price_day_b = " << pdb << ", \
+                      price_night_a = " << pna << ", \
+                      price_night_b = " << pnb << ", \
+                      threshold = " << threshold << ", \
+                      time_day_begins = CAST('" << td.dirPrice[i].hDay
+                                                << ":"
+                                                << td.dirPrice[i].mDay << "' AS TIME), \
+                      time_day_ends = CAST('" << td.dirPrice[i].hNight
+                                              << ":"
+                                              << td.dirPrice[i].mNight << "' AS TIME) \
+                 WHERE fk_tariff = " << id << " AND dir_num = " << i;
+
+        result = PQexec(connection, query.str().c_str());
+        }
+
+    if (PQresultStatus(result) != PGRES_COMMAND_OK)
+        {
+        strError = PQresultErrorMessage(result);
+        PQclear(result);
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): '%s'\n", strError.c_str());
+        if (RollbackTransaction())
+            {
+            printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to rollback transaction'\n");
+            }
+        return -1;
+        }
+
+    PQclear(result);
+    }
+
+if (CommitTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to commit transaction'\n");
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::RestoreTariff(STG::TariffData * td,
+                                    const std::string & tariffName) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+    if (Reset())
+        {
+        strError = "Connection lost";
+        printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): '%s'\n", strError.c_str());
+        return -1;
+        }
+    }
+
+PGresult * result;
+
+if (StartTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to start transaction'\n");
+    return -1;
+    }
+
+std::string ename = tariffName;
+
+if (EscapeString(ename))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to escape name'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+td->tariffConf.name = tariffName;
+
+std::ostringstream query;
+query << "SELECT pk_tariff, \
+                 fee, \
+                 free, \
+                 passive_cost, \
+                 traff_type";
+
+if (version > 6)
+    query << ", period";
+
+if (version > 7)
+    query << ", change_policy \
+              , change_policy_timeout";
+
+query << " FROM tb_tariffs WHERE name = '" << ename << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    PQclear(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): '%s'\n", strError.c_str());
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+int tuples = PQntuples(result);
+
+if (tuples != 1)
+    {
+    strError = "Failed to fetch tariff data";
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
+    PQclear(result);
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+int id;
+
+    {
+    std::stringstream tuple;
+    tuple << PQgetvalue(result, 0, 0) << " ";
+    tuple << PQgetvalue(result, 0, 1) << " ";
+    tuple << PQgetvalue(result, 0, 2) << " ";
+    tuple << PQgetvalue(result, 0, 3) << " ";
+    tuple << PQgetvalue(result, 0, 4) << " ";
+
+    tuple >> id;
+    tuple >> td->tariffConf.fee;
+    tuple >> td->tariffConf.free;
+    tuple >> td->tariffConf.passiveCost;
+    unsigned traffType;
+    tuple >> traffType;
+    td->tariffConf.traffType = static_cast<STG::Tariff::TraffType>(traffType);
+    }
+
+if (version > 6)
+    td->tariffConf.period = STG::Tariff::parsePeriod(PQgetvalue(result, 0, 5));
+
+if (version > 7)
+    {
+    td->tariffConf.changePolicy = STG::Tariff::parseChangePolicy(PQgetvalue(result, 0, 6));
+    td->tariffConf.changePolicyTimeout = readTime(PQgetvalue(result, 0, 7));
+    }
+
+PQclear(result);
+
+query.str("");
+query << "SELECT dir_num, \
+                 price_day_a, \
+                 price_day_b, \
+                 price_night_a, \
+                 price_night_b, \
+                 threshold, \
+                 EXTRACT(hour FROM time_day_begins), \
+                 EXTRACT(minute FROM time_day_begins), \
+                 EXTRACT(hour FROM time_day_ends), \
+                 EXTRACT(minute FROM time_day_ends) \
+          FROM tb_tariffs_params \
+          WHERE fk_tariff = " << id;
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    PQclear(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): '%s'\n", strError.c_str());
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+tuples = PQntuples(result);
+
+if (tuples != DIR_NUM)
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Tariff params count and DIR_NUM does not feet (wanted %d, actually %d)'\n", DIR_NUM, tuples);
+    }
+
+for (int i = 0; i < std::min(tuples, DIR_NUM); ++i)
+    {
+    int dir;
+
+        {
+        std::stringstream tuple;
+        tuple << PQgetvalue(result, i, 0) << " ";
+        tuple << PQgetvalue(result, i, 1) << " ";
+        tuple << PQgetvalue(result, i, 2) << " ";
+        tuple << PQgetvalue(result, i, 3) << " ";
+        tuple << PQgetvalue(result, i, 4) << " ";
+        tuple << PQgetvalue(result, i, 5) << " ";
+        tuple << PQgetvalue(result, i, 6) << " ";
+        tuple << PQgetvalue(result, i, 7) << " ";
+        tuple << PQgetvalue(result, i, 8) << " ";
+        tuple << PQgetvalue(result, i, 9) << " ";
+
+        tuple >> dir;
+        tuple >> td->dirPrice[dir].priceDayA;
+        td->dirPrice[dir].priceDayA /= 1024 * 1024;
+        tuple >> td->dirPrice[dir].priceDayB;
+        td->dirPrice[dir].priceDayB /= 1024 * 1024;
+        tuple >> td->dirPrice[dir].priceNightA;
+        td->dirPrice[dir].priceNightA /= 1024 * 1024;
+        tuple >> td->dirPrice[dir].priceNightB;
+        td->dirPrice[dir].priceNightB /= 1024 * 1024;
+        tuple >> td->dirPrice[dir].threshold;
+        tuple >> td->dirPrice[dir].hDay;
+        tuple >> td->dirPrice[dir].mDay;
+        tuple >> td->dirPrice[dir].hNight;
+        tuple >> td->dirPrice[dir].mNight;
+        }
+
+    if (std::fabs(td->dirPrice[dir].priceDayA - td->dirPrice[dir].priceNightA) < 1.0e-3 / pt_mega &&
+        std::fabs(td->dirPrice[dir].priceDayB - td->dirPrice[dir].priceNightB) < 1.0e-3 / pt_mega)
+        {
+        td->dirPrice[dir].singlePrice = true;
+        }
+    else
+        {
+        td->dirPrice[dir].singlePrice = false;
+        }
+    if (td->dirPrice[dir].threshold == (int)0xffFFffFF)
+        {
+        td->dirPrice[dir].noDiscount = true;
+        }
+    else
+        {
+
+        td->dirPrice[dir].noDiscount = false;
+        }
+
+    }
+
+PQclear(result);
+
+if (CommitTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to commit transaction'\n");
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+
diff --git a/projects/stargazer/plugins/store/postgresql/postgresql_store_users.cpp b/projects/stargazer/plugins/store/postgresql/postgresql_store_users.cpp
new file mode 100644 (file)
index 0000000..6919ed0
--- /dev/null
@@ -0,0 +1,1591 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+/*
+ *  User manipulation methods
+ *
+ *  $Revision: 1.14 $
+ *  $Date: 2010/05/07 07:26:36 $
+ *
+ */
+
+#include "postgresql_store.h"
+
+#include "stg/user_conf.h"
+#include "stg/user_stat.h"
+#include "stg/user_ips.h"
+#include "stg/user_traff.h"
+#include "stg/common.h"
+#include "stg/const.h"
+#include "stg/locker.h"
+#include "../../../stg_timer.h"
+
+#include <string>
+#include <vector>
+#include <sstream>
+#include <ctime>
+
+#include <libpq-fe.h>
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::GetUsersList(std::vector<std::string> * usersList) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::GetUsersList(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+    if (Reset())
+        {
+        strError = "Connection lost";
+        printfd(__FILE__, "POSTGRESQL_STORE::GetUsersList(): '%s'\n", strError.c_str());
+        return -1;
+        }
+    }
+
+PGresult * result;
+
+if (StartTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::GetUsersList(): 'Failed to start transaction'\n");
+    return -1;
+    }
+
+result = PQexec(connection, "SELECT name FROM tb_users");
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    PQclear(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::GetUsersList(): '%s'\n", strError.c_str());
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::GetUsersList(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+int tuples = PQntuples(result);
+
+for (int i = 0; i < tuples; ++i)
+    {
+    usersList->push_back(PQgetvalue(result, i, 0));
+    }
+
+PQclear(result);
+
+if (CommitTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::GetUsersList(): 'Failed to commit transaction'\n");
+    return -1;
+    }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::AddUser(const std::string & name) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::AddUser(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+    if (Reset())
+        {
+        strError = "Connection lost";
+        printfd(__FILE__, "POSTGRESQL_STORE::AddUser(): '%s'\n", strError.c_str());
+        return -1;
+        }
+    }
+
+PGresult * result;
+
+if (StartTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::AddUser(): 'Failed to start transaction'\n");
+    return -1;
+    }
+
+std::string elogin = name;
+
+if (EscapeString(elogin))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::AddUser(): 'Failed to escape login'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::AddUser(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+std::ostringstream query;
+query << "SELECT sp_add_user('" << elogin << "')";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    PQclear(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::AddUser(): '%s'\n", strError.c_str());
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::AddUser(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+PQclear(result);
+
+if (CommitTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::AddUser(): 'Failed to commit transaction'\n");
+    return -1;
+    }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::DelUser(const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::DelUser(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+    if (Reset())
+        {
+        strError = "Connection lost";
+        printfd(__FILE__, "POSTGRESQL_STORE::DelUser(): '%s'\n", strError.c_str());
+        return -1;
+        }
+    }
+
+PGresult * result;
+
+if (StartTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::DelUser(): 'Failed to start transaction'\n");
+    return -1;
+    }
+
+std::string elogin = login;
+
+if (EscapeString(elogin))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::DelUser(): 'Failed to escape login'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::DelUser(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+std::ostringstream query;
+query << "DELETE FROM tb_users WHERE name = '" << elogin << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    PQclear(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::DelUser(): '%s'\n", strError.c_str());
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::DelUser(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+PQclear(result);
+
+if (CommitTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::DelUser(): 'Failed to commit transaction'\n");
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::SaveUserStat(const STG::UserStat & stat,
+                                   const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+return SaveStat(stat, login);
+}
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::SaveStat(const STG::UserStat & stat,
+                               const std::string & login,
+                               int year,
+                               int month) const
+{
+if (PQstatus(connection) != CONNECTION_OK)
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+    if (Reset())
+        {
+        strError = "Connection lost";
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): '%s'\n", strError.c_str());
+        return -1;
+        }
+    }
+
+PGresult * result;
+
+if (StartTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Failed to start transaction'\n");
+    return -1;
+    }
+
+std::string elogin = login;
+
+if (EscapeString(elogin))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Failed to escape login'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+std::ostringstream query;
+query << "UPDATE tb_users SET "
+            "cash = " << stat.cash << ", "
+            "free_mb = " << stat.freeMb << ", "
+            "last_activity_time = CAST('" << formatTime(stat.lastActivityTime) << "' AS TIMESTAMP), "
+            "last_cash_add = " << stat.lastCashAdd << ", "
+            "last_cash_add_time = CAST('" << formatTime(stat.lastCashAddTime) << "' AS TIMESTAMP), "
+            "passive_time = " << stat.passiveTime << " "
+         "WHERE name = '" << elogin << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    PQclear(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): '%s'\n", strError.c_str());
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+PQclear(result);
+
+std::string date;
+
+MakeDate(date, year, month);
+
+for (int dir = 0; dir < DIR_NUM; ++dir)
+    {
+    query.str("");
+    query << "SELECT sp_add_stats_traffic ("
+                "'" << elogin << "', "
+                "CAST('" << date << "' AS DATE), "
+                "CAST(" << dir << " AS SMALLINT), "
+                "CAST(" << stat.monthUp[dir] << " AS BIGINT), "
+                "CAST(" << stat.monthDown[dir] << " AS BIGINT))";
+
+    result = PQexec(connection, query.str().c_str());
+
+    if (PQresultStatus(result) != PGRES_TUPLES_OK)
+        {
+        strError = PQresultErrorMessage(result);
+        PQclear(result);
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): '%s'\n", strError.c_str());
+        if (RollbackTransaction())
+            {
+            printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Failed to rollback transaction'\n");
+            }
+        return -1;
+        }
+
+    PQclear(result);
+    }
+
+if (CommitTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Failed to commit transaction'\n");
+    return -1;
+    }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::SaveUserConf(const STG::UserConf & conf,
+                                 const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+    if (Reset())
+        {
+        strError = "Connection lost";
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): '%s'\n", strError.c_str());
+        return -1;
+        }
+    }
+
+PGresult * result;
+
+if (StartTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to start transaction'\n");
+    return -1;
+    }
+
+std::string elogin = login;
+
+if (EscapeString(elogin))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape login'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+std::ostringstream query;
+query << "SELECT pk_user FROM tb_users WHERE name = '" << elogin << "'";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    PQclear(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): '%s'\n", strError.c_str());
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+int tuples = PQntuples(result);
+
+if (tuples != 1)
+    {
+    strError = "Failed to fetch user's ID";
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
+    PQclear(result);
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+uint32_t uid;
+
+    {
+    std::stringstream tuple;
+    tuple << PQgetvalue(result, 0, 0);
+
+    PQclear(result);
+
+    tuple >> uid;
+    }
+
+std::string eaddress = conf.address;
+std::string eemail = conf.email;
+std::string egroup = conf.group;
+std::string enote = conf.note;
+std::string epassword = conf.password;
+std::string ephone = conf.phone;
+std::string erealname = conf.realName;
+std::string etariffname = conf.tariffName;
+std::string enexttariff = conf.nextTariff;
+std::string ecorporation = conf.corp;
+
+if (EscapeString(eaddress))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape address'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+if (EscapeString(eemail))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape email'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+if (EscapeString(egroup))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape group'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+if (EscapeString(enote))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape note'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+if (EscapeString(epassword))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape password'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+if (EscapeString(ephone))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape phone'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+if (EscapeString(erealname))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape real name'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+if (EscapeString(etariffname))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape tariff name'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+if (EscapeString(enexttariff))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape next tariff name'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+if (EscapeString(ecorporation))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape corporation name'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+query.str("");
+query << "UPDATE tb_users SET "
+             "address = '" << eaddress << "', "
+             "always_online = " << (conf.alwaysOnline ? "'t'" : "'f'") << ", "
+             "credit = " << conf.credit << ", "
+             "credit_expire = CAST('" << formatTime(conf.creditExpire) << "' AS TIMESTAMP), "
+             "disabled = " << (conf.disabled ? "'t'" : "'f'") << ", "
+             "disabled_detail_stat = " << (conf.disabledDetailStat ? "'t'" : "'f'") << ", "
+             "email = '" << eemail << "', "
+             "grp = '" << egroup << "', "
+             "note = '" << enote << "', "
+             "passive = " << (conf.passive ? "'t'" : "'f'") << ", "
+             "passwd = '" << epassword << "', "
+             "phone = '" << ephone << "', "
+             "real_name = '" << erealname << "', "
+             "fk_tariff = (SELECT pk_tariff "
+                   "FROM tb_tariffs "
+                   "WHERE name = '" << etariffname << "'), "
+             "fk_tariff_change = (SELECT pk_tariff "
+                   "FROM tb_tariffs "
+                   "WHERE name = '" << enexttariff << "'), "
+             "fk_corporation = (SELECT pk_corporation "
+                   "FROM tb_corporations "
+                   "WHERE name = '" << ecorporation << "') "
+         "WHERE pk_user = " << uid;
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    PQclear(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): '%s'\n", strError.c_str());
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+PQclear(result);
+
+if (SaveUserServices(uid, conf.services))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to save user's services'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+if (SaveUserData(uid, conf.userdata))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to save user's data'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+if (SaveUserIPs(uid, conf.ips))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to save user's IPs'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+if (CommitTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to commit transaction'\n");
+    return -1;
+    }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::RestoreUserStat(STG::UserStat * stat,
+                                    const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+    if (Reset())
+        {
+        strError = "Connection lost";
+        printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): '%s'\n", strError.c_str());
+        return -1;
+        }
+    }
+
+PGresult * result;
+
+if (StartTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to start transaction'\n");
+    return -1;
+    }
+
+std::string elogin = login;
+
+if (EscapeString(elogin))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to escape login'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+    {
+    std::ostringstream query;
+    query << "SELECT cash, free_mb, "
+                "last_activity_time, last_cash_add, "
+                "last_cash_add_time, passive_time "
+             "FROM tb_users "
+             "WHERE name = '" << elogin << "'";
+
+    result = PQexec(connection, query.str().c_str());
+    }
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): '%s'\n", strError.c_str());
+    PQclear(result);
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+int tuples = PQntuples(result);
+
+if (tuples != 1)
+    {
+    strError = "Failed to fetch user's stat";
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
+    PQclear(result);
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+    {
+    std::stringstream tuple;
+    tuple << PQgetvalue(result, 0, 0) << " ";
+    tuple << PQgetvalue(result, 0, 1) << " ";
+    stat->lastActivityTime = readTime(PQgetvalue(result, 0, 2));
+    tuple << PQgetvalue(result, 0, 3) << " ";
+    stat->lastCashAddTime = readTime(PQgetvalue(result, 0, 4));
+    tuple << PQgetvalue(result, 0, 5) << " ";
+
+    PQclear(result);
+
+    tuple >> stat->cash
+          >> stat->freeMb
+          >> stat->lastCashAdd
+          >> stat->passiveTime;
+    }
+
+    {
+    std::ostringstream query;
+    query << "SELECT dir_num, upload, download "
+             "FROM tb_stats_traffic "
+             "WHERE fk_user IN (SELECT pk_user FROM tb_users WHERE name = '" << elogin << "') AND "
+                   "DATE_TRUNC('month', stats_date) = DATE_TRUNC('month', CAST('" << formatTime(stgTime) << "' AS TIMESTAMP))";
+
+    result = PQexec(connection, query.str().c_str());
+    }
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): '%s'\n", strError.c_str());
+    PQclear(result);
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+tuples = PQntuples(result);
+
+for (int i = 0; i < tuples; ++i)
+    {
+    std::stringstream tuple;
+    tuple << PQgetvalue(result, i, 0) << " ";
+    tuple << PQgetvalue(result, i, 1) << " ";
+    tuple << PQgetvalue(result, i, 2) << " ";
+
+    int dir;
+
+    tuple >> dir;
+    tuple >> stat->monthUp[dir];
+    tuple >> stat->monthDown[dir];
+    }
+
+PQclear(result);
+
+if (CommitTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to commit transaction'\n");
+    return -1;
+    }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::RestoreUserConf(STG::UserConf * conf,
+                                    const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+    if (Reset())
+        {
+        strError = "Connection lost";
+        printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): '%s'\n", strError.c_str());
+        return -1;
+        }
+    }
+
+PGresult * result;
+
+if (StartTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to start transaction'\n");
+    return -1;
+    }
+
+std::string elogin = login;
+
+if (EscapeString(elogin))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to escape login'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+    {
+    std::ostringstream query;
+    query << "SELECT tb_users.pk_user, tb_users.address, tb_users.always_online, "
+                    "tb_users.credit, tb_users.credit_expire, tb_users.disabled, "
+                    "tb_users.disabled_detail_stat, tb_users.email, tb_users.grp, "
+                    "tb_users.note, tb_users.passive, tb_users.passwd, tb_users.phone, "
+                    "tb_users.real_name, tf1.name, tf2.name, tb_corporations.name "
+             "FROM tb_users LEFT JOIN tb_tariffs AS tf1 "
+                                "ON tf1.pk_tariff = tb_users.fk_tariff "
+                           "LEFT JOIN tb_tariffs AS tf2 "
+                                "ON tf2.pk_tariff = tb_users.fk_tariff_change "
+                           "LEFT JOIN tb_corporations "
+                                "ON tb_corporations.pk_corporation = tb_users.fk_corporation "
+             "WHERE tb_users.name = '" << elogin << "'";
+
+    result = PQexec(connection, query.str().c_str());
+    }
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): '%s'\n", strError.c_str());
+    PQclear(result);
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+int tuples = PQntuples(result);
+
+if (tuples != 1)
+    {
+    strError = "Failed to fetch user's stat";
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
+    PQclear(result);
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+uint32_t uid;
+
+    {
+    std::stringstream tuple;
+    tuple << PQgetvalue(result, 0, 0) << " ";               // uid
+    conf->address = PQgetvalue(result, 0, 1);               // address
+    conf->alwaysOnline = !strncmp(PQgetvalue(result, 0, 2), "t", 1);
+    tuple << PQgetvalue(result, 0, 3) << " ";               // credit
+    conf->creditExpire = readTime(PQgetvalue(result, 0, 4));  // creditExpire
+    conf->disabled = !strncmp(PQgetvalue(result, 0, 5), "t", 1);
+    conf->disabledDetailStat = !strncmp(PQgetvalue(result, 0, 6), "t", 1);
+    conf->email = PQgetvalue(result, 0, 7);                 // email
+    conf->group = PQgetvalue(result, 0, 8);                 // group
+    conf->note = PQgetvalue(result, 0, 9);                  // note
+    conf->passive = !strncmp(PQgetvalue(result, 0, 10), "t", 1);
+    conf->password = PQgetvalue(result, 0, 11);             // password
+    conf->phone = PQgetvalue(result, 0, 12);                // phone
+    conf->realName = PQgetvalue(result, 0, 13);             // realName
+    conf->tariffName = PQgetvalue(result, 0, 14);           // tariffName
+    conf->nextTariff = PQgetvalue(result, 0, 15);           // nextTariff
+    conf->corp = PQgetvalue(result, 0, 16);                 // corp
+
+    PQclear(result);
+
+    if (conf->tariffName == "")
+        conf->tariffName = NO_TARIFF_NAME;
+    if (conf->corp == "")
+        conf->corp = NO_CORP_NAME;
+
+    tuple >> uid
+          >> conf->credit;
+    }
+
+    {
+    std::ostringstream query;
+    query << "SELECT name FROM tb_services "
+             "WHERE pk_service IN (SELECT fk_service "
+                                  "FROM tb_users_services "
+                                  "WHERE fk_user = " << uid << ")";
+
+    result = PQexec(connection, query.str().c_str());
+    }
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): '%s'\n", strError.c_str());
+    PQclear(result);
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+tuples = PQntuples(result);
+
+for (int i = 0; i < tuples; ++i)
+    {
+    conf->services.push_back(PQgetvalue(result, i, 0));
+    }
+
+PQclear(result);
+
+    {
+    std::ostringstream query;
+    query << "SELECT num, data "
+             "FROM tb_users_data "
+             "WHERE fk_user = " << uid;
+
+    result = PQexec(connection, query.str().c_str());
+    }
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): '%s'\n", strError.c_str());
+    PQclear(result);
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+tuples = PQntuples(result);
+
+for (int i = 0; i < tuples; ++i)
+    {
+    int num;
+    if (str2x(PQgetvalue(result, i, 0), num))
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Failed to convert string to int'\n");
+        }
+    else
+        {
+        if (num < USERDATA_NUM &&
+            num >= 0)
+            {
+            conf->userdata[num] = PQgetvalue(result, i, 1);
+            }
+        }
+    }
+
+PQclear(result);
+
+    {
+    std::ostringstream query;
+    query << "SELECT host(ip), masklen(ip) "
+             "FROM tb_allowed_ip "
+             "WHERE fk_user = " << uid;
+
+    result = PQexec(connection, query.str().c_str());
+    }
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): '%s'\n", strError.c_str());
+    PQclear(result);
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+tuples = PQntuples(result);
+
+STG::UserIPs ips;
+for (int i = 0; i < tuples; ++i)
+    {
+    STG::IPMask im;
+
+    im.ip = inet_strington(PQgetvalue(result, i, 0));
+
+    if (str2x(PQgetvalue(result, i, 1), im.mask))
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Failed to fetch mask'\n");
+        continue;
+        }
+
+    ips.add(im);
+    }
+conf->ips = ips;
+
+PQclear(result);
+
+if (CommitTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Failed to commit transaction'\n");
+    return -1;
+    }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::WriteUserChgLog(const std::string & login,
+                                    const std::string & admLogin,
+                                    uint32_t admIP,
+                                    const std::string & paramName,
+                                    const std::string & oldValue,
+                                    const std::string & newValue,
+                                    const std::string & message = "") const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+    if (Reset())
+        {
+        strError = "Connection lost";
+        printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): '%s'\n", strError.c_str());
+        return -1;
+        }
+    }
+
+PGresult * result;
+
+if (StartTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to start transaction'\n");
+    return -1;
+    }
+
+std::string elogin(login);
+std::string eadminLogin(admLogin);
+std::string eparam(paramName);
+std::string eold(oldValue);
+std::string enew(newValue);
+std::string emessage(message);
+
+if (EscapeString(elogin))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to escape login'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+if (EscapeString(eadminLogin))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to escape admin's login'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+if (EscapeString(eparam))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to escape param's name'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+if (EscapeString(eold))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to escape old value'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+if (EscapeString(enew))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to escape new value'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+std::ostringstream query;
+query << "SELECT sp_add_param_log_entry("
+            "'" << elogin << "', "
+            "'" << eadminLogin << "', CAST('"
+            << inet_ntostring(admIP) << "/32' AS INET), "
+            "'" << eparam << "', "
+            "CAST('" << formatTime(stgTime) << "' AS TIMESTAMP), "
+            "'" << eold << "', "
+            "'" << enew << "', "
+            "'" << emessage << "')";
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    PQclear(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): '%s'\n", strError.c_str());
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+PQclear(result);
+
+if (CommitTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to commit transaction'\n");
+    return -1;
+    }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::WriteUserConnect(const std::string & login, uint32_t ip) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserConnect(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+    if (Reset())
+        {
+        strError = "Connection lost";
+        printfd(__FILE__, "POSTGRESQL_STORE::WriteUserConnect(): '%s'\n", strError.c_str());
+        return -1;
+        }
+    }
+
+PGresult * result;
+
+if (StartTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserConnect(): 'Failed to start transaction'\n");
+    return -1;
+    }
+
+std::string elogin(login);
+
+if (EscapeString(elogin))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserConnect(): 'Failed to escape login'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::WriteUserConnect(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+std::ostringstream query;
+if (version < 6)
+    {
+    query << "SELECT sp_add_session_log_entry("
+                 "'" << elogin << "', "
+                 "CAST('" << formatTime(stgTime) << "' AS TIMESTAMP), "
+                 "'c', CAST('"
+                 << inet_ntostring(ip) << "/32' AS INET), 0)";
+    }
+else
+    {
+    query << "SELECT sp_add_session_log_entry("
+                 "'" << elogin << "', "
+                 "CAST('" << formatTime(stgTime) << "' AS TIMESTAMP), "
+                 "'c', CAST('"
+                 << inet_ntostring(ip) << "/32' AS INET), 0, 0, '')";
+    }
+
+result = PQexec(connection, query.str().c_str());
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    PQclear(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserConnect(): '%s'\n", strError.c_str());
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::WriteUserConnect(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+PQclear(result);
+
+if (CommitTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserConnect(): 'Failed to commit transaction'\n");
+    return -1;
+    }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::WriteUserDisconnect(const std::string & login,
+                    const STG::DirTraff & monthUp,
+                    const STG::DirTraff & monthDown,
+                    const STG::DirTraff & sessionUp,
+                    const STG::DirTraff & sessionDown,
+                    double cash,
+                    double freeMb,
+                    const std::string & reason) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+    if (Reset())
+        {
+        strError = "Connection lost";
+        printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): '%s'\n", strError.c_str());
+        return -1;
+        }
+    }
+
+PGresult * result;
+
+if (StartTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to start transaction'\n");
+    return -1;
+    }
+
+std::string elogin(login);
+
+if (EscapeString(elogin))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to escape login'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+std::string ereason(reason);
+
+if (EscapeString(ereason))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to escape reason'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+    {
+    std::ostringstream query;
+    if (version < 6)
+        {
+        // Old database version - no freeMb logging support
+        query << "SELECT sp_add_session_log_entry("
+                    "'" << elogin << "', "
+                    "CAST('" << formatTime(stgTime) << "' AS TIMESTAMP), "
+                    "'d', CAST('0.0.0.0/0' AS INET), "
+                    << cash << ")";
+        }
+    else
+        {
+        query << "SELECT sp_add_session_log_entry("
+                    "'" << elogin << "', "
+                    "CAST('" << formatTime(stgTime) << "' AS TIMESTAMP), "
+                    "'d', CAST('0.0.0.0/0' AS INET), "
+                    << cash << ", " << freeMb << ", '" << ereason << "')";
+        }
+
+    result = PQexec(connection, query.str().c_str());
+    }
+
+if (PQresultStatus(result) != PGRES_TUPLES_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    PQclear(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): '%s'\n", strError.c_str());
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+int tuples = PQntuples(result);
+
+if (tuples != 1)
+    {
+    strError = "Failed to fetch session's log ID";
+    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
+    PQclear(result);
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+uint32_t lid;
+
+if (str2x(PQgetvalue(result, 0, 0), lid))
+    {
+    strError = "Failed to convert string to int";
+    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): '%s'\n", strError.c_str());
+    PQclear(result);
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+PQclear(result);
+
+for (int i = 0; i < DIR_NUM; ++i)
+    {
+    std::ostringstream query;
+    query << "INSERT INTO tb_sessions_data "
+                "(fk_session_log, "
+                 "dir_num, "
+                 "session_upload, "
+                 "session_download, "
+                 "month_upload, "
+                 "month_download)"
+             "VALUES ("
+                << lid << ", "
+                << i << ", "
+                << sessionUp[i] << ", "
+                << sessionDown[i] << ", "
+                << monthUp[i] << ", "
+                << monthDown[i] << ")";
+
+    result = PQexec(connection, query.str().c_str());
+
+    if (PQresultStatus(result) != PGRES_COMMAND_OK)
+        {
+        strError = PQresultErrorMessage(result);
+        PQclear(result);
+        printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): '%s'\n", strError.c_str());
+        if (RollbackTransaction())
+            {
+            printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to rollback transaction'\n");
+            }
+        return -1;
+        }
+
+    PQclear(result);
+    }
+
+if (CommitTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to commit transaction'\n");
+    return -1;
+    }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::WriteDetailedStat(const STG::TraffStat & statTree,
+                                      time_t lastStat,
+                                      const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+if (PQstatus(connection) != CONNECTION_OK)
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::WriteDetailedStat(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
+    if (Reset())
+        {
+        strError = "Connection lost";
+        printfd(__FILE__, "POSTGRESQL_STORE::WriteDetailedStat(): '%s'\n", strError.c_str());
+        return -1;
+        }
+    }
+
+if (StartTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::WriteDetailedStat(): 'Failed to start transaction'\n");
+    return -1;
+    }
+
+std::string elogin(login);
+
+if (EscapeString(elogin))
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::WriteDetailedStat(): 'Failed to escape login'\n");
+    if (RollbackTransaction())
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::WriteDetailedStat(): 'Failed to rollback transaction'\n");
+        }
+    return -1;
+    }
+
+STG::TraffStat::const_iterator it;
+time_t currTime = time(NULL);
+
+for (it = statTree.begin(); it != statTree.end(); ++it)
+    {
+    std::ostringstream query;
+    query << "INSERT INTO tb_detail_stats "
+                "(till_time, from_time, fk_user, "
+                 "dir_num, ip, download, upload, cost) "
+             "VALUES ("
+                "CAST('" << formatTime(currTime) << "' AS TIMESTAMP), "
+                "CAST('" << formatTime(lastStat) << "' AS TIMESTAMP), "
+                "(SELECT pk_user FROM tb_users WHERE name = '" << elogin << "'), "
+                << it->first.dir << ", "
+                << "CAST('" << inet_ntostring(it->first.ip) << "' AS INET), "
+                << it->second.down << ", "
+                << it->second.up << ", "
+                << it->second.cash << ")";
+
+    PGresult * result = PQexec(connection, query.str().c_str());
+
+    if (PQresultStatus(result) != PGRES_COMMAND_OK)
+        {
+        strError = PQresultErrorMessage(result);
+        PQclear(result);
+        printfd(__FILE__, "POSTGRESQL_STORE::WriteDetailedStat(): '%s'\n", strError.c_str());
+        if (RollbackTransaction())
+            {
+            printfd(__FILE__, "POSTGRESQL_STORE::WriteDetailedStat(): 'Failed to rollback transaction'\n");
+            }
+        return -1;
+        }
+
+    PQclear(result);
+    }
+
+if (CommitTransaction())
+    {
+    printfd(__FILE__, "POSTGRESQL_STORE::WriteDetailedStat(): 'Failed to commit transaction'\n");
+    return -1;
+    }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::SaveMonthStat(const STG::UserStat & stat, int month, int year, const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+
+return SaveStat(stat, login, year, month);
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::SaveUserServices(uint32_t uid,
+                                       const std::vector<std::string> & services) const
+{
+PGresult * result;
+
+    {
+    std::ostringstream query;
+    query << "DELETE FROM tb_users_services WHERE fk_user = " << uid;
+
+    result = PQexec(connection, query.str().c_str());
+
+    if (PQresultStatus(result) != PGRES_COMMAND_OK)
+        {
+        strError = PQresultErrorMessage(result);
+        PQclear(result);
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserServices(): '%s'\n", strError.c_str());
+        return -1;
+        }
+
+    PQclear(result);
+    }
+
+std::vector<std::string>::const_iterator it;
+
+for (it = services.begin(); it != services.end(); ++it)
+    {
+    std::string ename = *it;
+
+    if (EscapeString(ename))
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserServices(): 'Failed to escape service name'\n");
+        return -1;
+        }
+
+    std::ostringstream query;
+    query << "INSERT INTO tb_users_services "
+                "(fk_user, fk_service) "
+             "VALUES "
+                "(" << uid << ", "
+                  "(SELECT pk_service "
+                   "FROM tb_services "
+                   "WHERE name = '" << ename << "'))";
+
+    result = PQexec(connection, query.str().c_str());
+
+    if (PQresultStatus(result) != PGRES_COMMAND_OK)
+        {
+        strError = PQresultErrorMessage(result);
+        PQclear(result);
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserServices(): '%s'\n", strError.c_str());
+        return -1;
+        }
+
+    PQclear(result);
+    }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::SaveUserIPs(uint32_t uid,
+                                  const STG::UserIPs & ips) const
+{
+PGresult * result;
+
+    {
+    std::ostringstream query;
+    query << "DELETE FROM tb_allowed_ip WHERE fk_user = " << uid;
+
+    result = PQexec(connection, query.str().c_str());
+    }
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    PQclear(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserIPs(): '%s'\n", strError.c_str());
+    return -1;
+    }
+
+PQclear(result);
+
+for (size_t i = 0; i < ips.count(); ++i)
+    {
+    std::ostringstream query;
+    query << "INSERT INTO tb_allowed_ip "
+                "(fk_user, ip) "
+             "VALUES "
+                "(" << uid << ", CAST('"
+                    << inet_ntostring(ips[i].ip) << "/"
+                    << static_cast<int>(ips[i].mask) << "' AS INET))";
+
+    result = PQexec(connection, query.str().c_str());
+
+    if (PQresultStatus(result) != PGRES_COMMAND_OK)
+        {
+        strError = PQresultErrorMessage(result);
+        PQclear(result);
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserIPs(): '%s'\n", strError.c_str());
+        return -1;
+        }
+
+    PQclear(result);
+    }
+
+return 0;
+}
+
+//-----------------------------------------------------------------------------
+int POSTGRESQL_STORE::SaveUserData(uint32_t uid,
+                                   const std::vector<std::string> & data) const
+{
+for (unsigned i = 0; i < data.size(); ++i)
+    {
+    std::string edata = data[i];
+
+    if (EscapeString(edata))
+        {
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserData(): 'Failed to escape userdata field'\n");
+        return -1;
+        }
+
+    PGresult * result;
+
+    std::ostringstream query;
+    query << "SELECT sp_set_user_data("
+                << uid << ", "
+                << "CAST(" << i << " AS SMALLINT), "
+                << "'" << edata << "')";
+
+    result = PQexec(connection, query.str().c_str());
+
+    if (PQresultStatus(result) != PGRES_TUPLES_OK)
+        {
+        strError = PQresultErrorMessage(result);
+        PQclear(result);
+        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserData(): '%s'\n", strError.c_str());
+        return -1;
+        }
+
+    PQclear(result);
+    }
+
+return 0;
+}
+
diff --git a/projects/stargazer/plugins/store/postgresql/postgresql_store_utils.cpp b/projects/stargazer/plugins/store/postgresql/postgresql_store_utils.cpp
new file mode 100644 (file)
index 0000000..9a5101e
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+/*
+ *  Vairous utility methods
+ *
+ *  $Revision: 1.3 $
+ *  $Date: 2009/10/22 10:01:08 $
+ *
+ */
+
+#include "postgresql_store.h"
+
+#include "stg/common.h"
+
+#include <string>
+#include <ctime>
+
+#include <libpq-fe.h>
+
+extern volatile time_t stgTime;
+
+int POSTGRESQL_STORE::StartTransaction() const
+{
+PGresult * result = PQexec(connection, "BEGIN");
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    PQclear(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::StartTransaction(): '%s'\n", strError.c_str());
+    return -1;
+    }
+
+PQclear(result);
+
+return 0;
+}
+
+int POSTGRESQL_STORE::CommitTransaction() const
+{
+PGresult * result = PQexec(connection, "COMMIT");
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    PQclear(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::CommitTransaction(): '%s'\n", strError.c_str());
+    return -1;
+    }
+
+PQclear(result);
+
+return 0;
+}
+
+int POSTGRESQL_STORE::RollbackTransaction() const
+{
+PGresult * result = PQexec(connection, "ROLLBACK");
+
+if (PQresultStatus(result) != PGRES_COMMAND_OK)
+    {
+    strError = PQresultErrorMessage(result);
+    PQclear(result);
+    printfd(__FILE__, "POSTGRESQL_STORE::RollbackTransaction(): '%s'\n", strError.c_str());
+    return -1;
+    }
+
+PQclear(result);
+
+return 0;
+}
+
+int POSTGRESQL_STORE::EscapeString(std::string & value) const
+{
+int error = 0;
+char * buf = new char[(value.length() << 1) + 1];
+
+PQescapeStringConn(connection,
+                   buf,
+                   value.c_str(),
+                   value.length(),
+                   &error);
+
+if (error)
+    {
+    strError = PQerrorMessage(connection);
+    printfd(__FILE__, "POSTGRESQL_STORE::EscapeString(): '%s'\n", strError.c_str());
+    delete[] buf;
+    return -1;
+    }
+
+value = buf;
+
+delete[] buf;
+return 0;
+}
+
+void POSTGRESQL_STORE::MakeDate(std::string & date, int year, int month) const
+{
+struct tm brokenTime;
+
+brokenTime.tm_wday = 0;
+brokenTime.tm_yday = 0;
+brokenTime.tm_isdst = 0;
+
+if (year)
+    {
+    brokenTime.tm_hour = 0;
+    brokenTime.tm_min = 0;
+    brokenTime.tm_sec = 0;
+    brokenTime.tm_year = year;
+    brokenTime.tm_mon = month;
+    }
+else
+    {
+    time_t curTime = stgTime;
+    localtime_r(&curTime, &brokenTime);
+    }
+
+brokenTime.tm_mday = DaysInMonth(brokenTime.tm_year + 1900, brokenTime.tm_mon);
+
+char buf[32];
+
+strftime(buf, 32, "%Y-%m-%d", &brokenTime);
+
+date = buf;
+}
diff --git a/projects/stargazer/plugins/store/postgresql/postgresql_store_utils.h b/projects/stargazer/plugins/store/postgresql/postgresql_store_utils.h
new file mode 100644 (file)
index 0000000..4ffa6ec
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef POSTGRESQL_UTILS_STORE_H
+#define POSTGRESQL_UTILS_STORE_H
+
+#include <functional>
+
+struct ToLower : public std::unary_function<char, char>
+{
+char operator() (char c) const  { return static_cast<char>(std::tolower(c)); }
+};
+
+#endif
diff --git a/projects/stargazer/scripts/clean_db b/projects/stargazer/scripts/clean_db
new file mode 100755 (executable)
index 0000000..31a85a9
--- /dev/null
@@ -0,0 +1,44 @@
+#!/bin/bash
+
+# Этот скрипт производит очистку файловой БД stargazer-а.
+# Его можно вызывать вручную или покрону, к примеру раз в неделю или раз в месяц.
+
+
+# Эта переменная задает сколько месяцев детальной статистики оставить в БД
+SAVE_MONTHS=3
+
+# Эта переменная задает сколько строк оставить в логах юзеров
+MAX_LOG_LINES=5000
+
+# Тут определяется путь к БД
+DB=/var/stargazer/
+
+
+
+
+declare -i NOW=`date +%s`
+declare -i DT=SAVE_MONTHS*31*24*3600
+declare -i stat_time=0
+
+for usr in $DB/users/*
+do
+    echo cleaning `basename $usr`
+    for ys in $usr/detail_stat/*
+    do
+       year=`basename $ys`
+       
+       for ms in $ys/*
+       do
+           month=`basename $ms`
+            stat_time=`date --date="$year/$month/01" +%s`          
+           
+           if (( $NOW - $stat_time > $DT ))
+           then
+               rm -fr $ms
+           fi
+       done
+    done
+    tail -n $MAX_LOG_LINES $usr/log > /tmp/stg_usr_log.`basename $usr`
+    mv -f /tmp/stg_usr_log.`basename $usr` $usr/log
+done
+
diff --git a/projects/stargazer/scripts/monitor b/projects/stargazer/scripts/monitor
new file mode 100755 (executable)
index 0000000..1f608a7
--- /dev/null
@@ -0,0 +1,66 @@
+#!/bin/bash
+
+# Данный скрипт производит мониторинг СТГ-сервера на зависание и в 
+# случае его зависания перезапускает.
+# Для работы скрипта в настройках СТГ должен быть указан параметер
+# MonitorDir 
+# Скрипт отрабатывает один раз и выходит. Т.е. он не работает постоянно 
+# и следит за СТГ. Его нужно вызывать по крону или как-то еще с нужной
+# периодичностью!!!
+
+
+# Путь к файлам монитора. Должен совпадать со значением MonitorDir 
+# в настройках сервера
+MONITOR_DIR=/var/stargazer/monitor/
+
+
+# Максимальная задержка обновления файлов монитора в секундах.
+# При привышении этого значения сервер считается зависшим и будет 
+# перезапущен
+DT=300
+
+
+
+
+declare -i now=`date +%s`
+declare -i DT=300
+declare -i file_time=0
+
+stg_running=`ps ax | grep stargazer`
+if [ -z "$stg_running" ]
+then
+    echo "Stargazer is not running"
+    exit 0
+fi
+
+#wakeuper for traffcounter
+ping -c 1 127.0.0.1 > /dev/null
+sleep 1
+
+for mon in $MONITOR_DIR/*
+do
+    if [ ! -r $mon ]
+    then
+        echo "no monitor files"
+        exit 0
+    fi
+    file_time=`stat -c%Y $mon`
+
+    if (( $now - $file_time > $DT )) 
+    then
+        echo "Stargazer is deadlocked!"
+               
+       # Команда остаовки СТГ
+       killall -KILL stargazer
+               
+       rm -f $MONITOR_DIR/*
+       sleep 15
+       
+       # Команда запуска СТГ
+       /etc/init.d/stargazer start
+       
+    fi
+    
+done
+
+
diff --git a/projects/stargazer/scripts/shaper/OnConnect b/projects/stargazer/scripts/shaper/OnConnect
new file mode 100755 (executable)
index 0000000..67bf32b
--- /dev/null
@@ -0,0 +1,54 @@
+#!/bin/bash
+
+int_iface=eth1
+
+# Login
+LOGIN=$1
+
+#user IP
+IP=$2
+
+#cash
+CASH=$3
+
+#user ID
+ID=$4
+
+#Selected dirs to connect
+DIRS=$5
+
+default_speed=32kbit
+
+# =========== shaping by tariff ===========
+#tariff=$(grep -i "^tariff=" /var/stargazer/users/$LOGIN/conf | cut -f 2 -d"=")
+#echo "tariff=$tariff" > /var/stargazer/users/$LOGIN/connect.log
+#case $tariff in
+#    minimum)  speedkb=128kbit;;  # 128 kbit
+#    middle)   speedkb=256kbit;;  # 256 kbi
+#    maximum)  speedkb=512kbit;;        # 512 kbit
+#    *)        speedkb=$default_speed;;  # default speed
+#esac
+# ========= shaping by tariff end ========= 
+
+# ========= shaping by userdata0 ==========
+speedR=$(grep -i "^Userdata0=" /var/stargazer/users/$LOGIN/conf | cut -f 2 -d"=")
+speed=$(echo $speedR | grep "^[0-9]*[0-9]$")
+
+if [ -z "$speed" ] 
+then
+    speedkb=$default_speed
+else
+    speedkb="$speed"kbit
+fi
+# ======= shaping by userdata0 end ========
+
+declare -i mark=$ID+10
+
+echo "$mark" > /var/stargazer/users/$LOGIN/shaper_mark
+echo "$speedkb" > /var/stargazer/users/$LOGIN/shaper_rate
+
+iptables -t mangle -A FORWARD -d $IP -j MARK --set-mark $mark
+
+tc class add dev $int_iface parent 1:1 classid 1:$mark htb rate $speedkb burst 40k
+tc filter add dev $int_iface parent 1: protocol ip prio 3 handle $mark fw classid 1:$mark
+
diff --git a/projects/stargazer/scripts/shaper/OnDisconnect b/projects/stargazer/scripts/shaper/OnDisconnect
new file mode 100755 (executable)
index 0000000..e015eec
--- /dev/null
@@ -0,0 +1,37 @@
+#!/bin/bash
+
+int_iface=eth1
+
+# Login
+LOGIN=$1
+
+#user IP
+IP=$2
+
+#cash
+CASH=$3
+
+#user ID
+ID=$4
+
+#Selected dirs to disconnect
+DIRS=$4
+
+mark=$(cat /var/stargazer/users/$LOGIN/shaper_mark)
+rate=$(cat /var/stargazer/users/$LOGIN/shaper_rate)
+
+if [ -n "$mark" ]
+then
+    iptables -t mangle -D FORWARD -d $IP -j MARK --set-mark $mark
+    while [ $? == 0 ]
+    do
+           iptables -t mangle -D FORWARD -d $IP -j MARK --set-mark $mark
+    done
+fi
+
+tc filter del dev $int_iface parent 1: protocol ip prio 3 handle $mark fw classid 1:$mark
+tc class del dev $int_iface parent 1:1 classid 1:$mark htb rate $rate burst 40k
+
+#echo "D `date +%Y.%m.%d-%H.%M.%S` $IP $CASH" >> /var/stargazer/users/$LOGIN/connect.log
+
+
diff --git a/projects/stargazer/scripts/shaper/Readme.txt b/projects/stargazer/scripts/shaper/Readme.txt
new file mode 100644 (file)
index 0000000..a5fd925
--- /dev/null
@@ -0,0 +1,59 @@
+Настройка шейпера для STG в Linux.
+
+По мотивам форума:
+http://local.com.ua/forum/index.php?showtopic=7920
+
+Настройка сводится к указанию сетевого интерфейса, обращенного к пользователю 
+в скриптах shaper.sh, shaper.stop.sh, OnConnect и OnDisconnect, и уточнению 
+скоростоей и тарифов в скрипте OnConnect (если нужно).
+
+Скрипты сделаны для БД на файлах, однако, сделать их для БД на Firebird или 
+MySQL не составит большого труда.
+
+В OnConnect есть два типа шейпинга.
+1. На основании тарифа. Т.е. для каждого тарифа у задана скорость и задано 
+дефолтное значение, на случай отсутсвия тарифа в списке скоростей или 
+забывчивости админа.
+2. На основании Userdata0. В этом поле просто прописывается число равное 
+скорости в kbit/sec. Также есть дефолтное значение скорости в 32 kbit/sec 
+на случай отсутсвия в Userdata0 корректного значения.
+
+В скрипте первый способ закомментирован. Для того чтобы выбрать один из них нужно
+либо удалить, либо закомментировать строчики между
+
+# ========= shaping by tariff ==========
+.........
+# ======= shaping by tariff end ========
+
+
+# ========= shaping by userdata0 ==========
+.........
+# ======= shaping by userdata0 end ========
+
+
+и нужную часть расскоментировать, если она закомментрована.
+
+Скрипт shaper.sh должен быть выполнен один раз при загрузке системы.
+
+Интерфейс обращенный к пользователю определяется в переменной
+int_iface= 
+(присутствует во всех 4-х файлах shaper.sh, shaper.stop.sh, OnConnect и 
+OnDisconnect !!!)
+
+Скорость по умолчанию в OnConnect в переменной default_speed
+
+Зависимость скорости от тарифа задается в следующем фрагменте кода:
+case $tariff in
+    minimum)  speedkb=128kbit;;
+    middle)   speedkb=256kbit;;
+    maximum)  speedkb=512kbit;;
+    *)        speedkb=$default_speed;;
+esac
+
+Т.е. тут нужно вместо minimum, ... maximum подставить имена ваших тарифов 
+и соотв. скорость. Пользователи с тарифами не указанными в списке будут иметь 
+дефолтную скорость.
+
+Скорость ограничевается только для входящего тарафика, однако расширить 
+эти скрипты для исходящего не составит труда.
diff --git a/projects/stargazer/scripts/shaper/shaper.sh b/projects/stargazer/scripts/shaper/shaper.sh
new file mode 100755 (executable)
index 0000000..2b4f042
--- /dev/null
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+int_iface=eth1
+
+iptables -t mangle --flush
+
+tc qdisc add dev $int_iface root handle 1: htb
+tc class add dev $int_iface parent 1: classid 1:1 htb rate 100mbit ceil 100mbit burst 200k
+
diff --git a/projects/stargazer/scripts/shaper/shaper.stop.sh b/projects/stargazer/scripts/shaper/shaper.stop.sh
new file mode 100755 (executable)
index 0000000..993a13a
--- /dev/null
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+int_iface=eth1
+
+#iptables -t mangle --flush
+
+tc qdisc del dev $int_iface root handle 1: htb
+
diff --git a/projects/stargazer/scripts/shaper_vpn_radius/Readme b/projects/stargazer/scripts/shaper_vpn_radius/Readme
new file mode 100644 (file)
index 0000000..772dddd
--- /dev/null
@@ -0,0 +1,58 @@
+Настройка такой конфигурации происходит в 3 этапа:
+1. Настройка VPN с использованием pptpd;
+2. Настройка авторизации VPN через FreeRADIUS;
+3. Настройка шейпера;
+
+1. Настройка VPN
+
+Необходимо установить пакеты ppp и pptpd. Также необходима поддержка PPP в ядре:
+    Device Drivers  --->
+        Network device support  --->
+            <M> PPP (point-to-point protocol) support
+            <M>   PPP support for sync tty ports
+            <M>   PPP Deflate compression
+            <M>   PPP BSD-Compress compression
+            <M>   PPP MPPE compression (encryption) (EXPERIMENTAL)
+            <M>   PPP over Ethernet (EXPERIMENTAL)
+В файле /etc/pptpd.conf прописываем файл настроек PPP (параметр option). Также
+указываем адреса сервера внутри сети VPN (параметр localip) и диапазон адресов 
+клиентов (параметр remoteip). См. пример файла конфигурации.
+В настройках PPP указываем имя сервера (параметр name), параметры шифрования. 
+Для использования шифрования MPPE необходима его поддержка в ядре. Кроме того, 
+в процессе аутентификации MPPE использует MS-CHAPv2. По этому при 
+использовании шифрования MPPE также необходимо указать необходимость 
+поддержки MS-CHAPv2 клиентом. По желанию указываем proxyarp (для того чтобы 
+клиенты в сети VPN "видели" друг друга) и defaultroute. Прописываем в файле 
+/etc/ppp/chap-secrets тестового пользователя и проверяем работоспособность 
+VPN.
+
+2. Настройка авторизации VPN через FreeRADIUS
+
+Необходимо установить пакет freeradius.
+Настройку сервера (файл radiusd.conf) проводим в соответствии с документацией 
+на модуль rlm_stg.so (см. документацию на систему Stargazer).
+Настройку Stargazer с плагином для FreeRADIUS проводим в соответствиии с 
+документацией на модуль mod_radius.so (см. документацию на систему Stargazer).
+В файле clients.conf, расположенном в дирректории с конфигурационными файлами 
+FreeRADIUS, описываем, какие клиенты могут использовать FreeRADIUS. 
+Рекомендуется заменить стандартный пароль, которым шифруется обмен информации 
+с клиентом, "testing123" на что-то более приемлимое с точки зрения безопасности. 
+После этого запускаем FreeRADIUS и удостоверяемся, что он работает строчкой 
+"Mon Mar 31 16:06:17 2008 : Info: Ready to process requests." в журнале 
+(обычно, /var/log/radius/radius.log). Если журнал FreeRADIUS не позволяет 
+определить проблему - можно запустить сервер в отладочном режме с ключем -X. 
+В этом режиме более детальное журналирование проводится в консоль.
+Если на данном этапе все работает - в файл насттроек PPP прописываем строчку 
+plugin radius.so. После этого VPN должен нормально авторизоваться 
+пользователями системы Stargazer.
+
+3. Настройка шейпера
+
+Собственно настройки шейпер не требует. Всё, что нужно прописано в скриптах 
+OnConnect и OnDisconnect. Шейпер предназначен для работы с хранилищем на 
+файлах, однако, переделать скипт под MySQL или Firebird не составит труда.
+Скорость для пользоватлея задается в поле Userdata0 в kbit/sec. В этом поле 
+должно быть прописано просто число без всяких kbit/sec и т.п. Если в этом поле
+у пользователя нет данных или стоит некорректное значение, пользователь будет 
+ограничен скоростью определенной в переменной default_speed в скрипте 
+OnConnect.
diff --git a/projects/stargazer/scripts/shaper_vpn_radius/firewall/firewall b/projects/stargazer/scripts/shaper_vpn_radius/firewall/firewall
new file mode 100755 (executable)
index 0000000..36a2703
--- /dev/null
@@ -0,0 +1,94 @@
+#!/bin/bash
+
+#adsl-start
+
+modprobe ip_queue
+
+int_addr=10.0.0.2
+ext_addr=192.168.1.34
+
+int_net=10.0.0.0/16
+ext_net=192.168.1.0/24
+
+echo 1 > /proc/sys/net/ipv4/ip_forward
+
+iptables -P INPUT DROP
+iptables -P OUTPUT ACCEPT
+iptables -P FORWARD ACCEPT
+
+iptables -t nat -F
+iptables -t filter -F
+
+# 
+#iptables -A INPUT  -d $ip1 -j ACCEPT
+#iptables -A OUTPUT -s $ip1 -j ACCEPT
+
+# Разрешам говорить самому с собой
+iptables -A INPUT  -d 127.0.0.1 -j ACCEPT
+iptables -A OUTPUT -s 127.0.0.1 -j ACCEPT
+
+#iptables -A INPUT  -d $ip4 -j ACCEPT
+#iptables -A INPUT  -s $ip4 -j ACCEPT
+#iptables -A OUTPUT -s $ip4 -j ACCEPT
+#iptables -A OUTPUT -d $ip4 -j ACCEPT
+
+iptables -A INPUT  -p icmp -j ACCEPT
+iptables -A OUTPUT -p icmp -j ACCEPT
+
+iptables -A INPUT  -p 47 -j ACCEPT
+iptables -A FORWARD -p 47 -j ACCEPT
+iptables -A OUTPUT -p 47 -j ACCEPT
+
+#SSH On this machine
+iptables -A INPUT  -p tcp -d $int_addr --dport 22 -j ACCEPT
+iptables -A OUTPUT -p tcp -s $int_addr --sport 22 -j ACCEPT
+iptables -A INPUT  -p tcp -d $ext_addr --dport 22 -j ACCEPT
+iptables -A OUTPUT -p tcp -s $ext_addr --sport 22 -j ACCEPT
+
+#WEB On this machine
+#iptables -A INPUT  -p tcp -d $ip2 --dport 80 -j ACCEPT
+#iptables -A OUTPUT -p tcp -s $ip2 --sport 80 -j ACCEPT
+#iptables -A INPUT  -p tcp -d $ip3 --dport 80 -j ACCEPT
+#iptables -A OUTPUT -p tcp -s $ip3 --sport 80 -j ACCEPT
+
+#PPTP
+iptables -A INPUT   -p tcp --dport 1723 -j ACCEPT
+iptables -A OUTPUT  -p tcp --sport 1723 -j ACCEPT
+iptables -A INPUT  -p udp --dport 1723 -j ACCEPT
+iptables -A OUTPUT -p udp --sport 1723 -j ACCEPT
+
+#FTP
+#iptables -A INPUT  -p tcp -d $ip2 -j ACCEPT
+#iptables -A OUTPUT -p tcp -s $ip2 -j ACCEPT
+#iptables -A INPUT  -p tcp -d $ip3 -j ACCEPT
+#iptables -A OUTPUT -p tcp -s $ip3 -j ACCEPT
+
+#iptables -A INPUT  -p tcp -d $ip2 --dport 20:21 -j ACCEPT
+#iptables -A OUTPUT -p tcp -s $ip2 --sport 20:21 -j ACCEPT
+#iptables -A INPUT  -p tcp -d $ip3 --dport 20:21 -j ACCEPT
+#iptables -A OUTPUT -p tcp -s $ip3 --sport 20:21 -j ACCEPT
+
+#iptables -A INPUT  -p tcp -d $ip2 --dport 1024:65535 --sport 1024:65535 -j ACCEPT
+#iptables -A INPUT  -p tcp -d $ip3 --dport 1024:65535 --sport 1024:65535 -j ACCEPT
+#iptables -A OUTPUT -p tcp -s $ip2 --sport 1024:65535 --dport 1024:65535 -j ACCEPT
+#iptables -A OUTPUT -p tcp -s $ip3 --sport 1024:65535 --dport 1024:65535 -j ACCEPT
+
+#DNS
+iptables -A INPUT  -p tcp --sport 53 -j ACCEPT
+iptables -A OUTPUT -p tcp --dport 53 -j ACCEPT
+iptables -A INPUT  -p udp --sport 53 -j ACCEPT
+iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
+
+#iptables -t nat -A PREROUTING -p tcp -d $ip1 --dport 80 -j ACCEPT
+#iptables -t nat -A PREROUTING -p tcp -d $ip2 --dport 80 -j ACCEPT
+#iptables -t nat -A PREROUTING -p tcp -d $ip3 --dport 80 -j ACCEPT
+#iptables -t nat -A PREROUTING -p tcp -d $ip4 --dport 80 -j ACCEPT
+
+#iptables -t nat -A PREROUTING -p tcp -s 192.168.1.7 -j ACCEPT
+#iptables -t nat -A PREROUTING -p tcp -s 192.168.1.16 -j ACCEPT
+#iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 3128
+
+iptables -t nat -A POSTROUTING -d 0.0.0.0/0 -s 192.168.2.0/24 -j MASQUERADE
+
+
+
diff --git a/projects/stargazer/scripts/shaper_vpn_radius/freeradius/clients.conf b/projects/stargazer/scripts/shaper_vpn_radius/freeradius/clients.conf
new file mode 100644 (file)
index 0000000..a855b2d
--- /dev/null
@@ -0,0 +1,78 @@
+#
+# clients.conf - client configuration directives
+#
+#######################################################################
+
+#######################################################################
+#
+#  Definition of a RADIUS client (usually a NAS).
+#
+#  The information given here over rides anything given in the
+#  'clients' file, or in the 'naslist' file.  The configuration here
+#  contains all of the information from those two files, and allows
+#  for more configuration items.
+#
+#  The "shortname" is be used for logging.  The "nastype", "login" and
+#  "password" fields are mainly used for checkrad and are optional.
+#
+
+#
+#  Defines a RADIUS client.  The format is 'client [hostname|ip-address]'
+#
+#  '127.0.0.1' is another name for 'localhost'.  It is enabled by default,
+#  to allow testing of the server after an initial installation.  If you
+#  are not going to be permitting RADIUS queries from localhost, we suggest
+#  that you delete, or comment out, this entry.
+#
+client 127.0.0.1 {
+       #
+       #  The shared secret use to "encrypt" and "sign" packets between
+       #  the NAS and FreeRADIUS.  You MUST change this secret from the
+       #  default, otherwise it's not a secret any more!
+       #
+       #  The secret can be any string, up to 31 characters in length.
+       #
+       secret          = testing123
+
+       #
+       #  The short name is used as an alias for the fully qualified
+       #  domain name, or the IP address.
+       #
+       shortname       = localhost
+
+       #
+       # the following three fields are optional, but may be used by
+       # checkrad.pl for simultaneous use checks
+       #
+
+       #
+       # The nastype tells 'checkrad.pl' which NAS-specific method to
+       #  use to query the NAS for simultaneous use.
+       #
+       #  Permitted NAS types are:
+       #
+       #       cisco
+       #       computone
+       #       livingston
+       #       max40xx
+       #       multitech
+       #       netserver
+       #       pathras
+       #       patton
+       #       portslave
+       #       tc
+       #       usrhiper
+       #       other           # for all other types
+
+       #
+       nastype     = other     # localhost isn't usually a NAS...
+
+       #
+       #  The following two configurations are for future use.
+       #  The 'naspasswd' file is currently used to store the NAS
+       #  login name and password, which is used by checkrad.pl
+       #  when querying the NAS for simultaneous use.
+       #
+#      login       = !root
+#      password    = someadminpas
+}
diff --git a/projects/stargazer/scripts/shaper_vpn_radius/freeradius/radiusd.conf b/projects/stargazer/scripts/shaper_vpn_radius/freeradius/radiusd.conf
new file mode 100644 (file)
index 0000000..c41d28d
--- /dev/null
@@ -0,0 +1,1119 @@
+##
+## radiusd.conf        -- FreeRADIUS server configuration file.
+##
+##     http://www.freeradius.org/
+##     $Id: radiusd.conf,v 1.1 2008/03/31 13:54:59 faust Exp $
+##
+
+#      The location of other config files and
+#      logfiles are declared in this file
+#
+#      Also general configuration for modules can be done
+#      in this file, it is exported through the API to
+#      modules that ask for it.
+#
+#      The configuration variables defined here are of the form ${foo}
+#      They are local to this file, and do not change from request to
+#      request.
+#
+#      The per-request variables are of the form %{Attribute-Name}, and
+#      are taken from the values of the attribute in the incoming
+#      request.  See 'doc/variables.txt' for more information.
+
+prefix = /usr
+exec_prefix = /usr
+sysconfdir = /etc
+localstatedir = /var
+sbindir = ${exec_prefix}/sbin
+logdir = /var/log/freeradius
+raddbdir = /etc/freeradius
+radacctdir = ${logdir}/radacct
+
+#  Location of config and logfiles.
+confdir = ${raddbdir}
+run_dir = ${localstatedir}/run/freeradius
+
+#
+#  The logging messages for the server are appended to the
+#  tail of this file.
+#
+log_file = ${logdir}/radius.log
+
+#
+# libdir: Where to find the rlm_* modules.
+#
+#   This should be automatically set at configuration time.
+#
+#   If the server builds and installs, but fails at execution time
+#   with an 'undefined symbol' error, then you can use the libdir
+#   directive to work around the problem.
+#
+#   The cause is usually that a library has been installed on your
+#   system in a place where the dynamic linker CANNOT find it.  When
+#   executing as root (or another user), your personal environment MAY
+#   be set up to allow the dynamic linker to find the library.  When
+#   executing as a daemon, FreeRADIUS MAY NOT have the same
+#   personalized configuration.
+#
+#   To work around the problem, find out which library contains that symbol,
+#   and add the directory containing that library to the end of 'libdir',
+#   with a colon separating the directory names.  NO spaces are allowed.
+#
+#   e.g. libdir = /usr/local/lib:/opt/package/lib
+#
+#   You can also try setting the LD_LIBRARY_PATH environment variable
+#   in a script which starts the server.
+#
+#   If that does not work, then you can re-configure and re-build the
+#   server to NOT use shared libraries, via:
+#
+#      ./configure --disable-shared
+#      make
+#      make install
+#
+libdir = /usr/lib/freeradius
+
+#  pidfile: Where to place the PID of the RADIUS server.
+#
+#  The server may be signalled while it's running by using this
+#  file.
+#
+#  This file is written when ONLY running in daemon mode.
+#
+#  e.g.:  kill -HUP `cat /var/run/freeradius/freeradius.pid`
+#
+pidfile = ${run_dir}/freeradius.pid
+
+
+# user/group: The name (or #number) of the user/group to run radiusd as.
+#
+#   If these are commented out, the server will run as the user/group
+#   that started it.  In order to change to a different user/group, you
+#   MUST be root ( or have root privleges ) to start the server.
+#
+#   We STRONGLY recommend that you run the server with as few permissions
+#   as possible.  That is, if you're not using shadow passwords, the
+#   user and group items below should be set to 'nobody'.
+#
+#    On SCO (ODT 3) use "user = nouser" and "group = nogroup".
+#
+#  NOTE that some kernels refuse to setgid(group) when the value of
+#  (unsigned)group is above 60000; don't use group nobody on these systems!
+#
+#  On systems with shadow passwords, you might have to set 'group = shadow'
+#  for the server to be able to read the shadow password file.  If you can
+#  authenticate users while in debug mode, but not in daemon mode, it may be
+#  that the debugging mode server is running as a user that can read the
+#  shadow info, and the user listed below can not.
+#
+user = freerad
+group = freerad
+
+#  max_request_time: The maximum time (in seconds) to handle a request.
+#
+#  Requests which take more time than this to process may be killed, and
+#  a REJECT message is returned.
+#
+#  WARNING: If you notice that requests take a long time to be handled,
+#  then this MAY INDICATE a bug in the server, in one of the modules
+#  used to handle a request, OR in your local configuration.
+#
+#  This problem is most often seen when using an SQL database.  If it takes
+#  more than a second or two to receive an answer from the SQL database,
+#  then it probably means that you haven't indexed the database.  See your
+#  SQL server documentation for more information.
+#
+#  Useful range of values: 5 to 120
+#
+max_request_time = 30
+
+#  delete_blocked_requests: If the request takes MORE THAN 'max_request_time'
+#  to be handled, then maybe the server should delete it.
+#
+#  If you're running in threaded, or thread pool mode, this setting
+#  should probably be 'no'.  Setting it to 'yes' when using a threaded
+#  server MAY cause the server to crash!
+#
+delete_blocked_requests = no
+
+#  cleanup_delay: The time to wait (in seconds) before cleaning up
+#  a reply which was sent to the NAS.
+#
+#  The RADIUS request is normally cached internally for a short period
+#  of time, after the reply is sent to the NAS.  The reply packet may be
+#  lost in the network, and the NAS will not see it.  The NAS will then
+#  re-send the request, and the server will respond quickly with the
+#  cached reply.
+#
+#  If this value is set too low, then duplicate requests from the NAS
+#  MAY NOT be detected, and will instead be handled as seperate requests.
+#
+#  If this value is set too high, then the server will cache too many
+#  requests, and some new requests may get blocked.  (See 'max_requests'.)
+#
+#  Useful range of values: 2 to 10
+#
+cleanup_delay = 5
+
+#  max_requests: The maximum number of requests which the server keeps
+#  track of.  This should be 256 multiplied by the number of clients.
+#  e.g. With 4 clients, this number should be 1024.
+#
+#  If this number is too low, then when the server becomes busy,
+#  it will not respond to any new requests, until the 'cleanup_delay'
+#  time has passed, and it has removed the old requests.
+#
+#  If this number is set too high, then the server will use a bit more
+#  memory for no real benefit.
+#
+#  If you aren't sure what it should be set to, it's better to set it
+#  too high than too low.  Setting it to 1000 per client is probably
+#  the highest it should be.
+#
+#  Useful range of values: 256 to infinity
+#
+max_requests = 1024
+
+#  bind_address:  Make the server listen on a particular IP address, and
+#  send replies out from that address.  This directive is most useful
+#  for machines with multiple IP addresses on one interface.
+#
+#  It can either contain "*", or an IP address, or a fully qualified
+#  Internet domain name.  The default is "*"
+#
+#  As of 1.0, you can also use the "listen" directive.  See below for
+#  more information.
+#
+bind_address = *
+
+#  port: Allows you to bind FreeRADIUS to a specific port.
+#
+#  The default port that most NAS boxes use is 1645, which is historical.
+#  RFC 2138 defines 1812 to be the new port.  Many new servers and
+#  NAS boxes use 1812, which can create interoperability problems.
+#
+#  The port is defined here to be 0 so that the server will pick up
+#  the machine's local configuration for the radius port, as defined
+#  in /etc/services.
+#
+#  If you want to use the default RADIUS port as defined on your server,
+#  (usually through 'grep radius /etc/services') set this to 0 (zero).
+#
+#  A port given on the command-line via '-p' over-rides this one.
+#
+#  As of 1.0, you can also use the "listen" directive.  See below for
+#  more information.
+#
+port = 0
+
+#
+#  By default, the server uses "bind_address" to listen to all IP's
+#  on a machine, or just one IP.  The "port" configuration is used
+#  to select the authentication port used when listening on those
+#  addresses.
+#
+#  If you want the server to listen on additional addresses, you can
+#  use the "listen" section.  A sample section (commented out) is included
+#  below.  This "listen" section duplicates the functionality of the
+#  "bind_address" and "port" configuration entries, but it only listens
+#  for authentication packets.
+#
+#  If you comment out the "bind_address" and "port" configuration entries,
+#  then it becomes possible to make the server accept only accounting,
+#  or authentication packets.  Previously, it always listened for both
+#  types of packets, and it was impossible to make it listen for only
+#  one type of packet.
+#
+#listen {
+       #  IP address on which to listen.
+       #  Allowed values are:
+       #       dotted quad (1.2.3.4)
+       #       hostname    (radius.example.com)
+       #       wildcard    (*)
+#      ipaddr = *
+
+       #  Port on which to listen.
+       #  Allowed values are:
+       #       integer port number (1812)
+       #       0 means "use /etc/services for the proper port"
+#      port = 0
+
+       #  Type of packets to listen for.
+       #  Allowed values are:
+       #       auth    listen for authentication packets
+       #       acct    listen for accounting packets
+       #
+#      type = auth
+#}
+
+
+#  hostname_lookups: Log the names of clients or just their IP addresses
+#  e.g., www.freeradius.org (on) or 206.47.27.232 (off).
+#
+#  The default is 'off' because it would be overall better for the net
+#  if people had to knowingly turn this feature on, since enabling it
+#  means that each client request will result in AT LEAST one lookup
+#  request to the nameserver.   Enabling hostname_lookups will also
+#  mean that your server may stop randomly for 30 seconds from time
+#  to time, if the DNS requests take too long.
+#
+#  Turning hostname lookups off also means that the server won't block
+#  for 30 seconds, if it sees an IP address which has no name associated
+#  with it.
+#
+#  allowed values: {no, yes}
+#
+hostname_lookups = no
+
+#  Core dumps are a bad thing.  This should only be set to 'yes'
+#  if you're debugging a problem with the server.
+#
+#  allowed values: {no, yes}
+#
+allow_core_dumps = no
+
+#  Regular expressions
+#
+#  These items are set at configure time.  If they're set to "yes",
+#  then setting them to "no" turns off regular expression support.
+#
+#  If they're set to "no" at configure time, then setting them to "yes"
+#  WILL NOT WORK.  It will give you an error.
+#
+regular_expressions    = yes
+extended_expressions   = yes
+
+#  Log the full User-Name attribute, as it was found in the request.
+#
+# allowed values: {no, yes}
+#
+log_stripped_names = no
+
+#  Log authentication requests to the log file.
+#
+#  allowed values: {no, yes}
+#
+log_auth = no
+
+#  Log passwords with the authentication requests.
+#  log_auth_badpass  - logs password if it's rejected
+#  log_auth_goodpass - logs password if it's correct
+#
+#  allowed values: {no, yes}
+#
+log_auth_badpass = no
+log_auth_goodpass = no
+
+# usercollide:  Turn "username collision" code on and off.  See the
+# "doc/duplicate-users" file
+#
+#  WARNING
+#  !!!!!!!  Setting this to "yes" may result in the server behaving
+#  !!!!!!!  strangely.  The "username collision" code will ONLY work
+#  !!!!!!!  with clear-text passwords.  Even then, it may not do what
+#  !!!!!!!  you want, or what you expect.
+#  !!!!!!!
+#  !!!!!!!  We STRONGLY RECOMMEND that you do not use this feature,
+#  !!!!!!!  and that you find another way of acheiving the same goal.
+#  !!!!!!!
+#  !!!!!!!  e,g. module fail-over.  See 'doc/configurable_failover'
+#  WARNING
+#
+usercollide = no
+
+# lower_user / lower_pass:  
+# Lower case the username/password "before" or "after"
+# attempting to authenticate.  
+#
+#  If "before", the server will first modify the request and then try
+#  to auth the user.  If "after", the server will first auth using the
+#  values provided by the user.  If that fails it will reprocess the
+#  request after modifying it as you specify below.
+#
+#  This is as close as we can get to case insensitivity.  It is the
+#  admin's job to ensure that the username on the auth db side is
+#  *also* lowercase to make this work
+#
+# Default is 'no' (don't lowercase values)
+# Valid values = "before" / "after" / "no"
+#
+lower_user = no
+lower_pass = no
+
+# nospace_user / nospace_pass:
+#
+#  Some users like to enter spaces in their username or password
+#  incorrectly.  To save yourself the tech support call, you can
+#  eliminate those spaces here:
+#
+# Default is 'no' (don't remove spaces)
+# Valid values = "before" / "after" / "no" (explanation above)
+#
+nospace_user = no
+nospace_pass = no
+
+#  The program to execute to do concurrency checks.
+checkrad = ${sbindir}/checkrad
+
+# SECURITY CONFIGURATION
+#
+#  There may be multiple methods of attacking on the server.  This
+#  section holds the configuration items which minimize the impact
+#  of those attacks
+#
+security {
+       #
+       #  max_attributes: The maximum number of attributes
+       #  permitted in a RADIUS packet.  Packets which have MORE
+       #  than this number of attributes in them will be dropped.
+       #
+       #  If this number is set too low, then no RADIUS packets
+       #  will be accepted.
+       #
+       #  If this number is set too high, then an attacker may be
+       #  able to send a small number of packets which will cause
+       #  the server to use all available memory on the machine.
+       #
+       #  Setting this number to 0 means "allow any number of attributes"
+       max_attributes = 200
+
+       #
+       #  reject_delay: When sending an Access-Reject, it can be
+       #  delayed for a few seconds.  This may help slow down a DoS
+       #  attack.  It also helps to slow down people trying to brute-force
+       #  crack a users password.
+       #
+       #  Setting this number to 0 means "send rejects immediately"
+       #
+       #  If this number is set higher than 'cleanup_delay', then the
+       #  rejects will be sent at 'cleanup_delay' time, when the request
+       #  is deleted from the internal cache of requests.
+       #
+       #  Useful ranges: 1 to 5
+       reject_delay = 1
+
+       #
+       #  status_server: Whether or not the server will respond
+       #  to Status-Server requests.
+       #
+       #  Normally this should be set to "no", because they're useless.
+       #  See: http://www.freeradius.org/rfc/rfc2865.html#Keep-Alives
+       #
+       #  However, certain NAS boxes may require them. 
+       #
+       #  When sent a Status-Server message, the server responds with
+       #  an Access-Accept packet, containing a Reply-Message attribute,
+       #  which is a string describing how long the server has been
+       #  running.
+       #
+       status_server = no
+}
+
+# PROXY CONFIGURATION
+#
+#  proxy_requests: Turns proxying of RADIUS requests on or off.
+#
+#  The server has proxying turned on by default.  If your system is NOT
+#  set up to proxy requests to another server, then you can turn proxying
+#  off here.  This will save a small amount of resources on the server.
+#
+#  If you have proxying turned off, and your configuration files say
+#  to proxy a request, then an error message will be logged.
+#
+#  To disable proxying, change the "yes" to "no", and comment the
+#  $INCLUDE line.
+#
+#  allowed values: {no, yes}
+#
+proxy_requests  = yes
+$INCLUDE  ${confdir}/proxy.conf
+
+
+# CLIENTS CONFIGURATION
+#
+#  Client configuration is defined in "clients.conf".  
+#
+
+#  The 'clients.conf' file contains all of the information from the old
+#  'clients' and 'naslist' configuration files.  We recommend that you
+#  do NOT use 'client's or 'naslist', although they are still
+#  supported.
+#
+#  Anything listed in 'clients.conf' will take precedence over the
+#  information from the old-style configuration files.
+#
+$INCLUDE  ${confdir}/clients.conf
+
+
+# SNMP CONFIGURATION
+#
+#  Snmp configuration is only valid if SNMP support was enabled
+#  at compile time.
+#
+#  To enable SNMP querying of the server, set the value of the
+#  'snmp' attribute to 'yes'
+#
+snmp   = no
+$INCLUDE  ${confdir}/snmp.conf
+
+
+# THREAD POOL CONFIGURATION
+#
+#  The thread pool is a long-lived group of threads which
+#  take turns (round-robin) handling any incoming requests.
+#
+#  You probably want to have a few spare threads around,
+#  so that high-load situations can be handled immediately.  If you
+#  don't have any spare threads, then the request handling will
+#  be delayed while a new thread is created, and added to the pool.
+#
+#  You probably don't want too many spare threads around,
+#  otherwise they'll be sitting there taking up resources, and
+#  not doing anything productive.
+#
+#  The numbers given below should be adequate for most situations.
+#
+thread pool {
+       #  Number of servers to start initially --- should be a reasonable
+       #  ballpark figure.
+       start_servers = 5
+
+       #  Limit on the total number of servers running.
+       #
+       #  If this limit is ever reached, clients will be LOCKED OUT, so it
+       #  should NOT BE SET TOO LOW.  It is intended mainly as a brake to
+       #  keep a runaway server from taking the system with it as it spirals
+       #  down...
+       #
+       #  You may find that the server is regularly reaching the
+       #  'max_servers' number of threads, and that increasing
+       #  'max_servers' doesn't seem to make much difference.
+       #
+       #  If this is the case, then the problem is MOST LIKELY that
+       #  your back-end databases are taking too long to respond, and
+       #  are preventing the server from responding in a timely manner.
+       #
+       #  The solution is NOT do keep increasing the 'max_servers'
+       #  value, but instead to fix the underlying cause of the
+       #  problem: slow database, or 'hostname_lookups=yes'.
+       #
+       #  For more information, see 'max_request_time', above.
+       #
+       max_servers = 32
+
+       #  Server-pool size regulation.  Rather than making you guess
+       #  how many servers you need, FreeRADIUS dynamically adapts to
+       #  the load it sees, that is, it tries to maintain enough
+       #  servers to handle the current load, plus a few spare
+       #  servers to handle transient load spikes.
+       #
+       #  It does this by periodically checking how many servers are
+       #  waiting for a request.  If there are fewer than
+       #  min_spare_servers, it creates a new spare.  If there are
+       #  more than max_spare_servers, some of the spares die off.
+       #  The default values are probably OK for most sites.
+       #
+       min_spare_servers = 3
+       max_spare_servers = 10
+
+       #  There may be memory leaks or resource allocation problems with
+       #  the server.  If so, set this value to 300 or so, so that the
+       #  resources will be cleaned up periodically.
+       #
+       #  This should only be necessary if there are serious bugs in the
+       #  server which have not yet been fixed.
+       #
+       #  '0' is a special value meaning 'infinity', or 'the servers never
+       #  exit'
+       max_requests_per_server = 0
+}
+
+# MODULE CONFIGURATION
+#
+#  The names and configuration of each module is located in this section.
+#
+#  After the modules are defined here, they may be referred to by name,
+#  in other sections of this configuration file.
+#
+modules {
+       #
+       #  Each module has a configuration as follows:
+       #
+       #       name [ instance ] {
+       #               config_item = value
+       #               ...
+       #       }
+       #
+       #  The 'name' is used to load the 'rlm_name' library
+       #  which implements the functionality of the module.
+       #
+       #  The 'instance' is optional.  To have two different instances
+       #  of a module, it first must be referred to by 'name'.
+       #  The different copies of the module are then created by
+       #  inventing two 'instance' names, e.g. 'instance1' and 'instance2'
+       #
+       #  The instance names can then be used in later configuration
+       #  INSTEAD of the original 'name'.  See the 'radutmp' configuration
+       #  below for an example.
+       #
+
+       # PAP module to authenticate users based on their stored password
+       #
+       #  Supports multiple encryption schemes
+       #  clear: Clear text
+       #  crypt: Unix crypt
+       #    md5: MD5 ecnryption
+       #   sha1: SHA1 encryption.
+       #  DEFAULT: crypt
+       pap {
+               encryption_scheme = crypt
+       }
+
+       # CHAP module
+       #
+       #  To authenticate requests containing a CHAP-Password attribute.
+       #
+       chap {
+               authtype = CHAP
+       }
+
+       #  Extensible Authentication Protocol
+       #
+       #  For all EAP related authentications.
+       #  Now in another file, because it is very large.
+       #
+$INCLUDE ${confdir}/eap.conf
+
+       # Microsoft CHAP authentication
+       #
+       #  This module supports MS-CHAP and MS-CHAPv2 authentication.
+       #  It also enforces the SMB-Account-Ctrl attribute.
+       #
+       mschap {
+               #
+               #  As of 0.9, the mschap module does NOT support
+               #  reading from /etc/smbpasswd.
+               #
+               #  If you are using /etc/smbpasswd, see the 'passwd'
+               #  module for an example of how to use /etc/smbpasswd
+
+               # if use_mppe is not set to no mschap will
+               # add MS-CHAP-MPPE-Keys for MS-CHAPv1 and
+               # MS-MPPE-Recv-Key/MS-MPPE-Send-Key for MS-CHAPv2
+               #
+               use_mppe = yes
+               authtype = MS-CHAP
+
+               # if mppe is enabled require_encryption makes
+               # encryption moderate
+               #
+               #require_encryption = yes
+
+               # require_strong always requires 128 bit key
+               # encryption
+               #
+               #require_strong = yes
+
+               # Windows sends us a username in the form of
+               # DOMAIN\user, but sends the challenge response
+               # based on only the user portion.  This hack
+               # corrects for that incorrect behavior.
+               #
+               #with_ntdomain_hack = no
+
+               # The module can perform authentication itself, OR
+               # use a Windows Domain Controller.  This configuration
+               # directive tells the module to call the ntlm_auth
+               # program, which will do the authentication, and return
+               # the NT-Key.  Note that you MUST have "winbindd" and
+               # "nmbd" running on the local machine for ntlm_auth
+               # to work.  See the ntlm_auth program documentation
+               # for details.
+               #
+               # Be VERY careful when editing the following line!
+               #
+               #ntlm_auth = "/path/to/ntlm_auth --request-nt-key --username=%{Stripped-User-Name:-%{User-Name:-None}} --challenge=%{mschap:Challenge:-00} --nt-response=%{mschap:NT-Response:-00}"
+       }
+
+       # Preprocess the incoming RADIUS request, before handing it off
+       # to other modules.
+       #
+       #  This module processes the 'huntgroups' and 'hints' files.
+       #  In addition, it re-writes some weird attributes created
+       #  by some NASes, and converts the attributes into a form which
+       #  is a little more standard.
+       #
+       preprocess {
+               huntgroups = ${confdir}/huntgroups
+               hints = ${confdir}/hints
+
+               # This hack changes Ascend's wierd port numberings
+               # to standard 0-??? port numbers so that the "+" works
+               # for IP address assignments.
+               with_ascend_hack = no
+               ascend_channels_per_line = 23
+
+               # Windows NT machines often authenticate themselves as
+               # NT_DOMAIN\username
+               #
+               # If this is set to 'yes', then the NT_DOMAIN portion
+               # of the user-name is silently discarded.
+               #
+               # This configuration entry SHOULD NOT be used.
+               # See the "realms" module for a better way to handle
+               # NT domains.
+               with_ntdomain_hack = no
+
+               # Specialix Jetstream 8500 24 port access server.
+               #
+               # If the user name is 10 characters or longer, a "/"
+               # and the excess characters after the 10th are
+               # appended to the user name.
+               #
+               # If you're not running that NAS, you don't need
+               # this hack.
+               with_specialix_jetstream_hack = no
+
+               # Cisco (and Quintum in Cisco mode) sends it's VSA attributes
+               # with the attribute name *again* in the string, like:
+               #
+               #   H323-Attribute = "h323-attribute=value".
+               #
+               # If this configuration item is set to 'yes', then
+               # the redundant data in the the attribute text is stripped
+               # out.  The result is:
+               #
+               #  H323-Attribute = "value"
+               #
+               # If you're not running a Cisco or Quintum NAS, you don't
+               # need this hack.
+               with_cisco_vsa_hack = no
+       }
+
+       # Write a detailed log of all accounting records received.
+       #
+       detail {
+               #  Note that we do NOT use NAS-IP-Address here, as
+               #  that attribute MAY BE from the originating NAS, and
+               #  NOT from the proxy which actually sent us the
+               #  request.  The Client-IP-Address attribute is ALWAYS
+               #  the address of the client which sent us the
+               #  request.
+               #
+               #  The following line creates a new detail file for
+               #  every radius client (by IP address or hostname).
+               #  In addition, a new detail file is created every
+               #  day, so that the detail file doesn't have to go
+               #  through a 'log rotation'
+               #
+               #  If your detail files are large, you may also want
+               #  to add a ':%H' (see doc/variables.txt) to the end
+               #  of it, to create a new detail file every hour, e.g.:
+               #
+               #   ..../detail-%Y%m%d:%H
+               #
+               #  This will create a new detail file for every hour.
+               #
+               detailfile = ${radacctdir}/%{Client-IP-Address}/detail-%Y%m%d
+
+               #
+               #  The Unix-style permissions on the 'detail' file.
+               #
+               #  The detail file often contains secret or private
+               #  information about users.  So by keeping the file
+               #  permissions restrictive, we can prevent unwanted
+               #  people from seeing that information.
+               detailperm = 0600
+
+               #
+               # Certain attributes such as User-Password may be
+               # "sensitive", so they should not be printed in the
+               # detail file.  This section lists the attributes
+               # that should be suppressed.
+               #
+               # The attributes should be listed one to a line.
+               #
+               #suppress {
+                       # User-Password
+               #}
+       }
+
+       #
+       #  Create a unique accounting session Id.  Many NASes re-use
+       #  or repeat values for Acct-Session-Id, causing no end of
+       #  confusion.
+       #
+       #  This module will add a (probably) unique session id 
+       #  to an accounting packet based on the attributes listed
+       #  below found in the packet.  See doc/rlm_acct_unique for
+       #  more information.
+       #
+       acct_unique {
+               key = "User-Name, Acct-Session-Id, NAS-IP-Address, Client-IP-Address, NAS-Port"
+       }
+
+       #  Write a 'utmp' style file, of which users are currently
+       #  logged in, and where they've logged in from.
+       #
+       #  This file is used mainly for Simultaneous-Use checking,
+       #  and also 'radwho', to see who's currently logged in.
+       #
+       radutmp {
+               #  Where the file is stored.  It's not a log file,
+               #  so it doesn't need rotating.
+               #
+               filename = ${logdir}/radutmp
+
+               #  The field in the packet to key on for the
+               #  'user' name,  If you have other fields which you want
+               #  to use to key on to control Simultaneous-Use,
+               #  then you can use them here.
+               #
+               #  Note, however, that the size of the field in the
+               #  'utmp' data structure is small, around 32
+               #  characters, so that will limit the possible choices
+               #  of keys.
+               #
+               #  You may want instead: %{Stripped-User-Name:-%{User-Name}}
+               username = %{User-Name}
+
+
+               #  Whether or not we want to treat "user" the same
+               #  as "USER", or "User".  Some systems have problems
+               #  with case sensitivity, so this should be set to
+               #  'no' to enable the comparisons of the key attribute
+               #  to be case insensitive.
+               #
+               case_sensitive = yes
+
+               #  Accounting information may be lost, so the user MAY
+               #  have logged off of the NAS, but we haven't noticed.
+               #  If so, we can verify this information with the NAS,
+               #
+               #  If we want to believe the 'utmp' file, then this
+               #  configuration entry can be set to 'no'.
+               #
+               check_with_nas = yes            
+
+               # Set the file permissions, as the contents of this file
+               # are usually private.
+               perm = 0600
+
+               callerid = "yes"
+       }
+
+       # "Safe" radutmp - does not contain caller ID, so it can be
+       # world-readable, and radwho can work for normal users, without
+       # exposing any information that isn't already exposed by who(1).
+       #
+       # This is another 'instance' of the radutmp module, but it is given
+       # then name "sradutmp" to identify it later in the "accounting"
+       # section.
+       radutmp sradutmp {
+               filename = ${logdir}/sradutmp
+               perm = 0644
+               callerid = "no"
+       }
+
+       # attr_filter - filters the attributes received in replies from
+       # proxied servers, to make sure we send back to our RADIUS client
+       # only allowed attributes.
+       attr_filter {
+               attrsfile = ${confdir}/attrs
+       }
+
+       #  counter module:
+       #  This module takes an attribute (count-attribute).
+       #  It also takes a key, and creates a counter for each unique
+       #  key.  The count is incremented when accounting packets are
+       #  received by the server.  The value of the increment depends
+       #  on the attribute type.
+       #  If the attribute is Acct-Session-Time or of an integer type we add the
+       #  value of the attribute. If it is anything else we increase the
+       #  counter by one.
+       #
+       #  The 'reset' parameter defines when the counters are all reset to
+       #  zero.  It can be hourly, daily, weekly, monthly or never.
+       #
+       #  hourly: Reset on 00:00 of every hour
+       #  daily: Reset on 00:00:00 every day
+       #  weekly: Reset on 00:00:00 on sunday
+       #  monthly: Reset on 00:00:00 of the first day of each month
+       #
+       #  It can also be user defined. It should be of the form:
+       #  num[hdwm] where:
+       #  h: hours, d: days, w: weeks, m: months
+       #  If the letter is ommited days will be assumed. In example:
+       #  reset = 10h (reset every 10 hours)
+       #  reset = 12  (reset every 12 days)
+       #
+       #
+       #  The check-name attribute defines an attribute which will be
+       #  registered by the counter module and can be used to set the
+       #  maximum allowed value for the counter after which the user
+       #  is rejected.
+       #  Something like:
+       #
+       #  DEFAULT Max-Daily-Session := 36000
+       #          Fall-Through = 1
+       #
+       #  You should add the counter module in the instantiate
+       #  section so that it registers check-name before the files
+       #  module reads the users file.
+       #
+       #  If check-name is set and the user is to be rejected then we
+       #  send back a Reply-Message and we log a Failure-Message in
+       #  the radius.log
+       #  If the count attribute is Acct-Session-Time then on each login
+       #  we send back the remaining online time as a Session-Timeout attribute
+       #
+       #  The counter-name can also be used instead of using the check-name
+       #  like below:
+       #
+       #  DEFAULT  Daily-Session-Time > 3600, Auth-Type = Reject
+       #      Reply-Message = "You've used up more than one hour today"
+       #
+       #  The allowed-servicetype attribute can be used to only take
+       #  into account specific sessions. For example if a user first
+       #  logs in through a login menu and then selects ppp there will
+       #  be two sessions. One for Login-User and one for Framed-User
+       #  service type. We only need to take into account the second one.
+       #
+       #  The module should be added in the instantiate, authorize and
+       #  accounting sections.  Make sure that in the authorize
+       #  section it comes after any module which sets the
+       #  'check-name' attribute.
+       #
+       counter daily {
+               filename = ${raddbdir}/db.daily
+               key = User-Name
+               count-attribute = Acct-Session-Time
+               reset = daily
+               counter-name = Daily-Session-Time
+               check-name = Max-Daily-Session
+               allowed-servicetype = Framed-User
+               cache-size = 5000
+       }
+
+       #
+       # The "always" module is here for debugging purposes. Each
+       # instance simply returns the same result, always, without
+       # doing anything.
+       always fail {
+               rcode = fail
+       }
+       always reject {
+               rcode = reject
+       }
+       always ok {
+               rcode = ok
+               simulcount = 0
+               mpp = no
+       }
+
+       stg {
+               local_port = 6667
+               server = localhost
+               port = 6666
+               password = 123456
+       }
+
+}
+
+# Instantiation
+#
+#  This section orders the loading of the modules.  Modules
+#  listed here will get loaded BEFORE the later sections like
+#  authorize, authenticate, etc. get examined.
+#
+#  This section is not strictly needed.  When a section like
+#  authorize refers to a module, it's automatically loaded and
+#  initialized.  However, some modules may not be listed in any
+#  of the following sections, so they can be listed here.
+#
+#  Also, listing modules here ensures that you have control over
+#  the order in which they are initalized.  If one module needs
+#  something defined by another module, you can list them in order
+#  here, and ensure that the configuration will be OK.
+#
+instantiate {
+       stg
+}
+
+#  Authorization. First preprocess (hints and huntgroups files),
+#  then realms, and finally look in the "users" file.
+#
+#  The order of the realm modules will determine the order that
+#  we try to find a matching realm.
+#
+#  Make *sure* that 'preprocess' comes before any realm if you 
+#  need to setup hints for the remote radius server
+authorize {
+       #
+       #  The preprocess module takes care of sanitizing some bizarre
+       #  attributes in the request, and turning them into attributes
+       #  which are more standard.
+       #
+       #  It takes care of processing the 'raddb/hints' and the
+       #  'raddb/huntgroups' files.
+       #
+       #  It also adds the %{Client-IP-Address} attribute to the request.
+       preprocess
+
+       #
+       #  The chap module will set 'Auth-Type := CHAP' if we are
+       #  handling a CHAP request and Auth-Type has not already been set
+       chap
+
+       #
+       #  If the users are logging in with an MS-CHAP-Challenge
+       #  attribute for authentication, the mschap module will find
+       #  the MS-CHAP-Challenge attribute, and add 'Auth-Type := MS-CHAP'
+       #  to the request, which will cause the server to then use
+       #  the mschap module for authentication.
+       mschap
+
+       #
+       #  This module takes care of EAP-MD5, EAP-TLS, and EAP-LEAP
+       #  authentication.
+       #
+       #  It also sets the EAP-Type attribute in the request
+       #  attribute list to the EAP type from the packet.
+       eap
+
+       stg
+}
+
+
+#  Authentication.
+#
+#
+#  This section lists which modules are available for authentication.
+#  Note that it does NOT mean 'try each module in order'.  It means
+#  that a module from the 'authorize' section adds a configuration
+#  attribute 'Auth-Type := FOO'.  That authentication type is then
+#  used to pick the apropriate module from the list below.
+#
+
+#  In general, you SHOULD NOT set the Auth-Type attribute.  The server
+#  will figure it out on its own, and will do the right thing.  The
+#  most common side effect of erroneously setting the Auth-Type
+#  attribute is that one authentication method will work, but the
+#  others will not.
+#
+#  The common reasons to set the Auth-Type attribute by hand
+#  is to either forcibly reject the user, or forcibly accept him.
+#
+authenticate {
+       #
+       #  PAP authentication, when a back-end database listed
+       #  in the 'authorize' section supplies a password.  The
+       #  password can be clear-text, or encrypted.
+       Auth-Type PAP {
+               stg
+               pap
+       }
+
+       #
+       #  Most people want CHAP authentication
+       #  A back-end database listed in the 'authorize' section
+       #  MUST supply a CLEAR TEXT password.  Encrypted passwords
+       #  won't work.
+       Auth-Type CHAP {
+               stg
+               chap
+       }
+
+       #
+       #  MSCHAP authentication.
+       Auth-Type MS-CHAP {
+               stg
+               mschap
+       }
+
+       #
+       #  Allow EAP authentication.
+       eap
+}
+
+
+#
+#  Pre-accounting.  Decide which accounting type to use.
+#
+preacct {
+       preprocess
+
+       #
+       #  Ensure that we have a semi-unique identifier for every
+       #  request, and many NAS boxes are broken.
+       acct_unique
+}
+
+#
+#  Accounting.  Log the accounting data.
+#
+accounting {
+       #
+       #  Create a 'detail'ed log of the packets.
+       #  Note that accounting requests which are proxied
+       #  are also logged in the detail file.
+       detail
+#      daily
+
+       #
+       #  For Simultaneous-Use tracking.
+       #
+       #  Due to packet losses in the network, the data here
+       #  may be incorrect.  There is little we can do about it.
+       radutmp
+
+       stg
+
+}
+
+
+#  Session database, used for checking Simultaneous-Use. Either the radutmp 
+#  or rlm_sql module can handle this.
+#  The rlm_sql module is *much* faster
+session {
+       radutmp
+}
+
+
+#  Post-Authentication
+#  Once we KNOW that the user has been authenticated, there are
+#  additional steps we can take.
+post-auth {
+       stg
+}
+
+#
+#  When the server decides to proxy a request to a home server,
+#  the proxied request is first passed through the pre-proxy
+#  stage.  This stage can re-write the request, or decide to
+#  cancel the proxy.
+#
+#  Only a few modules currently have this method.
+#
+pre-proxy {
+}
+
+#
+#  When the server receives a reply to a request it proxied
+#  to a home server, the request may be massaged here, in the
+#  post-proxy stage.
+#
+post-proxy {
+       #
+       #  If you are proxying LEAP, you MUST configure the EAP
+       #  module, and you MUST list it here, in the post-proxy
+       #  stage.
+       #
+       #  You MUST also use the 'nostrip' option in the 'realm'
+       #  configuration.  Otherwise, the User-Name attribute
+       #  in the proxied request will not match the user name
+       #  hidden inside of the EAP packet, and the end server will
+       #  reject the EAP request.
+       #
+       eap
+}
diff --git a/projects/stargazer/scripts/shaper_vpn_radius/ppp/ip-down.d/stg b/projects/stargazer/scripts/shaper_vpn_radius/ppp/ip-down.d/stg
new file mode 100755 (executable)
index 0000000..e9c7eaf
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+rm -f /var/stargazer/ifaces/$PPP_REMOTE
\ No newline at end of file
diff --git a/projects/stargazer/scripts/shaper_vpn_radius/ppp/ip-up.d/stg b/projects/stargazer/scripts/shaper_vpn_radius/ppp/ip-up.d/stg
new file mode 100755 (executable)
index 0000000..6a0b645
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+echo $PPP_IFACE > /var/stargazer/ifaces/$PPP_REMOTE
\ No newline at end of file
diff --git a/projects/stargazer/scripts/shaper_vpn_radius/ppp/pptpd-options b/projects/stargazer/scripts/shaper_vpn_radius/ppp/pptpd-options
new file mode 100644 (file)
index 0000000..af58ba4
--- /dev/null
@@ -0,0 +1,97 @@
+###############################################################################
+# $Id: pptpd-options,v 1.1 2008/03/31 13:55:20 faust Exp $
+#
+# Sample Poptop PPP options file /etc/ppp/pptpd-options
+# Options used by PPP when a connection arrives from a client.
+# This file is pointed to by /etc/pptpd.conf option keyword.
+# Changes are effective on the next connection.  See "man pppd".
+#
+# You are expected to change this file to suit your system.  As
+# packaged, it requires PPP 2.4.2 and the kernel MPPE module.
+###############################################################################
+
+
+# Authentication
+
+# Name of the local system for authentication purposes 
+# (must match the second field in /etc/ppp/chap-secrets entries)
+name pptpd
+
+# Optional: domain name to use for authentication
+# domain mydomain.net
+
+# Strip the domain prefix from the username before authentication.
+# (applies if you use pppd with chapms-strip-domain patch)
+#chapms-strip-domain
+
+
+# Encryption
+# Debian: on systems with a kernel built with the package
+# kernel-patch-mppe >= 2.4.2 and using ppp >= 2.4.2, ...
+# {{{
+refuse-pap
+refuse-chap
+refuse-mschap
+# Require the peer to authenticate itself using MS-CHAPv2 [Microsoft
+# Challenge Handshake Authentication Protocol, Version 2] authentication.
+require-mschap-v2
+# Require MPPE 128-bit encryption
+# (note that MPPE requires the use of MSCHAP-V2 during authentication)
+require-mppe-128
+# }}}
+
+
+
+
+# Network and Routing
+
+# If pppd is acting as a server for Microsoft Windows clients, this
+# option allows pppd to supply one or two DNS (Domain Name Server)
+# addresses to the clients.  The first instance of this option
+# specifies the primary DNS address; the second instance (if given)
+# specifies the secondary DNS address.
+# Attention! This information may not be taken into account by a Windows
+# client. See KB311218 in Microsoft's knowledge base for more information.
+#ms-dns 10.0.0.1
+#ms-dns 10.0.0.2
+
+# If pppd is acting as a server for Microsoft Windows or "Samba"
+# clients, this option allows pppd to supply one or two WINS (Windows
+# Internet Name Services) server addresses to the clients.  The first
+# instance of this option specifies the primary WINS address; the
+# second instance (if given) specifies the secondary WINS address.
+#ms-wins 10.0.0.3
+#ms-wins 10.0.0.4
+
+# Add an entry to this system's ARP [Address Resolution Protocol]
+# table with the IP address of the peer and the Ethernet address of this
+# system.  This will have the effect of making the peer appear to other
+# systems to be on the local ethernet.
+# (you do not need this if your PPTP server is responsible for routing
+# packets to the clients -- James Cameron)
+proxyarp
+
+# Debian: do not replace the default route
+defaultroute
+
+
+# Logging
+
+# Enable connection debugging facilities.
+# (see your syslog configuration for where pppd sends to)
+#debug
+
+# Print out all the option values which have been set.
+# (often requested by mailing list to verify options)
+#dump
+
+
+# Miscellaneous
+
+# Create a UUCP-style lock file for the pseudo-tty to ensure exclusive
+# access.
+lock
+
+# Disable BSD-Compress compression
+nobsdcomp 
+plugin radius.so
\ No newline at end of file
diff --git a/projects/stargazer/scripts/shaper_vpn_radius/pptpd.conf b/projects/stargazer/scripts/shaper_vpn_radius/pptpd.conf
new file mode 100644 (file)
index 0000000..5c64b83
--- /dev/null
@@ -0,0 +1,82 @@
+###############################################################################
+# $Id: pptpd.conf,v 1.1 2008/03/31 13:54:13 faust Exp $
+#
+# Sample Poptop configuration file /etc/pptpd.conf
+#
+# Changes are effective when pptpd is restarted.
+###############################################################################
+
+# TAG: ppp
+#      Path to the pppd program, default '/usr/sbin/pppd' on Linux
+#
+#ppp /usr/sbin/pppd
+
+# TAG: option
+#      Specifies the location of the PPP options file.
+#      By default PPP looks in '/etc/ppp/options'
+#
+option /etc/ppp/pptpd-options
+
+# TAG: debug
+#      Turns on (more) debugging to syslog
+#
+#debug
+
+# TAG: stimeout
+#      Specifies timeout (in seconds) on starting ctrl connection
+#
+# stimeout 10
+
+# TAG: noipparam
+#       Suppress the passing of the client's IP address to PPP, which is
+#       done by default otherwise.
+#
+#noipparam
+
+# TAG: logwtmp
+#      Use wtmp(5) to record client connections and disconnections.
+#
+logwtmp
+
+# TAG: bcrelay <if>
+#      Turns on broadcast relay to clients from interface <if>
+#
+#bcrelay eth1
+
+# TAG: localip
+# TAG: remoteip
+#      Specifies the local and remote IP address ranges.
+#
+#       Any addresses work as long as the local machine takes care of the
+#       routing.  But if you want to use MS-Windows networking, you should
+#       use IP addresses out of the LAN address space and use the proxyarp
+#       option in the pppd options file, or run bcrelay.
+#
+#      You can specify single IP addresses seperated by commas or you can
+#      specify ranges, or both. For example:
+#
+#              192.168.0.234,192.168.0.245-249,192.168.0.254
+#
+#      IMPORTANT RESTRICTIONS:
+#
+#      1. No spaces are permitted between commas or within addresses.
+#
+#      2. If you give more IP addresses than MAX_CONNECTIONS, it will
+#         start at the beginning of the list and go until it gets 
+#         MAX_CONNECTIONS IPs. Others will be ignored.
+#
+#      3. No shortcuts in ranges! ie. 234-8 does not mean 234 to 238,
+#         you must type 234-238 if you mean this.
+#
+#      4. If you give a single localIP, that's ok - all local IPs will
+#         be set to the given one. You MUST still give at least one remote
+#         IP for each simultaneous client.
+#
+# (Recommended)
+#localip 192.168.0.1
+#remoteip 192.168.0.234-238,192.168.0.245
+# or
+#localip 192.168.0.234-238,192.168.0.245
+#remoteip 192.168.1.234-238,192.168.1.245
+localip 192.168.2.1
+remoteip 192.168.2.2-254
diff --git a/projects/stargazer/scripts/shaper_vpn_radius/radiusclient/servers b/projects/stargazer/scripts/shaper_vpn_radius/radiusclient/servers
new file mode 100644 (file)
index 0000000..03a1d94
--- /dev/null
@@ -0,0 +1 @@
+localhost testing123
diff --git a/projects/stargazer/scripts/shaper_vpn_radius/stargazer/OnChange b/projects/stargazer/scripts/shaper_vpn_radius/stargazer/OnChange
new file mode 100755 (executable)
index 0000000..6d99f17
--- /dev/null
@@ -0,0 +1,8 @@
+#! /bin/sh
+
+login=$1
+param=$2
+oldValue=$3
+newValue=$4
+
+#echo "User: '$login'. Parameter $param changed from '$oldValue' to '$newValue'" >> /var/stargazer/users.chg.log
diff --git a/projects/stargazer/scripts/shaper_vpn_radius/stargazer/OnConnect b/projects/stargazer/scripts/shaper_vpn_radius/stargazer/OnConnect
new file mode 100755 (executable)
index 0000000..099a219
--- /dev/null
@@ -0,0 +1,64 @@
+#!/bin/bash
+
+#Этот скрипт вызывается в момент, когда пользователь
+#успешно прошел авторизацию на сервере. Задача скрипта - перестроить 
+#файрвол так, что бы пользователь получил доступ в интернет
+
+# Login
+LOGIN=$1
+
+#user IP
+IP=$2
+
+#cash
+CASH=$3
+
+#user ID
+ID=$4
+
+#Selected dirs to connect
+DIRS=$5
+
+iptables -A INPUT -s $IP -j QUEUE
+iptables -A OUTPUT -d $IP -j QUEUE
+iptables -A FORWARD -s $IP -j QUEUE
+iptables -A FORWARD -d $IP -j QUEUE
+
+# shaper
+
+default_speed=32
+
+speedR=$(grep -i "^Userdata0=" /var/stargazer/users/$LOGIN/conf | cut -f 2 -d"=")
+#echo "speedR=$speedR" >> /var/stargazer/users/$LOGIN/connect.log
+speed=$(echo $speedR | grep "^[0-9]*[0-9]$")
+
+if [ -z "$speed" ] 
+then
+    speed=$default_speed
+fi
+
+speedkbit=$speed"kbit"
+
+#echo "speed=$speedkbit" >> /var/stargazer/users/$LOGIN/connect.log
+declare -i mark=$ID+1
+
+iptables -t mangle -A FORWARD -d $IP -j MARK --set-mark $mark
+
+sleep 1
+
+if [ -f "/var/stargazer/ifaces/$IP" ]
+then
+    #echo "1" >> /var/stargazer/users/$LOGIN/connect.log
+    ppp_iface=$(cat /var/stargazer/ifaces/$IP)
+else
+    #echo "2" >> /var/stargazer/users/$LOGIN/connect.log
+    exit 0
+fi
+
+tc qdisc add dev $ppp_iface root handle 1: htb
+tc class add dev $ppp_iface parent 1: classid 1:1 htb rate 100mbit ceil 100mbit burst 200k
+tc class add dev $ppp_iface parent 1:1 classid 1:10 htb rate $speedkbit burst 20k
+tc filter add dev $ppp_iface parent 1: protocol ip prio 3 handle $mark fw classid 1:10
+
+#echo "C `date +%Y.%m.%d-%H.%M.%S` $IP $CASH $ID $mark $speed $ppp_iface" >> /var/stargazer/users/$LOGIN/connect.log
+
diff --git a/projects/stargazer/scripts/shaper_vpn_radius/stargazer/OnDisconnect b/projects/stargazer/scripts/shaper_vpn_radius/stargazer/OnDisconnect
new file mode 100755 (executable)
index 0000000..482e926
--- /dev/null
@@ -0,0 +1,70 @@
+#!/bin/bash
+
+# Этот скрипт вызывается в момент, когда пользователь
+# желает отключится от интернета или вышел таймаут у пользователя
+# и сервер сам отключает пользователя
+# Задача скрипта подобна задаче скрипта OnConnect - перестроить 
+# файрвол так, что бы пользователю закрыть доступ в интернет
+
+# Login
+LOGIN=$1
+
+#user IP
+IP=$2
+
+#cash
+CASH=$3
+
+#user ID
+ID=$4
+
+#Selected dirs to disconnect
+DIRS=$4
+
+#echo "D `date +%Y.%m.%d-%H.%M.%S` $IP $CASH" >> /var/stargazer/users/$LOGIN/connect.log
+
+iptables -D INPUT -s $IP -j QUEUE
+while [ $? == 0 ]
+do
+    iptables -D INPUT -s $IP -j QUEUE
+done
+
+iptables -D OUTPUT -d $IP -j QUEUE
+while [ $? == 0 ]
+do
+    iptables -D OUTPUT -d $IP -j QUEUE
+done
+
+iptables -D FORWARD -s $IP -j QUEUE
+while [ $? == 0 ]
+do
+    iptables -D FORWARD -s $IP -j QUEUE
+done
+
+iptables -D FORWARD -d $IP -j QUEUE
+while [ $? == 0 ]
+do
+    iptables -D FORWARD -d $IP -j QUEUE
+done
+
+
+
+declare -i mark=$ID+1
+
+iptables -t mangle -D FORWARD -d $IP -j MARK --set-mark $mark
+while [ $? == 0 ]
+do
+    iptables -t mangle -D FORWARD -d $IP -j MARK --set-mark $mark
+done
+
+
+if [ -f /var/stargazer/ifaces/$IP ]
+then
+    ppp_iface=$(cat /var/stargazer/ifaces/$IP)
+else
+    exit 0
+fi
+
+tc qdisc del dev $ppp_iface root
+
+
diff --git a/projects/stargazer/scripts/shaper_vpn_radius/stargazer/OnUserAdd b/projects/stargazer/scripts/shaper_vpn_radius/stargazer/OnUserAdd
new file mode 100755 (executable)
index 0000000..22d321c
--- /dev/null
@@ -0,0 +1,14 @@
+#! /bin/sh
+
+# Использование (неиспользование) этого скрипта дело вкуса.
+# Он не выполняет критических функций. Его задача автматизировать
+# действия характерные при добавлении пользователя сети, например добавлекние 
+# пользователю почты
+
+# Login
+login=$1
+
+#echo "added user $login" >> /var/stargazer/add_del.log
+
+
+
diff --git a/projects/stargazer/scripts/shaper_vpn_radius/stargazer/OnUserDel b/projects/stargazer/scripts/shaper_vpn_radius/stargazer/OnUserDel
new file mode 100755 (executable)
index 0000000..248e5b3
--- /dev/null
@@ -0,0 +1,7 @@
+#! /bin/sh
+
+# Login
+login=$1
+
+#echo "deleted user $login" >> /var/stargazer/add_del.log
+
diff --git a/projects/stargazer/scripts/shaper_vpn_radius/stargazer/rules b/projects/stargazer/scripts/shaper_vpn_radius/stargazer/rules
new file mode 100644 (file)
index 0000000..3fb4828
--- /dev/null
@@ -0,0 +1,3 @@
+ALL     192.168.0.0/16  DIR1 
+ALL     10.0.0.0/8      DIR2
+ALL     0.0.0.0/0       DIR0
\ No newline at end of file
diff --git a/projects/stargazer/scripts/shaper_vpn_radius/stargazer/stargazer.conf b/projects/stargazer/scripts/shaper_vpn_radius/stargazer/stargazer.conf
new file mode 100644 (file)
index 0000000..221c85c
--- /dev/null
@@ -0,0 +1,298 @@
+
+# Имя лог-файла куда пишутся события
+LogFile = /var/log/stargazer.log
+
+
+
+# Имя файла в котором определяются правила подсчета трафика
+Rules = /etc/stargazer/rules
+
+
+
+# Время через которое пишется d БД детальная статистика пользователя
+# Значения: 1, 1/2, 1/4, 1/6.
+# 1 - раз в чаc, 1/2 - раз в пол часа, 1/4 - раз в 15 мин, 1/6 - раз в 10 мин
+DetailStatWritePeriod=1/6
+
+
+
+# Периодичность записи записи в БД информации о статистике пользователя (минуты)
+# При большом кол-ве пользователей эту величину стоит увеличить, т.к.
+# запись в БД может занимать длительное время.
+# Значения: 1...1440 (минуты)
+StatWritePeriod = 10
+
+
+
+# День снятия абонплаты
+# Значения: 0...31. 0 - Последний день месяца
+DayFee = 1
+
+
+
+# Абонплата снимается в последний (yes) или первый (no) день учетного периода.
+# Это влияет на то, как будет снята абонплата (АП) при переходе на новый тариф.
+# Если у пользователя был тариф A с АП=100 и он хочет перейти на тариф B с АП=200,
+# то при переходе на новый тариф со счета пользователя снимется 100, если
+# DayFeeIsLastDay = yes и 200, если DayFeeIsLastDay = no
+DayFeeIsLastDay = yes
+
+
+
+# День сброса данных о трафике за месяц и день перехода пользователей на новые тарифы
+# Значения: 0...31. 0 - Последний день месяца
+DayResetTraff = 1
+
+
+
+# "Размазанное" снятие абонплаты. Снятие АП не раз в месяц, а каждый
+# день 1/30 или 1/31 части АП
+# Значения: yes, no
+SpreadFee = no
+
+
+
+# Данная опция определяет может ли пользователь получить доступ в интерент
+# если у него на счету нет денег, но остался предоплаченный трафик
+# Значения: yes, no
+FreeMbAllowInet = no
+
+
+
+# Эта опция определяет что будет писаться в стоимость трафика в detail_stat.
+# Если у пользователя еще есть предоплаченный трафик и WriteFreeMbTraffCost = no,
+# то в detail_stat стоимость будет 0. Если у пользователя уже нет
+# предоплаченного трафика и WriteFreeMbTraffCost = no, то в detail_stat
+# будет записана стоиость трафика. При WriteFreeMbTraffCost = yes стоимость
+# трафика будет записана в любом случае.
+WriteFreeMbTraffCost = no
+
+
+
+# Необязательный параметр. Указывает снимать полную абонплату у пользователя даже
+# если он быз заморожен только часть учетного периода.
+# По умолчанию установлен в no
+# FullFee=no
+
+# Необязательный параметр указывающий показывать на счету и позволять 
+# использовать пользователю абонплату. По умолчанию установлен в yes
+# ShowFeeInCash=yes
+
+
+
+# Названия направлений. Направления без названий не будут отображаться в
+# авторизаторе и конфигураторе. Названия состоящие из нескольких слов должны
+# быть взяты в кавычки
+<DirNames>
+    DirName0 = Local
+    DirName1 = City
+    DirName2 = World
+    DirName3 =
+    DirName4 =
+    DirName5 =
+    DirName6 =
+    DirName7 =
+    DirName8 =
+    DirName9 =
+</DirNames>
+
+
+
+# Кол-во запускаемых процессов stg-exec.
+# Эти процессы отвечают за выполнение скриптов OnConnect, OnDisconnect, ...
+# Кол-во процессов означает сколько скриптов могут выполнятся одновременно.
+# Значения: 1...1024
+ExecutersNum = 2
+
+
+
+# Message Key для stg-exec.
+# Идентификатор очереди сообщений для выполнятеля скриптов.
+# Его изменение может понадобится если есть необходимость запустить несколько
+# экземпляров stg. Если вы не понимаете, что это, не трогайте этот параметр!
+# Значения: 0...2^32
+# Значение по умолчанию: 5555
+# ExecMsgKey = 5555
+
+
+
+# Путь к директории, в которой находятся модули сервера
+ModulesPath = /usr/lib/stg
+
+# Определяет директорию, в которой будут находится файлы "монитора"
+# работы сервера. В этой директории будут созданы пустые файлы, время 
+# модификации которых будет меняться примерно раз в минуту. Если какой-то 
+# компонент сервера зависнет, файл(ы) перестанет обновлятся, и по этому 
+# признаку можно определить сбой в работе сервера и при надобности 
+# перезапустить. Если параметр не указан или пустой, мониторинг производится 
+# не будет. Параметр не является обязательным, по умолчанию пустой.
+# MonitorDir=/var/stargazer/monitor
+
+
+################################################################################
+# Store module
+# Настройки плагина работающего с БД сервера
+
+# Второй параметр - это имя модуля без mod_ в начале и .so в конце
+# Т.е. полное имя модуля mod_store_files.so
+<StoreModule store_files>
+
+    # Рабочая директория сервера, тут содержатся данные о тарифах, пользователях,
+    # администраторах и т.д.
+    WorkDir = /var/stargazer
+
+
+    # Владелец, группа и права доступа на файлы статистики (stat) пользователя
+    ConfOwner = root
+    ConfGroup = root
+    ConfMode = 600
+
+
+    # Владелец, группа и права доступа на файлы конфигурации (conf) пользователя
+    StatOwner = root
+    StatGroup = root
+    StatMode = 640
+
+    # Владелец, группа и права доступа на лог-файлы (log) пользователя
+    UserLogOwner = root
+    UserLogGroup = root
+    UserLogMode = 640
+
+</StoreModule>
+
+#<StoreModule store_firebird>
+#    # Адрес сервера БД
+#    server=localhost
+#
+#    # Путь к БД на сервере или ее алиас
+#    path=/var/stg/stargazer.fdb
+#
+#    # Имя пользователя БД
+#    user=stg
+#
+#    # Пароль пользователя БД
+#    password=123456
+#</StoreModule>
+
+#<StoreModule store_mysql>
+#    # Имя пользователя БД
+#    dbuser = stg
+#
+#    # Пароль пользователя БД
+#    rootdbpass = 123456
+#
+#    # Имя БД на сервере
+#    dbname = stg
+#
+#    # Адрес сервера БД
+#    dbhost = localhost
+#</StoreModule>
+
+
+
+################################################################################
+# Прочие модули
+
+<Modules>
+
+    # Настройки плагина авторизации Always Online "mod_auth_ao.so"
+    # Второй параметр - это имя модуля без mod_ в начале и .so в конце
+    # Т.е. полное имя модуля mod_auth_ao.so
+    #<Module auth_ao>
+    #</Module>
+
+
+
+    # Настройки плагина авторизации InetAccess "mod_auth_ia.so"
+    # Второй параметр - это имя модуля без mod_ в начале и .so в конце
+    # Т.е. полное имя модуля mod_auth_ia.so
+    #<Module auth_ia>
+    #    Port = 5555
+    #    UserDelay = 15
+    #    UserTimeout = 65
+    #    FreeMb = 0
+    #</Module>
+
+
+
+    # Настройки модуля конфигурации SgConfig "mod_conf_sg.so"
+    # Второй параметр - это имя модуля без mod_ в начале и .so в конце
+    <Module conf_sg>
+
+        # Порт по которому сервер взаимодействует с конфигуратором
+        # Значения: 1...65535
+        Port = 5555
+
+    </Module>
+
+
+
+    # Модуль захвата трафика "mod_cap_ether.so"
+    # Второй параметер - это имя модуля без mod_ в начале и .so в конце
+    # Без параметров. Только имя модуля.
+    <Module cap_ipq>
+        # Модуль без параметров
+    </Module>
+
+
+
+    # Настройки модуля пингующего пользователей "mod_ping.so"
+    # Второй параметр - это имя модуля без mod_ в начале и .so в конце
+    <Module ping>
+
+        # Время, в секундах, между пингами одного и того же пользователя
+        # Значения: 10...3600
+        PingDelay = 15
+
+    </Module>
+    
+    <Module radius>
+       Password = 123456
+       ServerIP = 127.0.0.1
+       Port = 6666
+       AuthServices = Login-User
+       AcctServices = Framed-User
+    </Module>
+
+#    # Настройки модуля для удаленного выполнения скриптов OnConnect и
+#    # OnDisconnect "mod_remote_script.so"
+#    # Второй параметр - это имя модуля без mod_ в начале и .so в конце
+#    <Module remote_script>
+#
+#        # Время, в секундах, между посылками подтверждений, того, что пользователь
+#        # всё еще онлайн
+#        # Значения: 10...600
+#        SendPeriod = 15
+#
+#        # Соответствие подсетей, в которой находится пользователь и
+#        # соответствующего роутера. Первая часть строки - подсеть, заданная
+#        # как IP-адрес и маска, через пробел - IP-адрес роутера на котором
+#        # должны выполняться скрипты
+#        # Например эта запись "192.168.1.0/24 192.168.1.1" означает, что для
+#        # всех пользователей из подсети 192.168.1.0/24, скрипты будут
+#        # выполняться на роутере с адресом 192.168.1.1
+#        # Subnet0...Subnet100
+#        Subnet0 = 192.168.1.0/24 192.168.1.7
+#        Subnet1 = 192.168.2.0/24 192.168.2.5
+#        Subnet2 = 192.168.3.0/24 192.168.2.5
+#        Subnet3 = 192.168.4.0/24 192.168.2.5
+#
+#        # Пароль для шифрования пакетов между stg-сервером и сервером,
+#        # выполняющим скрипты
+#        Password = 123456
+#
+#        # Этот параметр определяет какие параметры пользователя передаются
+#        # на удаленный сервер
+#        # Cash, FreeMb, Passive, Disabled, AlwaysOnline, TariffName, NextTariff, Address,
+#        # Note, Group, Email, RealName, Credit, EnabledDirs, Userdata0...Userdata9
+#        UserParams=Cash Tariff EnabledDirs
+#
+#        # Порт по которому сервер отсылает сообщения на роутер
+#        # Значения: 1...65535
+#        Port = 9999
+#
+#    </Module>
+
+</Modules>
+################################################################################
+
diff --git a/projects/stargazer/services_impl.cpp b/projects/stargazer/services_impl.cpp
new file mode 100644 (file)
index 0000000..36640c8
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#include "services_impl.h"
+
+#include "stg/admin.h"
+#include "stg/admin_conf.h"
+#include "stg/store.h"
+#include "stg/common.h"
+
+#include <algorithm>
+#include <cassert>
+
+using STG::ServicesImpl;
+
+//-----------------------------------------------------------------------------
+ServicesImpl::ServicesImpl(Store * st)
+    : store(st),
+      WriteServLog(Logger::get()),
+      searchDescriptors(),
+      handle(0)
+{
+Read();
+}
+//-----------------------------------------------------------------------------
+int ServicesImpl::Add(const ServiceConf & service, const Admin * admin)
+{
+std::lock_guard<std::mutex> lock(mutex);
+const auto& priv = admin->priv();
+
+if (!priv.serviceChg)
+    {
+    std::string s = admin->logStr() + " Add service \'" + service.name + "\'. Access denied.";
+    strError = "Access denied.";
+    WriteServLog(s.c_str());
+    return -1;
+    }
+
+iterator si(std::find(data.begin(), data.end(), service));
+
+if (si != data.end())
+    {
+    strError = "Service \'" + service.name + "\' cannot not be added. Service already exist.";
+    WriteServLog("%s %s", admin->logStr().c_str(), strError.c_str());
+
+    return -1;
+    }
+
+data.push_back(service);
+
+if (store->AddService(service.name) == 0)
+    {
+    WriteServLog("%s Service \'%s\' added.",
+                 admin->logStr().c_str(), service.name.c_str());
+    return 0;
+    }
+
+strError = "Service \'" + service.name + "\' was not added. Error: " + store->GetStrError();
+WriteServLog("%s %s", admin->logStr().c_str(), strError.c_str());
+
+return -1;
+}
+//-----------------------------------------------------------------------------
+int ServicesImpl::Del(const std::string & name, const Admin * admin)
+{
+std::lock_guard<std::mutex> lock(mutex);
+const auto& priv = admin->priv();
+
+if (!priv.serviceChg)
+    {
+    std::string s = admin->logStr() + " Delete service \'" + name + "\'. Access denied.";
+    strError = "Access denied.";
+    WriteServLog(s.c_str());
+    return -1;
+    }
+
+iterator si(std::find(data.begin(), data.end(), ServiceConf(name)));
+
+if (si == data.end())
+    {
+    strError = "Service \'" + name + "\' cannot be deleted. Service does not exist.";
+    WriteServLog("%s %s", admin->logStr().c_str(), strError.c_str());
+    return -1;
+    }
+
+std::map<int, const_iterator>::iterator csi;
+csi = searchDescriptors.begin();
+while (csi != searchDescriptors.end())
+    {
+    if (csi->second == si)
+        (csi->second)++;
+    ++csi;
+    }
+
+data.erase(si);
+if (store->DelService(name) < 0)
+    {
+    strError = "Service \'" + name + "\' was not deleted. Error: " + store->GetStrError();
+    WriteServLog("%s %s", admin->logStr().c_str(), strError.c_str());
+
+    return -1;
+    }
+
+WriteServLog("%s Service \'%s\' deleted.", admin->logStr().c_str(), name.c_str());
+return 0;
+}
+//-----------------------------------------------------------------------------
+int ServicesImpl::Change(const ServiceConf & service, const Admin * admin)
+{
+std::lock_guard<std::mutex> lock(mutex);
+const auto& priv = admin->priv();
+
+if (!priv.serviceChg)
+    {
+    std::string s = admin->logStr() + " Change service \'" + service.name + "\'. Access denied.";
+    strError = "Access denied.";
+    WriteServLog(s.c_str());
+    return -1;
+    }
+
+iterator si(std::find(data.begin(), data.end(), service));
+
+if (si == data.end())
+    {
+    strError = "Service \'" + service.name + "\' cannot be changed " + ". Service does not exist.";
+    WriteServLog("%s %s", admin->logStr().c_str(), strError.c_str());
+    return -1;
+    }
+
+printfd(__FILE__, "Old cost = %f, old pay day = %u\n", si->cost, static_cast<unsigned>(si->payDay));
+*si = service;
+printfd(__FILE__, "New cost = %f, New pay day = %u\n", si->cost, static_cast<unsigned>(si->payDay));
+if (store->SaveService(service))
+    {
+    WriteServLog("Cannot write service %s.", service.name.c_str());
+    WriteServLog("%s", store->GetStrError().c_str());
+    return -1;
+    }
+
+WriteServLog("%s Service \'%s\' changed.",
+             admin->logStr().c_str(), service.name.c_str());
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+bool ServicesImpl::Read()
+{
+std::lock_guard<std::mutex> lock(mutex);
+std::vector<std::string> servicesList;
+if (store->GetServicesList(&servicesList) < 0)
+    {
+    WriteServLog(store->GetStrError().c_str());
+    return true;
+    }
+
+for (size_t i = 0; i < servicesList.size(); i++)
+    {
+    ServiceConf service;
+
+    if (store->RestoreService(&service, servicesList[i]))
+        {
+        WriteServLog(store->GetStrError().c_str());
+        return true;
+        }
+
+    data.push_back(service);
+    }
+return false;
+}
+//-----------------------------------------------------------------------------
+bool ServicesImpl::Find(const std::string & name, ServiceConf * service) const
+{
+assert(service != NULL && "Pointer to service is not null");
+
+std::lock_guard<std::mutex> lock(mutex);
+if (data.empty())
+    return true;
+
+const_iterator si(std::find(data.begin(), data.end(), ServiceConf(name)));
+
+if (si != data.end())
+    {
+    *service = *si;
+    return false;
+    }
+
+return true;
+}
+//-----------------------------------------------------------------------------
+bool ServicesImpl::Find(const std::string & name, ServiceConfOpt * service) const
+{
+assert(service != NULL && "Pointer to service is not null");
+
+std::lock_guard<std::mutex> lock(mutex);
+if (data.empty())
+    return true;
+
+const_iterator si(std::find(data.begin(), data.end(), ServiceConf(name)));
+
+if (si != data.end())
+    {
+    *service = *si;
+    return false;
+    }
+
+return true;
+}
+//-----------------------------------------------------------------------------
+bool ServicesImpl::Exists(const std::string & name) const
+{
+std::lock_guard<std::mutex> lock(mutex);
+if (data.empty())
+    {
+    printfd(__FILE__, "No services in the system!\n");
+    return true;
+    }
+
+const_iterator si(std::find(data.begin(), data.end(), ServiceConf(name)));
+
+if (si != data.end())
+    return true;
+
+return false;
+}
+//-----------------------------------------------------------------------------
+int ServicesImpl::OpenSearch() const
+{
+std::lock_guard<std::mutex> lock(mutex);
+handle++;
+searchDescriptors[handle] = data.begin();
+return handle;
+}
+//-----------------------------------------------------------------------------
+int ServicesImpl::SearchNext(int h, ServiceConf * service) const
+{
+std::lock_guard<std::mutex> lock(mutex);
+if (searchDescriptors.find(h) == searchDescriptors.end())
+    {
+    WriteServLog("SERVICES. Incorrect search handle.");
+    return -1;
+    }
+
+if (searchDescriptors[h] == data.end())
+    return -1;
+
+*service = *searchDescriptors[h]++;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int ServicesImpl::CloseSearch(int h) const
+{
+std::lock_guard<std::mutex> lock(mutex);
+if (searchDescriptors.find(h) != searchDescriptors.end())
+    {
+    searchDescriptors.erase(searchDescriptors.find(h));
+    return 0;
+    }
+
+WriteServLog("SERVICES. Incorrect search handle.");
+return -1;
+}
+//-----------------------------------------------------------------------------
diff --git a/projects/stargazer/services_impl.h b/projects/stargazer/services_impl.h
new file mode 100644 (file)
index 0000000..8a66f63
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#pragma once
+
+#include "stg/services.h"
+#include "stg/service_conf.h"
+#include "stg/locker.h"
+#include "stg/noncopyable.h"
+#include "stg/logger.h"
+
+#include <vector>
+#include <map>
+#include <string>
+#include <mutex>
+
+namespace STG
+{
+
+struct Admin;
+struct Store;
+
+class ServicesImpl : public Services {
+    public:
+        explicit ServicesImpl(Store* st);
+
+        int Add(const ServiceConf& service, const Admin* admin) override;
+        int Del(const std::string& name, const Admin* admin) override;
+        int Change(const ServiceConf& service, const Admin* admin) override;
+        bool Find(const std::string& name, ServiceConf* service) const override;
+        bool Find(const std::string& name, ServiceConfOpt* service) const override;
+        bool Exists(const std::string& name) const override;
+        const std::string& GetStrError() const override { return strError; }
+
+        size_t Count() const override { return data.size(); }
+
+        int OpenSearch() const override;
+        int SearchNext(int, ServiceConf* service) const override;
+        int CloseSearch(int) const override;
+
+    private:
+        typedef std::vector<ServiceConf>::iterator       iterator;
+        typedef std::vector<ServiceConf>::const_iterator const_iterator;
+
+        bool Read();
+
+        std::vector<ServiceConf> data;
+        Store*                 store;
+        Logger&            WriteServLog;
+        mutable std::map<int, const_iterator> searchDescriptors;
+        mutable unsigned int    handle;
+        mutable std::mutex mutex;
+        std::string             strError;
+};
+
+}
diff --git a/projects/stargazer/settings_impl.cpp b/projects/stargazer/settings_impl.cpp
new file mode 100644 (file)
index 0000000..656198f
--- /dev/null
@@ -0,0 +1,452 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+#include "settings_impl.h"
+
+#include "stg/logger.h"
+#include "stg/dotconfpp.h"
+#include "stg/common.h"
+#include "stg/const.h"
+
+#include <stdexcept>
+#include <cstring>
+#include <cerrno>
+
+using STG::SettingsImpl;
+using STG::ParamValue;
+
+namespace
+{
+
+struct Error : public std::runtime_error
+{
+    Error(const std::string& message) : runtime_error(message) {}
+};
+
+std::vector<std::string> toValues(const DOTCONFDocumentNode& node)
+{
+    std::vector<std::string> values;
+
+    size_t i = 0;
+    const char* value = NULL;
+    while ((value = node.getValue(i++)) != NULL)
+        values.push_back(value);
+
+    return values;
+}
+
+std::vector<ParamValue> toPVS(const DOTCONFDocumentNode& node)
+{
+    std::vector<ParamValue> pvs;
+
+    const DOTCONFDocumentNode* child = node.getChildNode();
+    while (child != NULL)
+        {
+        if (child->getName() == NULL)
+            continue;
+
+        if (child->getChildNode() == NULL)
+            pvs.push_back(ParamValue(child->getName(), toValues(*child)));
+        else
+            pvs.push_back(ParamValue(child->getName(), toValues(*child), toPVS(*child)));
+
+        child = child->getNextNode();
+        }
+
+    return pvs;
+}
+
+unsigned toPeriod(const char* value)
+{
+    if (value == NULL)
+        throw Error("No detail stat period value.");
+
+    std::string period(value);
+    if (period == "1")
+        return STG::dsPeriod_1;
+    else if (period == "1/2")
+        return STG::dsPeriod_1_2;
+    else if (period == "1/4")
+        return STG::dsPeriod_1_4;
+    else if (period == "1/6")
+        return STG::dsPeriod_1_6;
+
+    throw Error("Invalid detail stat period value: '" + period + "'. Should be one of '1', '1/2', '1/4' or '1/6'.");
+}
+
+void errorCallback(void* /*data*/, const char* buf)
+{
+    printfd(__FILE__, "SettingsImpl::errorCallback() - %s\n", buf);
+    STG::Logger::get()("%s", buf);
+}
+
+}
+
+//-----------------------------------------------------------------------------
+SettingsImpl::SettingsImpl(const std::string & cd)
+    : modulesPath("/usr/lib/stg"),
+      dirName(DIR_NUM),
+      confDir(cd.empty() ? "/etc/stargazer" : cd),
+      scriptsDir(confDir),
+      rules(confDir + "/rules"),
+      logFile("/var/log/stargazer.log"),
+      pidFile("/var/run/stargazer.pid"),
+      monitorDir("/var/stargazer/monitoring"),
+      monitoring(false),
+      detailStatWritePeriod(dsPeriod_1_6),
+      statWritePeriod(10),
+      stgExecMsgKey(5555),
+      executersNum(1),
+      fullFee(false),
+      dayFee(0),
+      dayResetTraff(0),
+      spreadFee(false),
+      freeMbAllowInet(false),
+      dayFeeIsLastDay(false),
+      stopOnError(true),
+      writeFreeMbTraffCost(false),
+      showFeeInCash(true),
+      messageTimeout(0),
+      feeChargeType(0),
+      reconnectOnTariffChange(false),
+      disableSessionLog(false)
+{
+    filterParamsLog.push_back("*");
+}
+//-----------------------------------------------------------------------------
+int SettingsImpl::ReadSettings()
+{
+const char * requiredOptions[] = {
+    "ModulesPath",
+    "Modules",
+    "StoreModule",
+    "Rules",
+    "LogFile",
+    "DetailStatWritePeriod",
+    "DayFee",
+    "DayResetTraff",
+    "SpreadFee",
+    "FreeMbAllowInet",
+    "DayFeeIsLastDay",
+    "WriteFreeMbTraffCost",
+    NULL
+    };
+int storeModulesCount = 0;
+modulesSettings.clear();
+
+DOTCONFDocument conf(DOTCONFDocument::CASEINSENSITIVE);
+conf.setErrorCallback(errorCallback, nullptr);
+conf.setRequiredOptionNames(requiredOptions);
+std::string confFile = confDir + "/stargazer.conf";
+
+if(conf.setContent(confFile.c_str()) != 0)
+    {
+    strError = "Cannot read file " + confFile;
+    return -1;
+    }
+
+auto node = conf.getFirstNode();
+
+while (node)
+    {
+    if (strcasecmp(node->getName(), "ScriptDir") == 0)
+        {
+        scriptsDir = node->getValue(0);
+        }
+
+    if (strcasecmp(node->getName(), "LogFile") == 0)
+        {
+        logFile = node->getValue(0);
+        }
+
+    if (strcasecmp(node->getName(), "PIDFile") == 0)
+        {
+        pidFile = node->getValue(0);
+        }
+
+    if (strcasecmp(node->getName(), "ModulesPath") == 0)
+        {
+        modulesPath = node->getValue(0);
+        }
+
+    if (strcasecmp(node->getName(), "Rules") == 0)
+        {
+        rules = node->getValue(0);
+        }
+
+    if (strcasecmp(node->getName(), "DetailStatWritePeriod") == 0)
+        {
+        try
+        {
+            detailStatWritePeriod = toPeriod(node->getValue(0));
+        }
+        catch (const Error& error)
+        {
+            strError = error.what();
+            return -1;
+        }
+        }
+
+    if (strcasecmp(node->getName(), "StatWritePeriod") == 0)
+        {
+        if (ParseUnsignedInRange(node->getValue(0), 1, 1440, &statWritePeriod) != 0)
+            {
+            strError = "Incorrect StatWritePeriod value: \'" + std::string(node->getValue(0)) + "\'";
+            return -1;
+            }
+        }
+
+    if (strcasecmp(node->getName(), "ExecMsgKey") == 0)
+        {
+        if (ParseInt(node->getValue(0), &stgExecMsgKey) != 0)
+            {
+            strError = "Incorrect ExecMsgKey value: \'" + std::string(node->getValue(0)) + "\'";
+            return -1;
+            }
+        }
+
+    if (strcasecmp(node->getName(), "ExecutersNum") == 0)
+        {
+        if (ParseUnsignedInRange(node->getValue(0), 1, 1024, &executersNum) != 0)
+            {
+            strError = "Incorrect ExecutersNum value: \'" + std::string(node->getValue(0)) + "\'";
+            return -1;
+            }
+        }
+
+    if (strcasecmp(node->getName(), "DayFee") == 0)
+        {
+        if (ParseUnsignedInRange(node->getValue(0), 0, 31, &dayFee) != 0)
+            {
+            strError = "Incorrect DayFee value: \'" + std::string(node->getValue(0)) + "\'";
+            return -1;
+            }
+        }
+
+    if (strcasecmp(node->getName(), "FullFee") == 0)
+        {
+        if (ParseYesNo(node->getValue(0), &fullFee) != 0)
+            {
+            strError = "Incorrect FullFee value: \'" + std::string(node->getValue(0)) + "\'";
+            return -1;
+            }
+        }
+
+    if (strcasecmp(node->getName(), "DayResetTraff") == 0)
+        {
+        if (ParseUnsignedInRange(node->getValue(0), 0, 31, &dayResetTraff) != 0)
+            {
+            strError = "Incorrect DayResetTraff value: \'" + std::string(node->getValue(0)) + "\'";
+            return -1;
+            }
+        }
+
+    if (strcasecmp(node->getName(), "SpreadFee") == 0)
+        {
+        if (ParseYesNo(node->getValue(0), &spreadFee) != 0)
+            {
+            strError = "Incorrect SpreadFee value: \'" + std::string(node->getValue(0)) + "\'";
+            return -1;
+            }
+        }
+
+    if (strcasecmp(node->getName(), "FreeMbAllowInet") == 0)
+        {
+        if (ParseYesNo(node->getValue(0), &freeMbAllowInet) != 0)
+            {
+            strError = "Incorrect FreeMbAllowInet value: \'" + std::string(node->getValue(0)) + "\'";
+            return -1;
+            }
+        }
+
+    if (strcasecmp(node->getName(), "DayFeeIsLastDay") == 0)
+        {
+        if (ParseYesNo(node->getValue(0), &dayFeeIsLastDay) != 0)
+            {
+            strError = "Incorrect DayFeeIsLastDay value: \'" + std::string(node->getValue(0)) + "\'";
+            return -1;
+            }
+        }
+
+    if (strcasecmp(node->getName(), "StopOnError") == 0)
+        {
+        if (ParseYesNo(node->getValue(0), &stopOnError) != 0)
+            {
+            strError = "Incorrect StopOnError value: \'" + std::string(node->getValue(0)) + "\'";
+            return -1;
+            }
+        }
+
+    if (strcasecmp(node->getName(), "WriteFreeMbTraffCost") == 0)
+        {
+        if (ParseYesNo(node->getValue(0), &writeFreeMbTraffCost) != 0)
+            {
+            strError = "Incorrect WriteFreeMbTraffCost value: \'" + std::string(node->getValue(0)) + "\'";
+            return -1;
+            }
+        }
+
+    if (strcasecmp(node->getName(), "ShowFeeInCash") == 0)
+        {
+        if (ParseYesNo(node->getValue(0), &showFeeInCash) != 0)
+            {
+            strError = "Incorrect ShowFeeInCash value: \'" + std::string(node->getValue(0)) + "\'";
+            return -1;
+            }
+        }
+
+    if (strcasecmp(node->getName(), "MonitorDir") == 0)
+        {
+        monitorDir = node->getValue(0);
+        struct stat stat;
+        monitoring = false;
+
+        if (!lstat(monitorDir.c_str(), &stat) && S_ISDIR(stat.st_mode))
+            {
+            monitoring = true;
+            }
+        }
+
+    if (strcasecmp(node->getName(), "MessageTimeout") == 0)
+        {
+        if (ParseUnsigned(node->getValue(0), &messageTimeout) != 0)
+            {
+            strError = "Incorrect MessageTimeout value: \'" + std::string(node->getValue(0)) + "\'";
+            return -1;
+            }
+        }
+
+    if (strcasecmp(node->getName(), "FeeChargeType") == 0)
+        {
+        if (ParseUnsignedInRange(node->getValue(0), 0, 3, &feeChargeType) != 0)
+            {
+            strError = "Incorrect FeeChargeType value: \'" + std::string(node->getValue(0)) + "\'";
+            return -1;
+            }
+        }
+
+    if (strcasecmp(node->getName(), "ReconnectOnTariffChange") == 0)
+        {
+        if (ParseYesNo(node->getValue(0), &reconnectOnTariffChange) != 0)
+            {
+            strError = "Incorrect ReconnectOnTariffChange value: \'" + std::string(node->getValue(0)) + "\'";
+            return -1;
+            }
+        }
+
+    if (strcasecmp(node->getName(), "DisableSessionLog") == 0)
+        {
+        if (ParseYesNo(node->getValue(0), &disableSessionLog) != 0)
+            {
+            strError = "Incorrect DisableSessionLog value: \'" + std::string(node->getValue(0)) + "\'";
+            return -1;
+            }
+        }
+
+    if (strcasecmp(node->getName(), "FilterParamsLog") == 0)
+        {
+        filterParamsLog.clear();
+        for (int i = 0; node->getValue(i) != NULL; ++i)
+            filterParamsLog.push_back(node->getValue(i));
+        }
+
+    if (strcasecmp(node->getName(), "DirNames") == 0)
+        {
+        const DOTCONFDocumentNode * child = node->getChildNode();
+        if (child)
+            {
+            const DOTCONFDocumentNode * dirNameNode;
+            dirName.reserve(DIR_NUM);
+            for (int i = 0; i < DIR_NUM; i++)
+                {
+                char strDirName[12];
+                sprintf(strDirName, "DirName%d", i);
+                dirNameNode = conf.findNode(strDirName, node);
+                if (dirNameNode && dirNameNode->getValue(0))
+                    {
+                    dirName[i] = dirNameNode->getValue(0);
+                    }
+                }
+            }
+        }
+
+    if (strcasecmp(node->getName(), "StoreModule") == 0)
+        {
+        if (node->getValue(1))
+            {
+            strError = "Unexpected \'" + std::string(node->getValue(1)) + "\'.";
+            return -1;
+            }
+
+        if (storeModulesCount)
+            {
+            strError = "Should be only one StoreModule.";
+            return -1;
+            }
+        storeModulesCount++;
+
+        if (node->getValue(0) == NULL)
+            {
+            strError = "No module name in the StoreModule section.";
+            return -1;
+            }
+        storeModuleSettings.moduleName = node->getValue(0);
+        storeModuleSettings.moduleParams = toPVS(*node);
+        }
+
+    if (strcasecmp(node->getName(), "Modules") == 0)
+        {
+        if (node->getValue(0))
+            {
+            strError = "Unexpected \'" + std::string(node->getValue(0)) + "\'.";
+            return -1;
+            }
+        const DOTCONFDocumentNode * child = node->getChildNode();
+        while (child)
+            {
+            if (strcasecmp(child->getName(), "Module") != 0)
+                {
+                child = child->getNextNode();
+                continue;
+                }
+
+            if (child->getValue(0) == NULL)
+                {
+                strError = "No module name in the Module section.";
+                return -1;
+                }
+
+            modulesSettings.push_back(ModuleSettings(child->getValue(0), toPVS(*child)));
+
+            child = child->getNextNode();
+            }
+        }
+
+    if (strcasecmp(node->getName(), "ScriptParams") == 0)
+        {
+        for (int i = 0; node->getValue(i) != NULL; ++i)
+            scriptParams.push_back(node->getValue(i));
+        }
+    node = node->getNextNode();
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
diff --git a/projects/stargazer/settings_impl.h b/projects/stargazer/settings_impl.h
new file mode 100644 (file)
index 0000000..4b73dcd
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+#pragma once
+
+#include "stg/settings.h"
+#include "stg/common.h"
+#include "stg/module_settings.h"
+
+#include <string>
+#include <vector>
+
+class DOTCONFDocumentNode;
+
+namespace STG
+{
+
+//-----------------------------------------------------------------------------
+enum DETAIL_STAT_PERIOD {
+    dsPeriod_1,
+    dsPeriod_1_2,
+    dsPeriod_1_4,
+    dsPeriod_1_6
+};
+//-----------------------------------------------------------------------------
+class SettingsImpl : public Settings {
+    public:
+        explicit SettingsImpl(const std::string &);
+
+        SettingsImpl(const SettingsImpl&) = default;
+        SettingsImpl& operator=(const SettingsImpl&) = default;
+        SettingsImpl(SettingsImpl&&) = default;
+        SettingsImpl& operator=(SettingsImpl&&) = default;
+
+        int Reload() { return ReadSettings(); }
+        int ReadSettings();
+
+        std::string GetStrError() const { return strError; }
+
+        int                 GetExecMsgKey() const { return stgExecMsgKey; }
+        unsigned            GetExecutersNum() const { return executersNum; }
+        const std::string & GetDirName(size_t num) const { return dirName[num]; }
+        const std::string & GetConfDir() const { return confDir; }
+        const std::string & GetScriptsDir() const { return scriptsDir; }
+        const std::string & GetRulesFileName() const { return rules; }
+        const std::string & GetLogFileName() const { return logFile; }
+        const std::string & GetPIDFileName() const { return pidFile; }
+        unsigned            GetDetailStatWritePeriod() const
+            { return detailStatWritePeriod; }
+        unsigned            GetStatWritePeriod() const { return statWritePeriod * 60; }
+        unsigned            GetDayFee() const { return dayFee; }
+        bool                GetFullFee() const { return fullFee; }
+        unsigned            GetDayResetTraff() const { return dayResetTraff; }
+        bool                GetSpreadFee() const { return spreadFee; }
+        bool                GetFreeMbAllowInet() const { return freeMbAllowInet; }
+        bool                GetDayFeeIsLastDay() const { return dayFeeIsLastDay; }
+        bool                GetStopOnError() const { return stopOnError; }
+        bool                GetWriteFreeMbTraffCost() const
+            { return writeFreeMbTraffCost; }
+        bool                GetShowFeeInCash() const { return showFeeInCash; }
+        const std::string & GetMonitorDir() const { return monitorDir; }
+        bool                GetMonitoring() const { return monitoring; }
+        unsigned            GetMessageTimeout() const { return messageTimeout * 3600 * 24; }
+        unsigned            GetFeeChargeType() const { return feeChargeType; }
+        bool                GetReconnectOnTariffChange() const { return reconnectOnTariffChange; }
+        bool                GetDisableSessionLog() const { return disableSessionLog; }
+        const std::vector<std::string> & GetFilterParamsLog() const { return filterParamsLog; }
+
+        const std::string & GetModulesPath() const { return modulesPath; }
+        const ModuleSettings & GetStoreModuleSettings() const
+        { return storeModuleSettings; }
+        const std::vector<ModuleSettings> & GetModulesSettings() const
+        { return modulesSettings; }
+        const std::vector<std::string> & GetScriptParams() const { return scriptParams; }
+
+    private:
+        std::string strError;
+
+        //////////settings
+        std::string modulesPath;
+        std::vector<std::string> dirName;
+        std::string confDir;
+        std::string scriptsDir;
+        std::string rules;
+        std::string logFile;
+        std::string pidFile;
+        std::string monitorDir;
+        std::vector<std::string> scriptParams;
+        bool        monitoring;
+        unsigned    detailStatWritePeriod;
+        unsigned    statWritePeriod;
+        int         stgExecMsgKey;
+        unsigned    executersNum;
+        bool        fullFee;
+        unsigned    dayFee;
+        unsigned    dayResetTraff;
+        bool        spreadFee;
+        bool        freeMbAllowInet;
+        bool        dayFeeIsLastDay;
+        bool        stopOnError;
+        bool        writeFreeMbTraffCost;
+        bool        showFeeInCash;
+        unsigned    messageTimeout;
+        unsigned    feeChargeType;
+        bool        reconnectOnTariffChange;
+        bool        disableSessionLog;
+        std::vector<std::string> filterParamsLog;
+
+        std::vector<ModuleSettings> modulesSettings;
+        ModuleSettings storeModuleSettings;
+};
+//-----------------------------------------------------------------------------
+
+}
diff --git a/projects/stargazer/stg_timer.cpp b/projects/stargazer/stg_timer.cpp
new file mode 100644 (file)
index 0000000..572b069
--- /dev/null
@@ -0,0 +1,146 @@
+#include "stg_timer.h"
+
+#include "stg/common.h"
+
+#include <ctime>
+#include <cstring>
+#include <csignal>
+
+#include <pthread.h>
+
+void * StgTimer(void *);
+
+static int nonstop;
+static pthread_t thrStgTimer;
+static bool isTimerRunning = false;
+volatile time_t stgTime;
+
+#ifdef STG_TIMER_DEBUG
+const int TIME_SPEED = 1;
+/*
+ 1  - 1x  speed
+ 2  - 2x  speed
+ 5  - 5x  speed
+ 10 - 10x speed
+ */
+
+const int START_TIME = 2;
+/*
+ 0 - as is
+ 1 - start before new day (3 min before)   29.11.2005 23:57:00
+ 2 - start before new month (3 min before) 30.11.2005 23:57:00
+ */
+#endif
+
+//-----------------------------------------------------------------------------
+void * StgTimer(void *)
+{
+#ifdef STG_TIMER_DEBUG
+struct tm lt;
+memset(&lt, 0, sizeof(lt));
+
+lt.tm_year = 2016 - 1900; // 2005
+lt.tm_mon  = 7 - 1;      // Nov
+lt.tm_hour = 23;          // 23 h
+lt.tm_min = 57;           // 50 min
+lt.tm_sec = 0;            // 00 sec
+lt.tm_isdst = -1;
+
+switch (START_TIME)
+    {
+    case 0:
+        stgTime = time(NULL);
+        break;
+
+    case 1:
+        lt.tm_mday = 29;
+        stgTime = mktime(&lt);
+        break;
+
+    case 2:
+        lt.tm_mday = 31;
+        stgTime = mktime(&lt);
+        break;
+    }
+#else
+stgTime = time(NULL);
+#endif
+
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+nonstop = 1;
+isTimerRunning = true;
+while (nonstop)
+    {
+    #ifdef STG_TIMER_DEBUG
+    struct timespec ts;
+    if (TIME_SPEED == 1)
+        {
+        ts.tv_sec = 1;
+        ts.tv_nsec = 0;
+        }
+    else
+        {
+        ts.tv_sec = 0;
+        ts.tv_nsec = 1000000000 / TIME_SPEED;
+        }
+    nanosleep(&ts, NULL);
+    stgTime++;
+    #else
+    struct timespec ts = {0, 500000000};
+    nanosleep(&ts, NULL);
+    stgTime = time(NULL);
+    #endif
+    }
+isTimerRunning = false;
+
+return NULL;
+}
+//-----------------------------------------------------------------------------
+int RunStgTimer()
+{
+static int a = 0;
+isTimerRunning = false;
+
+if (a == 0)
+    if (pthread_create(&thrStgTimer, NULL, &StgTimer, NULL))
+        {
+        isTimerRunning = false;
+        return -1;
+        }
+
+a = 1;
+return 0;
+}
+//-----------------------------------------------------------------------------
+void StopStgTimer()
+{
+nonstop = 0;
+pthread_join(thrStgTimer, NULL); // Cleanup thread resources
+printfd(__FILE__, "STG_TIMER stopped\n");
+}
+//-----------------------------------------------------------------------------
+bool IsStgTimerRunning()
+{
+return isTimerRunning;
+}
+//-----------------------------------------------------------------------------
+int stgUsleep(unsigned long t)
+{
+#ifdef STG_TIMER_DEBUG
+struct timespec ts = {static_cast<time_t>((t / TIME_SPEED) / 1000000), static_cast<long>(((t / TIME_SPEED) % 1000000) * 1000)};
+return nanosleep(&ts, NULL);
+#else
+struct timespec ts = {static_cast<time_t>(t / 1000000), static_cast<long>((t % 1000000) * 1000)};
+return nanosleep(&ts, NULL);
+#endif
+}
+//-----------------------------------------------------------------------------
+void WaitTimer()
+{
+    for (int i = 0; i < 5 && !isTimerRunning; i++)
+        stgUsleep(200000);
+}
+//-----------------------------------------------------------------------------
diff --git a/projects/stargazer/stg_timer.h b/projects/stargazer/stg_timer.h
new file mode 100644 (file)
index 0000000..75553b3
--- /dev/null
@@ -0,0 +1,21 @@
+ /*
+ $Revision: 1.9 $
+ $Date: 2010/11/03 10:37:52 $
+ $Author: faust $
+ */
+
+#ifndef STG_TIMER_H
+#define STG_TIMER_H
+
+#include <ctime>
+
+extern volatile time_t stgTime;
+int RunStgTimer();
+void StopStgTimer();
+void WaitTimer();
+bool IsStgTimerRunning();
+int stgUsleep(unsigned long t);
+
+#endif //STG_TIMER_H
+
+
diff --git a/projects/stargazer/store_loader.cpp b/projects/stargazer/store_loader.cpp
new file mode 100644 (file)
index 0000000..9164685
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#include <dlfcn.h>
+
+#include "stg/common.h"
+#include "stg/store.h"
+#include "store_loader.h"
+#include "settings_impl.h"
+
+using STG::StoreLoader;
+
+StoreLoader::StoreLoader(const SettingsImpl& settings) noexcept
+    : isLoaded(false),
+      handle(NULL),
+      plugin(NULL),
+      storeSettings(settings.GetStoreModuleSettings()),
+      pluginFileName(settings.GetModulesPath() + "/mod_" + storeSettings.moduleName + ".so")
+{
+}
+
+StoreLoader::~StoreLoader()
+{
+    unload();
+}
+
+bool StoreLoader::load() noexcept
+{
+    if (isLoaded)
+    {
+        errorStr = "Store plugin '" + pluginFileName + "' was already loaded!";
+        printfd(__FILE__, "StoreLoader::load() - %s\n", errorStr.c_str());
+        return false;
+    }
+
+    if (pluginFileName.empty())
+    {
+        errorStr = "Empty store plugin filename";
+        printfd(__FILE__, "StoreLoader::load() - %s\n", errorStr.c_str());
+        return true;
+    }
+
+    handle = dlopen(pluginFileName.c_str(), RTLD_NOW);
+
+    if (!handle)
+    {
+        errorStr = "Error loading plugin '"
+            + pluginFileName + "': '" + dlerror() + "'";
+        printfd(__FILE__, "StoreLoader::Load() - %s\n", errorStr.c_str());
+        return true;
+    }
+
+    isLoaded = true;
+
+    using Getter = Store* (*)();
+    auto GetStore = reinterpret_cast<Getter>(dlsym(handle, "GetStore"));
+    if (!GetStore)
+    {
+        errorStr = std::string("GetStore() not found! ") + dlerror();
+        printfd(__FILE__, "StoreLoader::load() - %s\n", errorStr.c_str());
+        return true;
+    }
+
+    plugin = GetStore();
+
+    if (!plugin)
+    {
+        errorStr = "Plugin was not created!";
+        printfd(__FILE__, "StoreLoader::Load() - %s\n");
+        return true;
+    }
+
+    plugin->SetSettings(storeSettings);
+    if (plugin->ParseSettings())
+    {
+        errorStr = plugin->GetStrError();
+        printfd(__FILE__, "StoreLoader::Load() - Failed to parse settings. Plugin reports: '%s'\n", errorStr.c_str());
+        return true;
+    }
+
+    return false;
+}
+
+bool StoreLoader::unload() noexcept
+{
+    if (!isLoaded)
+        return true;
+
+    delete plugin;
+
+    if (dlclose(handle))
+    {
+        errorStr = "Failed to unload plugin '";
+        errorStr += pluginFileName + "': ";
+        errorStr += dlerror();
+        printfd(__FILE__, "StoreLoader::Unload() - %s\n", errorStr.c_str());
+        return true;
+    }
+
+    isLoaded = false;
+
+    return false;
+}
diff --git a/projects/stargazer/store_loader.h b/projects/stargazer/store_loader.h
new file mode 100644 (file)
index 0000000..c187b54
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
+ */
+
+#pragma once
+
+#include "stg/module_settings.h"
+
+#include <string>
+
+namespace STG
+{
+
+struct Store;
+class SettingsImpl;
+
+class StoreLoader {
+    public:
+        explicit StoreLoader(const SettingsImpl& settings) noexcept;
+        ~StoreLoader();
+
+        StoreLoader(const StoreLoader&) = delete;
+        StoreLoader& operator=(const StoreLoader&) = delete;
+
+        bool load() noexcept;
+        bool unload() noexcept;
+
+        Store& get() noexcept { return *plugin; }
+
+        const std::string& GetStrError() const noexcept { return errorStr; }
+
+    private:
+        bool isLoaded;
+        void* handle;
+        Store* plugin;
+        std::string errorStr;
+        ModuleSettings storeSettings;
+        std::string pluginFileName;
+};
+
+}
diff --git a/projects/stargazer/tariff_impl.cpp b/projects/stargazer/tariff_impl.cpp
new file mode 100644 (file)
index 0000000..7d85462
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Date: 07.11.2007
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+/*
+ $Revision: 1.11 $
+ $Date: 2010/10/07 16:57:21 $
+ $Author: faust $
+ */
+
+#include "tariff_impl.h"
+
+#include "stg_timer.h"
+#include "stg/common.h"
+
+#include <ctime>
+#include <algorithm> // std::max
+
+using STG::TariffImpl;
+
+//-----------------------------------------------------------------------------
+TariffImpl & TariffImpl::operator=(const TariffData & td)
+{
+tariffData = td;
+return *this;
+}
+//-----------------------------------------------------------------------------
+double TariffImpl::GetPriceWithTraffType(uint64_t up,
+                                     uint64_t down,
+                                     int dir,
+                                     time_t t) const
+{
+return GetPriceWithoutFreeMb(dir, GetTraffByType(up, down) / (1024 * 1024), t);
+}
+//-----------------------------------------------------------------------------
+int64_t TariffImpl::GetTraffByType(uint64_t up, uint64_t down) const
+{
+switch (tariffData.tariffConf.traffType)
+    {
+    case TRAFF_UP:
+        return up;
+
+    case TRAFF_DOWN:
+        return down;
+
+    case TRAFF_MAX:
+        return std::max(up, down);
+
+    default:  //TRAFF_UP_DOWN:
+        return up + down;
+    }
+}
+//-----------------------------------------------------------------------------
+int TariffImpl::GetThreshold(int dir) const
+{
+    return tariffData.dirPrice[dir].threshold;
+}
+//-----------------------------------------------------------------------------
+void TariffImpl::Print() const
+{
+printfd(__FILE__, "Traiff name: %s\n", tariffData.tariffConf.name.c_str());
+}
+//-----------------------------------------------------------------------------
+int TariffImpl::Interval(int dir, time_t t) const
+{
+// Start of the day (and end of the night) in sec from 00:00:00
+int s1 = tariffData.dirPrice[dir].hDay * 3600 +
+         tariffData.dirPrice[dir].mDay * 60;
+// Start of the night (and end of the day) in sec from 00:00:00
+int s2 = tariffData.dirPrice[dir].hNight * 3600 +
+         tariffData.dirPrice[dir].mNight * 60;
+
+struct tm * lt;
+
+lt = localtime(&t);
+
+// Position of time t in sec from 00:00:00
+// Ignoring seconds due to minute precision
+int lts = lt->tm_hour * 3600 + lt->tm_min * 60;
+
+if (s1 < s2)
+    {
+    // Normal situation (00:00:00 is a night)
+    if (lts > s1 && lts < s2)
+        return TARIFF_DAY;
+    else
+        return TARIFF_NIGHT;
+    }
+else
+    {
+    // Not so common but possible situation (00:00:00 is a day)
+    if (lts < s1 && lts > s2)
+        return TARIFF_NIGHT;
+    else
+        return TARIFF_DAY;
+    }
+}
+//-----------------------------------------------------------------------------
+double TariffImpl::GetPriceWithoutFreeMb(int dir, int64_t mb, time_t t) const
+{
+int interval = Interval(dir, t);
+
+/*
+ * 0011 - NB
+ * *01* - NA
+ * 0**1 - DB
+ * **** - DA
+ */
+
+bool nd = tariffData.dirPrice[dir].noDiscount;
+bool sp = tariffData.dirPrice[dir].singlePrice;
+bool th = (interval == TARIFF_NIGHT);
+bool tr = (mb > tariffData.dirPrice[dir].threshold);
+
+if (!nd && !sp && th && tr)
+    return tariffData.dirPrice[dir].priceNightB;
+else if (!nd && tr)
+    return tariffData.dirPrice[dir].priceDayB;
+else if (!sp && th)
+    return tariffData.dirPrice[dir].priceNightA;
+else
+    return tariffData.dirPrice[dir].priceDayA;
+}
+//-----------------------------------------------------------------------------
+std::string TariffImpl::TariffChangeIsAllowed(const Tariff & to, time_t currentTime) const
+{
+time_t timeout = GetChangePolicyTimeout();
+if (currentTime > timeout && timeout != 0)
+    return "";
+switch (GetChangePolicy())
+    {
+    case Tariff::ALLOW:
+        return "";
+    case Tariff::TO_CHEAP:
+        if (to.GetFee() < GetFee())
+            return "";
+        else
+            return "New tariff '" + to.GetName() + "' is more expensive than current tariff '" + GetName() + "'. The policy is '" + Tariff::toString(GetChangePolicy()) + "'.";
+    case Tariff::TO_EXPENSIVE:
+        if (to.GetFee() >= GetFee())
+            return "";
+        else
+            return "New tariff '" + to.GetName() + "' is more cheap than current tariff '" + GetName() + "'. The policy is '" + Tariff::toString(GetChangePolicy()) + "'.";
+    case Tariff::DENY:
+        return "Current tariff '" + GetName() + "', new tariff '" + to.GetName() + "'. The policy is '" + Tariff::toString(GetChangePolicy()) + "'.";
+    }
+return "";
+}
+//-----------------------------------------------------------------------------
diff --git a/projects/stargazer/tariff_impl.h b/projects/stargazer/tariff_impl.h
new file mode 100644 (file)
index 0000000..a45df06
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Date: 07.11.2007
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+#pragma once
+
+#include "stg/tariff.h"
+#include "stg/tariff_conf.h"
+
+#include <string>
+
+#include <ctime>
+#include <cstdint>
+
+#define TARIFF_DAY     0
+#define TARIFF_NIGHT   1
+
+namespace STG
+{
+
+class TariffImpl : public Tariff {
+    public:
+        explicit TariffImpl(const std::string & name)
+            : tariffData(name)
+        {}
+        explicit TariffImpl(const TariffData & td)
+            : tariffData(td)
+        {}
+
+        TariffImpl(const TariffImpl&) = default;
+        TariffImpl& operator=(const TariffImpl&) = default;
+        TariffImpl(TariffImpl&&) = default;
+        TariffImpl& operator=(TariffImpl&&) = default;
+
+        double  GetPriceWithTraffType(uint64_t up,
+                                      uint64_t down,
+                                      int dir,
+                                      time_t t) const;
+        double  GetFreeMb() const { return tariffData.tariffConf.free; }
+        double  GetPassiveCost() const { return tariffData.tariffConf.passiveCost; }
+        double  GetFee() const { return tariffData.tariffConf.fee; }
+        double  GetFree() const { return tariffData.tariffConf.free; }
+        Period  GetPeriod() const { return tariffData.tariffConf.period; }
+        ChangePolicy GetChangePolicy() const { return tariffData.tariffConf.changePolicy; }
+        time_t GetChangePolicyTimeout() const { return tariffData.tariffConf.changePolicyTimeout; }
+
+        void    Print() const;
+
+        const   std::string & GetName() const { return tariffData.tariffConf.name; }
+        void    SetName(const std::string & name) { tariffData.tariffConf.name = name; }
+
+        int     GetTraffType() const { return tariffData.tariffConf.traffType; }
+        int64_t GetTraffByType(uint64_t up, uint64_t down) const;
+        int     GetThreshold(int dir) const;
+        const TariffData & GetTariffData() const { return tariffData; }
+
+        TariffImpl & operator=(const TariffData & td);
+        bool     operator==(const TariffImpl & rhs) const { return GetName() == rhs.GetName(); }
+        bool     operator!=(const TariffImpl & rhs) const { return GetName() != rhs.GetName(); }
+        std::string TariffChangeIsAllowed(const Tariff & to, time_t currentTime) const;
+
+    private:
+        TariffData     tariffData;
+
+        double  GetPriceWithoutFreeMb(int dir, int64_t mb, time_t t) const;
+        int     Interval(int dir, time_t t) const;
+};
+
+}
diff --git a/projects/stargazer/tariffs_impl.cpp b/projects/stargazer/tariffs_impl.cpp
new file mode 100644 (file)
index 0000000..9cc829d
--- /dev/null
@@ -0,0 +1,276 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Date: 07.11.2007
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+/*
+ $Revision: 1.9 $
+ $Date: 2010/10/07 18:43:21 $
+ $Author: faust $
+ */
+
+#include <cassert>
+#include <algorithm>
+#include <vector>
+
+#include "stg/locker.h"
+#include "stg/logger.h"
+#include "stg/store.h"
+#include "stg/admin.h"
+#include "stg/admin_conf.h"
+#include "tariffs_impl.h"
+
+using STG::TariffsImpl;
+
+//-----------------------------------------------------------------------------
+TariffsImpl::TariffsImpl(Store * st)
+    : store(st),
+      WriteServLog(Logger::get()),
+      noTariff(NO_TARIFF_NAME)
+{
+ReadTariffs();
+}
+//-----------------------------------------------------------------------------
+int TariffsImpl::ReadTariffs()
+{
+std::lock_guard<std::mutex> lock(m_mutex);
+
+std::vector<std::string> tariffsList;
+if (store->GetTariffsList(&tariffsList))
+    {
+    WriteServLog("Cannot get tariffs list.");
+    WriteServLog("%s", store->GetStrError().c_str());
+    }
+
+Data::size_type tariffsNum = tariffsList.size();
+
+for (Data::size_type i = 0; i < tariffsNum; i++)
+    {
+    TariffData td;
+    if (store->RestoreTariff(&td, tariffsList[i]))
+        {
+        WriteServLog("Cannot read tariff %s.", tariffsList[i].c_str());
+        WriteServLog("%s", store->GetStrError().c_str());
+        return -1;
+        }
+    tariffs.push_back(TariffImpl(td));
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+size_t TariffsImpl::Count() const
+{
+std::lock_guard<std::mutex> lock(m_mutex);
+return tariffs.size();
+}
+//-----------------------------------------------------------------------------
+const STG::Tariff* TariffsImpl::FindByName(const std::string & name) const
+{
+if (name == NO_TARIFF_NAME)
+    return &noTariff;
+
+std::lock_guard<std::mutex> lock(m_mutex);
+const auto ti = find(tariffs.begin(), tariffs.end(), TariffImpl(name));
+
+if (ti != tariffs.end())
+    return &(*ti);
+
+return NULL;
+}
+//-----------------------------------------------------------------------------
+int TariffsImpl::Chg(const TariffData & td, const Admin * admin)
+{
+const auto& priv = admin->priv();
+
+if (!priv.tariffChg)
+    {
+    std::string s = admin->logStr() + " Change tariff \'"
+               + td.tariffConf.name + "\'. Access denied.";
+    strError = "Access denied.";
+    WriteServLog(s.c_str());
+    return -1;
+    }
+
+std::lock_guard<std::mutex> lock(m_mutex);
+
+auto ti = find(tariffs.begin(), tariffs.end(), TariffImpl(td.tariffConf.name));
+
+if (ti == tariffs.end())
+    {
+    strError = "Tariff \'" + td.tariffConf.name + "\' cannot be changed. Tariff does not exist.";
+    WriteServLog("%s %s", admin->logStr().c_str(), strError.c_str());
+    return -1;
+    }
+
+*ti = td;
+
+if (store->SaveTariff(td, td.tariffConf.name))
+    {
+    std::string error = "Tariff " + td.tariffConf.name + " writing error. " + store->GetStrError();
+    WriteServLog(error.c_str());
+    return -1;
+    }
+
+WriteServLog("%s Tariff \'%s\' changed.",
+             admin->logStr().c_str(), td.tariffConf.name.c_str());
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int TariffsImpl::Del(const std::string & name, const Admin * admin)
+{
+const auto& priv = admin->priv();
+
+if (!priv.tariffChg)
+    {
+    std::string s = admin->logStr() + " Delete tariff \'"
+               + name + "\'. Access denied.";
+    strError = "Access denied.";
+    WriteServLog(s.c_str());
+    return -1;
+    }
+
+TariffData td;
+
+    {
+    std::lock_guard<std::mutex> lock(m_mutex);
+
+    const auto ti = find(tariffs.begin(), tariffs.end(), TariffImpl(name));
+
+    if (ti == tariffs.end())
+        {
+        strError = "Tariff \'" + name + "\' cannot be deleted. Tariff does not exist.";
+        WriteServLog("%s %s", admin->logStr().c_str(), strError.c_str());
+        return -1;
+        }
+
+    if (store->DelTariff(name))
+        {
+        WriteServLog("Cannot delete tariff %s.", name.c_str());
+        WriteServLog("%s", store->GetStrError().c_str());
+        return -1;
+        }
+
+    td = ti->GetTariffData();
+
+    tariffs.erase(ti);
+    }
+
+auto ni = onDelNotifiers.begin();
+while (ni != onDelNotifiers.end())
+    {
+    (*ni)->Notify(td);
+    ++ni;
+    }
+
+WriteServLog("%s Tariff \'%s\' deleted.",
+             admin->logStr().c_str(),
+             name.c_str());
+return 0;
+}
+//-----------------------------------------------------------------------------
+int TariffsImpl::Add(const std::string & name, const Admin * admin)
+{
+const auto& priv = admin->priv();
+
+if (!priv.tariffChg)
+    {
+    std::string s = admin->logStr() + " Add tariff \'"
+               + name + "\'. Access denied.";
+    strError = "Access denied.";
+    WriteServLog(s.c_str());
+    return -1;
+    }
+
+    {
+    std::lock_guard<std::mutex> lock(m_mutex);
+
+    const auto ti = find(tariffs.begin(), tariffs.end(), TariffImpl(name));
+
+    if (ti != tariffs.end())
+        {
+        strError = "Tariff \'" + name + "\' cannot be added. Tariff already exist.";
+        WriteServLog("%s %s", admin->logStr().c_str(), strError.c_str());
+        return -1;
+        }
+
+    tariffs.push_back(TariffImpl(name));
+    }
+
+if (store->AddTariff(name) < 0)
+    {
+    strError = "Tariff " + name + " adding error. " + store->GetStrError();
+    WriteServLog(strError.c_str());
+    return -1;
+    }
+
+// Fire all "on add" notifiers
+auto ni = onAddNotifiers.begin();
+while (ni != onAddNotifiers.end())
+    {
+    (*ni)->Notify(tariffs.back().GetTariffData());
+    ++ni;
+    }
+
+WriteServLog("%s Tariff \'%s\' added.",
+                 admin->logStr().c_str(), name.c_str());
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+void TariffsImpl::GetTariffsData(std::vector<TariffData> * tdl) const
+{
+assert(tdl != NULL && "Tariffs data list is not null");
+std::lock_guard<std::mutex> lock(m_mutex);
+
+auto it = tariffs.begin();
+for (; it != tariffs.end(); ++it)
+    {
+    tdl->push_back(it->GetTariffData());
+    }
+}
+//-----------------------------------------------------------------------------
+void TariffsImpl::AddNotifierAdd(NotifierBase<TariffData> * n)
+{
+std::lock_guard<std::mutex> lock(m_mutex);
+onAddNotifiers.insert(n);
+}
+//-----------------------------------------------------------------------------
+void TariffsImpl::DelNotifierAdd(NotifierBase<TariffData> * n)
+{
+std::lock_guard<std::mutex> lock(m_mutex);
+onAddNotifiers.erase(n);
+}
+//-----------------------------------------------------------------------------
+void TariffsImpl::AddNotifierDel(NotifierBase<TariffData> * n)
+{
+std::lock_guard<std::mutex> lock(m_mutex);
+onDelNotifiers.insert(n);
+}
+//-----------------------------------------------------------------------------
+void TariffsImpl::DelNotifierDel(NotifierBase<TariffData> * n)
+{
+std::lock_guard<std::mutex> lock(m_mutex);
+onDelNotifiers.erase(n);
+}
+//-----------------------------------------------------------------------------
diff --git a/projects/stargazer/tariffs_impl.h b/projects/stargazer/tariffs_impl.h
new file mode 100644 (file)
index 0000000..4b554b4
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Date: 07.11.2007
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+#pragma once
+
+#include "stg/tariff.h"
+#include "stg/tariffs.h"
+#include "stg/tariff_conf.h"
+#include "tariff_impl.h"
+
+#include <string>
+#include <vector>
+#include <set>
+#include <mutex>
+
+namespace STG
+{
+
+struct Store;
+class Logger;
+struct Admin;
+
+class TariffsImpl : public Tariffs {
+    public:
+        using Data = std::vector<TariffImpl>;
+
+        explicit TariffsImpl(Store * store);
+
+        int ReadTariffs () override;
+        const Tariff * FindByName(const std::string & name) const override;
+        const Tariff * GetNoTariff() const override { return &noTariff; }
+        size_t Count() const override;
+        int Del(const std::string & name, const Admin * admin) override;
+        int Add(const std::string & name, const Admin * admin) override;
+        int Chg(const TariffData & td, const Admin * admin) override;
+
+        void AddNotifierAdd(NotifierBase<TariffData> * notifier) override;
+        void DelNotifierAdd(NotifierBase<TariffData> * notifier) override;
+
+        void AddNotifierDel(NotifierBase<TariffData> * notifier) override;
+        void DelNotifierDel(NotifierBase<TariffData> * notifier) override;
+
+        void GetTariffsData(std::vector<TariffData> * tdl) const override;
+
+        const std::string & GetStrError() const override { return strError; }
+
+    private:
+        Data               tariffs;
+        Store*             store;
+        Logger&            WriteServLog;
+        mutable std::mutex m_mutex;
+        std::string        strError;
+        TariffImpl         noTariff;
+
+        std::set<NotifierBase<TariffData>*> onAddNotifiers;
+        std::set<NotifierBase<TariffData>*> onDelNotifiers;
+};
+
+}
diff --git a/projects/stargazer/traffcounter_impl.cpp b/projects/stargazer/traffcounter_impl.cpp
new file mode 100644 (file)
index 0000000..0897d6b
--- /dev/null
@@ -0,0 +1,857 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Date: 27.10.2002
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+/*
+ $Revision: 1.58 $
+ $Date: 2010/11/03 11:28:07 $
+ $Author: faust $
+ */
+
+/* inet_aton */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <csignal>
+#include <cassert>
+#include <cstdio> // fopen and similar
+#include <cstdlib> // strtol
+
+#include "stg/common.h"
+#include "stg/locker.h"
+#include "stg/const.h" // MONITOR_TIME_DELAY_SEC
+#include "traffcounter_impl.h"
+#include "stg_timer.h"
+#include "users_impl.h"
+
+#define FLUSH_TIME  (10)
+#define REMOVE_TIME  (31)
+
+using STG::TraffCounterImpl;
+
+const char protoName[PROTOMAX][8] =
+{"TCP", "UDP", "ICMP", "TCP_UDP", "ALL"};
+
+enum protoNum
+{
+tcp = 0, udp, icmp, tcp_udp, all
+};
+
+//-----------------------------------------------------------------------------
+TraffCounterImpl::TraffCounterImpl(UsersImpl * u, const std::string & fn)
+    : WriteServLog(Logger::get()),
+      rulesFileName(fn),
+      monitoring(false),
+      touchTimeP(stgTime - MONITOR_TIME_DELAY_SEC),
+      users(u),
+      running(false),
+      stopped(true),
+      addUserNotifier(*this),
+      delUserNotifier(*this)
+{
+for (int i = 0; i < DIR_NUM; i++)
+    strprintf(&dirName[i], "DIR%d", i);
+
+dirName[DIR_NUM] = "NULL";
+
+users->AddNotifierUserAdd(&addUserNotifier);
+users->AddNotifierUserDel(&delUserNotifier);
+
+pthread_mutex_init(&mutex, NULL);
+}
+//-----------------------------------------------------------------------------
+TraffCounterImpl::~TraffCounterImpl()
+{
+pthread_mutex_destroy(&mutex);
+}
+//-----------------------------------------------------------------------------
+int TraffCounterImpl::Start()
+{
+STG_LOCKER lock(&mutex);
+
+if (!stopped)
+    return 0;
+
+if (ReadRules())
+    {
+    printfd(__FILE__, "TraffCounterImpl::Start() - Cannot read rules\n");
+    WriteServLog("TraffCounter: Cannot read rules.");
+    return -1;
+    }
+
+printfd(__FILE__, "TraffCounter::Start()\n");
+int h = users->OpenSearch();
+assert(h && "USERS::OpenSearch is always correct");
+UserImpl * u;
+
+while (users->SearchNext(h, &u) == 0)
+    SetUserNotifiers(u);
+users->CloseSearch(h);
+
+running = true;
+if (pthread_create(&thread, NULL, Run, this))
+    {
+    printfd(__FILE__, "TraffCounterImpl::Start() - Cannot start thread\n");
+    WriteServLog("TraffCounter: Error: Cannot start thread.");
+    return -1;
+    }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int TraffCounterImpl::Stop()
+{
+if (stopped)
+    return 0;
+
+running = false;
+
+int h = users->OpenSearch();
+assert(h && "USERS::OpenSearch is always correct");
+
+UserImpl * u;
+while (users->SearchNext(h, &u) == 0)
+    UnSetUserNotifiers(u);
+users->CloseSearch(h);
+
+//5 seconds to thread stops itself
+struct timespec ts = {0, 200000000};
+for (int i = 0; i < 25 && !stopped; i++)
+    {
+    nanosleep(&ts, NULL);
+    }
+
+if (!stopped)
+    return -1;
+
+printfd(__FILE__, "TraffCounter::Stop()\n");
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+void * TraffCounterImpl::Run(void * data)
+{
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+TraffCounterImpl * tc = static_cast<TraffCounterImpl *>(data);
+tc->stopped = false;
+int c = 0;
+
+time_t touchTime = stgTime - MONITOR_TIME_DELAY_SEC;
+struct timespec ts = {0, 500000000};
+while (tc->running)
+    {
+    nanosleep(&ts, 0);
+    if (!tc->running)
+        {
+        tc->FlushAndRemove();
+        break;
+        }
+
+    if (tc->monitoring && (touchTime + MONITOR_TIME_DELAY_SEC <= stgTime))
+        {
+        std::string monFile(tc->monitorDir + "/traffcounter_r");
+        printfd(__FILE__, "Monitor=%d file TraffCounter %s\n", tc->monitoring, monFile.c_str());
+        touchTime = stgTime;
+        TouchFile(monFile);
+        }
+
+    if (++c % FLUSH_TIME == 0)
+        tc->FlushAndRemove();
+    }
+
+tc->stopped = true;
+return NULL;
+}
+//-----------------------------------------------------------------------------
+void TraffCounterImpl::process(const RawPacket & rawPacket)
+{
+if (!running)
+    return;
+
+if (monitoring && (touchTimeP + MONITOR_TIME_DELAY_SEC <= stgTime))
+    {
+    std::string monFile = monitorDir + "/traffcounter_p";
+    printfd(__FILE__, "Monitor=%d file TraffCounter %s\n", monitoring, monFile.c_str());
+    touchTimeP = stgTime;
+    TouchFile(monFile);
+    }
+
+STG_LOCKER lock(&mutex);
+
+//printfd(__FILE__, "TraffCounter::Process()\n");
+//TODO replace find with lower_bound.
+
+// Searching a new packet in a tree.
+pp_iter pi = packets.find(rawPacket);
+
+// Packet found - update length and time
+if (pi != packets.end())
+    {
+    pi->second.lenU += rawPacket.GetLen();
+    pi->second.lenD += rawPacket.GetLen();
+    pi->second.updateTime = stgTime;
+    /*printfd(__FILE__, "=============================\n");
+    printfd(__FILE__, "Packet found!\n");
+    printfd(__FILE__, "Version=%d\n", rawPacket.GetIPVersion());
+    printfd(__FILE__, "HeaderLen=%d\n", rawPacket.GetHeaderLen());
+    printfd(__FILE__, "PacketLen=%d\n", rawPacket.GetLen());
+    printfd(__FILE__, "SIP=%s\n", inet_ntostring(rawPacket.GetSrcIP()).c_str());
+    printfd(__FILE__, "DIP=%s\n", inet_ntostring(rawPacket.GetDstIP()).c_str());
+    printfd(__FILE__, "src port=%d\n", rawPacket.GetSrcPort());
+    printfd(__FILE__, "pst port=%d\n", rawPacket.GetDstPort());
+    printfd(__FILE__, "len=%d\n", rawPacket.GetLen());
+    printfd(__FILE__, "proto=%d\n", rawPacket.GetProto());
+    printfd(__FILE__, "PacketDirU=%d\n", pi->second.dirU);
+    printfd(__FILE__, "PacketDirD=%d\n", pi->second.dirD);
+    printfd(__FILE__, "=============================\n");*/
+    return;
+    }
+
+PacketExtraData ed;
+
+// Packet not found - add new packet
+
+ed.updateTime = stgTime;
+ed.flushTime = stgTime;
+
+/*
+ userU is that whose user_ip == packet_ip_src
+ userD is that whose user_ip == packet_ip_dst
+ */
+
+uint32_t ipU = rawPacket.GetSrcIP();
+uint32_t ipD = rawPacket.GetDstIP();
+
+// Searching users with such IP
+if (users->FindByIPIdx(ipU, &ed.userU) == 0)
+    {
+    ed.userUPresent = true;
+    }
+
+if (users->FindByIPIdx(ipD, &ed.userD) == 0)
+    {
+    ed.userDPresent = true;
+    }
+
+if (ed.userUPresent ||
+    ed.userDPresent)
+    {
+    DeterminateDir(rawPacket, &ed.dirU, &ed.dirD);
+
+    ed.lenD = ed.lenU = rawPacket.GetLen();
+
+    //TODO use result of lower_bound to inserting new record
+
+    // Adding packet to a tree.
+    std::pair<pp_iter, bool> insertResult = packets.insert(std::make_pair(rawPacket, ed));
+    pp_iter newPacket = insertResult.first;
+
+    // Adding packet reference to an IP index.
+    ip2packets.insert(std::make_pair(ipU, newPacket));
+    ip2packets.insert(std::make_pair(ipD, newPacket));
+    }
+}
+//-----------------------------------------------------------------------------
+void TraffCounterImpl::FlushAndRemove()
+{
+STG_LOCKER lock(&mutex);
+
+Packets::size_type oldPacketsSize = packets.size();
+Index::size_type oldIp2packetsSize = ip2packets.size();
+
+pp_iter pi;
+pi = packets.begin();
+Packets newPackets;
+ip2packets.erase(ip2packets.begin(), ip2packets.end());
+while (pi != packets.end())
+    {
+    //Flushing
+    if (stgTime - pi->second.flushTime > FLUSH_TIME)
+        {
+        if (pi->second.userUPresent)
+            {
+            //printfd(__FILE__, "+++ Flushing U user %s (%s:%d) of length %d\n", pi->second.userU->GetLogin().c_str(), inet_ntostring(pi->first.GetSrcIP()).c_str(), pi->first.GetSrcPort(), pi->second.lenU);
+
+            // Add stat
+            if (pi->second.dirU < DIR_NUM)
+                {
+                #ifdef TRAFF_STAT_WITH_PORTS
+                pi->second.userU->AddTraffStatU(pi->second.dirU,
+                                                pi->first.GetDstIP(),
+                                                pi->first.GetDstPort(),
+                                                pi->second.lenU);
+                #else
+                pi->second.userU->AddTraffStatU(pi->second.dirU,
+                                                pi->first.GetDstIP(),
+                                                pi->second.lenU);
+                #endif
+                }
+
+            pi->second.lenU = 0;
+            pi->second.flushTime = stgTime;
+            }
+
+        if (pi->second.userDPresent)
+            {
+            //printfd(__FILE__, "+++ Flushing D user %s (%s:%d) of length %d\n", pi->second.userD->GetLogin().c_str(), inet_ntostring(pi->first.GetDstIP()).c_str(), pi->first.GetDstPort(), pi->second.lenD);
+
+            // Add stat
+            if (pi->second.dirD < DIR_NUM)
+                {
+                #ifdef TRAFF_STAT_WITH_PORTS
+                pi->second.userD->AddTraffStatD(pi->second.dirD,
+                                                pi->first.GetSrcIP(),
+                                                pi->first.GetSrcPort(),
+                                                pi->second.lenD);
+                #else
+                pi->second.userD->AddTraffStatD(pi->second.dirD,
+                                                pi->first.GetSrcIP(),
+                                                pi->second.lenD);
+                #endif
+                }
+
+            pi->second.lenD = 0;
+            pi->second.flushTime = stgTime;
+            }
+        }
+
+    if (stgTime - pi->second.updateTime < REMOVE_TIME)
+        {
+        std::pair<pp_iter, bool> res = newPackets.insert(*pi);
+        if (res.second)
+            {
+            ip2packets.insert(std::make_pair(pi->first.GetSrcIP(), res.first));
+            ip2packets.insert(std::make_pair(pi->first.GetDstIP(), res.first));
+            }
+        }
+    ++pi;
+    }
+swap(packets, newPackets);
+printfd(__FILE__, "FlushAndRemove() packets: %d(rem %d) ip2packets: %d(rem %d)\n",
+        packets.size(),
+        oldPacketsSize - packets.size(),
+        ip2packets.size(),
+        oldIp2packetsSize - ip2packets.size());
+
+}
+//-----------------------------------------------------------------------------
+void TraffCounterImpl::AddUser(UserImpl * user)
+{
+printfd(__FILE__, "AddUser: %s\n", user->GetLogin().c_str());
+uint32_t uip = user->GetCurrIP();
+std::pair<ip2p_iter, ip2p_iter> pi;
+
+STG_LOCKER lock(&mutex);
+// Find all packets with IP belongs to this user
+pi = ip2packets.equal_range(uip);
+
+while (pi.first != pi.second)
+    {
+    if (pi.first->second->first.GetSrcIP() == uip)
+        {
+        assert((!pi.first->second->second.userUPresent ||
+                 pi.first->second->second.userU == user) &&
+               "U user present but it's not current user");
+
+        pi.first->second->second.lenU = 0;
+        pi.first->second->second.userU = user;
+        pi.first->second->second.userUPresent = true;
+        }
+
+    if (pi.first->second->first.GetDstIP() == uip)
+        {
+        assert((!pi.first->second->second.userDPresent ||
+                 pi.first->second->second.userD == user) &&
+               "D user present but it's not current user");
+
+        pi.first->second->second.lenD = 0;
+        pi.first->second->second.userD = user;
+        pi.first->second->second.userDPresent = true;
+        }
+
+    ++pi.first;
+    }
+}
+//-----------------------------------------------------------------------------
+void TraffCounterImpl::DelUser(uint32_t uip)
+{
+printfd(__FILE__, "DelUser: %s \n", inet_ntostring(uip).c_str());
+std::pair<ip2p_iter, ip2p_iter> pi;
+
+STG_LOCKER lock(&mutex);
+pi = ip2packets.equal_range(uip);
+
+while (pi.first != pi.second)
+    {
+    if (pi.first->second->first.GetSrcIP() == uip)
+        {
+        if (pi.first->second->second.dirU < DIR_NUM && pi.first->second->second.userUPresent)
+            {
+            #ifdef TRAFF_STAT_WITH_PORTS
+            pi.first->second->second.userU->AddTraffStatU(pi.first->second->second.dirU,
+                                                          pi.first->second->first.GetDstIP(),
+                                                          pi.first->second->first.GetDstPort(),
+                                                          pi.first->second->second.lenU);
+            #else
+            pi.first->second->second.userU->AddTraffStatU(pi.first->second->second.dirU,
+                                                          pi.first->second->first.GetDstIP(),
+                                                          pi.first->second->second.lenU);
+            #endif
+            }
+        pi.first->second->second.userUPresent = false;
+        }
+
+    if (pi.first->second->first.GetDstIP() == uip)
+        {
+        if (pi.first->second->second.dirD < DIR_NUM && pi.first->second->second.userDPresent)
+            {
+            #ifdef TRAFF_STAT_WITH_PORTS
+            pi.first->second->second.userD->AddTraffStatD(pi.first->second->second.dirD,
+                                                          pi.first->second->first.GetSrcIP(),
+                                                          pi.first->second->first.GetSrcPort(),
+                                                          pi.first->second->second.lenD);
+            #else
+            pi.first->second->second.userD->AddTraffStatD(pi.first->second->second.dirD,
+                                                          pi.first->second->first.GetSrcIP(),
+                                                          pi.first->second->second.lenD);
+            #endif
+            }
+
+        pi.first->second->second.userDPresent = false;
+        }
+
+    ++pi.first;
+    }
+
+ip2packets.erase(pi.first, pi.second);
+}
+//-----------------------------------------------------------------------------
+void TraffCounterImpl::SetUserNotifiers(UserImpl * user)
+{
+// Adding user. Adding notifiers to user.
+TRF_IP_BEFORE ipBNotifier(*this, user);
+ipBeforeNotifiers.push_front(ipBNotifier);
+user->AddCurrIPBeforeNotifier(&(*ipBeforeNotifiers.begin()));
+
+TRF_IP_AFTER ipANotifier(*this, user);
+ipAfterNotifiers.push_front(ipANotifier);
+user->AddCurrIPAfterNotifier(&(*ipAfterNotifiers.begin()));
+}
+//-----------------------------------------------------------------------------
+void TraffCounterImpl::UnSetUserNotifiers(UserImpl * user)
+{
+// Removing user. Removing notifiers from user.
+std::list<TRF_IP_BEFORE>::iterator bi;
+std::list<TRF_IP_AFTER>::iterator ai;
+
+bi = ipBeforeNotifiers.begin();
+while (bi != ipBeforeNotifiers.end())
+    {
+    if (user->GetLogin() == bi->GetUser()->GetLogin())
+        {
+        user->DelCurrIPBeforeNotifier(&(*bi));
+        ipBeforeNotifiers.erase(bi);
+        break;
+        }
+    ++bi;
+    }
+
+ai = ipAfterNotifiers.begin();
+while (ai != ipAfterNotifiers.end())
+    {
+    if (user->GetLogin() == ai->GetUser()->GetLogin())
+        {
+        user->DelCurrIPAfterNotifier(&(*ai));
+        ipAfterNotifiers.erase(ai);
+        break;
+        }
+    ++ai;
+    }
+}
+//-----------------------------------------------------------------------------
+void TraffCounterImpl::DeterminateDir(const RawPacket & packet,
+                                       int * dirU, // Direction for incoming packet
+                                       int * dirD) const // Direction for outgoing packet
+{
+bool addrMatchU = false;
+bool portMatchU = false;
+bool addrMatchD = false;
+bool portMatchD = false;
+bool foundU = false; // Was rule for U found ?
+bool foundD = false; // Was rule for D found ?
+//printfd(__FILE__, "foundU=%d, foundD=%d\n", foundU, foundD);
+
+enum { ICMP_RPOTO = 1, TCP_PROTO = 6, UDP_PROTO = 17 };
+
+std::list<Rule>::const_iterator ln;
+ln = rules.begin();
+
+while (ln != rules.end())
+    {
+    if (!foundU)
+        {
+        portMatchU = false;
+
+        switch (ln->proto)
+            {
+            case all:
+                portMatchU = true;
+                break;
+
+            case icmp:
+                portMatchU = (packet.GetProto() == ICMP_RPOTO);
+                break;
+
+            case tcp_udp:
+                if (packet.GetProto() == TCP_PROTO || packet.GetProto() == UDP_PROTO)
+                    portMatchU = (packet.GetDstPort() >= ln->port1) && (packet.GetDstPort() <= ln->port2);
+                break;
+
+            case tcp:
+                if (packet.GetProto() == TCP_PROTO)
+                    portMatchU = (packet.GetDstPort() >= ln->port1) && (packet.GetDstPort() <= ln->port2);
+                break;
+
+            case udp:
+                if (packet.GetProto() == UDP_PROTO)
+                    portMatchU = (packet.GetDstPort() >= ln->port1) && (packet.GetDstPort() <= ln->port2);
+                break;
+
+            default:
+                printfd(__FILE__, "Error! Incorrect rule!\n");
+                break;
+            }
+
+        addrMatchU = (packet.GetDstIP() & ln->mask) == ln->ip;
+
+        if (!foundU && addrMatchU && portMatchU)
+            {
+            foundU = true;
+            *dirU = ln->dir;
+            //printfd(__FILE__, "Up rule ok! %d\n", ln->dir);
+            }
+
+        } //if (!foundU)
+
+    if (!foundD)
+        {
+        portMatchD = false;
+
+        switch (ln->proto)
+            {
+            case all:
+                portMatchD = true;
+                break;
+
+            case icmp:
+                portMatchD = (packet.GetProto() == ICMP_RPOTO);
+                break;
+
+            case tcp_udp:
+                if (packet.GetProto() == TCP_PROTO || packet.GetProto() == UDP_PROTO)
+                    portMatchD = (packet.GetSrcPort() >= ln->port1) && (packet.GetSrcPort() <= ln->port2);
+                break;
+
+            case tcp:
+                if (packet.GetProto() == TCP_PROTO)
+                    portMatchD = (packet.GetSrcPort() >= ln->port1) && (packet.GetSrcPort() <= ln->port2);
+                break;
+
+            case udp:
+                if (packet.GetProto() == UDP_PROTO)
+                    portMatchD = (packet.GetSrcPort() >= ln->port1) && (packet.GetSrcPort() <= ln->port2);
+                break;
+
+            default:
+                printfd(__FILE__, "Error! Incorrect rule!\n");
+                break;
+            }
+
+        addrMatchD = (packet.GetSrcIP() & ln->mask) == ln->ip;
+
+        if (!foundD && addrMatchD && portMatchD)
+            {
+            foundD = true;
+            *dirD = ln->dir;
+            //printfd(__FILE__, "Down rule ok! %d\n", ln->dir);
+            }
+        } //if (!foundD)
+
+    ++ln;
+    }   //while (ln != rules.end())
+
+if (!foundU)
+    *dirU = DIR_NUM;
+
+if (!foundD)
+    *dirD = DIR_NUM;
+}
+//-----------------------------------------------------------------------------
+bool TraffCounterImpl::ReadRules(bool test)
+{
+//printfd(__FILE__, "TraffCounter::ReadRules()\n");
+
+Rule rul;
+FILE * f;
+char str[1024];
+char tp[100];   // protocol
+char ta[100];   // address
+char td[100];   // target direction
+int r;
+int lineNumber = 0;
+f = fopen(rulesFileName.c_str(), "rt");
+
+if (!f)
+    {
+    printfd(__FILE__, "TraffCounterImpl::ReadRules() - File '%s' cannot be opened.\n", rulesFileName.c_str());
+    WriteServLog("File '%s' cannot be oppened.", rulesFileName.c_str());
+    return true;
+    }
+
+while (fgets(str, 1023, f))
+    {
+    lineNumber++;
+    if (str[strspn(str," \t")] == '#' || str[strspn(str," \t")] == '\n')
+        {
+        continue;
+        }
+
+    r = sscanf(str,"%99s %99s %99s", tp, ta, td);
+    if (r != 3)
+        {
+        printfd(__FILE__, "TraffCounterImpl::ReadRules() - Error in file '%s' at line %d. There must be 3 parameters.\n", rulesFileName.c_str(), lineNumber);
+        WriteServLog("Error in file '%s' at line %d. There must be 3 parameters.", rulesFileName.c_str(), lineNumber);
+        fclose(f);
+        return true;
+        }
+
+    rul.proto = 0xff;
+    rul.dir = 0xff;
+
+    for (uint8_t i = 0; i < PROTOMAX; i++)
+        {
+        if (strcasecmp(tp, protoName[i]) == 0)
+            rul.proto = i;
+        }
+
+    for (uint32_t i = 0; i < DIR_NUM + 1; i++)
+        {
+        if (td == dirName[i])
+            rul.dir = i;
+        }
+
+    if (rul.dir == 0xff || rul.proto == 0xff)
+        {
+        printfd(__FILE__, "TraffCounterImpl::ReadRules() - Error in file '%s' at line %d.\n", rulesFileName.c_str(), lineNumber);
+        WriteServLog("Error in file %s. Line %d.",
+                     rulesFileName.c_str(), lineNumber);
+        fclose(f);
+        return true;
+        }
+
+    if (ParseAddress(ta, &rul) != 0)
+        {
+        printfd(__FILE__, "TraffCounterImpl::ReadRules() - Error in file '%s' at line %d. Error in adress.\n", rulesFileName.c_str(), lineNumber);
+        WriteServLog("Error in file %s. Error in adress. Line %d.",
+                     rulesFileName.c_str(), lineNumber);
+        fclose(f);
+        return true;
+        }
+    if (!test)
+        rules.push_back(rul);
+    }
+
+fclose(f);
+
+// Adding lastest rule: ALL 0.0.0.0/0 NULL
+rul.dir = DIR_NUM; //NULL
+rul.ip = 0;  //0.0.0.0
+rul.mask = 0;
+rul.port1 = 0;
+rul.port2 = 65535;
+rul.proto = all;
+
+if (!test)
+    rules.push_back(rul);
+
+return false;
+}
+//-----------------------------------------------------------------------------
+int TraffCounterImpl::Reload()
+{
+STG_LOCKER lock(&mutex);
+
+if (ReadRules(true))
+    {
+    printfd(__FILE__, "TraffCounterImpl::Reload() - Failed to reload rules.\n");
+    WriteServLog("TraffCounter: Cannot reload rules. Errors found.");
+    return -1;
+    }
+
+FreeRules();
+ReadRules();
+printfd(__FILE__, "TraffCounterImpl::Reload() -  Reloaded rules successfully.\n");
+WriteServLog("TraffCounter: Reloaded rules successfully.");
+return 0;
+}
+//-----------------------------------------------------------------------------
+bool TraffCounterImpl::ParseAddress(const char * ta, Rule * rule) const
+{
+char addr[50], mask[20], port1[20], port2[20], ports[40];
+
+size_t len = strlen(ta);
+char n = 0;
+size_t i, p;
+memset(addr, 0, sizeof(addr));
+for (i = 0; i < len; i++)
+    {
+    if (ta[i] == '/' || ta[i] == ':')
+        {
+        addr[i] = 0;
+        n = ta[i];
+        break;
+        }
+    addr[i] = ta[i];
+    n = 0;
+    }
+addr[i + 1] = 0;
+p = i + 1;
+
+if (n == '/')
+    {
+    // mask
+    for (; i < len; i++)
+        {
+        if (ta[i] == ':')
+            {
+            mask[i - p] = 0;
+            n = ':';
+            break;
+            }
+        mask[i - p] = ta[i];
+        }
+    mask[i - p] = 0;
+    }
+else
+    {
+    strcpy(mask, "32");
+    }
+
+p = i + 1;
+i++;
+
+if (n == ':')
+    {
+    // port
+    if (!(rule->proto == tcp || rule->proto == udp || rule->proto == tcp_udp))
+        {
+        printfd(__FILE__, "TraffCounterImpl::ParseAddress() - No ports specified for this protocol.\n");
+        WriteServLog("No ports specified for this protocol.");
+        return true;
+        }
+
+    for (; i < len; i++)
+        ports[i - p] = ta[i];
+
+    ports[i - p] = 0;
+    }
+else
+    {
+    strcpy(ports, "0-65535");
+    }
+
+char *sss;
+char pts[100];
+strcpy(pts, ports);
+
+if ((sss = strchr(ports, '-')) != NULL)
+    {
+    strncpy(port1, ports, int(sss-ports));
+    port1[int(sss - ports)] = 0;
+    strcpy(port2, sss + 1);
+    }
+else
+    {
+    strcpy(port1, ports);
+    strcpy(port2, ports);
+    }
+
+// Convert strings to mask, ports and IP
+uint16_t prt1, prt2, msk;
+struct in_addr ipaddr;
+char *res;
+
+msk = static_cast<uint16_t>(strtol(mask, &res, 10));
+if (*res != 0)
+    return true;
+
+prt1 = static_cast<uint16_t>(strtol(port1, &res, 10));
+if (*res != 0)
+    return true;
+
+prt2 = static_cast<uint16_t>(strtol(port2, &res, 10));
+if (*res != 0)
+    return true;
+
+int r = inet_aton(addr, &ipaddr);
+if (r == 0)
+    return true;
+
+rule->ip = ipaddr.s_addr;
+rule->mask = CalcMask(msk);
+
+if ((ipaddr.s_addr & rule->mask) != ipaddr.s_addr)
+    {
+    printfd(__FILE__, "TraffCounterImpl::ParseAddress() - Address does'n match mask.\n");
+    WriteServLog("Address does'n match mask.");
+    return true;
+    }
+
+rule->port1 = prt1;
+rule->port2 = prt2;
+
+return false;
+}
+//-----------------------------------------------------------------------------
+uint32_t TraffCounterImpl::CalcMask(uint32_t msk) const
+{
+if (msk >= 32) return 0xFFffFFff;
+if (msk == 0) return 0;
+return htonl(0xFFffFFff << (32 - msk));
+}
+//---------------------------------------------------------------------------
+void TraffCounterImpl::FreeRules()
+{
+rules.clear();
+}
+//-----------------------------------------------------------------------------
+void TraffCounterImpl::SetMonitorDir(const std::string & dir)
+{
+monitorDir = dir;
+monitoring = !monitorDir.empty();
+}
+//-----------------------------------------------------------------------------
diff --git a/projects/stargazer/traffcounter_impl.h b/projects/stargazer/traffcounter_impl.h
new file mode 100644 (file)
index 0000000..78027cb
--- /dev/null
@@ -0,0 +1,271 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+#pragma once
+
+#include "stg/traffcounter.h"
+#include "stg/logger.h"
+#include "stg/raw_ip_packet.h"
+#include "stg/noncopyable.h"
+#include "stg/notifer.h"
+#include "actions.h"
+#include "eventloop.h"
+#include "user_impl.h"
+
+#include <ctime>
+#include <list>
+#include <map>
+#include <string>
+#include <cstdint>
+
+#include <pthread.h>
+
+#define PROTOMAX    (5)
+
+namespace STG
+{
+
+class UsersImpl;
+
+//-----------------------------------------------------------------------------
+struct Rule {
+uint32_t    ip;             // IP
+uint32_t    mask;           // Network mask
+uint16_t    port1;          // Min port
+uint16_t    port2;          // Max port
+uint8_t     proto;          // Protocol
+uint32_t    dir;            // Direction
+};
+//-----------------------------------------------------------------------------
+struct PacketExtraData {
+    PacketExtraData()
+        : flushTime(0),
+          updateTime(0),
+          userU(NULL),
+          userUPresent(false),
+          userD(NULL),
+          userDPresent(false),
+          dirU(DIR_NUM),
+          dirD(DIR_NUM),
+          lenU(0),
+          lenD(0)
+    {}
+
+    time_t      flushTime;          // Last flush time
+    time_t      updateTime;         // Last update time
+    UserImpl * userU;              // Uploader
+    bool        userUPresent;       // Uploader is registered user
+    UserImpl * userD;              // Downloader
+    bool        userDPresent;       // Downloader is registered user
+    int         dirU;               // Upload direction
+    int         dirD;               // Download direction
+    uint32_t    lenU;               // Upload length
+    uint32_t    lenD;               // Download length
+};
+//-----------------------------------------------------------------------------
+class TraffCounterImpl;
+//-----------------------------------------------------------------------------
+class TRF_IP_BEFORE: public PropertyNotifierBase<uint32_t> {
+public:
+                TRF_IP_BEFORE(TraffCounterImpl & t, UserImpl * u)
+                    : PropertyNotifierBase<uint32_t>(),
+                      traffCnt(t),
+                      user(u)
+                {}
+                TRF_IP_BEFORE(const TRF_IP_BEFORE & rvalue)
+                    : PropertyNotifierBase<uint32_t>(),
+                      traffCnt(rvalue.traffCnt),
+                      user(rvalue.user)
+                {}
+    void        Notify(const uint32_t & oldValue, const uint32_t & newValue);
+    void        SetUser(UserImpl * u) { user = u; }
+    UserImpl * GetUser() const { return user; }
+
+private:
+    TRF_IP_BEFORE & operator=(const TRF_IP_BEFORE & rvalue);
+
+    TraffCounterImpl & traffCnt;
+    UserImpl * user;
+};
+//-----------------------------------------------------------------------------
+class TRF_IP_AFTER: public PropertyNotifierBase<uint32_t> {
+public:
+                TRF_IP_AFTER(TraffCounterImpl & t, UserImpl * u)
+                    : PropertyNotifierBase<uint32_t>(),
+                      traffCnt(t),
+                      user(u)
+                {}
+                TRF_IP_AFTER(const TRF_IP_AFTER & rvalue)
+                    : PropertyNotifierBase<uint32_t>(),
+                      traffCnt(rvalue.traffCnt),
+                      user(rvalue.user)
+                {}
+    void        Notify(const uint32_t & oldValue, const uint32_t & newValue);
+    void        SetUser(UserImpl * u) { user = u; }
+    UserImpl * GetUser() const { return user; }
+private:
+    TRF_IP_AFTER & operator=(const TRF_IP_AFTER & rvalue);
+
+    TraffCounterImpl & traffCnt;
+    UserImpl * user;
+};
+
+using UserImplPtr = UserImpl*;
+//-----------------------------------------------------------------------------
+class ADD_USER_NONIFIER: public NotifierBase<UserImplPtr> {
+public:
+            explicit ADD_USER_NONIFIER(TraffCounterImpl & t) :
+                NotifierBase<UserImplPtr>(),
+                traffCnt(t)
+            {}
+    virtual ~ADD_USER_NONIFIER() {}
+    void    Notify(const UserImplPtr & user);
+
+private:
+    ADD_USER_NONIFIER(const ADD_USER_NONIFIER & rvalue);
+    ADD_USER_NONIFIER & operator=(const ADD_USER_NONIFIER & rvalue);
+
+    TraffCounterImpl & traffCnt;
+};
+//-----------------------------------------------------------------------------
+class DEL_USER_NONIFIER: public NotifierBase<UserImplPtr> {
+public:
+            explicit DEL_USER_NONIFIER(TraffCounterImpl & t) :
+                NotifierBase<UserImplPtr>(),
+                traffCnt(t)
+            {}
+    virtual ~DEL_USER_NONIFIER() {}
+    void    Notify(const UserImplPtr & user);
+
+private:
+    DEL_USER_NONIFIER(const DEL_USER_NONIFIER & rvalue);
+    DEL_USER_NONIFIER & operator=(const DEL_USER_NONIFIER & rvalue);
+
+    TraffCounterImpl & traffCnt;
+};
+//-----------------------------------------------------------------------------
+class TraffCounterImpl : public TraffCounter {
+    friend class ADD_USER_NONIFIER;
+    friend class DEL_USER_NONIFIER;
+    friend class TRF_IP_BEFORE;
+    friend class TRF_IP_AFTER;
+    public:
+        TraffCounterImpl(UsersImpl * users, const std::string & rulesFileName);
+        ~TraffCounterImpl();
+
+        int         Reload();
+        int         Start();
+        int         Stop();
+
+        void        process(const RawPacket & rawPacket) override;
+        void        SetMonitorDir(const std::string & monitorDir);
+
+        size_t      rulesCount() const override { return rules.size(); }
+
+    private:
+        bool        ParseAddress(const char * ta, Rule * rule) const;
+        uint32_t    CalcMask(uint32_t msk) const;
+        void        FreeRules();
+        bool        ReadRules(bool test = false);
+
+        static void * Run(void * data);
+
+        void        DeterminateDir(const RawPacket & packet,
+                                   int * dirU, // Direction for upload
+                                   int * dirD) const; // Direction for download
+
+        void        FlushAndRemove();
+
+        void        AddUser(UserImpl * user);
+        void        DelUser(uint32_t uip);
+        void        SetUserNotifiers(UserImpl * user);
+        void        UnSetUserNotifiers(UserImpl * user);
+
+        typedef std::list<Rule>::iterator rule_iter;
+
+        std::list<Rule>          rules;
+
+        typedef std::map<RawPacket, PacketExtraData> Packets;
+        typedef Packets::iterator pp_iter;
+        typedef std::multimap<uint32_t, pp_iter> Index;
+        typedef Index::iterator ip2p_iter;
+        typedef Index::const_iterator ip2p_citer;
+
+        Packets packets; // Packets tree
+
+        Index ip2packets; // IP-to-Packet index
+
+        std::string              dirName[DIR_NUM + 1];
+
+        Logger &             WriteServLog;
+        std::string              rulesFileName;
+
+        std::string              monitorDir;
+        bool                     monitoring;
+        time_t                   touchTimeP;
+
+        UsersImpl *             users;
+
+        bool                     running;
+        bool                     stopped;
+        pthread_mutex_t          mutex;
+        pthread_t                thread;
+
+        std::list<TRF_IP_BEFORE> ipBeforeNotifiers;
+        std::list<TRF_IP_AFTER>  ipAfterNotifiers;
+
+        ADD_USER_NONIFIER        addUserNotifier;
+        DEL_USER_NONIFIER        delUserNotifier;
+};
+//-----------------------------------------------------------------------------
+inline
+void TRF_IP_BEFORE::Notify(const uint32_t & oldValue, const uint32_t &)
+{
+// User changes his address. Remove old IP
+if (!oldValue)
+    return;
+
+EVENT_LOOP_SINGLETON::GetInstance().Enqueue(traffCnt, &TraffCounterImpl::DelUser, oldValue);
+}
+//-----------------------------------------------------------------------------
+inline
+void TRF_IP_AFTER::Notify(const uint32_t &, const uint32_t & newValue)
+{
+// User changes his address. Add new IP
+if (!newValue)
+    return;
+
+EVENT_LOOP_SINGLETON::GetInstance().Enqueue(traffCnt, &TraffCounterImpl::AddUser, user);
+}
+//-----------------------------------------------------------------------------
+inline
+void ADD_USER_NONIFIER::Notify(const UserImplPtr & user)
+{
+EVENT_LOOP_SINGLETON::GetInstance().Enqueue(traffCnt, &TraffCounterImpl::SetUserNotifiers, user);
+}
+//-----------------------------------------------------------------------------
+inline
+void DEL_USER_NONIFIER::Notify(const UserImplPtr & user)
+{
+EVENT_LOOP_SINGLETON::GetInstance().Enqueue(traffCnt, &TraffCounterImpl::UnSetUserNotifiers, user);
+EVENT_LOOP_SINGLETON::GetInstance().Enqueue(traffCnt, &TraffCounterImpl::DelUser, user->GetCurrIP());
+}
+//-----------------------------------------------------------------------------
+}
diff --git a/projects/stargazer/user_impl.cpp b/projects/stargazer/user_impl.cpp
new file mode 100644 (file)
index 0000000..2b7cc3a
--- /dev/null
@@ -0,0 +1,1543 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Date: 27.10.2002
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+/*
+ $Revision: 1.101 $
+ $Date: 2010/11/03 10:50:03 $
+ $Author: faust $
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include "user_impl.h"
+#include "settings_impl.h"
+#include "stg_timer.h"
+
+#include "stg/users.h"
+#include "stg/common.h"
+#include "stg/scriptexecuter.h"
+#include "stg/tariff.h"
+#include "stg/tariffs.h"
+#include "stg/services.h"
+#include "stg/service_conf.h"
+#include "stg/admin.h"
+
+#include <algorithm>
+#include <functional>
+
+#include <cassert>
+#include <cstdlib>
+#include <cmath>
+
+#include <pthread.h>
+#include <unistd.h> // access
+
+using STG::UserImpl;
+
+namespace
+{
+
+std::string dirsToString(const bool * dirs)
+{
+std::string res;
+for (size_t i = 0; i < DIR_NUM; i++)
+    res += dirs[i] ? '1' : '0';
+return res;
+}
+
+void dirsFromBits(bool * dirs, uint32_t bits)
+{
+for (size_t i = 0; i < DIR_NUM; i++)
+    dirs[i] = bits & (1 << i);
+}
+
+}
+
+UserImpl::UserImpl(const Settings * s,
+           const Store * st,
+           const Tariffs * t,
+           const Admin * a,
+           const Users * u,
+           const Services & svcs)
+    : users(u),
+      properties(*s),
+      WriteServLog(Logger::get()),
+      lastScanMessages(0),
+      id(0),
+      __connected(0),
+      connected(__connected),
+      __currIP(0),
+      currIP(__currIP),
+      lastIPForDisconnect(0),
+      pingTime(0),
+      sysAdmin(a),
+      store(st),
+      tariffs(t),
+      tariff(NULL),
+      m_services(svcs),
+      settings(s),
+      authorizedModificationTime(0),
+      deleted(false),
+      lastWriteStat(0),
+      lastWriteDetailedStat(0),
+      cash(properties.cash),
+      up(properties.up),
+      down(properties.down),
+      lastCashAdd(properties.lastCashAdd),
+      passiveTime(properties.passiveTime),
+      lastCashAddTime(properties.lastCashAddTime),
+      freeMb(properties.freeMb),
+      lastActivityTime(properties.lastActivityTime),
+      password(properties.password),
+      passive(properties.passive),
+      disabled(properties.disabled),
+      disabledDetailStat(properties.disabledDetailStat),
+      alwaysOnline(properties.alwaysOnline),
+      tariffName(properties.tariffName),
+      nextTariff(properties.nextTariff),
+      address(properties.address),
+      note(properties.note),
+      group(properties.group),
+      email(properties.email),
+      phone(properties.phone),
+      realName(properties.realName),
+      credit(properties.credit),
+      creditExpire(properties.creditExpire),
+      ips(properties.ips),
+      userdata0(properties.userdata0),
+      userdata1(properties.userdata1),
+      userdata2(properties.userdata2),
+      userdata3(properties.userdata3),
+      userdata4(properties.userdata4),
+      userdata5(properties.userdata5),
+      userdata6(properties.userdata6),
+      userdata7(properties.userdata7),
+      userdata8(properties.userdata8),
+      userdata9(properties.userdata9),
+      sessionUploadModTime(stgTime),
+      sessionDownloadModTime(stgTime),
+      passiveNotifier(this),
+      disabledNotifier(this),
+      tariffNotifier(this),
+      cashNotifier(this),
+      ipNotifier(this)
+{
+Init();
+}
+//-----------------------------------------------------------------------------
+void UserImpl::Init()
+{
+password = "*_EMPTY_PASSWORD_*";
+tariffName = NO_TARIFF_NAME;
+tariff = tariffs->FindByName(tariffName);
+ips = UserIPs::parse("*");
+lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
+lastWriteDetailedStat = stgTime;
+
+properties.tariffName.AddBeforeNotifier(&tariffNotifier);
+properties.passive.AddBeforeNotifier(&passiveNotifier);
+properties.disabled.AddAfterNotifier(&disabledNotifier);
+properties.cash.AddBeforeNotifier(&cashNotifier);
+ips.AddAfterNotifier(&ipNotifier);
+
+pthread_mutexattr_t attr;
+pthread_mutexattr_init(&attr);
+pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+pthread_mutex_init(&mutex, &attr);
+}
+//-----------------------------------------------------------------------------
+UserImpl::UserImpl(const UserImpl & u)
+    : users(u.users),
+      properties(*u.settings),
+      WriteServLog(Logger::get()),
+      lastScanMessages(0),
+      login(u.login),
+      id(u.id),
+      __connected(0),
+      connected(__connected),
+      __currIP(u.__currIP),
+      currIP(__currIP),
+      lastIPForDisconnect(0),
+      pingTime(u.pingTime),
+      sysAdmin(u.sysAdmin),
+      store(u.store),
+      tariffs(u.tariffs),
+      tariff(u.tariff),
+      m_services(u.m_services),
+      traffStat(u.traffStat),
+      traffStatSaved(u.traffStatSaved),
+      settings(u.settings),
+      authorizedModificationTime(u.authorizedModificationTime),
+      messages(u.messages),
+      deleted(u.deleted),
+      lastWriteStat(u.lastWriteStat),
+      lastWriteDetailedStat(u.lastWriteDetailedStat),
+      cash(properties.cash),
+      up(properties.up),
+      down(properties.down),
+      lastCashAdd(properties.lastCashAdd),
+      passiveTime(properties.passiveTime),
+      lastCashAddTime(properties.lastCashAddTime),
+      freeMb(properties.freeMb),
+      lastActivityTime(properties.lastActivityTime),
+      password(properties.password),
+      passive(properties.passive),
+      disabled(properties.disabled),
+      disabledDetailStat(properties.disabledDetailStat),
+      alwaysOnline(properties.alwaysOnline),
+      tariffName(properties.tariffName),
+      nextTariff(properties.nextTariff),
+      address(properties.address),
+      note(properties.note),
+      group(properties.group),
+      email(properties.email),
+      phone(properties.phone),
+      realName(properties.realName),
+      credit(properties.credit),
+      creditExpire(properties.creditExpire),
+      ips(properties.ips),
+      userdata0(properties.userdata0),
+      userdata1(properties.userdata1),
+      userdata2(properties.userdata2),
+      userdata3(properties.userdata3),
+      userdata4(properties.userdata4),
+      userdata5(properties.userdata5),
+      userdata6(properties.userdata6),
+      userdata7(properties.userdata7),
+      userdata8(properties.userdata8),
+      userdata9(properties.userdata9),
+      sessionUpload(),
+      sessionDownload(),
+      sessionUploadModTime(stgTime),
+      sessionDownloadModTime(stgTime),
+      passiveNotifier(this),
+      disabledNotifier(this),
+      tariffNotifier(this),
+      cashNotifier(this),
+      ipNotifier(this)
+{
+if (&u == this)
+    return;
+
+properties.tariffName.AddBeforeNotifier(&tariffNotifier);
+properties.passive.AddBeforeNotifier(&passiveNotifier);
+properties.disabled.AddAfterNotifier(&disabledNotifier);
+properties.cash.AddBeforeNotifier(&cashNotifier);
+ips.AddAfterNotifier(&ipNotifier);
+
+properties.SetProperties(u.properties);
+
+pthread_mutexattr_t attr;
+pthread_mutexattr_init(&attr);
+pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+pthread_mutex_init(&mutex, &attr);
+}
+//-----------------------------------------------------------------------------
+UserImpl::~UserImpl()
+{
+properties.tariffName.DelBeforeNotifier(&tariffNotifier);
+properties.passive.DelBeforeNotifier(&passiveNotifier);
+properties.disabled.DelAfterNotifier(&disabledNotifier);
+properties.cash.DelBeforeNotifier(&cashNotifier);
+pthread_mutex_destroy(&mutex);
+}
+//-----------------------------------------------------------------------------
+void UserImpl::SetLogin(const std::string & l)
+{
+STG_LOCKER lock(&mutex);
+static int idGen = 0;
+assert(login.empty() && "Login is already set");
+login = l;
+id = idGen++;
+}
+//-----------------------------------------------------------------------------
+int UserImpl::ReadConf()
+{
+STG_LOCKER lock(&mutex);
+UserConf conf;
+
+if (store->RestoreUserConf(&conf, login))
+    {
+    WriteServLog("Cannot read conf for user %s.", login.c_str());
+    WriteServLog("%s", store->GetStrError().c_str());
+    printfd(__FILE__, "Cannot read conf for user %s.\n", login.c_str());
+    printfd(__FILE__, "%s\n", store->GetStrError().c_str());
+    return -1;
+    }
+
+properties.SetConf(conf);
+
+tariff = tariffs->FindByName(tariffName);
+if (tariff == NULL)
+    {
+    WriteServLog("Cannot read user %s. Tariff %s not exist.",
+                 login.c_str(), properties.tariffName.Get().c_str());
+    return -1;
+    }
+
+std::vector<Message::Header> hdrsList;
+
+if (store->GetMessageHdrs(&hdrsList, login))
+    {
+    printfd(__FILE__, "Error GetMessageHdrs %s\n", store->GetStrError().c_str());
+    WriteServLog("Cannot read user %s. Error reading message headers: %s.",
+                 login.c_str(),
+                 store->GetStrError().c_str());
+    return -1;
+    }
+
+std::vector<Message::Header>::const_iterator it;
+for (it = hdrsList.begin(); it != hdrsList.end(); ++it)
+    {
+    Message msg;
+    if (store->GetMessage(it->id, &msg, login) == 0)
+        {
+        messages.push_back(msg);
+        }
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int UserImpl::ReadStat()
+{
+STG_LOCKER lock(&mutex);
+UserStat stat;
+
+if (store->RestoreUserStat(&stat, login))
+    {
+    WriteServLog("Cannot read stat for user %s.", login.c_str());
+    WriteServLog("%s", store->GetStrError().c_str());
+    printfd(__FILE__, "Cannot read stat for user %s.\n", login.c_str());
+    printfd(__FILE__, "%s\n", store->GetStrError().c_str());
+    return -1;
+    }
+
+properties.SetStat(stat);
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int UserImpl::WriteConf()
+{
+STG_LOCKER lock(&mutex);
+UserConf conf(properties.GetConf());
+
+printfd(__FILE__, "UserImpl::WriteConf()\n");
+
+if (store->SaveUserConf(conf, login))
+    {
+    WriteServLog("Cannot write conf for user %s.", login.c_str());
+    WriteServLog("%s", store->GetStrError().c_str());
+    printfd(__FILE__, "Cannot write conf for user %s.\n", login.c_str());
+    printfd(__FILE__, "%s\n", store->GetStrError().c_str());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int UserImpl::WriteStat()
+{
+STG_LOCKER lock(&mutex);
+UserStat stat(properties.GetStat());
+
+if (store->SaveUserStat(stat, login))
+    {
+    WriteServLog("Cannot write stat for user %s.", login.c_str());
+    WriteServLog("%s", store->GetStrError().c_str());
+    printfd(__FILE__, "Cannot write stat for user %s.\n", login.c_str());
+    printfd(__FILE__, "%s\n", store->GetStrError().c_str());
+    return -1;
+    }
+
+lastWriteStat = stgTime;
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int UserImpl::WriteMonthStat()
+{
+STG_LOCKER lock(&mutex);
+time_t tt = stgTime - 3600;
+struct tm t1;
+localtime_r(&tt, &t1);
+
+UserStat stat(properties.GetStat());
+if (store->SaveMonthStat(stat, t1.tm_mon, t1.tm_year, login))
+    {
+    WriteServLog("Cannot write month stat for user %s.", login.c_str());
+    WriteServLog("%s", store->GetStrError().c_str());
+    printfd(__FILE__, "Cannot write month stat for user %s.\n", login.c_str());
+    printfd(__FILE__, "%s\n", store->GetStrError().c_str());
+    return -1;
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int UserImpl::Authorize(uint32_t ip, uint32_t dirs, const Auth * auth)
+{
+STG_LOCKER lock(&mutex);
+/*
+ *  Authorize user. It only means that user will be authorized. Nothing more.
+ *  User can be connected or disconnected while authorized.
+ *  Example: user is authorized but disconnected due to 0 money or blocking
+ */
+
+/*
+ * TODO: in fact "authorization" means allowing access to a service. What we
+ * call "authorization" here, int STG, is "authentication". So this should be
+ * fixed in future.
+ */
+
+/*
+ * Prevent double authorization by identical authorizers
+ */
+if (authorizedBy.find(auth) != authorizedBy.end())
+    return 0;
+
+if (!ip)
+    return -1;
+
+dirsFromBits(enabledDirs, dirs);
+
+if (!authorizedBy.empty())
+    {
+    if (currIP != ip)
+        {
+        // We are already authorized, but with different IP address
+        errorStr = "User " + login + " already authorized with IP address " + inet_ntostring(ip);
+        return -1;
+        }
+
+    User * u = NULL;
+    if (!users->FindByIPIdx(ip, &u))
+        {
+        // Address presents in IP-index.
+        // If it's not our IP - report it.
+        if (u != this)
+            {
+            errorStr = "IP address " + inet_ntostring(ip) + " is already in use";
+            return -1;
+            }
+        }
+    }
+else
+    {
+    if (users->IsIPInIndex(ip))
+        {
+        // Address is already present in IP-index.
+        errorStr = "IP address " + inet_ntostring(ip) + " is already in use";
+        return -1;
+        }
+
+    if (ips.ConstData().find(ip))
+        {
+        currIP = ip;
+        lastIPForDisconnect = currIP;
+        }
+    else
+        {
+        printfd(__FILE__, " user %s: ips = %s\n", login.c_str(), ips.ConstData().toString().c_str());
+        errorStr = "IP address " + inet_ntostring(ip) + " does not belong to user " + login;
+        return -1;
+        }
+    }
+
+if (authorizedBy.empty())
+    authorizedModificationTime = stgTime;
+authorizedBy.insert(auth);
+
+ScanMessage();
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+void UserImpl::Unauthorize(const Auth * auth, const std::string & reason)
+{
+STG_LOCKER lock(&mutex);
+/*
+ *  Authorizer tries to unauthorize user, that was not authorized by it
+ */
+if (!authorizedBy.erase(auth))
+    return;
+
+authorizedModificationTime = stgTime;
+
+if (authorizedBy.empty())
+    {
+    lastDisconnectReason = reason;
+    lastIPForDisconnect = currIP;
+    currIP = 0; // DelUser in traffcounter
+    if (connected)
+        Disconnect(false, "not authorized");
+    return;
+    }
+}
+//-----------------------------------------------------------------------------
+bool UserImpl::IsAuthorizedBy(const Auth * auth) const
+{
+STG_LOCKER lock(&mutex);
+// Is this user authorized by specified authorizer?
+return authorizedBy.find(auth) != authorizedBy.end();
+}
+//-----------------------------------------------------------------------------
+std::vector<std::string> UserImpl::GetAuthorizers() const
+{
+    STG_LOCKER lock(&mutex);
+    std::vector<std::string> list;
+    std::transform(authorizedBy.begin(), authorizedBy.end(), std::back_inserter(list), [](const auto auth){ return auth->GetVersion(); });
+    return list;
+}
+//-----------------------------------------------------------------------------
+void UserImpl::Connect(bool fakeConnect)
+{
+/*
+ * Connect user to Internet. This function is differ from Authorize() !!!
+ */
+
+STG_LOCKER lock(&mutex);
+
+if (!fakeConnect)
+    {
+    std::string scriptOnConnect = settings->GetScriptsDir() + "/OnConnect";
+
+    if (access(scriptOnConnect.c_str(), X_OK) == 0)
+        {
+        std::string dirs = dirsToString(enabledDirs);
+
+        std::string scriptOnConnectParams;
+        strprintf(&scriptOnConnectParams,
+                  "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
+                  scriptOnConnect.c_str(),
+                  login.c_str(),
+                  inet_ntostring(currIP).c_str(),
+                  cash.ConstData(),
+                  id,
+                  dirs.c_str());
+
+        std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
+        while (it != settings->GetScriptParams().end())
+            {
+            scriptOnConnectParams += " \"" + GetParamValue(it->c_str()) + "\"";
+            ++it;
+            }
+
+        ScriptExec(scriptOnConnectParams.c_str());
+        }
+    else
+        {
+        WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
+        }
+
+    connected = true;
+    }
+
+if (!settings->GetDisableSessionLog() && store->WriteUserConnect(login, currIP))
+    {
+    WriteServLog("Cannot write connect for user %s.", login.c_str());
+    WriteServLog("%s", store->GetStrError().c_str());
+    }
+
+if (!fakeConnect)
+    lastIPForDisconnect = currIP;
+}
+//-----------------------------------------------------------------------------
+void UserImpl::Disconnect(bool fakeDisconnect, const std::string & reason)
+{
+/*
+ *  Disconnect user from Internet. This function is differ from UnAuthorize() !!!
+ */
+
+STG_LOCKER lock(&mutex);
+
+if (!lastIPForDisconnect)
+    {
+    printfd(__FILE__, "lastIPForDisconnect\n");
+    return;
+    }
+
+if (!fakeDisconnect)
+    {
+    lastDisconnectReason = reason;
+    std::string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect";
+
+    if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
+        {
+        std::string dirs = dirsToString(enabledDirs);
+
+        std::string scriptOnDisonnectParams;
+        strprintf(&scriptOnDisonnectParams,
+                "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
+                scriptOnDisonnect.c_str(),
+                login.c_str(),
+                inet_ntostring(lastIPForDisconnect).c_str(),
+                cash.ConstData(),
+                id,
+                dirs.c_str());
+
+        std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
+        while (it != settings->GetScriptParams().end())
+            {
+            scriptOnDisonnectParams += " \"" + GetParamValue(it->c_str()) + "\"";
+            ++it;
+            }
+
+        ScriptExec(scriptOnDisonnectParams.c_str());
+        }
+    else
+        {
+        WriteServLog("Script OnDisconnect cannot be executed. File not found.");
+        }
+
+    connected = false;
+    }
+
+std::string reasonMessage(reason);
+if (!lastDisconnectReason.empty())
+    reasonMessage += ": " + lastDisconnectReason;
+
+if (!settings->GetDisableSessionLog() && store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload,
+                                                                    cash, freeMb, reasonMessage))
+    {
+    WriteServLog("Cannot write disconnect for user %s.", login.c_str());
+    WriteServLog("%s", store->GetStrError().c_str());
+    }
+
+if (!fakeDisconnect)
+    lastIPForDisconnect = 0;
+
+sessionUpload.reset();
+sessionDownload.reset();
+sessionUploadModTime = stgTime;
+sessionDownloadModTime = stgTime;
+}
+//-----------------------------------------------------------------------------
+void UserImpl::Run()
+{
+STG_LOCKER lock(&mutex);
+
+if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
+    {
+    printfd(__FILE__, "UserImpl::WriteStat user=%s\n", GetLogin().c_str());
+    WriteStat();
+    }
+if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
+    {
+    WriteServLog("User: %s. Credit expired.", login.c_str());
+    credit = 0;
+    creditExpire = 0;
+    WriteConf();
+    }
+
+if (passive.ConstData()
+    && (stgTime % 30 == 0)
+    && (passiveTime.ModificationTime() != stgTime))
+    {
+    passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
+    printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
+    }
+
+if (!authorizedBy.empty())
+    {
+    if (connected)
+        properties.Stat().lastActivityTime = stgTime;
+
+    if (!connected && IsInetable())
+        Connect();
+
+    if (connected && !IsInetable())
+        {
+        if (disabled)
+            Disconnect(false, "disabled");
+        else if (passive)
+            Disconnect(false, "passive");
+        else
+            Disconnect(false, "no cash");
+        }
+
+    if (stgTime - lastScanMessages > 10)
+        {
+        ScanMessage();
+        lastScanMessages = stgTime;
+        }
+    }
+else
+    {
+    if (connected)
+        Disconnect(false, "not authorized");
+    }
+
+}
+//-----------------------------------------------------------------------------
+void UserImpl::UpdatePingTime(time_t t)
+{
+STG_LOCKER lock(&mutex);
+if (t)
+    pingTime = t;
+else
+    pingTime = stgTime;
+}
+//-----------------------------------------------------------------------------
+bool UserImpl::IsInetable()
+{
+if (disabled || passive)
+    return false;
+
+if (settings->GetFreeMbAllowInet())
+    {
+    if (freeMb >= 0)
+        return true;
+    }
+
+if (settings->GetShowFeeInCash() || tariff == NULL)
+    return (cash >= -credit);
+
+return (cash - tariff->GetFee() >= -credit);
+}
+//-----------------------------------------------------------------------------
+std::string UserImpl::GetEnabledDirs() const
+{
+return dirsToString(enabledDirs);
+}
+//-----------------------------------------------------------------------------
+#ifdef TRAFF_STAT_WITH_PORTS
+void UserImpl::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
+#else
+void UserImpl::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
+#endif
+{
+STG_LOCKER lock(&mutex);
+
+if (!connected || tariff == NULL)
+    return;
+
+double cost = 0;
+DirTraff dt(up);
+
+int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
+int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
+
+dt[dir] += len;
+
+int tt = tariff->GetTraffType();
+if (tt == Tariff::TRAFF_UP ||
+    tt == Tariff::TRAFF_UP_DOWN ||
+    // Check NEW traff data
+    (tt == Tariff::TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
+    {
+    double dc = 0;
+    if (traff < threshold &&
+        traff + len >= threshold)
+        {
+        // cash = partBeforeThreshold * priceBeforeThreshold +
+        //        partAfterThreshold * priceAfterThreshold
+        int64_t before = threshold - traff; // Chunk part before threshold
+        int64_t after = len - before; // Chunk part after threshold
+        dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
+                                           down.ConstData()[dir],
+                                           dir,
+                                           stgTime) * before +
+             tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
+                                           down.ConstData()[dir],
+                                           dir,
+                                           stgTime) * after;
+        }
+    else
+        {
+        dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
+                                           down.ConstData()[dir],
+                                           dir,
+                                           stgTime) * len;
+        }
+
+    if (freeMb.ConstData() <= 0) // FreeMb is exhausted
+        cost = dc;
+    else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
+        cost = dc - freeMb.ConstData();
+
+    // Direct access to internal data structures via friend-specifier
+    properties.Stat().freeMb -= dc;
+    properties.Stat().cash -= cost;
+    cash.ModifyTime();
+    freeMb.ModifyTime();
+    }
+
+up = dt;
+sessionUpload[dir] += len;
+sessionUploadModTime = stgTime;
+
+//Add detailed stat
+
+if (!settings->GetWriteFreeMbTraffCost() &&
+     freeMb.ConstData() >= 0)
+    cost = 0;
+
+#ifdef TRAFF_STAT_WITH_PORTS
+IPDirPair idp(ip, dir, port);
+#else
+IPDirPair idp(ip, dir);
+#endif
+
+std::map<IPDirPair, StatNode>::iterator lb;
+lb = traffStat.lower_bound(idp);
+if (lb == traffStat.end() || lb->first != idp)
+    {
+    traffStat.insert(lb,
+                     std::make_pair(idp,
+                                    StatNode(len, 0, cost)));
+    }
+else
+    {
+    lb->second.cash += cost;
+    lb->second.up += len;
+    }
+}
+//-----------------------------------------------------------------------------
+#ifdef TRAFF_STAT_WITH_PORTS
+void UserImpl::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
+#else
+void UserImpl::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
+#endif
+{
+STG_LOCKER lock(&mutex);
+
+if (!connected || tariff == NULL)
+    return;
+
+double cost = 0;
+DirTraff dt(down);
+
+int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
+int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
+
+dt[dir] += len;
+
+int tt = tariff->GetTraffType();
+if (tt == Tariff::TRAFF_DOWN ||
+    tt == Tariff::TRAFF_UP_DOWN ||
+    // Check NEW traff data
+    (tt == Tariff::TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
+    {
+    double dc = 0;
+    if (traff < threshold &&
+        traff + len >= threshold)
+        {
+        // cash = partBeforeThreshold * priceBeforeThreshold +
+        //        partAfterThreshold * priceAfterThreshold
+        int64_t before = threshold - traff; // Chunk part before threshold
+        int64_t after = len - before; // Chunk part after threshold
+        dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
+                                           down.ConstData()[dir], // Traff before chunk
+                                           dir,
+                                           stgTime) * before +
+             tariff->GetPriceWithTraffType(up.ConstData()[dir],
+                                           dt[dir], // Traff after chunk
+                                           dir,
+                                           stgTime) * after;
+        }
+    else
+        {
+        dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
+                                           down.ConstData()[dir],
+                                           dir,
+                                           stgTime) * len;
+        }
+
+    if (freeMb.ConstData() <= 0) // FreeMb is exhausted
+        cost = dc;
+    else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
+        cost = dc - freeMb.ConstData();
+
+    properties.Stat().freeMb -= dc;
+    properties.Stat().cash -= cost;
+    cash.ModifyTime();
+    freeMb.ModifyTime();
+    }
+
+down = dt;
+sessionDownload[dir] += len;
+sessionDownloadModTime = stgTime;
+
+//Add detailed stat
+
+if (!settings->GetWriteFreeMbTraffCost() &&
+     freeMb.ConstData() >= 0)
+    cost = 0;
+
+#ifdef TRAFF_STAT_WITH_PORTS
+IPDirPair idp(ip, dir, port);
+#else
+IPDirPair idp(ip, dir);
+#endif
+
+std::map<IPDirPair, StatNode>::iterator lb;
+lb = traffStat.lower_bound(idp);
+if (lb == traffStat.end() || lb->first != idp)
+    {
+    traffStat.insert(lb,
+                     std::make_pair(idp,
+                                    StatNode(0, len, cost)));
+    }
+else
+    {
+    lb->second.cash += cost;
+    lb->second.down += len;
+    }
+}
+//-----------------------------------------------------------------------------
+void UserImpl::AddCurrIPBeforeNotifier(CURR_IP_NOTIFIER * notifier)
+{
+STG_LOCKER lock(&mutex);
+currIP.AddBeforeNotifier(notifier);
+}
+//-----------------------------------------------------------------------------
+void UserImpl::DelCurrIPBeforeNotifier(const CURR_IP_NOTIFIER * notifier)
+{
+STG_LOCKER lock(&mutex);
+currIP.DelBeforeNotifier(notifier);
+}
+//-----------------------------------------------------------------------------
+void UserImpl::AddCurrIPAfterNotifier(CURR_IP_NOTIFIER * notifier)
+{
+STG_LOCKER lock(&mutex);
+currIP.AddAfterNotifier(notifier);
+}
+//-----------------------------------------------------------------------------
+void UserImpl::DelCurrIPAfterNotifier(const CURR_IP_NOTIFIER * notifier)
+{
+STG_LOCKER lock(&mutex);
+currIP.DelAfterNotifier(notifier);
+}
+//-----------------------------------------------------------------------------
+void UserImpl::AddConnectedBeforeNotifier(CONNECTED_NOTIFIER * notifier)
+{
+STG_LOCKER lock(&mutex);
+connected.AddBeforeNotifier(notifier);
+}
+//-----------------------------------------------------------------------------
+void UserImpl::DelConnectedBeforeNotifier(const CONNECTED_NOTIFIER * notifier)
+{
+STG_LOCKER lock(&mutex);
+connected.DelBeforeNotifier(notifier);
+}
+//-----------------------------------------------------------------------------
+void UserImpl::AddConnectedAfterNotifier(CONNECTED_NOTIFIER * notifier)
+{
+STG_LOCKER lock(&mutex);
+connected.AddAfterNotifier(notifier);
+}
+//-----------------------------------------------------------------------------
+void UserImpl::DelConnectedAfterNotifier(const CONNECTED_NOTIFIER * notifier)
+{
+STG_LOCKER lock(&mutex);
+connected.DelAfterNotifier(notifier);
+}
+//-----------------------------------------------------------------------------
+void UserImpl::OnAdd()
+{
+STG_LOCKER lock(&mutex);
+
+std::string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
+
+if (access(scriptOnAdd.c_str(), X_OK) == 0)
+    {
+    std::string scriptOnAddParams = scriptOnAdd + " \"" + login + "\"";
+
+    ScriptExec(scriptOnAddParams.c_str());
+    }
+else
+    {
+    WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
+    }
+}
+//-----------------------------------------------------------------------------
+void UserImpl::OnDelete()
+{
+STG_LOCKER lock(&mutex);
+
+std::string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
+
+if (access(scriptOnDel.c_str(), X_OK) == 0)
+    {
+    std::string scriptOnDelParams = scriptOnDel + " \"" + login + "\"";
+
+    ScriptExec(scriptOnDelParams.c_str());
+    }
+else
+    {
+    WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
+    }
+
+Run();
+}
+//-----------------------------------------------------------------------------
+int UserImpl::WriteDetailStat(bool hard)
+{
+printfd(__FILE__, "UserImpl::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
+
+if (!traffStatSaved.second.empty())
+    {
+    if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
+        {
+        printfd(__FILE__, "UserImpl::WriteDetailStat() - failed to write detail stat from queue\n");
+        WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
+        WriteServLog("%s", store->GetStrError().c_str());
+        return -1;
+        }
+    traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
+    }
+
+TraffStat ts;
+
+    {
+    STG_LOCKER lock(&mutex);
+    ts.swap(traffStat);
+    }
+
+printfd(__FILE__, "UserImpl::WriteDetailedStat() - size = %d\n", ts.size());
+
+if (ts.size() && !disabledDetailStat)
+    {
+    if (store->WriteDetailedStat(ts, lastWriteDetailedStat, login))
+        {
+        printfd(__FILE__, "UserImpl::WriteDetailStat() - failed to write current detail stat\n");
+        WriteServLog("Cannot write detail stat for user %s.", login.c_str());
+        WriteServLog("%s", store->GetStrError().c_str());
+        if (!hard)
+            {
+            printfd(__FILE__, "UserImpl::WriteDetailStat() - pushing detail stat to queue\n");
+            STG_LOCKER lock(&mutex);
+            traffStatSaved.second.swap(ts);
+            traffStatSaved.first = lastWriteDetailedStat;
+            }
+        return -1;
+        }
+    }
+lastWriteDetailedStat = stgTime;
+return 0;
+}
+//-----------------------------------------------------------------------------
+double UserImpl::GetPassiveTimePart() const
+{
+STG_LOCKER lock(&mutex);
+
+static int daysInMonth[12] =
+{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+struct tm tms;
+time_t t = stgTime;
+localtime_r(&t, &tms);
+
+time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
+
+if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
+    {
+    // Leap year
+    secMonth += 24 * 3600;
+    }
+
+time_t dt = secMonth - passiveTime;
+
+if (dt < 0)
+    dt = 0;
+
+return static_cast<double>(dt) / secMonth;
+}
+//-----------------------------------------------------------------------------
+void UserImpl::SetPassiveTimeAsNewUser()
+{
+STG_LOCKER lock(&mutex);
+
+time_t t = stgTime;
+struct tm tm;
+localtime_r(&t, &tm);
+int daysCurrMon = DaysInCurrentMonth();
+double pt = tm.tm_mday - 1;
+pt /= daysCurrMon;
+
+passiveTime = static_cast<time_t>(pt * 24 * 3600 * daysCurrMon);
+}
+//-----------------------------------------------------------------------------
+void UserImpl::MidnightResetSessionStat()
+{
+STG_LOCKER lock(&mutex);
+
+if (connected)
+    {
+    Disconnect(true, "fake");
+    Connect(true);
+    }
+}
+//-----------------------------------------------------------------------------
+void UserImpl::ProcessNewMonth()
+{
+STG_LOCKER lock(&mutex);
+//  Reset traff
+if (connected)
+    Disconnect(true, "fake");
+
+WriteMonthStat();
+
+properties.Stat().monthUp.reset();
+properties.Stat().monthDown.reset();
+
+if (connected)
+    Connect(true);
+
+//  Set new tariff
+if (nextTariff.ConstData() != "")
+    {
+    const Tariff * nt = tariffs->FindByName(nextTariff);
+    if (nt == NULL)
+        {
+        WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
+                     login.c_str(), properties.tariffName.Get().c_str());
+        }
+    else
+        {
+        std::string message = tariff->TariffChangeIsAllowed(*nt, stgTime);
+        if (message.empty())
+            {
+            properties.tariffName.Set(nextTariff, *sysAdmin, login, *store);
+            }
+        else
+            {
+            WriteServLog("Tariff change is prohibited for user %s. %s",
+                         login.c_str(),
+                         message.c_str());
+            }
+        }
+    ResetNextTariff();
+    WriteConf();
+    }
+}
+//-----------------------------------------------------------------------------
+void UserImpl::ProcessDayFeeSpread()
+{
+STG_LOCKER lock(&mutex);
+
+if (passive.ConstData() || tariff == NULL)
+    return;
+
+if (tariff->GetPeriod() != Tariff::MONTH)
+    return;
+
+double fee = tariff->GetFee() / DaysInCurrentMonth();
+
+if (std::fabs(fee) < 1.0e-3)
+    return;
+
+double c = cash;
+switch (settings->GetFeeChargeType())
+    {
+    case 0:
+        properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
+        break;
+    case 1:
+        if (c + credit >= 0)
+            properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
+        break;
+    case 2:
+        if (c + credit >= fee)
+            properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
+        break;
+    case 3:
+        if (c >= 0)
+            properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
+        break;
+    }
+ResetPassiveTime();
+}
+//-----------------------------------------------------------------------------
+void UserImpl::ProcessDayFee()
+{
+STG_LOCKER lock(&mutex);
+
+if (tariff == NULL)
+    return;
+
+if (tariff->GetPeriod() != Tariff::MONTH)
+    return;
+
+double passiveTimePart = 1.0;
+if (!settings->GetFullFee())
+    {
+    passiveTimePart = GetPassiveTimePart();
+    }
+else
+    {
+    if (passive.ConstData())
+        {
+        printfd(__FILE__, "Don't charge fee `cause we are passive\n");
+        return;
+        }
+    }
+double fee = tariff->GetFee() * passiveTimePart;
+
+ResetPassiveTime();
+
+if (std::fabs(fee) < 1.0e-3)
+    {
+    SetPrepaidTraff();
+    return;
+    }
+
+double c = cash;
+printfd(__FILE__, "login: %8s Cash=%f Credit=%f  Fee=%f PassiveTimePart=%f fee=%f\n",
+        login.c_str(),
+        cash.ConstData(),
+        credit.ConstData(),
+        tariff->GetFee(),
+        passiveTimePart,
+        fee);
+switch (settings->GetFeeChargeType())
+    {
+    case 0:
+        properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
+        SetPrepaidTraff();
+        break;
+    case 1:
+        if (c + credit >= 0)
+            {
+            properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
+            SetPrepaidTraff();
+            }
+        break;
+    case 2:
+        if (c + credit >= fee)
+            {
+            properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
+            SetPrepaidTraff();
+            }
+        break;
+    case 3:
+        if (c >= 0)
+            {
+            properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
+            SetPrepaidTraff();
+            }
+        break;
+    }
+}
+//-----------------------------------------------------------------------------
+void UserImpl::ProcessDailyFee()
+{
+STG_LOCKER lock(&mutex);
+
+if (passive.ConstData() || tariff == NULL)
+    return;
+
+if (tariff->GetPeriod() != Tariff::DAY)
+    return;
+
+double fee = tariff->GetFee();
+
+if (fee == 0.0)
+    return;
+
+double c = cash;
+switch (settings->GetFeeChargeType())
+    {
+    case 0:
+        properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
+        break;
+    case 1:
+        if (c + credit >= 0)
+            properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
+        break;
+    case 2:
+        if (c + credit >= fee)
+            properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
+        break;
+    }
+ResetPassiveTime();
+}
+//-----------------------------------------------------------------------------
+void UserImpl::ProcessServices()
+{
+struct tm tms;
+time_t t = stgTime;
+localtime_r(&t, &tms);
+
+double passiveTimePart = 1.0;
+if (!settings->GetFullFee())
+    {
+    passiveTimePart = GetPassiveTimePart();
+    }
+else
+    {
+    if (passive.ConstData())
+        {
+        printfd(__FILE__, "Don't charge fee `cause we are passive\n");
+        return;
+        }
+    }
+
+for (size_t i = 0; i < properties.Conf().services.size(); ++i)
+    {
+    ServiceConf conf;
+    if (m_services.Find(properties.Conf().services[i], &conf))
+        continue;
+    if (conf.payDay == tms.tm_mday ||
+        (conf.payDay == 0 && tms.tm_mday == DaysInCurrentMonth()))
+        {
+        double c = cash;
+        double fee = conf.cost * passiveTimePart;
+        printfd(__FILE__, "Service fee. login: %8s Cash=%f Credit=%f  Fee=%f PassiveTimePart=%f fee=%f\n",
+                login.c_str(),
+                cash.ConstData(),
+                credit.ConstData(),
+                tariff->GetFee(),
+                passiveTimePart,
+                fee);
+        switch (settings->GetFeeChargeType())
+            {
+            case 0:
+                properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
+                SetPrepaidTraff();
+                break;
+            case 1:
+                if (c + credit >= 0)
+                    {
+                    properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
+                    SetPrepaidTraff();
+                    }
+                break;
+            case 2:
+                if (c + credit >= fee)
+                    {
+                    properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
+                    SetPrepaidTraff();
+                    }
+                break;
+            case 3:
+                if (c >= 0)
+                    {
+                    properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
+                    SetPrepaidTraff();
+                    }
+                break;
+            }
+        }
+    }
+}
+//-----------------------------------------------------------------------------
+void UserImpl::SetPrepaidTraff()
+{
+if (tariff != NULL)
+    properties.freeMb.Set(tariff->GetFree(), *sysAdmin, login, *store, "Prepaid traffic");
+}
+//-----------------------------------------------------------------------------
+int UserImpl::AddMessage(Message * msg)
+{
+STG_LOCKER lock(&mutex);
+
+if (SendMessage(*msg))
+    {
+    if (store->AddMessage(msg, login))
+        {
+        errorStr = store->GetStrError();
+        WriteServLog("Error adding message: '%s'", errorStr.c_str());
+        printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
+        return -1;
+        }
+    messages.push_back(*msg);
+    }
+else
+    {
+    if (msg->header.repeat > 0)
+        {
+        msg->header.repeat--;
+        #ifndef DEBUG
+        //TODO: gcc v. 4.x generate ICE on x86_64
+        msg->header.lastSendTime = static_cast<int>(time(NULL));
+        #else
+        msg->header.lastSendTime = static_cast<int>(stgTime);
+        #endif
+        if (store->AddMessage(msg, login))
+            {
+            errorStr = store->GetStrError();
+            WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
+            printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
+            return -1;
+            }
+        messages.push_back(*msg);
+        }
+    }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int UserImpl::SendMessage(Message & msg) const
+{
+// No lock `cause we are already locked from caller
+int ret = -1;
+std::set<const Auth*>::iterator it(authorizedBy.begin());
+while (it != authorizedBy.end())
+    {
+    if (!(*it++)->SendMessage(msg, currIP))
+        ret = 0;
+    }
+if (!ret)
+    {
+#ifndef DEBUG
+    //TODO: gcc v. 4.x generate ICE on x86_64
+    msg.header.lastSendTime = static_cast<int>(time(NULL));
+#else
+    msg.header.lastSendTime = static_cast<int>(stgTime);
+#endif
+    msg.header.repeat--;
+    }
+return ret;
+}
+//-----------------------------------------------------------------------------
+void UserImpl::ScanMessage()
+{
+// No lock `cause we are already locked from caller
+// We need not check for the authorizedBy `cause it has already checked by caller
+
+auto it = messages.begin();
+while (it != messages.end())
+    {
+    if (settings->GetMessageTimeout() > 0 &&
+        difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
+        {
+        // Timeout exceeded
+        if (store->DelMessage(it->header.id, login))
+            {
+            WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
+            printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
+            }
+        messages.erase(it++);
+        continue;
+        }
+    if (it->GetNextSendTime() <= stgTime)
+        {
+        if (SendMessage(*it))
+            {
+            // We need to check all messages in queue for timeout
+            ++it;
+            continue;
+            }
+        if (it->header.repeat < 0)
+            {
+            if (store->DelMessage(it->header.id, login))
+                {
+                WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
+                printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
+                }
+            messages.erase(it++);
+            }
+        else
+            {
+            if (store->EditMessage(*it, login))
+                {
+                WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
+                printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
+                }
+            ++it;
+            }
+        }
+    else
+        {
+        ++it;
+        }
+    }
+}
+//-----------------------------------------------------------------------------
+std::string UserImpl::GetParamValue(const std::string & name) const
+{
+    std::string lowerName = ToLower(name);
+    if (lowerName == "id")
+        {
+        std::ostringstream stream;
+        stream << id;
+        return stream.str();
+        }
+    if (lowerName == "login")       return login;
+    if (lowerName == "currip")      return currIP.ToString();
+    if (lowerName == "enableddirs") return GetEnabledDirs();
+    if (lowerName == "tariff")      return properties.tariffName;
+    if (properties.Exists(lowerName))
+        return properties.GetPropertyValue(lowerName);
+    else
+        {
+        WriteServLog("User’s parameter '%s' does not exist.", name.c_str());
+        return "";
+        }
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void STG::CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
+{
+if (newPassive && !oldPassive && user->tariff != NULL)
+    user->properties.cash.Set(user->cash - user->tariff->GetPassiveCost(),
+                            *user->sysAdmin,
+                            user->login,
+                            *user->store,
+                            "Freeze");
+}
+//-----------------------------------------------------------------------------
+void STG::CHG_DISABLED_NOTIFIER::Notify(const int & oldValue, const int & newValue)
+{
+if (oldValue && !newValue && user->GetConnected())
+    user->Disconnect(false, "disabled");
+else if (!oldValue && newValue && user->IsInetable())
+    user->Connect(false);
+}
+//-----------------------------------------------------------------------------
+void STG::CHG_TARIFF_NOTIFIER::Notify(const std::string &, const std::string & newTariff)
+{
+STG_LOCKER lock(&user->mutex);
+if (user->settings->GetReconnectOnTariffChange() && user->connected)
+    user->Disconnect(false, "Change tariff");
+user->tariff = user->tariffs->FindByName(newTariff);
+if (user->settings->GetReconnectOnTariffChange() &&
+    !user->authorizedBy.empty() &&
+    user->IsInetable())
+    {
+    // This notifier gets called *before* changing the tariff, and in Connect we want to see new tariff name.
+    user->properties.Conf().tariffName = newTariff;
+    user->Connect(false);
+    }
+}
+//-----------------------------------------------------------------------------
+void STG::CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
+{
+user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
+user->lastCashAdd = newCash - oldCash;
+}
+//-----------------------------------------------------------------------------
+void STG::CHG_IPS_NOTIFIER::Notify(const UserIPs & from, const UserIPs & to)
+{
+printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.toString().c_str(), to.toString().c_str());
+if (user->connected)
+    user->Disconnect(false, "Change IP");
+if (!user->authorizedBy.empty() && user->IsInetable())
+    user->Connect(false);
+}
diff --git a/projects/stargazer/user_impl.h b/projects/stargazer/user_impl.h
new file mode 100644 (file)
index 0000000..2e254d6
--- /dev/null
@@ -0,0 +1,324 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+#pragma once
+
+#include "stg/user.h"
+#include "stg/user_stat.h"
+#include "stg/user_conf.h"
+#include "stg/user_ips.h"
+#include "stg/user_property.h"
+#include "stg/auth.h"
+#include "stg/message.h"
+#include "stg/noncopyable.h"
+#include "stg/const.h"
+
+#include <vector>
+#include <string>
+#include <set>
+
+#include <ctime>
+#include <cstdint>
+
+namespace STG
+{
+
+//-----------------------------------------------------------------------------
+struct Tariff;
+struct Tariffs;
+struct Admin;
+class UserImpl;
+#ifdef USE_ABSTRACT_SETTINGS
+struct Settings;
+#else
+class SettingsImpl;
+#endif
+//-----------------------------------------------------------------------------
+class CHG_PASSIVE_NOTIFIER : public PropertyNotifierBase<int> {
+    public:
+        explicit CHG_PASSIVE_NOTIFIER(UserImpl * u) : user(u) {}
+        void Notify(const int & oldPassive, const int & newPassive);
+
+    private:
+        UserImpl * user;
+};
+//-----------------------------------------------------------------------------
+class CHG_DISABLED_NOTIFIER : public PropertyNotifierBase<int> {
+public:
+    explicit CHG_DISABLED_NOTIFIER(UserImpl * u) : user(u) {}
+    void Notify(const int & oldValue, const int & newValue);
+
+private:
+    UserImpl * user;
+};
+//-----------------------------------------------------------------------------
+class CHG_TARIFF_NOTIFIER : public PropertyNotifierBase<std::string> {
+public:
+    explicit CHG_TARIFF_NOTIFIER(UserImpl * u) : user(u) {}
+    void Notify(const std::string & oldTariff, const std::string & newTariff);
+
+private:
+    UserImpl * user;
+};
+//-----------------------------------------------------------------------------
+class CHG_CASH_NOTIFIER : public PropertyNotifierBase<double> {
+public:
+    explicit CHG_CASH_NOTIFIER(UserImpl * u) : user(u) {}
+    void Notify(const double & oldCash, const double & newCash);
+
+private:
+    UserImpl * user;
+};
+//-----------------------------------------------------------------------------
+class CHG_IPS_NOTIFIER : public PropertyNotifierBase<UserIPs> {
+public:
+    explicit CHG_IPS_NOTIFIER(UserImpl * u) : user(u) {}
+    void Notify(const UserIPs & oldIPs, const UserIPs & newIPs);
+
+private:
+    UserImpl * user;
+};
+//-----------------------------------------------------------------------------
+class UserImpl : public User {
+    friend class CHG_PASSIVE_NOTIFIER;
+    friend class CHG_DISABLED_NOTIFIER;
+    friend class CHG_TARIFF_NOTIFIER;
+    friend class CHG_CASH_NOTIFIER;
+    friend class CHG_IPS_NOTIFIER;
+    public:
+#ifdef USE_ABSTRACT_SETTINGS
+        using Settings = STG::Settings;
+#else
+        using Settings = STG::SettingsImpl;
+#endif
+        UserImpl(const Settings * settings,
+                  const Store * store,
+                  const Tariffs * tariffs,
+                  const Admin * sysAdmin,
+                  const Users * u,
+                  const Services & svcs);
+        UserImpl(const UserImpl & u);
+        virtual ~UserImpl();
+
+        int             ReadConf();
+        int             ReadStat();
+        int             WriteConf() override;
+        int             WriteStat() override;
+        int             WriteMonthStat();
+
+        const std::string & GetLogin() const override { return login; }
+        void            SetLogin(std::string const & l);
+
+        uint32_t        GetCurrIP() const override{ return currIP; }
+        time_t          GetCurrIPModificationTime() const override { return currIP.ModificationTime(); }
+
+        void            AddCurrIPBeforeNotifier(CURR_IP_NOTIFIER * notifier) override;
+        void            DelCurrIPBeforeNotifier(const CURR_IP_NOTIFIER * notifier) override;
+
+        void            AddCurrIPAfterNotifier(CURR_IP_NOTIFIER * notifier) override;
+        void            DelCurrIPAfterNotifier(const CURR_IP_NOTIFIER * notifier) override;
+
+        void            AddConnectedBeforeNotifier(CONNECTED_NOTIFIER * notifier) override;
+        void            DelConnectedBeforeNotifier(const CONNECTED_NOTIFIER * notifier) override;
+
+        void            AddConnectedAfterNotifier(CONNECTED_NOTIFIER * notifier) override;
+        void            DelConnectedAfterNotifier(const CONNECTED_NOTIFIER * notifier) override;
+
+        int             GetID() const override { return id; }
+
+        double          GetPassiveTimePart() const override;
+        void            ResetPassiveTime() { passiveTime = 0; }
+        void            SetPassiveTimeAsNewUser();
+
+        int             WriteDetailStat(bool hard = false);
+
+        const Tariff *  GetTariff() const override { return tariff; }
+        void            ResetNextTariff() override { nextTariff = ""; }
+
+        #ifdef TRAFF_STAT_WITH_PORTS
+        void            AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len);
+        void            AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len);
+        #else
+        void            AddTraffStatU(int dir, uint32_t ip, uint32_t len);
+        void            AddTraffStatD(int dir, uint32_t ip, uint32_t len);
+        #endif
+
+        const DirTraff & GetSessionUpload() const override { return sessionUpload; }
+        const DirTraff & GetSessionDownload() const override { return sessionDownload; }
+        time_t GetSessionUploadModificationTime() const override { return sessionUploadModTime; }
+        time_t GetSessionDownloadModificationTime() const override { return sessionDownloadModTime; }
+
+        bool            GetConnected() const override { return connected; }
+        time_t          GetConnectedModificationTime() const override { return connected.ModificationTime(); }
+        const std::string & GetLastDisconnectReason() const override { return lastDisconnectReason; }
+        int             GetAuthorized() const override { return static_cast<int>(authorizedBy.size()); }
+        time_t          GetAuthorizedModificationTime() const override { return authorizedModificationTime; }
+        int             Authorize(uint32_t ip, uint32_t enabledDirs, const Auth * auth);
+        void            Unauthorize(const Auth * auth,
+                                    const std::string & reason = std::string());
+        bool            IsAuthorizedBy(const Auth * auth) const override;
+        std::vector<std::string> GetAuthorizers() const override;
+
+        int             AddMessage(Message * msg) override;
+
+        void            UpdatePingTime(time_t t = 0) override;
+        time_t          GetPingTime() const override { return pingTime; }
+
+        void            Run() override;
+
+        const std::string & GetStrError() const override { return errorStr; }
+
+        UserProperties & GetProperties() override { return properties; }
+        const UserProperties & GetProperties() const override { return properties; }
+
+        void            SetDeleted() override { deleted = true; }
+        bool            GetDeleted() const override { return deleted; }
+
+        time_t          GetLastWriteStatTime() const override { return lastWriteStat; }
+
+        void            MidnightResetSessionStat();
+        void            ProcessDayFee();
+        void            ProcessDayFeeSpread();
+        void            ProcessNewMonth();
+        void            ProcessDailyFee();
+        void            ProcessServices();
+
+        bool            IsInetable() override;
+        std::string     GetEnabledDirs() const override;
+
+        void            OnAdd() override;
+        void            OnDelete() override;
+
+        virtual std::string GetParamValue(const std::string & name) const override;
+
+    private:
+        UserImpl & operator=(const UserImpl & rvalue);
+
+        void            Init();
+
+        const Users*   users;
+        UserProperties properties;
+        STG::Logger&   WriteServLog;
+
+        void            Connect(bool fakeConnect = false);
+        void            Disconnect(bool fakeDisconnect, const std::string & reason);
+        int             SaveMonthStat(int month, int year);
+
+        void            SetPrepaidTraff();
+
+        int             SendMessage(Message & msg) const;
+        void            ScanMessage();
+
+        time_t          lastScanMessages;
+
+        std::string     login;
+        int             id;
+        bool            __connected;
+        UserProperty<bool> connected;
+
+        bool            enabledDirs[DIR_NUM];
+
+        uint32_t        __currIP; // Current user's ip
+        UserProperty<uint32_t> currIP;
+
+        uint32_t        lastIPForDisconnect; // User's ip after unauth but before disconnect
+        std::string     lastDisconnectReason;
+
+        time_t          pingTime;
+
+        const Admin *   sysAdmin;
+        const Store *   store;
+
+        const Tariffs * tariffs;
+        const Tariff *  tariff;
+
+        const Services & m_services;
+
+        TraffStat      traffStat;
+        std::pair<time_t, TraffStat> traffStatSaved;
+
+        const Settings * settings;
+
+        std::set<const Auth *> authorizedBy;
+        time_t          authorizedModificationTime;
+
+        std::vector<Message> messages;
+
+        bool            deleted;
+
+        time_t          lastWriteStat;
+        time_t          lastWriteDetailedStat;
+
+        // Properties
+        UserProperty<double>         & cash;
+        UserProperty<DirTraff>      & up;
+        UserProperty<DirTraff>      & down;
+        UserProperty<double>         & lastCashAdd;
+        UserProperty<time_t>         & passiveTime;
+        UserProperty<time_t>         & lastCashAddTime;
+        UserProperty<double>         & freeMb;
+        UserProperty<time_t>         & lastActivityTime;
+        UserProperty<std::string>    & password;
+        UserProperty<int>            & passive;
+        UserProperty<int>            & disabled;
+        UserProperty<int>            & disabledDetailStat;
+        UserProperty<int>            & alwaysOnline;
+        UserProperty<std::string>    & tariffName;
+        UserProperty<std::string>    & nextTariff;
+        UserProperty<std::string>    & address;
+        UserProperty<std::string>    & note;
+        UserProperty<std::string>    & group;
+        UserProperty<std::string>    & email;
+        UserProperty<std::string>    & phone;
+        UserProperty<std::string>    & realName;
+        UserProperty<double>         & credit;
+        UserProperty<time_t>         & creditExpire;
+        UserProperty<UserIPs>       & ips;
+        UserProperty<std::string>    & userdata0;
+        UserProperty<std::string>    & userdata1;
+        UserProperty<std::string>    & userdata2;
+        UserProperty<std::string>    & userdata3;
+        UserProperty<std::string>    & userdata4;
+        UserProperty<std::string>    & userdata5;
+        UserProperty<std::string>    & userdata6;
+        UserProperty<std::string>    & userdata7;
+        UserProperty<std::string>    & userdata8;
+        UserProperty<std::string>    & userdata9;
+
+        // End properties
+
+        DirTraff                sessionUpload;
+        DirTraff                sessionDownload;
+        time_t                   sessionUploadModTime;
+        time_t                   sessionDownloadModTime;
+
+        CHG_PASSIVE_NOTIFIER     passiveNotifier;
+        CHG_DISABLED_NOTIFIER    disabledNotifier;
+        CHG_TARIFF_NOTIFIER      tariffNotifier;
+        CHG_CASH_NOTIFIER        cashNotifier;
+        CHG_IPS_NOTIFIER         ipNotifier;
+
+        mutable pthread_mutex_t  mutex;
+
+        std::string              errorStr;
+};
+//-----------------------------------------------------------------------------
+
+}
diff --git a/projects/stargazer/user_property.cpp b/projects/stargazer/user_property.cpp
new file mode 100644 (file)
index 0000000..e2213a6
--- /dev/null
@@ -0,0 +1,39 @@
+#include "stg/user_property.h"
+
+STG::UserProperties::UserProperties(const Settings& s)
+    : cash            (stat.cash,             "cash",             false, true, s, properties),
+      up              (stat.monthUp,          "upload",           false, true, s, properties),
+      down            (stat.monthDown,        "download",         false, true, s, properties),
+      lastCashAdd     (stat.lastCashAdd,      "lastCashAdd",      false, true, s, properties),
+      passiveTime     (stat.passiveTime,      "passiveTime",      false, true, s, properties),
+      lastCashAddTime (stat.lastCashAddTime,  "lastCashAddTime",  false, true, s, properties),
+      freeMb          (stat.freeMb,           "freeMb",           false, true, s, properties),
+      lastActivityTime(stat.lastActivityTime, "lastActivityTime", false, true, s, properties),
+
+      password    (conf.password,     "password",     true,  false, s, properties),
+      passive     (conf.passive,      "passive",      false, false, s, properties),
+      disabled    (conf.disabled,     "disabled",     false, false, s, properties),
+      disabledDetailStat(conf.disabledDetailStat, "DisabledDetailStat", false, false, s, properties),
+      alwaysOnline(conf.alwaysOnline, "alwaysOnline", false, false, s, properties),
+      tariffName  (conf.tariffName,   "tariffName",   false, false, s, properties),
+      nextTariff  (conf.nextTariff,   "nextTariff",   false, false, s, properties),
+      address     (conf.address,      "address",      false, false, s, properties),
+      note        (conf.note,         "note",         false, false, s, properties),
+      group       (conf.group,        "group",        false, false, s, properties),
+      email       (conf.email,        "email",        false, false, s, properties),
+      phone       (conf.phone,        "phone",        false, false, s, properties),
+      realName    (conf.realName,     "realName",     false, false, s, properties),
+      credit      (conf.credit,       "credit",       false, false, s, properties),
+      creditExpire(conf.creditExpire, "creditExpire", false, false, s, properties),
+      ips         (conf.ips,          "ips",          false, false, s, properties),
+      userdata0   (conf.userdata[0],  "userdata0",    false, false, s, properties),
+      userdata1   (conf.userdata[1],  "userdata1",    false, false, s, properties),
+      userdata2   (conf.userdata[2],  "userdata2",    false, false, s, properties),
+      userdata3   (conf.userdata[3],  "userdata3",    false, false, s, properties),
+      userdata4   (conf.userdata[4],  "userdata4",    false, false, s, properties),
+      userdata5   (conf.userdata[5],  "userdata5",    false, false, s, properties),
+      userdata6   (conf.userdata[6],  "userdata6",    false, false, s, properties),
+      userdata7   (conf.userdata[7],  "userdata7",    false, false, s, properties),
+      userdata8   (conf.userdata[8],  "userdata8",    false, false, s, properties),
+      userdata9   (conf.userdata[9],  "userdata9",    false, false, s, properties)
+{}
diff --git a/projects/stargazer/users_impl.cpp b/projects/stargazer/users_impl.cpp
new file mode 100644 (file)
index 0000000..ca8f681
--- /dev/null
@@ -0,0 +1,853 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Date: 27.10.2002
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+#include <pthread.h>
+
+#include <csignal>
+#include <cassert>
+#include <algorithm>
+#include <utility>
+#include <string>
+#include <vector>
+
+#include "stg/settings.h"
+#include "stg/common.h"
+
+#include "users_impl.h"
+#include "stg_timer.h"
+
+extern volatile time_t stgTime;
+
+using STG::UsersImpl;
+
+//-----------------------------------------------------------------------------
+UsersImpl::UsersImpl(SettingsImpl * s, Store * st,
+                    Tariffs * t, Services & svcs,
+                    const Admin& sa)
+    : settings(s),
+      tariffs(t),
+      m_services(svcs),
+      store(st),
+      sysAdmin(sa),
+      WriteServLog(Logger::get()),
+      nonstop(false),
+      isRunning(false),
+      handle(0)
+{
+pthread_mutexattr_t attr;
+pthread_mutexattr_init(&attr);
+pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+pthread_mutex_init(&mutex, &attr);
+}
+//-----------------------------------------------------------------------------
+UsersImpl::~UsersImpl()
+{
+pthread_mutex_destroy(&mutex);
+}
+//-----------------------------------------------------------------------------
+int UsersImpl::FindByNameNonLock(const std::string & login, user_iter * user)
+{
+const std::map<std::string, user_iter>::const_iterator iter(loginIndex.find(login));
+if (iter == loginIndex.end())
+    return -1;
+if (user)
+    *user = iter->second;
+return 0;
+}
+//-----------------------------------------------------------------------------
+int UsersImpl::FindByNameNonLock(const std::string & login, const_user_iter * user) const
+{
+const std::map<std::string, user_iter>::const_iterator iter(loginIndex.find(login));
+if (iter == loginIndex.end())
+    return -1;
+if (user)
+    *user = iter->second;
+return 0;
+}
+//-----------------------------------------------------------------------------
+int UsersImpl::FindByName(const std::string & login, UserPtr * user)
+{
+STG_LOCKER lock(&mutex);
+user_iter u;
+if (FindByNameNonLock(login, &u))
+    return -1;
+*user = &(*u);
+return 0;
+}
+//-----------------------------------------------------------------------------
+int UsersImpl::FindByName(const std::string & login, ConstUserPtr * user) const
+{
+STG_LOCKER lock(&mutex);
+const_user_iter u;
+if (FindByNameNonLock(login, &u))
+    return -1;
+*user = &(*u);
+return 0;
+}
+//-----------------------------------------------------------------------------
+bool UsersImpl::Exists(const std::string & login) const
+{
+STG_LOCKER lock(&mutex);
+const std::map<std::string, user_iter>::const_iterator iter(loginIndex.find(login));
+return iter != loginIndex.end();
+}
+//-----------------------------------------------------------------------------
+bool UsersImpl::TariffInUse(const std::string & tariffName) const
+{
+STG_LOCKER lock(&mutex);
+std::list<UserImpl>::const_iterator iter;
+iter = users.begin();
+while (iter != users.end())
+    {
+    if (iter->GetProperties().tariffName.Get() == tariffName)
+        return true;
+    ++iter;
+    }
+return false;
+}
+//-----------------------------------------------------------------------------
+int UsersImpl::Add(const std::string & login, const Admin * admin)
+{
+STG_LOCKER lock(&mutex);
+const auto& priv = admin->priv();
+
+if (!priv.userAddDel)
+    {
+    WriteServLog("%s tried to add user \'%s\'. Access denied.",
+                 admin->logStr().c_str(), login.c_str());
+    return -1;
+    }
+
+if (store->AddUser(login))
+    return -1;
+
+UserImpl u(settings, store, tariffs, &sysAdmin, this, m_services);
+
+u.SetLogin(login);
+
+u.SetPassiveTimeAsNewUser();
+
+u.WriteConf();
+u.WriteStat();
+
+WriteServLog("%s User \'%s\' added.",
+             admin->logStr().c_str(), login.c_str());
+
+u.OnAdd();
+
+users.push_front(u);
+
+AddUserIntoIndexes(users.begin());
+
+    {
+    // Fire all "on add" notifiers
+    std::set<NotifierBase<UserPtr> *>::iterator ni = onAddNotifiers.begin();
+    while (ni != onAddNotifiers.end())
+        {
+        (*ni)->Notify(&users.front());
+        ++ni;
+        }
+    }
+
+    {
+    // Fire all "on add" implementation notifiers
+    std::set<NotifierBase<UserImplPtr> *>::iterator ni = onAddNotifiersImpl.begin();
+    while (ni != onAddNotifiersImpl.end())
+        {
+        (*ni)->Notify(&users.front());
+        ++ni;
+        }
+    }
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+void UsersImpl::Del(const std::string & login, const Admin * admin)
+{
+const auto& priv = admin->priv();
+user_iter u;
+
+if (!priv.userAddDel)
+    {
+    WriteServLog("%s tried to remove user \'%s\'. Access denied.",
+                 admin->logStr().c_str(), login.c_str());
+    return;
+    }
+
+
+    {
+    STG_LOCKER lock(&mutex);
+
+    if (FindByNameNonLock(login, &u))
+        {
+        WriteServLog("%s tried to delete user \'%s\': not found.",
+                     admin->logStr().c_str(),
+                     login.c_str());
+        return;
+        }
+
+    u->SetDeleted();
+    }
+
+    {
+    std::set<NotifierBase<UserPtr> *>::iterator ni = onDelNotifiers.begin();
+    while (ni != onDelNotifiers.end())
+        {
+        (*ni)->Notify(&(*u));
+        ++ni;
+        }
+    }
+
+    {
+    std::set<NotifierBase<UserImplPtr> *>::iterator ni = onDelNotifiersImpl.begin();
+    while (ni != onDelNotifiersImpl.end())
+        {
+        (*ni)->Notify(&(*u));
+        ++ni;
+        }
+    }
+
+    {
+    STG_LOCKER lock(&mutex);
+
+    u->OnDelete();
+
+    USER_TO_DEL utd;
+    utd.iter = u;
+    utd.delTime = stgTime;
+    usersToDelete.push_back(utd);
+
+    DelUserFromIndexes(u);
+
+    WriteServLog("%s User \'%s\' deleted.",
+                 admin->logStr().c_str(), login.c_str());
+
+    }
+}
+//-----------------------------------------------------------------------------
+bool UsersImpl::Authorize(const std::string & login, uint32_t ip,
+                           uint32_t enabledDirs, const Auth * auth)
+{
+user_iter iter;
+STG_LOCKER lock(&mutex);
+if (FindByNameNonLock(login, &iter))
+    {
+    WriteServLog("Attempt to authorize non-existant user '%s'", login.c_str());
+    return false;
+    }
+
+if (FindByIPIdx(ip, iter))
+    {
+    if (iter->GetLogin() != login)
+        {
+        WriteServLog("Attempt to authorize user '%s' from ip %s which already occupied by '%s'",
+                     login.c_str(), inet_ntostring(ip).c_str(),
+                     iter->GetLogin().c_str());
+        return false;
+        }
+    if (iter->Authorize(ip, enabledDirs, auth))
+        return false;
+    return true;
+    }
+
+if (iter->Authorize(ip, enabledDirs, auth))
+    return false;
+
+AddToIPIdx(iter);
+return true;
+}
+//-----------------------------------------------------------------------------
+bool UsersImpl::Unauthorize(const std::string & login,
+                             const Auth * auth,
+                             const std::string & reason)
+{
+user_iter iter;
+STG_LOCKER lock(&mutex);
+if (FindByNameNonLock(login, &iter))
+    {
+    WriteServLog("Attempt to unauthorize non-existant user '%s'", login.c_str());
+    printfd(__FILE__, "Attempt to unauthorize non-existant user '%s'", login.c_str());
+    return false;
+    }
+
+uint32_t ip = iter->GetCurrIP();
+
+iter->Unauthorize(auth, reason);
+
+if (!iter->GetAuthorized())
+    DelFromIPIdx(ip);
+
+return true;
+}
+//-----------------------------------------------------------------------------
+int UsersImpl::ReadUsers()
+{
+std::vector<std::string> usersList;
+usersList.clear();
+if (store->GetUsersList(&usersList) < 0)
+    {
+    WriteServLog(store->GetStrError().c_str());
+    return -1;
+    }
+
+user_iter ui;
+
+unsigned errors = 0;
+for (unsigned int i = 0; i < usersList.size(); i++)
+    {
+    UserImpl u(settings, store, tariffs, &sysAdmin, this, m_services);
+
+    u.SetLogin(usersList[i]);
+    users.push_front(u);
+    ui = users.begin();
+
+    AddUserIntoIndexes(ui);
+
+    if (settings->GetStopOnError())
+        {
+        if (ui->ReadConf() < 0)
+            return -1;
+
+        if (ui->ReadStat() < 0)
+            return -1;
+        }
+    else
+        {
+        if (ui->ReadConf() < 0)
+            errors++;
+
+        if (ui->ReadStat() < 0)
+            errors++;
+        }
+    }
+
+if (errors > 0)
+    return -1;
+return 0;
+}
+//-----------------------------------------------------------------------------
+void * UsersImpl::Run(void * d)
+{
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
+printfd(__FILE__, "=====================| pid: %d |===================== \n", getpid());
+UsersImpl * us = static_cast<UsersImpl *>(d);
+
+struct tm t;
+time_t tt = stgTime;
+localtime_r(&tt, &t);
+
+int min = t.tm_min;
+int day = t.tm_mday;
+
+printfd(__FILE__,"Day = %d Min = %d\n", day, min);
+
+time_t touchTime = stgTime - MONITOR_TIME_DELAY_SEC;
+std::string monFile = us->settings->GetMonitorDir() + "/users_r";
+printfd(__FILE__, "Monitor=%d file USERS %s\n", us->settings->GetMonitoring(), monFile.c_str());
+
+us->isRunning = true;
+while (us->nonstop)
+    {
+    //printfd(__FILE__,"New Minute. old = %02d current = %02d\n", min, t->tm_min);
+    //printfd(__FILE__,"New Day.    old = %2d current = %2d\n", day, t->tm_mday);
+
+    for_each(us->users.begin(), us->users.end(), [](auto& user){ user.Run(); });
+
+    tt = stgTime;
+    localtime_r(&tt, &t);
+
+    if (min != t.tm_min)
+        {
+        printfd(__FILE__,"Sec = %d\n", stgTime);
+        printfd(__FILE__,"New Minute. old = %d current = %d\n", min, t.tm_min);
+        min = t.tm_min;
+
+        us->NewMinute(t);
+        }
+
+    if (day != t.tm_mday)
+        {
+        printfd(__FILE__,"Sec = %d\n", stgTime);
+        printfd(__FILE__,"New Day. old = %d current = %d\n", day, t.tm_mday);
+        day = t.tm_mday;
+        us->NewDay(t);
+        }
+
+    if (us->settings->GetMonitoring() && (touchTime + MONITOR_TIME_DELAY_SEC <= stgTime))
+        {
+        //printfd(__FILE__, "Monitor=%d file TRAFFCOUNTER %s\n", tc->monitoring, monFile.c_str());
+        touchTime = stgTime;
+        TouchFile(monFile);
+        }
+
+    stgUsleep(100000);
+    } //while (us->nonstop)
+
+std::list<USER_TO_DEL>::iterator iter(us->usersToDelete.begin());
+while (iter != us->usersToDelete.end())
+    {
+    iter->delTime -= 2 * userDeleteDelayTime;
+    ++iter;
+    }
+us->RealDelUser();
+
+us->isRunning = false;
+
+return NULL;
+}
+//-----------------------------------------------------------------------------
+void UsersImpl::NewMinute(const struct tm & t)
+{
+//Write traff, reset session traff. Fake disconnect-connect
+if (t.tm_hour == 23 && t.tm_min == 59)
+    {
+    printfd(__FILE__,"MidnightResetSessionStat\n");
+    for_each(users.begin(), users.end(), [](auto& user){ user.MidnightResetSessionStat(); });
+    }
+
+if (TimeToWriteDetailStat(t))
+    {
+    //printfd(__FILE__, "USER::WriteInetStat\n");
+    int usersCnt = 0;
+
+    // ðÉÛÅÍ ÀÚÅÒÏ× ÞÁÓÔÑÍÉ. ÷ ÐÅÒÅÒÙ×ÁÈ ×ÙÚÙ×ÁÅÍ USER::Run
+    std::list<UserImpl>::iterator usr = users.begin();
+    while (usr != users.end())
+        {
+        usersCnt++;
+        usr->WriteDetailStat();
+        ++usr;
+        if (usersCnt % 10 == 0)
+            for_each(users.begin(), users.end(), [](auto& user){ user.Run(); });
+        }
+    }
+
+RealDelUser();
+}
+//-----------------------------------------------------------------------------
+void UsersImpl::NewDay(const struct tm & t)
+{
+struct tm t1;
+time_t tt = stgTime;
+localtime_r(&tt, &t1);
+int dayFee = settings->GetDayFee();
+
+if (dayFee == 0)
+    dayFee = DaysInCurrentMonth();
+
+printfd(__FILE__, "DayFee = %d\n", dayFee);
+printfd(__FILE__, "Today = %d DayResetTraff = %d\n", t1.tm_mday, settings->GetDayResetTraff());
+printfd(__FILE__, "DayFeeIsLastDay = %d\n", settings->GetDayFeeIsLastDay());
+
+if (!settings->GetDayFeeIsLastDay())
+    {
+    printfd(__FILE__, "DayResetTraff - 1 -\n");
+    DayResetTraff(t1);
+    //printfd(__FILE__, "DayResetTraff - 1 - 1 -\n");
+    }
+
+if (settings->GetSpreadFee())
+    {
+    printfd(__FILE__, "Spread DayFee\n");
+    for_each(users.begin(), users.end(), [](auto& user){ user.ProcessDayFeeSpread(); });
+    }
+else
+    {
+    if (t.tm_mday == dayFee)
+        {
+        printfd(__FILE__, "DayFee\n");
+        for_each(users.begin(), users.end(), [](auto& user){ user.ProcessDayFee(); });
+        }
+    }
+
+std::for_each(users.begin(), users.end(), [](auto& user){ user.ProcessDailyFee(); });
+std::for_each(users.begin(), users.end(), [](auto& user){ user.ProcessServices(); });
+
+if (settings->GetDayFeeIsLastDay())
+    {
+    printfd(__FILE__, "DayResetTraff - 2 -\n");
+    DayResetTraff(t1);
+    }
+}
+//-----------------------------------------------------------------------------
+void UsersImpl::DayResetTraff(const struct tm & t1)
+{
+int dayResetTraff = settings->GetDayResetTraff();
+if (dayResetTraff == 0)
+    dayResetTraff = DaysInCurrentMonth();
+if (t1.tm_mday == dayResetTraff)
+    {
+    printfd(__FILE__, "ResetTraff\n");
+    for_each(users.begin(), users.end(), [](auto& user){ user.ProcessNewMonth(); });
+    //for_each(users.begin(), users.end(), mem_fun_ref(&UserImpl::SetPrepaidTraff));
+    }
+}
+//-----------------------------------------------------------------------------
+int UsersImpl::Start()
+{
+if (ReadUsers())
+    {
+    WriteServLog("USERS: Error: Cannot read users!");
+    return -1;
+    }
+
+nonstop = true;
+if (pthread_create(&thread, NULL, Run, this))
+    {
+    WriteServLog("USERS: Error: Cannot start thread!");
+    return -1;
+    }
+return 0;
+}
+//-----------------------------------------------------------------------------
+int UsersImpl::Stop()
+{
+printfd(__FILE__, "USERS::Stop()\n");
+
+if (!isRunning)
+    {
+    //printfd(__FILE__, "Alredy stopped\n");
+    return 0;
+    }
+
+nonstop = false;
+
+//5 seconds to thread stops itself
+struct timespec ts = {0, 200000000};
+for (size_t i = 0; i < 25 * (users.size() / 50 + 1); i++)
+    {
+    if (!isRunning)
+        break;
+
+    nanosleep(&ts, NULL);
+    }
+
+//after 5 seconds waiting thread still running. now kill it
+if (isRunning)
+    {
+    printfd(__FILE__, "kill USERS thread.\n");
+    //TODO pthread_cancel()
+    if (pthread_kill(thread, SIGINT))
+        {
+        //errorStr = "Cannot kill USERS thread.";
+        //printfd(__FILE__, "Cannot kill USERS thread.\n");
+        //return 0;
+        }
+    printfd(__FILE__, "USERS killed\n");
+    }
+
+printfd(__FILE__, "Before USERS::Run()\n");
+for_each(users.begin(), users.end(), [](auto& user){ user.Run(); });
+
+// 'cause bind2st accepts only constant first param
+for (std::list<UserImpl>::iterator it = users.begin();
+     it != users.end();
+     ++it)
+    it->WriteDetailStat(true);
+
+for_each(users.begin(), users.end(), [](auto& user){ user.WriteStat(); });
+//for_each(users.begin(), users.end(), mem_fun_ref(&UserImpl::WriteConf));
+
+printfd(__FILE__, "USERS::Stop()\n");
+return 0;
+}
+//-----------------------------------------------------------------------------
+void UsersImpl::RealDelUser()
+{
+STG_LOCKER lock(&mutex);
+
+printfd(__FILE__, "RealDelUser() users to del: %d\n", usersToDelete.size());
+
+std::list<USER_TO_DEL>::iterator iter;
+iter = usersToDelete.begin();
+while (iter != usersToDelete.end())
+    {
+    printfd(__FILE__, "RealDelUser() user=%s\n", iter->iter->GetLogin().c_str());
+    if (iter->delTime + userDeleteDelayTime < stgTime)
+        {
+        printfd(__FILE__, "RealDelUser() user=%s removed from DB\n", iter->iter->GetLogin().c_str());
+        if (store->DelUser(iter->iter->GetLogin()))
+            {
+            WriteServLog("Error removing user \'%s\' from database.", iter->iter->GetLogin().c_str());
+            }
+        users.erase(iter->iter);
+        usersToDelete.erase(iter++);
+        }
+    else
+        {
+        ++iter;
+        }
+    }
+return;
+}
+//-----------------------------------------------------------------------------
+void UsersImpl::AddToIPIdx(user_iter user)
+{
+printfd(__FILE__, "USERS: Add IP Idx\n");
+uint32_t ip = user->GetCurrIP();
+//assert(ip && "User has non-null ip");
+if (!ip)
+    return; // User has disconnected
+
+STG_LOCKER lock(&mutex);
+
+const std::map<uint32_t, user_iter>::iterator it(
+        ipIndex.lower_bound(ip)
+);
+
+assert((it == ipIndex.end() || it->first != ip) && "User is not in index");
+
+ipIndex.insert(it, std::make_pair(ip, user));
+}
+//-----------------------------------------------------------------------------
+void UsersImpl::DelFromIPIdx(uint32_t ip)
+{
+printfd(__FILE__, "USERS: Del IP Idx\n");
+assert(ip && "User has non-null ip");
+
+STG_LOCKER lock(&mutex);
+
+const std::map<uint32_t, user_iter>::iterator it(
+        ipIndex.find(ip)
+);
+
+if (it == ipIndex.end())
+    return;
+
+ipIndex.erase(it);
+}
+//-----------------------------------------------------------------------------
+bool UsersImpl::FindByIPIdx(uint32_t ip, user_iter & iter) const
+{
+std::map<uint32_t, user_iter>::const_iterator it(ipIndex.find(ip));
+if (it == ipIndex.end())
+    return false;
+iter = it->second;
+return true;
+}
+//-----------------------------------------------------------------------------
+int UsersImpl::FindByIPIdx(uint32_t ip, UserPtr * usr) const
+{
+STG_LOCKER lock(&mutex);
+
+user_iter iter;
+if (FindByIPIdx(ip, iter))
+    {
+    *usr = &(*iter);
+    return 0;
+    }
+
+return -1;
+}
+//-----------------------------------------------------------------------------
+int UsersImpl::FindByIPIdx(uint32_t ip, UserImpl ** usr) const
+{
+STG_LOCKER lock(&mutex);
+
+user_iter iter;
+if (FindByIPIdx(ip, iter))
+    {
+    *usr = &(*iter);
+    return 0;
+    }
+
+return -1;
+}
+//-----------------------------------------------------------------------------
+bool UsersImpl::IsIPInIndex(uint32_t ip) const
+{
+STG_LOCKER lock(&mutex);
+
+std::map<uint32_t, user_iter>::const_iterator it(ipIndex.find(ip));
+
+return it != ipIndex.end();
+}
+//-----------------------------------------------------------------------------
+bool UsersImpl::IsIPInUse(uint32_t ip, const std::string & login, ConstUserPtr * user) const
+{
+STG_LOCKER lock(&mutex);
+std::list<UserImpl>::const_iterator iter;
+iter = users.begin();
+while (iter != users.end())
+    {
+    if (iter->GetLogin() != login &&
+        !iter->GetProperties().ips.Get().isAnyIP() &&
+        iter->GetProperties().ips.Get().find(ip))
+        {
+        if (user != NULL)
+            *user = &(*iter);
+        return true;
+        }
+    ++iter;
+    }
+return false;
+}
+//-----------------------------------------------------------------------------
+void UsersImpl::AddNotifierUserAdd(NotifierBase<UserPtr> * n)
+{
+STG_LOCKER lock(&mutex);
+onAddNotifiers.insert(n);
+}
+//-----------------------------------------------------------------------------
+void UsersImpl::DelNotifierUserAdd(NotifierBase<UserPtr> * n)
+{
+STG_LOCKER lock(&mutex);
+onAddNotifiers.erase(n);
+}
+//-----------------------------------------------------------------------------
+void UsersImpl::AddNotifierUserDel(NotifierBase<UserPtr> * n)
+{
+STG_LOCKER lock(&mutex);
+onDelNotifiers.insert(n);
+}
+//-----------------------------------------------------------------------------
+void UsersImpl::DelNotifierUserDel(NotifierBase<UserPtr> * n)
+{
+STG_LOCKER lock(&mutex);
+onDelNotifiers.erase(n);
+}
+//-----------------------------------------------------------------------------
+void UsersImpl::AddNotifierUserAdd(NotifierBase<UserImplPtr> * n)
+{
+STG_LOCKER lock(&mutex);
+onAddNotifiersImpl.insert(n);
+}
+//-----------------------------------------------------------------------------
+void UsersImpl::DelNotifierUserAdd(NotifierBase<UserImplPtr> * n)
+{
+STG_LOCKER lock(&mutex);
+onAddNotifiersImpl.erase(n);
+}
+//-----------------------------------------------------------------------------
+void UsersImpl::AddNotifierUserDel(NotifierBase<UserImplPtr> * n)
+{
+STG_LOCKER lock(&mutex);
+onDelNotifiersImpl.insert(n);
+}
+//-----------------------------------------------------------------------------
+void UsersImpl::DelNotifierUserDel(NotifierBase<UserImplPtr> * n)
+{
+STG_LOCKER lock(&mutex);
+onDelNotifiersImpl.erase(n);
+}
+//-----------------------------------------------------------------------------
+int UsersImpl::OpenSearch()
+{
+STG_LOCKER lock(&mutex);
+handle++;
+searchDescriptors[handle] = users.begin();
+return handle;
+}
+//-----------------------------------------------------------------------------
+int UsersImpl::SearchNext(int h, UserPtr * user)
+{
+    UserImpl * ptr = NULL;
+    if (SearchNext(h, &ptr))
+        return -1;
+    *user = ptr;
+    return 0;
+}
+//-----------------------------------------------------------------------------
+int UsersImpl::SearchNext(int h, UserImpl ** user)
+{
+STG_LOCKER lock(&mutex);
+
+if (searchDescriptors.find(h) == searchDescriptors.end())
+    {
+    WriteServLog("USERS. Incorrect search handle.");
+    return -1;
+    }
+
+if (searchDescriptors[h] == users.end())
+    return -1;
+
+while (searchDescriptors[h]->GetDeleted())
+    {
+    ++searchDescriptors[h];
+    if (searchDescriptors[h] == users.end())
+        {
+        return -1;
+        }
+    }
+
+*user = &(*searchDescriptors[h]);
+
+++searchDescriptors[h];
+
+return 0;
+}
+//-----------------------------------------------------------------------------
+int UsersImpl::CloseSearch(int h)
+{
+STG_LOCKER lock(&mutex);
+if (searchDescriptors.find(h) != searchDescriptors.end())
+    {
+    searchDescriptors.erase(searchDescriptors.find(h));
+    return 0;
+    }
+
+WriteServLog("USERS. Incorrect search handle.");
+return -1;
+}
+//-----------------------------------------------------------------------------
+void UsersImpl::AddUserIntoIndexes(user_iter user)
+{
+STG_LOCKER lock(&mutex);
+loginIndex.insert(make_pair(user->GetLogin(), user));
+}
+//-----------------------------------------------------------------------------
+void UsersImpl::DelUserFromIndexes(user_iter user)
+{
+STG_LOCKER lock(&mutex);
+loginIndex.erase(user->GetLogin());
+}
+//-----------------------------------------------------------------------------
+bool UsersImpl::TimeToWriteDetailStat(const struct tm & t)
+{
+int statTime = settings->GetDetailStatWritePeriod();
+
+switch (statTime)
+    {
+    case dsPeriod_1:
+        if (t.tm_min == 0)
+            return true;
+        break;
+    case dsPeriod_1_2:
+        if (t.tm_min % 30 == 0)
+            return true;
+        break;
+    case dsPeriod_1_4:
+        if (t.tm_min % 15 == 0)
+            return true;
+        break;
+    case dsPeriod_1_6:
+        if (t.tm_min % 10 == 0)
+            return true;
+        break;
+    }
+return false;
+}
diff --git a/projects/stargazer/users_impl.h b/projects/stargazer/users_impl.h
new file mode 100644 (file)
index 0000000..ef5ee0e
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
+ */
+
+#pragma once
+
+#include <pthread.h>
+
+#include <string>
+#include <map>
+#include <list>
+#include <set>
+#include <ctime>
+#include <cstdint>
+
+#include "stg/store.h"
+#include "stg/users.h"
+#include "stg/user.h"
+#include "stg/tariffs.h"
+#include "stg/logger.h"
+#include "stg/notifer.h"
+#include "stg/noncopyable.h"
+#include "actions.h"
+#include "eventloop.h"
+#include "settings_impl.h"
+#include "user_impl.h"
+
+namespace STG
+{
+
+const int userDeleteDelayTime = 120;
+
+typedef std::list<UserImpl>::iterator user_iter;
+typedef std::list<UserImpl>::const_iterator const_user_iter;
+
+class UsersImpl;
+//-----------------------------------------------------------------------------
+struct USER_TO_DEL {
+USER_TO_DEL()
+    : iter(),
+      delTime(0)
+{}
+
+std::list<UserImpl>::iterator iter;
+time_t  delTime;
+};
+//-----------------------------------------------------------------------------
+class UsersImpl : public Users {
+    friend class PROPERTY_NOTIFER_IP_BEFORE;
+    friend class PROPERTY_NOTIFER_IP_AFTER;
+
+public:
+    using UserImplPtr = UserImpl*;
+
+    UsersImpl(SettingsImpl * s, Store * store,
+              Tariffs * tariffs, Services & svcs,
+              const Admin& sysAdmin);
+    virtual ~UsersImpl();
+
+    int             FindByName(const std::string & login, UserPtr * user) override;
+    int             FindByName(const std::string & login, ConstUserPtr * user) const override;
+    bool            Exists(const std::string & login) const override;
+
+    bool            TariffInUse(const std::string & tariffName) const override;
+
+    void            AddNotifierUserAdd(NotifierBase<UserPtr> *) override;
+    void            DelNotifierUserAdd(NotifierBase<UserPtr> *) override;
+
+    void            AddNotifierUserDel(NotifierBase<UserPtr> *) override;
+    void            DelNotifierUserDel(NotifierBase<UserPtr> *) override;
+
+    void            AddNotifierUserAdd(NotifierBase<UserImplPtr> *);
+    void            DelNotifierUserAdd(NotifierBase<UserImplPtr> *);
+
+    void            AddNotifierUserDel(NotifierBase<UserImplPtr> *);
+    void            DelNotifierUserDel(NotifierBase<UserImplPtr> *);
+
+    int             Add(const std::string & login, const Admin * admin) override;
+    void            Del(const std::string & login, const Admin * admin) override;
+
+    bool            Authorize(const std::string & login, uint32_t ip,
+                              uint32_t enabledDirs, const Auth * auth) override;
+    bool            Unauthorize(const std::string & login,
+                                const Auth * auth,
+                                const std::string & reason) override;
+
+    int             ReadUsers() override;
+    size_t          Count() const override { return users.size(); }
+
+    int             FindByIPIdx(uint32_t ip, UserPtr * user) const override;
+    int             FindByIPIdx(uint32_t ip, UserImpl ** user) const;
+    bool            IsIPInIndex(uint32_t ip) const override;
+    bool            IsIPInUse(uint32_t ip, const std::string & login, ConstUserPtr * user) const override;
+
+    int             OpenSearch() override;
+    int             SearchNext(int handler, UserPtr * user) override;
+    int             SearchNext(int handler, UserImpl ** user);
+    int             CloseSearch(int handler) override;
+
+    int             Start() override;
+    int             Stop() override;
+
+private:
+    UsersImpl(const UsersImpl & rvalue);
+    UsersImpl & operator=(const UsersImpl & rvalue);
+
+    void            AddToIPIdx(user_iter user);
+    void            DelFromIPIdx(uint32_t ip);
+    bool            FindByIPIdx(uint32_t ip, user_iter & iter) const;
+
+    int             FindByNameNonLock(const std::string & login, user_iter * user);
+    int             FindByNameNonLock(const std::string & login, const_user_iter * user) const;
+
+    void            RealDelUser();
+    void            ProcessActions();
+
+    void            AddUserIntoIndexes(user_iter user);
+    void            DelUserFromIndexes(user_iter user);
+
+    static void *   Run(void *);
+    void            NewMinute(const struct tm & t);
+    void            NewDay(const struct tm & t);
+    void            DayResetTraff(const struct tm & t);
+
+    bool            TimeToWriteDetailStat(const struct tm & t);
+
+    std::list<UserImpl>                  users;
+    std::list<USER_TO_DEL>                usersToDelete;
+
+    std::map<uint32_t, user_iter>         ipIndex;
+    std::map<std::string, user_iter>      loginIndex;
+
+    SettingsImpl *     settings;
+    Tariffs *           tariffs;
+    Services &          m_services;
+    Store *             store;
+    const Admin&       sysAdmin;
+    Logger &        WriteServLog;
+
+    bool                nonstop;
+    bool                isRunning;
+
+    mutable pthread_mutex_t mutex;
+    pthread_t               thread;
+    mutable unsigned int    handle;
+
+    mutable std::map<int, user_iter>  searchDescriptors;
+
+    std::set<NotifierBase<UserPtr>*> onAddNotifiers;
+    std::set<NotifierBase<UserPtr>*> onDelNotifiers;
+    std::set<NotifierBase<UserImplPtr>*> onAddNotifiersImpl;
+    std::set<NotifierBase<UserImplPtr>*> onDelNotifiersImpl;
+};
+
+}
diff --git a/rscriptd/CMakeLists.txt b/rscriptd/CMakeLists.txt
deleted file mode 100644 (file)
index 9228b37..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-set ( CPP_FILES main.cpp listener.cpp pidfile.cpp )
-
-set ( THREADS_PREFER_PTHREAD_FLAG ON )
-find_package ( Threads REQUIRED )
-
-add_executable ( rscriptd ${CPP_FILES} )
-
-target_link_libraries ( rscriptd scriptexecuter conffiles logger crypto common Threads::Threads )
-
-# TODO: install
diff --git a/rscriptd/listener.cpp b/rscriptd/listener.cpp
deleted file mode 100644 (file)
index 3d8fd48..0000000
+++ /dev/null
@@ -1,513 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#include <arpa/inet.h>
-#include <sys/uio.h> // readv
-#include <sys/types.h> // for historical versions of BSD
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <unistd.h>
-
-#include <csignal>
-#include <cerrno>
-#include <ctime>
-#include <cstring>
-#include <sstream>
-#include <algorithm>
-
-#include "stg/scriptexecuter.h"
-#include "stg/locker.h"
-#include "stg/common.h"
-#include "stg/const.h"
-#include "listener.h"
-
-void InitEncrypt(BLOWFISH_CTX * ctx, const std::string & password);
-void Decrypt(BLOWFISH_CTX * ctx, char * dst, const char * src, int len8);
-
-//-----------------------------------------------------------------------------
-LISTENER::LISTENER()
-    : WriteServLog(STG::Logger::get()),
-      port(0),
-      running(false),
-      receiverStopped(true),
-      processorStopped(true),
-      userTimeout(0),
-      listenSocket(0),
-      version("rscriptd listener v.1.2")
-{
-pthread_mutex_init(&mutex, NULL);
-}
-//-----------------------------------------------------------------------------
-void LISTENER::SetPassword(const std::string & p)
-{
-password = p;
-printfd(__FILE__, "Encryption initiated with password \'%s\'\n", password.c_str());
-InitEncrypt(&ctxS, password);
-}
-//-----------------------------------------------------------------------------
-bool LISTENER::Start()
-{
-printfd(__FILE__, "LISTENER::Start()\n");
-running = true;
-
-if (PrepareNet())
-    {
-    return true;
-    }
-
-if (receiverStopped)
-    {
-    if (pthread_create(&receiverThread, NULL, Run, this))
-        {
-        errorStr = "Cannot create thread.";
-        return true;
-        }
-    }
-
-if (processorStopped)
-    {
-    if (pthread_create(&processorThread, NULL, RunProcessor, this))
-        {
-        errorStr = "Cannot create thread.";
-        return true;
-        }
-    }
-
-errorStr = "";
-
-return false;
-}
-//-----------------------------------------------------------------------------
-bool LISTENER::Stop()
-{
-running = false;
-
-printfd(__FILE__, "LISTENER::Stop()\n");
-
-struct timespec ts = {0, 500000000};
-nanosleep(&ts, NULL);
-
-if (!processorStopped)
-    {
-    //5 seconds to thread stops itself
-    for (int i = 0; i < 25 && !processorStopped; i++)
-        {
-        struct timespec ts = {0, 200000000};
-        nanosleep(&ts, NULL);
-        }
-
-    //after 5 seconds waiting thread still running. now killing it
-    if (!processorStopped)
-        {
-        //TODO pthread_cancel()
-        if (pthread_kill(processorThread, SIGINT))
-            {
-            errorStr = "Cannot kill thread.";
-            return true;
-            }
-        printfd(__FILE__, "LISTENER killed Timeouter\n");
-        }
-    }
-
-if (!receiverStopped)
-    {
-    //5 seconds to thread stops itself
-    for (int i = 0; i < 25 && !receiverStopped; i++)
-        {
-        struct timespec ts = {0, 200000000};
-        nanosleep(&ts, NULL);
-        }
-
-    //after 5 seconds waiting thread still running. now killing it
-    if (!receiverStopped)
-        {
-        //TODO pthread_cancel()
-        if (pthread_kill(receiverThread, SIGINT))
-            {
-            errorStr = "Cannot kill thread.";
-            return true;
-            }
-        printfd(__FILE__, "LISTENER killed Run\n");
-        }
-    }
-
-pthread_join(receiverThread, NULL);
-pthread_join(processorThread, NULL);
-
-pthread_mutex_destroy(&mutex);
-
-FinalizeNet();
-
-std::for_each(users.begin(), users.end(), DisconnectUser(*this));
-
-printfd(__FILE__, "LISTENER::Stoped successfully.\n");
-
-return false;
-}
-//-----------------------------------------------------------------------------
-void * LISTENER::Run(void * d)
-{
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-LISTENER * listener = static_cast<LISTENER *>(d);
-
-listener->Runner();
-
-return NULL;
-}
-//-----------------------------------------------------------------------------
-void LISTENER::Runner()
-{
-receiverStopped = false;
-
-while (running)
-    {
-    RecvPacket();
-    }
-
-receiverStopped = true;
-}
-//-----------------------------------------------------------------------------
-void * LISTENER::RunProcessor(void * d)
-{
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-LISTENER * listener = static_cast<LISTENER *>(d);
-
-listener->ProcessorRunner();
-
-return NULL;
-}
-//-----------------------------------------------------------------------------
-void LISTENER::ProcessorRunner()
-{
-processorStopped = false;
-
-while (running)
-    {
-    struct timespec ts = {0, 500000000};
-    nanosleep(&ts, NULL);
-    if (!pending.empty())
-        ProcessPending();
-    ProcessTimeouts();
-    }
-
-processorStopped = true;
-}
-//-----------------------------------------------------------------------------
-bool LISTENER::PrepareNet()
-{
-listenSocket = socket(AF_INET, SOCK_DGRAM, 0);
-
-if (listenSocket < 0)
-    {
-    errorStr = "Cannot create socket.";
-    return true;
-    }
-
-struct sockaddr_in listenAddr;
-listenAddr.sin_family = AF_INET;
-listenAddr.sin_port = htons(port);
-listenAddr.sin_addr.s_addr = inet_addr("0.0.0.0");
-
-if (bind(listenSocket, (struct sockaddr*)&listenAddr, sizeof(listenAddr)) < 0)
-    {
-    errorStr = "LISTENER: Bind failed.";
-    return true;
-    }
-
-printfd(__FILE__, "LISTENER::PrepareNet() >>>> Start successfull.\n");
-
-return false;
-}
-//-----------------------------------------------------------------------------
-bool LISTENER::FinalizeNet()
-{
-close(listenSocket);
-
-return false;
-}
-//-----------------------------------------------------------------------------
-bool LISTENER::RecvPacket()
-{
-struct iovec iov[2];
-
-char buffer[RS_MAX_PACKET_LEN];
-RS::PACKET_HEADER packetHead;
-
-iov[0].iov_base = reinterpret_cast<char *>(&packetHead);
-iov[0].iov_len = sizeof(packetHead);
-iov[1].iov_base = buffer;
-iov[1].iov_len = sizeof(buffer) - sizeof(packetHead);
-
-size_t dataLen = 0;
-while (dataLen < sizeof(buffer))
-    {
-    if (!WaitPackets(listenSocket))
-        {
-        if (!running)
-            return false;
-        continue;
-        }
-    int portion = readv(listenSocket, iov, 2);
-    if (portion < 0)
-        {
-        return true;
-        }
-    dataLen += portion;
-    }
-
-if (CheckHeader(packetHead))
-    {
-    printfd(__FILE__, "Invalid packet or incorrect protocol version!\n");
-    return true;
-    }
-
-std::string userLogin((char *)packetHead.login);
-PendingData data;
-data.login = userLogin;
-data.ip = ntohl(packetHead.ip);
-data.id = ntohl(packetHead.id);
-
-if (packetHead.packetType == RS_ALIVE_PACKET)
-    {
-    data.type = PendingData::ALIVE;
-    }
-else if (packetHead.packetType == RS_CONNECT_PACKET)
-    {
-    data.type = PendingData::CONNECT;
-    if (GetParams(buffer, data))
-        {
-        return true;
-        }
-    }
-else if (packetHead.packetType == RS_DISCONNECT_PACKET)
-    {
-    data.type = PendingData::DISCONNECT;
-    if (GetParams(buffer, data))
-        {
-        return true;
-        }
-    }
-
-STG_LOCKER lock(&mutex);
-pending.push_back(data);
-
-return false;
-}
-//-----------------------------------------------------------------------------
-bool LISTENER::GetParams(char * buffer, UserData & data)
-{
-RS::PACKET_TAIL packetTail;
-
-Decrypt(&ctxS, (char *)&packetTail, buffer, sizeof(packetTail) / 8);
-
-if (strncmp((char *)packetTail.magic, RS_ID, RS_MAGIC_LEN))
-    {
-    printfd(__FILE__, "Invalid crypto magic\n");
-    return true;
-    }
-
-std::ostringstream params;
-params << "\"" << data.login << "\" "
-       << inet_ntostring(data.ip) << " "
-       << data.id << " "
-       << (char *)packetTail.params;
-
-data.params = params.str();
-
-return false;
-}
-//-----------------------------------------------------------------------------
-void LISTENER::ProcessPending()
-{
-std::list<PendingData>::iterator it(pending.begin());
-size_t count = 0;
-printfd(__FILE__, "Pending: %d\n", pending.size());
-while (it != pending.end() && count < 256)
-    {
-    std::vector<AliveData>::iterator uit(
-            std::lower_bound(
-                users.begin(),
-                users.end(),
-                it->login)
-            );
-    if (it->type == PendingData::CONNECT)
-        {
-        printfd(__FILE__, "Connect packet\n");
-        if (uit == users.end() || uit->login != it->login)
-            {
-            printfd(__FILE__, "Connect new user '%s'\n", it->login.c_str());
-            // Add new user
-            Connect(*it);
-            users.insert(uit, AliveData(static_cast<UserData>(*it)));
-            }
-        else if (uit->login == it->login)
-            {
-            printfd(__FILE__, "Update existing user '%s'\n", it->login.c_str());
-            // Update already existing user
-            time(&uit->lastAlive);
-            uit->params = it->params;
-            }
-        else
-            {
-            printfd(__FILE__, "Hmmm... Strange connect for '%s'\n", it->login.c_str());
-            }
-        }
-    else if (it->type == PendingData::ALIVE)
-        {
-        printfd(__FILE__, "Alive packet\n");
-        if (uit != users.end() && uit->login == it->login)
-            {
-            printfd(__FILE__, "Alive user '%s'\n", it->login.c_str());
-            // Update existing user
-            time(&uit->lastAlive);
-            }
-        else
-            {
-            printfd(__FILE__, "Alive user '%s' is not found\n", it->login.c_str());
-            }
-        }
-    else if (it->type == PendingData::DISCONNECT)
-        {
-        printfd(__FILE__, "Disconnect packet\n");
-        if (uit != users.end() && uit->login == it->login.c_str())
-            {
-            printfd(__FILE__, "Disconnect user '%s'\n", it->login.c_str());
-            // Disconnect existing user
-            uit->params = it->params;
-            Disconnect(*uit);
-            users.erase(uit);
-            }
-        else
-            {
-            printfd(__FILE__, "Cannot find user '%s' for disconnect\n", it->login.c_str());
-            }
-        }
-    else
-        {
-        printfd(__FILE__, "Unknown packet type\n");
-        }
-    ++it;
-    ++count;
-    }
-STG_LOCKER lock(&mutex);
-pending.erase(pending.begin(), it);
-}
-//-----------------------------------------------------------------------------
-void LISTENER::ProcessTimeouts()
-{
-const std::vector<AliveData>::iterator it(
-        std::stable_partition(
-            users.begin(),
-            users.end(),
-            IsNotTimedOut(userTimeout)
-        )
-    );
-
-if (it != users.end())
-    {
-    printfd(__FILE__, "Total users: %d, users to disconnect: %d\n", users.size(), std::distance(it, users.end()));
-
-    std::for_each(
-            it,
-            users.end(),
-            DisconnectUser(*this)
-        );
-
-    users.erase(it, users.end());
-    }
-}
-//-----------------------------------------------------------------------------
-bool LISTENER::Connect(const UserData & data) const
-{
-printfd(__FILE__, "Connect %s\n", data.login.c_str());
-if (access(scriptOnConnect.c_str(), X_OK) == 0)
-    {
-    if (ScriptExec((scriptOnConnect + " " + data.params).c_str()))
-        {
-        WriteServLog("Script %s cannot be executed for an unknown reason.", scriptOnConnect.c_str());
-        return true;
-        }
-    }
-else
-    {
-    WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
-    return true;
-    }
-return false;
-}
-//-----------------------------------------------------------------------------
-bool LISTENER::Disconnect(const UserData & data) const
-{
-printfd(__FILE__, "Disconnect %s\n", data.login.c_str());
-if (access(scriptOnDisconnect.c_str(), X_OK) == 0)
-    {
-    if (ScriptExec((scriptOnDisconnect + " " + data.params).c_str()))
-        {
-        WriteServLog("Script %s cannot be executed for an unknown reson.", scriptOnDisconnect.c_str());
-        return true;
-        }
-    }
-else
-    {
-    WriteServLog("Script %s cannot be executed. File not found.", scriptOnDisconnect.c_str());
-    return true;
-    }
-return false;
-}
-//-----------------------------------------------------------------------------
-bool LISTENER::CheckHeader(const RS::PACKET_HEADER & header) const
-{
-if (strncmp((char *)header.magic, RS_ID, RS_MAGIC_LEN))
-    {
-    return true;
-    }
-if (strncmp((char *)header.protoVer, "02", RS_PROTO_VER_LEN))
-    {
-    return true;
-    }
-return false;
-}
-//-----------------------------------------------------------------------------
-inline
-void InitEncrypt(BLOWFISH_CTX * ctx, const std::string & password)
-{
-unsigned char keyL[PASSWD_LEN];
-memset(keyL, 0, PASSWD_LEN);
-strncpy((char *)keyL, password.c_str(), PASSWD_LEN);
-Blowfish_Init(ctx, keyL, PASSWD_LEN);
-}
-//-----------------------------------------------------------------------------
-inline
-void Decrypt(BLOWFISH_CTX * ctx, char * dst, const char * src, int len8)
-{
-if (dst != src)
-    memcpy(dst, src, len8 * 8);
-
-for (int i = 0; i < len8; i++)
-    Blowfish_Decrypt(ctx, (uint32_t *)(dst + i * 8), (uint32_t *)(dst + i * 8 + 4));
-}
-//-----------------------------------------------------------------------------
diff --git a/rscriptd/listener.h b/rscriptd/listener.h
deleted file mode 100644 (file)
index 7fb71ee..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#include <pthread.h>
-
-#include <string>
-#include <vector>
-#include <list>
-#include <functional>
-#include <cstdint>
-
-#include "stg/blowfish.h"
-#include "stg/rs_packets.h"
-#include "stg/logger.h"
-
-struct UserData
-{
-    std::string params;
-    std::string login;
-    uint32_t    ip;
-    uint32_t    id;
-};
-
-struct PendingData : public UserData
-{
-    enum {CONNECT, ALIVE, DISCONNECT} type;
-};
-
-struct AliveData : public UserData
-{
-    explicit AliveData(const UserData & data)
-        : UserData(data),
-          lastAlive(time(NULL))
-    {};
-    bool operator<(const std::string & rvalue) const { return login < rvalue; };
-    time_t      lastAlive;
-};
-
-class IsNotTimedOut : public std::unary_function<const AliveData &, bool> {
-    public:
-        explicit IsNotTimedOut(double to) : timeout(to), now(time(NULL)) {}
-        bool operator()(const AliveData & data) const
-        {
-            return difftime(now, data.lastAlive) < timeout;
-        }
-    private:
-        double timeout;
-        time_t now;
-};
-
-class LISTENER
-{
-public:
-                        LISTENER();
-                        ~LISTENER(){};
-
-    void                SetPort(uint16_t p) { port = p; };
-    void                SetPassword(const std::string & p);
-    void                SetUserTimeout(int t) { userTimeout = t; };
-    void                SetScriptOnConnect(const std::string & script) { scriptOnConnect = script; };
-    void                SetScriptOnDisconnect(const std::string & script) { scriptOnDisconnect = script; };
-
-    bool                Start();
-    bool                Stop();
-    bool                IsRunning() const { return !receiverStopped && !processorStopped; };
-
-    const std::string & GetStrError() const { return errorStr; };
-    const std::string & GetVersion() const { return version; };
-
-private:
-    // Threading stuff
-    static void *       Run(void * self);
-    static void *       RunProcessor(void * self);
-    void                Runner();
-    void                ProcessorRunner();
-    // Networking stuff
-    bool                PrepareNet();
-    bool                FinalizeNet();
-    bool                RecvPacket();
-    // Parsing stuff
-    bool                CheckHeader(const RS::PACKET_HEADER & header) const;
-    bool                GetParams(char * buffer, UserData & data);
-    // Processing stuff
-    void                ProcessPending();
-    void                ProcessTimeouts();
-    bool                Disconnect(const UserData & data) const;
-    bool                Connect(const UserData & data) const;
-
-    BLOWFISH_CTX        ctxS;
-    STG::Logger&        WriteServLog;
-
-    mutable std::string errorStr;
-    std::string         scriptOnConnect;
-    std::string         scriptOnDisconnect;
-    std::string         password;
-    uint16_t            port;
-
-    bool                running;
-    bool                receiverStopped;
-    bool                processorStopped;
-    std::vector<AliveData> users;
-    std::list<PendingData> pending;
-    int                 userTimeout;
-
-    pthread_t           receiverThread;
-    pthread_t           processorThread;
-    pthread_mutex_t     mutex;
-
-    int                 listenSocket;
-
-    std::string         version;
-
-    friend class DisconnectUser;
-};
-
-class DisconnectUser : public std::unary_function<const UserData &, void> {
-    public:
-        explicit DisconnectUser(LISTENER & l) : listener(l) {};
-        void operator()(const UserData & data)
-        {
-            listener.Disconnect(data);
-        };
-    private:
-        LISTENER & listener;
-};
-//-----------------------------------------------------------------------------
diff --git a/rscriptd/main.cpp b/rscriptd/main.cpp
deleted file mode 100644 (file)
index e7c54ee..0000000
+++ /dev/null
@@ -1,337 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
- /*
- $Revision: 1.19 $
- $Author: faust $
- $Date: 2010/09/10 06:37:45 $
- */
-
-#include <sys/types.h>
-#include <sys/ipc.h>
-#include <sys/msg.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-#include <fcntl.h> // creat
-#include <unistd.h>
-
-#include <cstdlib>
-#include <cstdio>
-#include <csignal>
-#include <cerrno>
-#include <cstring> // strerror
-#include <set>
-
-#include "stg/common.h"
-#include "stg/logger.h"
-#include "stg/scriptexecuter.h"
-#include "stg/conffiles.h"
-#include "stg/version.h"
-#include "listener.h"
-#include "pidfile.h"
-
-#ifdef DEBUG
-# define MAIN_DEBUG  1
-# define NO_DAEMON    1
-#endif
-
-#define START_FILE "/._ST_ART_ED_"
-
-std::set<pid_t> executersPid;
-volatile time_t stgTime = time(NULL);
-
-//-----------------------------------------------------------------------------
-void KillExecuters()
-{
-std::set<pid_t>::iterator pid;
-pid = executersPid.begin();
-while (pid != executersPid.end())
-    {
-    printfd(__FILE__, "KillExecuters pid=%d\n", *pid);
-    kill(*pid, SIGUSR1);
-    ++pid;
-    }
-}
-//-----------------------------------------------------------------------------
-#if defined(LINUX) || defined(DARWIN)
-int StartScriptExecuter(char * procName, int msgKey, int * msgID)
-#else
-int StartScriptExecuter(char *, int msgKey, int * msgID)
-#endif
-{
-auto & WriteServLog = STG::Logger::get();
-
-if (*msgID == -11)   // If msgID == -11 - first call. Create queue
-    {
-    for (int i = 0; i < 2; i++)
-        {
-        *msgID = msgget(msgKey, IPC_CREAT | IPC_EXCL | 0600);
-
-        if (*msgID == -1)
-            {
-            *msgID = msgget(msgKey, 0);
-            if (*msgID == -1)
-                {
-                WriteServLog("Message queue not created.");
-                return -1;
-                }
-            else
-                {
-                msgctl(*msgID, IPC_RMID, NULL);
-                }
-            }
-        else
-            {
-            WriteServLog("Message queue created successfully. msgKey=%d msgID=%d", msgKey, *msgID);
-            break;
-            }
-        }
-    }
-
-pid_t executerPid = fork();
-
-switch (executerPid)
-    {
-    case -1:    // Failure
-        WriteServLog("Fork error!");
-        return -1;
-
-    case 0:     // Child
-        //close(0);
-        //close(1);
-        //close(2);
-        //setsid();
-#if defined(LINUX) || defined(DARWIN)
-        Executer(*msgID, executerPid, procName);
-#else
-        Executer(*msgID, executerPid);
-#endif
-        return 1;
-
-    default:    // Parent
-        if (executersPid.empty())
-#if defined(LINUX) || defined(DARWIN)
-            Executer(*msgID, executerPid, NULL);
-#else
-            Executer(*msgID, executerPid);
-#endif
-        executersPid.insert(executerPid);
-    }
-return 0;
-}
-//-----------------------------------------------------------------------------
-void StopScriptExecuter(int msgID)
-{
-auto & WriteServLog = STG::Logger::get();
-
-for (int i = 0; i < 5; ++i)
-    {
-    struct msqid_ds data;
-    if (msgctl(msgID, IPC_STAT, &data))
-        {
-        int e = errno;
-        printfd(__FILE__, "StopScriptExecuter() - msgctl for IPC_STAT failed: '%s'\n", strerror(e));
-        WriteServLog( "Failed to check queue emptiness: '%s'", strerror(e));
-        break;
-        }
-
-    WriteServLog("Messages in queue: %d", data.msg_qnum);
-
-    if (data.msg_qnum == 0)
-        break;
-
-    struct timespec ts = {1, 0};
-    nanosleep(&ts, NULL);
-    }
-
-if (msgctl(msgID, IPC_RMID, NULL))
-    {
-    int e = errno;
-    printfd(__FILE__, "StopScriptExecuter() - msgctl for IPC_STAT failed: '%s'\n", strerror(e));
-    WriteServLog("Failed to remove queue: '%s'", strerror(e));
-    }
-else
-    {
-    WriteServLog("Queue removed successfully.");
-    }
-
-KillExecuters();
-}
-//-----------------------------------------------------------------------------
-#ifdef NO_DAEMON
-int ForkAndWait(const std::string &)
-#else
-int ForkAndWait(const std::string & confDir)
-#endif
-{
-#ifndef NO_DAEMON
-pid_t childPid = fork();
-
-switch (childPid)
-    {
-    case -1:    // Failure
-        return -1;
-        break;
-
-    case 0:     // Child
-        //close(0);
-        close(1);
-        close(2);
-        setsid();
-        break;
-
-    default:    // Parent
-        exit(1);
-        break;
-    }
-#endif
-return 0;
-}
-//-----------------------------------------------------------------------------
-int main(int argc, char * argv[])
-{
-CONFIGFILE * cfg = NULL;
-LISTENER * listener = NULL;
-int msgID = -11;
-int execNum = 0;
-int execMsgKey = 0;
-
-std::string logFileName;
-std::string confDir;
-std::string password;
-std::string onConnect;
-std::string onDisconnect;
-int port;
-int userTimeout;
-
-if (getuid())
-    {
-    printf("You must be root. Exit.\n");
-    exit(1);
-    }
-
-if (argc == 2)
-    cfg = new CONFIGFILE(argv[1]);
-else
-    cfg = new CONFIGFILE("/etc/rscriptd/rscriptd.conf");
-
-if (cfg->Error())
-    {
-    auto & WriteServLog = STG::Logger::get();
-    WriteServLog.setFileName("/var/log/rscriptd.log");
-    WriteServLog("Error reading config file!");
-    delete cfg;
-    return EXIT_FAILURE;
-    }
-
-cfg->ReadString("LogFileName", &logFileName, "/var/log/rscriptd.log");
-cfg->ReadInt("ExecutersNum", &execNum, 1);
-cfg->ReadInt("ExecMsgKey", &execMsgKey, 5555);
-cfg->ReadString("ConfigDir", &confDir, "/etc/rscriptd");
-cfg->ReadString("Password", &password, "");
-cfg->ReadInt("Port", &port, 5555);
-cfg->ReadInt("UserTimeout", &userTimeout, 60);
-cfg->ReadString("ScriptOnConnect", &onConnect, "/etc/rscriptd/OnConnect");
-cfg->ReadString("ScriptOnDisconnect", &onDisconnect, "/etc/rscriptd/OnDisconnect");
-
-if (ForkAndWait(confDir) < 0)
-    {
-    auto & WriteServLog = STG::Logger::get();
-    WriteServLog("Fork error!");
-    delete cfg;
-    return EXIT_FAILURE;
-    }
-
-auto & WriteServLog = STG::Logger::get();
-PIDFile pidFile("/var/run/rscriptd.pid");
-WriteServLog.setFileName(logFileName);
-WriteServLog("rscriptd v. %s", SERVER_VERSION);
-
-for (int i = 0; i < execNum; i++)
-    {
-    int ret = StartScriptExecuter(argv[0], execMsgKey, &msgID);
-    if (ret < 0)
-        {
-        STG::Logger::get()("Start Script Executer error!");
-        delete cfg;
-        return EXIT_FAILURE;
-        }
-    if (ret == 1)
-        {
-        delete cfg;
-        return EXIT_SUCCESS;
-        }
-    }
-
-listener = new LISTENER();
-listener->SetPort(port);
-listener->SetPassword(password);
-listener->SetUserTimeout(userTimeout);
-listener->SetScriptOnConnect(onConnect);
-listener->SetScriptOnDisconnect(onDisconnect);
-
-listener->Start();
-
-WriteServLog("rscriptd started successfully.");
-WriteServLog("+++++++++++++++++++++++++++++++++++++++++++++");
-
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-while (true)
-    {
-    sigfillset(&signalSet);
-    int sig = 0;
-    printfd(__FILE__, "Before sigwait\n");
-    sigwait(&signalSet, &sig);
-    printfd(__FILE__, "After sigwait. Signal: %d\n", sig);
-    bool stop = false;
-    switch (sig)
-        {
-        case SIGTERM:
-            stop = true;
-            break;
-        case SIGINT:
-            stop = true;
-            break;
-        default:
-            WriteServLog("Ignore signel %d", sig);
-            break;
-        }
-    if (stop)
-        break;
-    }
-
-listener->Stop();
-
-WriteServLog("+++++++++++++++++++++++++++++++++++++++++++++");
-
-StopScriptExecuter(msgID);
-
-WriteServLog("rscriptd stopped successfully.");
-WriteServLog("---------------------------------------------");
-
-delete listener;
-delete cfg;
-return EXIT_SUCCESS;
-}
-//-----------------------------------------------------------------------------
diff --git a/rscriptd/pidfile.cpp b/rscriptd/pidfile.cpp
deleted file mode 100644 (file)
index 5f3f497..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-/*
- $Revision: 1.1 $
- $Date: 2010/02/11 12:32:25 $
- $Author: faust $
- */
-
-/*
- *  An implementation of RAII pid-file writer
- */
-
-#include <fstream>
-#include <unistd.h>
-
-#include "pidfile.h"
-
-PIDFile::PIDFile(const std::string & fn)
-    : fileName(fn)
-{
-if (fileName != "")
-    {
-    std::ofstream pf(fileName.c_str());
-    pf << getpid() << std::endl;
-    pf.close();
-    }
-}
-
-PIDFile::~PIDFile()
-{
-if (fileName != "")
-    {
-    unlink(fileName.c_str());
-    }
-}
diff --git a/rscriptd/pidfile.h b/rscriptd/pidfile.h
deleted file mode 100644 (file)
index 82ff003..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-/*
- *  Header file for RAII pid-file writer
- */
-
-/*
- $Revision: 1.1 $
- $Date: 2010/02/11 12:32:25 $
- $Author: faust $
- */
-
-#ifndef __PID_FILE_H__
-#define __PID_FILE_H__
-
-#include <string>
-
-class PIDFile {
-public:
-    explicit PIDFile(const std::string & fn);
-    ~PIDFile();
-private:
-    std::string fileName;
-};
-
-#endif
diff --git a/rscriptd/rscriptd.conf b/rscriptd/rscriptd.conf
deleted file mode 100644 (file)
index 45b7b5c..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-################################################################################
-#                         Rscriptd Configuration file                          #
-################################################################################
-
-# LOG file name
-# Parameter: optional
-# Value: file path
-# Default: /var/log/rscriptd.log
-LogFileName = /var/log/rscriptd.log
-
-# Amount of rscriptd-exec processes.
-# These processes are responsible for the execution of scripts 
-# OnConnect and OnDisconnect.
-# Amount of processes means how many scripts can be executed simultaneously.
-# Recommend to leave 1 to avoid errors when executing scripts
-# Parameter: optional
-# Value: 1 ... 1024
-# Default: 1
-ExecutersNum = 1
-
-# Message queue identifier for the script executer.
-# It may be changed if there're a needs to run multiple copies of rscriptd.
-# Warning: If you do not understand it, do not touch this setting!
-# Parameter: optional
-# Value: 0 ... 2 ^ 32
-# Default: 5555
-# ExecMsgKey = 5555
-
-# The path to directory where config files are
-# Parameter: optional
-# Value: directory path
-# Default: /etc/rscriptd
-ConfigDir = /etc/rscriptd
-
-# Defines password for the encryption exchange between
-# Stargazer server and rscriptd.
-# Parameter: optional
-# Value: any
-# Default: 123456
-Password = 123456
-
-# Defines port number for communication between
-# Stargazer server and rscriptd.
-# Parameter: optional
-# Value: 1 ... 65535
-# Default: 9999
-Port = 9999
-
-# User timeout. If Stargazer does not respond during this time,
-# the user will be disconnected.
-# Parameter: optional
-# Values: 5 ... 600
-# Default: 60
-UserTimeout = 60
-
-# Defines file which runs when user gets access
-# Parameter: optional
-# Value: file path
-# Default: /etc/rscriptd/OnConnect
-ScriptOnConnect = /etc/rscriptd/OnConnect
-
-# Defines file which runs when user loses access
-# Parameter: optional
-# Value: file path
-# Default: /etc/rscriptd/OnDisconnect
-ScriptOnDisconnect = /etc/rscriptd/OnDisconnect
-
-################################################################################
diff --git a/sgauth/.gitignore b/sgauth/.gitignore
deleted file mode 100644 (file)
index f4bcc89..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-css.h
-sgauth
diff --git a/sgauth/CMakeLists.txt b/sgauth/CMakeLists.txt
deleted file mode 100644 (file)
index 2a87f3f..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-set ( CPP_FILES main.cpp settings_impl.cpp web.cpp )
-
-set ( THREADS_PREFER_PTHREAD_FLAG ON )
-find_package ( Threads REQUIRED )
-find_package ( Intl REQUIRED )
-
-file ( READ sgauth.css CSS_DATA )
-configure_file ( css.h.in css.h ESCAPE_QUOTES @ONLY )
-
-set ( CMAKE_INCLUDE_CURRENT_DIR ON )
-
-include_directories ( ${Intl_INCLUDE_DIRS} )
-
-add_executable ( sgauth ${CPP_FILES} )
-
-target_link_libraries ( sgauth conffiles ia crypto common ${Intl_LIBRARIES} Threads::Threads )
-
-# TODO: install
diff --git a/sgauth/css.h.in b/sgauth/css.h.in
deleted file mode 100644 (file)
index 5a14125..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#pragma once
-
-namespace SGAuth
-{
-
-const auto css = R"EOR(
-@CSS_DATA@
-)EOR";
-
-}
diff --git a/sgauth/main.cpp b/sgauth/main.cpp
deleted file mode 100644 (file)
index 3256ae5..0000000
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- */
-
- /*
- $Revision: 1.13 $
- $Date: 2010/04/14 09:01:29 $
- $Author: faust $
- */
-
-#include <unistd.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <csignal>
-#include <cstdio>
-#include <cstring>
-#include <iostream>
-#include <vector>
-
-#include "stg/ia.h"
-#include "stg/common.h"
-#include "web.h"
-#include "settings_impl.h"
-
-int mes;
-char infoText[256];
-char messageText[256];
-
-const int winKOI = 0;
-
-IA_CLIENT_PROT * clnp;
-WEB * web = NULL;
-
-time_t stgTime;
-
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-void Usage()
-{
-printf("sgauth <path_to_config>\n");
-}
-//-----------------------------------------------------------------------------
-void SetDirName(const std::vector<std::string> & dn, void *)
-{
-for (int j = 0; j < DIR_NUM; j++)
-    {
-    if (winKOI)
-        {
-        std::string dir;
-        KOIToWin(dn[j], &dir);
-        if (web)
-            web->SetDirName(dir, j);
-        }
-    else
-        {
-        if (web)
-            web->SetDirName(dn[j], j);
-        }
-    }
-}
-//-----------------------------------------------------------------------------
-void StatUpdate(const LOADSTAT & ls, void *)
-{
-if (web)
-    web->UpdateStat(ls);
-}
-//-----------------------------------------------------------------------------
-void StatusChanged(int, void *)
-{
-}
-//-----------------------------------------------------------------------------
-void ShowMessage(const std::string & message, int i, int, int, void *)
-{
-if (web)
-    web->AddMessage(message, i);
-}
-//-----------------------------------------------------------------------------
-void ShowError(const std::string & message, int, void *)
-{
-if (web)
-     web->AddMessage(message, 0);
-}
-//-----------------------------------------------------------------------------
-void CatchUSR1(int)
-{
-if (clnp->GetAuthorized())
-    {
-    std::cout << "Connect" << std::endl;
-    clnp->Connect();
-    }
-}
-//-----------------------------------------------------------------------------
-void CatchUSR2(int)
-{
-std::cout << "Disconnect" << std::endl;
-clnp->Disconnect();
-}
-//-----------------------------------------------------------------------------
-void CatchTERM(int)
-{
-std::cout << "Terminated" << std::endl;
-clnp->Disconnect();
-sleep(2);
-exit(0);
-}
-//-----------------------------------------------------------------------------
-static void SetSignalHandlers()
-{
-struct sigaction newsa, oldsa;
-sigset_t sigmask;
-
-sigemptyset(&sigmask);
-sigaddset(&sigmask, SIGTERM);
-newsa.sa_handler = CatchTERM;
-newsa.sa_mask = sigmask;
-newsa.sa_flags = 0;
-sigaction(SIGTERM, &newsa, &oldsa);
-
-sigemptyset(&sigmask);
-sigaddset(&sigmask, SIGINT);
-newsa.sa_handler = CatchTERM;
-newsa.sa_mask = sigmask;
-newsa.sa_flags = 0;
-sigaction(SIGINT, &newsa, &oldsa);
-
-sigemptyset(&sigmask);
-sigaddset(&sigmask, SIGUSR1);
-newsa.sa_handler = CatchUSR1;
-newsa.sa_mask = sigmask;
-newsa.sa_flags = 0;
-sigaction(SIGUSR1, &newsa, &oldsa);
-
-sigemptyset(&sigmask);
-sigaddset(&sigmask, SIGUSR2);
-newsa.sa_handler = CatchUSR2;
-newsa.sa_mask = sigmask;
-newsa.sa_flags = 0;
-sigaction(SIGUSR2, &newsa, &oldsa);
-
-return;
-}
-//-----------------------------------------------------------------------------
-int main(int argc, char *argv[])
-{
-SETTINGS_IMPL settings;
-
-if (argc == 2)
-    {
-    settings.SetConfFile(argv[1]);
-    }
-else
-    {
-    // Usage
-    }
-
-if (settings.ReadSettings())
-    {
-    printf("ReadSettingsError\n");
-    printf("%s\n", settings.GetStrError().c_str());
-    exit(-1);
-    }
-settings.Print();
-
-if (settings.GetDaemon())
-    {
-    switch (fork())
-        {
-        case -1:
-            exit(1);
-            break;
-
-        case 0:
-            setsid();
-            break;
-
-        default:
-            exit(0);
-            break;
-        }
-    }
-
-clnp = new IA_CLIENT_PROT(settings.GetServerName(), settings.GetServerPort(), settings.GetLocalName(), settings.GetLocalPort());
-
-if (!settings.GetNoWeb())
-    {
-    web = new WEB();
-    web->SetRefreshPagePeriod(settings.GetRefreshPeriod());
-    web->SetListenAddr(settings.GetListenWebIP());
-    web->Start();
-    }
-
-clnp->SetLogin(settings.GetLogin());
-clnp->SetPassword(settings.GetPassword());
-
-clnp->SetStatusChangedCb(StatusChanged, NULL);
-clnp->SetInfoCb(ShowMessage, NULL);
-clnp->SetErrorCb(ShowError, NULL);
-clnp->SetDirNameCb(SetDirName, NULL);
-clnp->SetStatChangedCb(StatUpdate, NULL);
-clnp->SetReconnect(settings.GetReconnect());
-
-clnp->Start();
-
-SetSignalHandlers();
-
-#ifdef LINUX
-for (int i = 1; i < argc; i++)
-    memset(argv[i], 0, strlen(argv[i]));
-
-if(argc > 1)
-    strcpy(argv[1], "Connecting...");
-#endif
-
-#ifdef FREEBSD
-setproctitle("Connecting...");
-#endif
-clnp->Connect();
-
-while (1)
-    {
-    struct timespec ts = {0, 200000000};
-    nanosleep(&ts, NULL);
-
-    char state[20];
-
-    if (clnp->GetAuthorized())
-        {
-        if (settings.GetShowPid())
-            sprintf(state, "On %d", getpid());
-        else
-            strcpy(state, "Online");
-        }
-    else
-        {
-        if (settings.GetShowPid())
-            sprintf(state, "Off %d", getpid());
-        else
-            strcpy(state, "Offline");
-        }
-
-    #ifdef LINUX
-    for (int i = 1; i < argc; i++)
-        memset(argv[i], 0, strlen(argv[i]));
-    if(argc > 1)
-        strcpy(argv[1], state);
-    #endif
-
-    #ifdef FREEBSD
-    setproctitle(state);
-    #endif
-
-    #ifdef FREEBSD_5
-    setproctitle(state);
-    #endif
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
diff --git a/sgauth/settings_impl.cpp b/sgauth/settings_impl.cpp
deleted file mode 100644 (file)
index 1a7b8dc..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#include <iostream>
-#include <cstring>
-
-#include "stg/common.h"
-#include "stg/conffiles.h"
-#include "settings_impl.h"
-
-SETTINGS_IMPL::SETTINGS_IMPL()
-    : port(0),
-      localPort(0),
-      listenWebIP(0),
-      refreshPeriod(0),
-      daemon(false),
-      noWeb(false),
-      reconnect(false),
-      showPid(false),
-      confFile("/etc/sgauth.conf")
-{
-}
-//-----------------------------------------------------------------------------
-int SETTINGS_IMPL::ReadSettings()
-{
-CONFIGFILE cf(confFile);
-
-if (cf.Error())
-    {
-    strError = "Cannot read file '" + confFile + "'";
-    return -1;
-    }
-
-cf.ReadString("Login", &login, "/?--?--?*");
-if (login == "/?--?--?*")
-    {
-    strError = "Parameter 'Login' not found.";
-    return -1;
-    }
-
-cf.ReadString("Password", &password, "/?--?--?*");
-if (login == "/?--?--?*")
-    {
-    strError = "Parameter 'Password' not found.";
-    return -1;
-    }
-
-cf.ReadString("ServerName", &serverName, "?*?*?");
-if (serverName == "?*?*?")
-    {
-    strError = "Parameter 'ServerName' not found.";
-    return -1;
-    }
-
-std::string temp;
-cf.ReadString("ListenWebIP", &temp, "127.0.0.1");
-listenWebIP = inet_strington(temp);
-if (listenWebIP == 0)
-    {
-    strError = "Parameter 'ListenWebIP' is not valid.";
-    return -1;
-    }
-
-cf.ReadString("ServerPort", &temp, "5555");
-if (ParseIntInRange(temp, 1, 65535, &port))
-    {
-    strError = "Parameter 'ServerPort' is not valid.";
-    return -1;
-    }
-
-cf.ReadString("LocalName", &localName, "");
-
-cf.ReadString("LocalPort", &temp, "0");
-if (ParseIntInRange(temp, 0, 65535, &localPort))
-    {
-    strError = "Parameter 'LocalPort' is not valid.";
-    return -1;
-    }
-
-cf.ReadString("RefreshPeriod", &temp, "5");
-if (ParseIntInRange(temp, 1, 24*3600, &refreshPeriod))
-    {
-    strError = "Parameter 'RefreshPeriod' is not valid.";
-    return -1;
-    }
-
-cf.ReadString("Reconnect", &temp, "yes");
-if (ParseYesNo(temp, &reconnect))
-    {
-    strError = "Parameter 'Reconnect' is not valid.";
-    return -1;
-    }
-
-cf.ReadString("Daemon", &temp, "yes");
-if (ParseYesNo(temp, &daemon))
-    {
-    strError = "Parameter 'Daemon' is not valid.";
-    return -1;
-    }
-
-cf.ReadString("ShowPid", &temp, "no");
-if (ParseYesNo(temp, &showPid))
-    {
-    strError = "Parameter 'ShowPid' is not valid.";
-    return -1;
-    }
-
-cf.ReadString("DisableWeb", &temp, "no");
-if (ParseYesNo(temp, &noWeb))
-    {
-    strError = "Parameter 'DisableWeb' is not valid.";
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-void SETTINGS_IMPL::Print() const
-{
-std::cout << "Login = " << login << "\n"
-          << "Password = " << password << "\n"
-          << "Ip = " << serverName << "\n"
-          << "Port = " << port << "\n"
-          << "LocalPort = " << localPort << "\n"
-          << "ListenWebIP = " << inet_ntostring(listenWebIP) << "\n"
-          << "RefreshPeriod = " << refreshPeriod << "\n"
-          << "Daemon = " << daemon << "\n"
-          << "DisableWeb = " << noWeb << "\n"
-          << "Reconnect = " << reconnect << "\n"
-          << "ShowPid = " << showPid << std::endl;
-}
diff --git a/sgauth/settings_impl.h b/sgauth/settings_impl.h
deleted file mode 100644 (file)
index c5305b8..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#ifndef SETTINGS_IMPL_H
-#define SETTINGS_IMPL_H
-
-#include <string>
-#include <cstdint>
-
-class SETTINGS_IMPL {
-public:
-                        SETTINGS_IMPL();
-                        ~SETTINGS_IMPL() {}
-    int                 Reload() { return 0; }
-    void                SetConfFile(const std::string & cf) { confFile = cf; }
-    int                 ReadSettings();
-
-    const std::string & GetStrError() const { return strError; }
-
-    const std::string & GetServerName() const { return serverName; }
-    uint16_t            GetServerPort() const { return port; }
-    const std::string & GetLocalName() const { return localName; }
-    uint16_t            GetLocalPort() const { return localPort; }
-
-    const std::string & GetLogin() const { return login; }
-    const std::string & GetPassword() const { return password; }
-
-    bool                GetDaemon() const { return daemon; }
-    bool                GetShowPid() const { return showPid; }
-    bool                GetNoWeb() const { return noWeb; }
-    bool                GetReconnect() const { return reconnect; }
-    int                 GetRefreshPeriod() const { return refreshPeriod; }
-    uint32_t            GetListenWebIP() const { return listenWebIP; }
-
-    void                Print() const;
-
-private:
-    std::string login;
-    std::string password;
-    std::string serverName;
-    int         port;
-    std::string localName;
-    int         localPort;
-    uint32_t    listenWebIP;
-    int         refreshPeriod;
-
-    bool        daemon;
-    bool        noWeb;
-    bool        reconnect;
-    bool        showPid;
-
-    std::string confFile;
-    std::string strError;
-};
-
-#endif
diff --git a/sgauth/sgauth.conf b/sgauth/sgauth.conf
deleted file mode 100644 (file)
index bb5fca3..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-################################################################################
-#                           Sgauth Configuration file                          #
-################################################################################
-
-# Stargazer server
-# Parameter: required
-# Values: IP address or DNS name
-# Default:
-ServerName = 192.168.1.2
-
-# Port on which Stargazer interacts with sgauth
-# Parameter: optional
-# Value: 1 ... 65535
-# Default: 5555
-ServerPort = 5555
-
-# User's login in Stargazer
-# Parameter: required
-# Value: any
-# Default:
-Login = test
-
-# Local host to bind
-# Parameter: optional
-# Values: IP address or DNS name
-# Default: 0.0.0.0
-LocalName = localhost
-
-# Port on which sgauth interacts with Stargazer
-# Parameter: optional
-# Value: 1 ... 65535
-# Default: 0
-LocalPort = 12345
-
-# User's password in Stargazer
-# Parameter: required
-# Value: any
-# Default:
-Password = 123456
-
-# Defines whether sgauth should try to reestablish connection to Stargazer
-# if it was lost
-# Parameter: optional
-# Value: yes, no
-# Default: yes
-Reconnect = yes
-
-# Defines whether sgauth should run as daemon
-# Parameter: optional
-# Value: yes, no
-# Default: yes
-Daemon = yes
-
-# Web-page refresh period in built-in webserver
-# Parameter: optional
-# Value: any numeric (minutes)
-# Default: 10
-RefreshPeriod = 10
-
-# Defines whether sgauth should use built-in webserver
-# Parameter: optional
-# Value: yes, no
-# Default: no
-DisableWeb = no
-
-# Defines address on which sgauth's built-in webserver will listen
-# Parameter: optional
-# Value: IP address or DNS name
-# Default: 127.0.0.1
-ListenWebIP = 127.0.0.1
-
-# Defines whether sgauth should show its process ID
-# Parameter: optional
-# Value: yes, no
-# Default: no
-ShowPid = no
-
-################################################################################
diff --git a/sgauth/sgauth.css b/sgauth/sgauth.css
deleted file mode 100644 (file)
index f816dbf..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-H3
-{
-color: black;
-}
-
-body
-{
-background-color: silver;
-}
-
-#TraffTable
-{
-background-color: white;
-}
-
-#TraffTableCaptionRow
-{
-background-color: silver;
-}
-
-#TraffTableCaptionCellC,
-#TraffTableUMCellC,
-#TraffTableDMCellC,
-#TraffTableUSCellC,
-#TraffTableDSCellC
-{
-background-color: silver;
-}
-
-#TraffTableDMRow,
-#TraffTableDSRow
-{
-background-color: #f2f0cc;
-}
-
-#TraffTableUMRow,
-#TraffTableUSRow
-{
-background-color: white;
-}
-
-#ConnectionStateOnline
-{
-color: green;
-font-size: 20px
-}
-
-#ConnectionStateOffline
-{
-color: red;
-font-size: 20px
-}
-
-p
-{
-padding: 2px;
-margin: 0px;
-}
-
-#MessagesTable
-{
-background-color: white;
-}
-
-#MessagesTableRowC
-{
-background-color: silver;
-}
-
-
-#MessagesTableRow0,
-#MessagesTableRow2,
-#MessagesTableRow4,
-#MessagesTableRow6,
-#MessagesTableRow8
-{
-background-color: #f2f0cc;
-}
diff --git a/sgauth/web.cpp b/sgauth/web.cpp
deleted file mode 100644 (file)
index a162acc..0000000
+++ /dev/null
@@ -1,461 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- */
-
- /*
- $Revision: 1.7 $
- $Date: 2010/03/15 12:58:17 $
- */
-
-#include <libintl.h>
-
-#include <csignal>
-#include <cstdio>
-#include <cstring>
-#include <ctime>
-
-#include "stg/common.h"
-#include "stg/ia.h"
-#include "web.h"
-
-extern WEB * web;
-extern IA_CLIENT_PROT * clnp;
-
-#define LISTEN_PORT (5580)
-
-#include "css.h"
-
-//---------------------------------------------------------------------------
-#ifndef WIN32
-void * RunWeb(void *)
-{
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-#else
-unsigned long WINAPI RunWeb(void *)
-{
-#endif
-while (1)
-    web->Run();
-return NULL;
-}
-//---------------------------------------------------------------------------
-WEB::WEB()
-    : res(0),
-      listenSocket(0),
-      outerSocket(0),
-      refreshPeriod(0),
-      listenWebAddr(0)
-{
-#ifdef WIN32
-res = WSAStartup(MAKEWORD(2,0), &wsaData);
-#endif
-
-for (int i = 0; i < DIR_NUM; i++)
-    dirName[i] = "-";
-
-refreshPeriod = 5;
-
-memset(&ls, 0, sizeof(ls));
-}
-//---------------------------------------------------------------------------
-void WEB::Start()
-{
-#ifdef WIN32
-unsigned long pt;
-CreateThread(
-    NULL,   // pointer to thread security attributes
-    16384,  // initial thread stack size, in bytes
-    RunWeb, // pointer to thread function
-    NULL,   // argument for new thread
-    0,      // CREATE_SUSPENDED, // creation flags
-    &pt     // pointer to returned thread identifier
-   );
-#else
-pthread_create(&thread, NULL, RunWeb, NULL);
-#endif
-}
-//---------------------------------------------------------------------------
-void WEB::PrepareNet()
-{
-listenSocket = socket(PF_INET, SOCK_STREAM, 0);
-
-struct sockaddr_in listenAddr;
-listenAddr.sin_family = AF_INET;
-listenAddr.sin_port = htons(LISTEN_PORT);
-listenAddr.sin_addr.s_addr = listenWebAddr;
-
-#ifndef WIN32
-int lng = 1;
-if (0 != setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR, &lng, 4))
-    {
-    printf("Setsockopt Fail\n");
-    printf(">>> Error %s\n", strerror(errno));
-    }
-#else
-//??? TODO
-#endif
-
-
-res = bind(listenSocket, (struct sockaddr*)&listenAddr, sizeof(listenAddr));
-
-if (res == -1)
-    {
-    printf("Bind failed.\n");
-    exit(0);
-    }
-
-res = listen(listenSocket, 0);
-if (res == -1)
-    {
-    printf("Listen failed.\n");
-    exit(0);
-    }
-}
-//---------------------------------------------------------------------------
-void WEB::SetRefreshPagePeriod(int p)
-{
-refreshPeriod = p;
-if (refreshPeriod <= 0 || refreshPeriod > 24*3600)
-    refreshPeriod = 5;
-}
-//---------------------------------------------------------------------------
-void WEB::SetListenAddr(uint32_t ip)
-{
-listenWebAddr = ip;
-}
-//---------------------------------------------------------------------------
-void WEB::Run()
-{
-PrepareNet();
-char recvBuffer[4096];
-while (1)
-    {
-    struct sockaddr_in outerAddr;
-
-    #ifndef WIN32
-    socklen_t outerAddrLen = sizeof(outerAddr);
-    #else
-    int outerAddrLen = sizeof(outerAddr);
-    #endif
-
-    outerSocket = accept(listenSocket, (struct sockaddr*)&outerAddr, &outerAddrLen);
-    if (outerSocket == -1)
-        {
-        printf(">>> Error %s\n", strerror(errno));
-        continue;
-        }
-    recv(outerSocket, recvBuffer, sizeof(recvBuffer), 0);
-
-    if (strncmp(recvBuffer, "GET /sgauth.css", strlen("GET /sgauth.css")) == 0)
-        {
-        SendCSS();
-        //printf("(1) recvBuffer=%s\n", recvBuffer);
-        }
-    else if (strncmp(recvBuffer, "GET /disconnect", strlen("GET /disconnect")) == 0)
-        {
-        clnp->Disconnect();
-        Redirect("/");
-        //printf("(2) recvBuffer=%s\n", recvBuffer);
-        }
-    else if (strncmp(recvBuffer, "GET /connect", strlen("GET /connect")) == 0)
-        {
-        clnp->Connect();
-        Redirect("/");
-        //printf("(3) recvBuffer=%s\n", recvBuffer);
-        }
-    else if (strncmp(recvBuffer, "GET /exit", strlen("GET /exit")) == 0)
-        {
-        Redirect("/");
-        clnp->Disconnect();
-        #ifdef WIN32
-        Sleep(1000);
-        #else
-        struct timespec ts = {1, 0};
-        nanosleep(&ts, NULL);
-        #endif
-        exit(0);
-        }
-    else
-       {
-       SendReply();
-       //printf("(4) recvBuffer=%s\n", recvBuffer);
-       }
-
-    #ifdef WIN32
-    closesocket(outerSocket);
-    #else
-    close(outerSocket);
-    #endif
-    }
-}
-//---------------------------------------------------------------------------
-int WEB::Redirect(const char * url)
-{
-const char * redirect =
-    "HTTP/1.0 200 OK\n"
-    "Content-Type: text/html\n"
-    "Connection: close"
-    "\n\n"
-    "<html>\n"
-    "<head>\n"
-    "<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0;%s\">\n"
-    "</head>\n"
-    "<body>\n"
-    "</body></html>\n\n";
-
-char buff[2000];
-sprintf(buff, redirect, url);
-send(outerSocket, buff, strlen(buff), 0);
-
-return 0;
-}
-//---------------------------------------------------------------------------
-int WEB::SendReply()
-{
-int j, rowNum;
-
-const char * replyHeader =
-    "HTTP/1.0 200 OK\n"
-    "Content-Type: text/html\n"
-    "Connection: close"
-    "\n\n"
-    "<html>\n"
-    "<head>\n"
-    "<META HTTP-EQUIV=\"Refresh\" CONTENT=\"%d\">\n"
-    "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=windows-1251\">\n"
-    "<title>sgauth</title>\n"
-    "<link rel=\"Stylesheet\" href=\"sgauth.css\">"
-    "</head>\n"
-    "<body>\n"
-    "<H3>Stargazer</H3><p>\n";
-
-const char * replyFooter = "</body></html>\n\n";
-
-char replyHeaderBuffer[2000];
-sprintf(replyHeaderBuffer, replyHeader, refreshPeriod);
-
-send(outerSocket, replyHeaderBuffer, strlen(replyHeaderBuffer), 0);
-
-char str[512];
-
-int st = clnp->GetAuthorized();
-
-sprintf(str, "<a href=\"connect\">%s</a><p>\n", gettext("Connect"));
-res = send(outerSocket, str, strlen(str), 0);
-
-sprintf(str, "<a href=\"disconnect\">%s</a><p>\n", gettext("Disconnect"));
-res = send(outerSocket, str, strlen(str), 0);
-
-sprintf(str, "<a href=\"/\">%s</a><p>\n", gettext("Refresh"));
-res = send(outerSocket, str, strlen(str), 0);
-
-sprintf(str, "<a href=\"exit\">%s</a><p>\n", gettext("Exit"));
-res = send(outerSocket, str, strlen(str), 0);
-
-sprintf(str, "<div id=\"%s\">%s</div><p>\n" , st ? "ConnectionStateOnline":"ConnectionStateOffline", st ? "Online":"Offline");
-res = send(outerSocket, str, strlen(str), 0);
-
-sprintf(str, "<div id=\"Cash\">%s: %.3f</div><p>\n" , gettext("Cash"), ls.cash / 1000.0);
-res = send(outerSocket, str, strlen(str), 0);
-
-sprintf(str, "<div id=\"Prepaid Traffic\">%s: %s</div><p>\n" ,
-        gettext("PrepaidTraffic"),
-        ls.freeMb[0] == 'C' ? ls.freeMb + 1 : ls.freeMb);
-res = send(outerSocket, str, strlen(str), 0);
-
-sprintf(str, "<TABLE id=\"TraffTable\">\n");
-res = send(outerSocket, str, strlen(str), 0);
-sprintf(str, "    <TR id=\"TraffTableCaptionRow\">\n");
-res = send(outerSocket, str, strlen(str), 0);
-sprintf(str, "       <TD id=\"TraffTableCaptionCellC\">&nbsp;</TD>\n");
-res = send(outerSocket, str, strlen(str), 0);
-
-rowNum = 0;
-for (j = 0; j < DIR_NUM; j++)
-    {
-    if (dirName[j][0] == 0)
-        continue;
-    std::string s;
-    KOIToWin(dirName[j], &s);// +++++++++ sigsegv ==========   TODO too long dir name crashes sgauth
-    sprintf(str, "       <TD id=\"TraffTableCaptionCell%d\">%s</TD>\n", rowNum++, s.c_str());
-    send(outerSocket, str, strlen(str), 0);
-    }
-
-sprintf(str,"    </TR>\n");
-send(outerSocket, str, strlen(str), 0);
-
-sprintf(str,"    <TR id=\"TraffTableUMRow\">\n");
-send(outerSocket, str, strlen(str), 0);
-
-sprintf(str,"        <TD id=\"TraffTableUMCellC\">%s</TD>\n", gettext("Month Upload"));
-send(outerSocket, str, strlen(str), 0);
-
-rowNum = 0;
-for (j = 0; j < DIR_NUM; j++)
-    {
-    if (dirName[j][0] == 0)
-        continue;
-    sprintf(str,"        <TD id=\"TraffTableUMCell%d\">%s</TD>\n", rowNum++, IntToKMG(ls.mu[j], ST_F));
-    res = send(outerSocket, str, strlen(str), 0);
-    }
-
-sprintf(str,"    </TR>\n");
-res = send(outerSocket, str, strlen(str), 0);
-sprintf(str,"    <TR id=\"TraffTableDMRow\">\n");
-res = send(outerSocket, str, strlen(str), 0);
-sprintf(str,"        <TD id=\"TraffTableDMCellC\">%s</TD>\n", gettext("Month Download"));
-res = send(outerSocket, str, strlen(str), 0);
-
-rowNum = 0;
-for (j = 0; j < DIR_NUM; j++)
-    {
-    if (dirName[j][0] == 0)
-        continue;
-    sprintf(str,"        <TD id=\"TraffTableDMCell%d\">%s</TD>\n", rowNum++, IntToKMG(ls.md[j], ST_F));
-    res = send(outerSocket, str, strlen(str), 0);
-    }
-sprintf(str,"    </TR>\n");
-res = send(outerSocket, str, strlen(str), 0);
-
-
-sprintf(str,"    <TR id=\"TraffTableUSRow\">\n");
-res = send(outerSocket, str, strlen(str), 0);
-sprintf(str,"        <TD id=\"TraffTableUSCellC\">%s</TD>\n", gettext("Session Upload"));
-res = send(outerSocket, str, strlen(str), 0);
-
-rowNum = 0;
-for (j = 0; j < DIR_NUM; j++)
-    {
-    if (dirName[j][0] == 0)
-        continue;
-    sprintf(str,"        <TD id=\"TraffTableUSCell%d\">%s</TD>\n", rowNum++, IntToKMG(ls.su[j], ST_F));
-    res = send(outerSocket, str, strlen(str), 0);
-    }
-
-sprintf(str,"    </TR>\n");
-res = send(outerSocket, str, strlen(str), 0);
-sprintf(str,"    <TR id=\"TraffTableDSRow\">\n");
-res = send(outerSocket, str, strlen(str), 0);
-sprintf(str,"        <TD id=\"TraffTableDSCellC\">%s</TD>\n", gettext("Session Download"));
-res = send(outerSocket, str, strlen(str), 0);
-
-for (j = 0; j < DIR_NUM; j++)
-    {
-    if (dirName[j][0] == 0)
-        continue;
-    sprintf(str,"        <TD id=\"TraffTableDSCell%d\">%s</TD>\n", j, IntToKMG(ls.sd[j], ST_F));
-    res = send(outerSocket, str, strlen(str), 0);
-    }
-
-sprintf(str,"    </TR>\n");
-res = send(outerSocket, str, strlen(str), 0);
-
-sprintf(str,"</TABLE>\n");
-res = send(outerSocket, str, strlen(str), 0);
-
-rowNum = 0;
-if (!messages.empty())
-    {
-    sprintf(str,"    <TABLE id=\"MessagesTable\">\n");
-    res = send(outerSocket, str, strlen(str), 0);
-
-    sprintf(str,"        <TR id=\"MessagesTableRowC\">\n");
-    send(outerSocket, str, strlen(str), 0);
-    sprintf(str,"            <TD>Date</TD>\n");
-    send(outerSocket, str, strlen(str), 0);
-    sprintf(str,"            <TD>Text</TD>\n");
-    send(outerSocket, str, strlen(str), 0);
-    sprintf(str,"        </TR>\n");
-    send(outerSocket, str, strlen(str), 0);
-
-    std::list<STG_MESSAGE>::reverse_iterator it;
-    it = messages.rbegin();
-    while (it != messages.rend())
-        {
-        sprintf(str,"        <TR id=\"MessagesTableRow%d\">\n", rowNum);
-        send(outerSocket, str, strlen(str), 0);
-        sprintf(str,"            <TD>%s</TD>\n", it->recvTime.c_str());
-        send(outerSocket, str, strlen(str), 0);
-        sprintf(str,"            <TD>%s</TD>\n", it->msg.c_str());
-        send(outerSocket, str, strlen(str), 0);
-        sprintf(str,"        </TR>\n");
-        send(outerSocket, str, strlen(str), 0);
-        ++it;
-        ++rowNum;
-        }
-
-    sprintf(str,"   </TABLE>\n");
-    res = send(outerSocket, str, strlen(str), 0);
-    }
-
-time_t t = time(NULL);
-sprintf(str,"Îáíîâëåíî: %s</b>" , ctime(&t));
-res = send(outerSocket, str, strlen(str), 0);
-
-send(outerSocket, replyFooter, strlen(replyFooter), 0);
-
-return 0;
-}
-//---------------------------------------------------------------------------
-int WEB::SendCSS()
-{
-const char * replyHeader =
-    "HTTP/1.0 200 OK\n"
-    "Content-Type: text/css\n"
-    "Connection: close\n\n";
-
-const char * replyFooter= "\n\n";
-
-send(outerSocket, replyHeader, strlen(replyHeader), 0);
-send(outerSocket, SGAuth::css, strlen(SGAuth::css), 0);
-send(outerSocket, replyFooter, strlen(replyFooter), 0);
-
-return 0;
-}
-//---------------------------------------------------------------------------
-void WEB::SetDirName(const std::string & dn, int n)
-{
-web->dirName[n] =  dn;
-}
-//---------------------------------------------------------------------------
-void WEB::AddMessage(const std::string & message, int type)
-{
-time_t t = time(NULL);
-STG_MESSAGE m;
-
-m.msg = message;
-m.type = type;
-m.recvTime = ctime(&t);
-
-messages.push_back(m);
-
-if (messages.size() > MAX_MESSAGES)
-    messages.pop_front();
-
-}
-//---------------------------------------------------------------------------
-void WEB::UpdateStat(const LOADSTAT & ls)
-{
-memcpy((void*)&(WEB::ls), &ls, sizeof(LOADSTAT));
-}
-//---------------------------------------------------------------------------
-
diff --git a/sgauth/web.h b/sgauth/web.h
deleted file mode 100644 (file)
index a933230..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- */
-
- /*
- $Revision: 1.3 $
- $Date: 2007/12/17 08:39:08 $
- */
-
-#ifndef WIN32
-#include <pthread.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdlib.h>
-#else
-#include <winsock2.h>
-#endif
-
-#include <string>
-#include <list>
-
-#include "stg/const.h"
-#include "stg/ia_packets.h"
-
-#define MAX_MESSAGES    (10)
-//-----------------------------------------------------------------------------
-struct STG_MESSAGE
-{
-std::string  msg;
-std::string  recvTime;
-int     type;
-};
-//-----------------------------------------------------------------------------
-class WEB
-{
-public:
-    WEB();
-    void Run();
-    void SetDirName(const std::string & dn, int n);
-    void SetRefreshPagePeriod(int p);
-    void SetListenAddr(uint32_t ip);
-    void AddMessage(const std::string & message, int type);
-    void UpdateStat(const LOADSTAT & ls);
-    void Start();
-private:
-    void PrepareNet();
-    int SendReply();
-    int SendCSS();
-    int Redirect(const char * url);
-
-    #ifdef WIN32
-    WSADATA wsaData;
-    #else
-    pthread_t thread;
-    #endif
-
-    std::string dirName[DIR_NUM];
-    int res;
-    int listenSocket;
-    int outerSocket;
-    int refreshPeriod;
-
-    uint32_t listenWebAddr;
-    LOADSTAT ls;
-
-    std::list<STG_MESSAGE> messages;
-};
-//-----------------------------------------------------------------------------
diff --git a/sgconf/CHANGES b/sgconf/CHANGES
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/sgconf/CMakeLists.txt b/sgconf/CMakeLists.txt
deleted file mode 100644 (file)
index c2666b8..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-find_package ( EXPAT REQUIRED )
-
-set ( CPP_FILES main.cpp options.cpp api_action.cpp actions.cpp admins.cpp tariffs.cpp users.cpp services.cpp corps.cpp info.cpp xml.cpp )
-
-set ( THREADS_PREFER_PTHREAD_FLAG ON )
-find_package ( Threads REQUIRED )
-
-add_executable ( sgconf ${CPP_FILES} )
-
-target_link_libraries ( sgconf srvconf crypto common EXPAT::EXPAT )
-
-# TODO: install
diff --git a/sgconf/README.txt b/sgconf/README.txt
deleted file mode 100644 (file)
index bb2db5b..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-Compiling:
-> ./build
-
-
diff --git a/sgconf/TODO b/sgconf/TODO
deleted file mode 100644 (file)
index 19b51f5..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-1. No default value for server.
-2. No default value for port.
diff --git a/sgconf/action.h b/sgconf/action.h
deleted file mode 100644 (file)
index 940ea7f..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#ifndef __STG_SGCONF_ACTION_H__
-#define __STG_SGCONF_ACTION_H__
-
-#include <string>
-#include <map>
-#include <stdexcept>
-
-namespace SGCONF
-{
-
-class OPTION_BLOCK;
-struct PARSER_STATE;
-struct CONFIG;
-
-class ACTION
-{
-    public:
-        virtual ~ACTION() {}
-
-        virtual ACTION * Clone() const = 0;
-        virtual std::string ParamDescription() const = 0;
-        virtual std::string DefaultDescription() const = 0;
-        virtual OPTION_BLOCK & Suboptions() = 0;
-        virtual PARSER_STATE Parse(int argc, char ** argv, void * data = NULL) = 0;
-        virtual void ParseValue(const std::string &) {}
-
-        class ERROR : public std::runtime_error
-        {
-            public:
-                ERROR(const std::string & message)
-                    : std::runtime_error(message.c_str()) {}
-        };
-};
-
-} // namespace SGCONF
-
-#endif
diff --git a/sgconf/actions.cpp b/sgconf/actions.cpp
deleted file mode 100644 (file)
index afa5162..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
diff --git a/sgconf/actions.h b/sgconf/actions.h
deleted file mode 100644 (file)
index 3181a10..0000000
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#pragma once
-
-#include "action.h"
-#include "options.h"
-#include "parser_state.h"
-
-#include "stg/common.h"
-#include "stg/optional.h"
-
-#include <string>
-
-#include <cassert>
-
-namespace SGCONF
-{
-
-typedef void (* FUNC0)();
-
-template <typename F>
-class FUNC0_ACTION : public ACTION
-{
-    public:
-        FUNC0_ACTION(const F & func) : m_func(func) {}
-
-        virtual ACTION * Clone() const { return new FUNC0_ACTION<F>(*this); }
-
-        virtual std::string ParamDescription() const { return ""; }
-        virtual std::string DefaultDescription() const { return ""; }
-        virtual OPTION_BLOCK & Suboptions() { return m_suboptions; }
-        virtual PARSER_STATE Parse(int argc, char ** argv, void * /*data*/)
-        {
-        m_func();
-        return PARSER_STATE(true, argc, argv);
-        }
-
-    private:
-        F m_func;
-        OPTION_BLOCK m_suboptions;
-};
-
-template <typename F>
-inline
-FUNC0_ACTION<F> * MakeFunc0Action(F func)
-{
-return new FUNC0_ACTION<F>(func);
-}
-
-template <typename T>
-class PARAM_ACTION : public ACTION
-{
-    public:
-        PARAM_ACTION(STG::Optional<T> & param,
-                     const T & defaultValue,
-                     const std::string & paramDescription)
-            : m_param(param),
-              m_defaltValue(defaultValue),
-              m_description(paramDescription),
-              m_hasDefault(true)
-        {}
-        PARAM_ACTION(STG::Optional<T> & param)
-            : m_param(param),
-              m_hasDefault(false)
-        {}
-        PARAM_ACTION(STG::Optional<T> & param,
-                     const std::string & paramDescription)
-            : m_param(param),
-              m_description(paramDescription),
-              m_hasDefault(false)
-        {}
-
-        virtual ACTION * Clone() const { return new PARAM_ACTION<T>(*this); }
-
-        virtual std::string ParamDescription() const { return m_description; }
-        virtual std::string DefaultDescription() const;
-        virtual OPTION_BLOCK & Suboptions() { return m_suboptions; }
-        virtual PARSER_STATE Parse(int argc, char ** argv, void * /*data*/);
-        virtual void ParseValue(const std::string & value);
-
-    private:
-        STG::Optional<T> & m_param;
-        T m_defaltValue;
-        std::string m_description;
-        bool m_hasDefault;
-        OPTION_BLOCK m_suboptions;
-};
-
-template <typename T>
-inline
-std::string PARAM_ACTION<T>::DefaultDescription() const
-{
-return m_hasDefault ? " (default: '" + std::to_string(m_defaltValue) + "')"
-                    : "";
-}
-
-template <>
-inline
-std::string PARAM_ACTION<std::string>::DefaultDescription() const
-{
-return m_hasDefault ? " (default: '" + m_defaltValue + "')"
-                    : "";
-}
-
-template <typename T>
-inline
-PARSER_STATE PARAM_ACTION<T>::Parse(int argc, char ** argv, void * /*data*/)
-{
-if (argc == 0 ||
-    argv == NULL ||
-    *argv == NULL)
-    throw ERROR("Missing argument.");
-T value;
-if (str2x(*argv, value))
-    throw ERROR(std::string("Bad argument: '") + *argv + "'");
-m_param = value;
-return PARSER_STATE(false, --argc, ++argv);
-}
-
-template <>
-inline
-PARSER_STATE PARAM_ACTION<bool>::Parse(int argc, char ** argv, void * /*data*/)
-{
-m_param = true;
-return PARSER_STATE(false, argc, argv);
-}
-
-template <typename T>
-inline
-void PARAM_ACTION<T>::ParseValue(const std::string & stringValue)
-{
-if (stringValue.empty())
-    throw ERROR("Missing value.");
-T value;
-if (str2x(stringValue, value))
-    throw ERROR(std::string("Bad value: '") + stringValue + "'");
-m_param = value;
-}
-
-template <>
-inline
-void PARAM_ACTION<std::string>::ParseValue(const std::string & stringValue)
-{
-m_param = stringValue;
-}
-
-template <>
-inline
-PARSER_STATE PARAM_ACTION<std::string>::Parse(int argc, char ** argv, void * /*data*/)
-{
-if (argc == 0 ||
-    argv == NULL ||
-    *argv == NULL)
-    throw ERROR("Missing argument.");
-m_param = *argv;
-return PARSER_STATE(false, --argc, ++argv);
-}
-
-template <typename T>
-inline
-PARAM_ACTION<T> * MakeParamAction(STG::Optional<T> & param,
-                                  const T & defaultValue,
-                                  const std::string & paramDescription)
-{
-return new PARAM_ACTION<T>(param, defaultValue, paramDescription);
-}
-
-template <typename T>
-inline
-PARAM_ACTION<T> * MakeParamAction(STG::Optional<T> & param)
-{
-return new PARAM_ACTION<T>(param);
-}
-
-template <typename T>
-inline
-PARAM_ACTION<T> * MakeParamAction(STG::Optional<T> & param,
-                                  const std::string & paramDescription)
-{
-return new PARAM_ACTION<T>(param, paramDescription);
-}
-
-class KV_ACTION : public ACTION
-{
-    public:
-        KV_ACTION(const std::string & name,
-                  const std::string & paramDescription)
-            : m_name(name),
-              m_description(paramDescription)
-        {}
-
-        virtual ACTION * Clone() const { return new KV_ACTION(*this); }
-
-        virtual std::string ParamDescription() const { return m_description; }
-        virtual std::string DefaultDescription() const { return ""; }
-        virtual OPTION_BLOCK & Suboptions() { return m_suboptions; }
-        virtual PARSER_STATE Parse(int argc, char ** argv, void * data);
-
-    private:
-        std::string m_name;
-        std::string m_description;
-        OPTION_BLOCK m_suboptions;
-};
-
-inline
-PARSER_STATE KV_ACTION::Parse(int argc, char ** argv, void * data)
-{
-if (argc == 0 ||
-    argv == NULL ||
-    *argv == NULL)
-    throw ERROR("Missing argument.");
-assert(data != NULL && "Expecting container pointer.");
-std::map<std::string, std::string> & kvs = *static_cast<std::map<std::string, std::string>*>(data);
-kvs[m_name] = *argv;
-return PARSER_STATE(false, --argc, ++argv);
-}
-
-inline
-KV_ACTION * MakeKVAction(const std::string & name,
-                         const std::string & paramDescription)
-{
-return new KV_ACTION(name, paramDescription);
-}
-
-} // namespace SGCONF
diff --git a/sgconf/admins.cpp b/sgconf/admins.cpp
deleted file mode 100644 (file)
index ea79621..0000000
+++ /dev/null
@@ -1,205 +0,0 @@
-#include "admins.h"
-
-#include "api_action.h"
-#include "options.h"
-#include "config.h"
-#include "utils.h"
-
-#include "stg/servconf.h"
-#include "stg/servconf_types.h"
-#include "stg/admin_conf.h"
-
-#include <iostream>
-#include <string>
-#include <map>
-#include <cstdint>
-#include <cassert>
-
-namespace
-{
-
-std::string Indent(size_t level, bool dash = false)
-{
-if (level == 0)
-    return "";
-return dash ? std::string(level * 4 - 2, ' ') + "- " : std::string(level * 4, ' ');
-}
-
-std::string PrivToString(const STG::Priv& priv)
-{
-return std::string("") +
-       (priv.corpChg ? "1" : "0") +
-       (priv.serviceChg ? "1" : "0") +
-       (priv.tariffChg ? "1" : "0") +
-       (priv.adminChg ? "1" : "0") +
-       (priv.userAddDel ? "1" : "0") +
-       (priv.userPasswd ? "1" : "0") +
-       (priv.userCash ? "1" : "0") +
-       (priv.userConf ? "1" : "0") +
-       (priv.userStat ? "1" : "0");
-}
-
-void PrintAdmin(const STG::GetAdmin::Info & info, size_t level = 0)
-{
-std::cout << Indent(level, true) << "login: " << info.login << "\n"
-          << Indent(level)       << "priviledges: " << PrivToString(info.priv) << "\n";
-}
-
-std::vector<SGCONF::API_ACTION::PARAM> GetAdminParams()
-{
-std::vector<SGCONF::API_ACTION::PARAM> params;
-params.push_back(SGCONF::API_ACTION::PARAM("password", "<password>", "password"));
-params.push_back(SGCONF::API_ACTION::PARAM("priv", "<priv>", "priviledges"));
-return params;
-}
-
-void ConvPriv(const std::string & value, STG::Optional<STG::Priv> & res)
-{
-if (value.length() != 9)
-    throw SGCONF::ACTION::ERROR("Priviledges value should be a 9-digits length binary number.");
-STG::Priv priv;
-priv.corpChg = (value[0] == '0' ? 0 : 1);
-priv.serviceChg = (value[1] == '0' ? 0 : 1);
-priv.tariffChg = (value[2] == '0' ? 0 : 1);
-priv.adminChg = (value[3] == '0' ? 0 : 1);
-priv.userAddDel = (value[4] == '0' ? 0 : 1);
-priv.userPasswd = (value[5] == '0' ? 0 : 1);
-priv.userCash = (value[6] == '0' ? 0 : 1);
-priv.userConf = (value[7] == '0' ? 0 : 1);
-priv.userStat = (value[8] == '0' ? 0 : 1);
-res = priv;
-}
-
-void SimpleCallback(bool result,
-                    const std::string & reason,
-                    void * /*data*/)
-{
-if (!result)
-    {
-    std::cerr << "Operation failed. Reason: '" << reason << "'." << std::endl;
-    return;
-    }
-std::cout << "Success.\n";
-}
-
-void GetAdminsCallback(bool result,
-                       const std::string & reason,
-                       const std::vector<STG::GetAdmin::Info> & info,
-                       void * /*data*/)
-{
-if (!result)
-    {
-    std::cerr << "Failed to get admin list. Reason: '" << reason << "'." << std::endl;
-    return;
-    }
-std::cout << "Admins:\n";
-for (size_t i = 0; i < info.size(); ++i)
-    PrintAdmin(info[i], 1);
-}
-
-void GetAdminCallback(bool result,
-                      const std::string & reason,
-                      const std::vector<STG::GetAdmin::Info> & info,
-                      void * data)
-{
-assert(data != NULL && "Expecting pointer to std::string with the admin's login.");
-const std::string & login = *static_cast<const std::string *>(data);
-if (!result)
-    {
-    std::cerr << "Failed to get admin. Reason: '" << reason << "'." << std::endl;
-    return;
-    }
-for (size_t i = 0; i < info.size(); ++i)
-    if (info[i].login == login)
-        PrintAdmin(info[i]);
-}
-
-
-bool GetAdminsFunction(const SGCONF::CONFIG & config,
-                       const std::string & /*arg*/,
-                       const std::map<std::string, std::string> & /*options*/)
-{
-STG::ServConf proto(config.server.data(),
-                    config.port.data(),
-                    config.localAddress.data(),
-                    config.localPort.data(),
-                    config.userName.data(),
-                    config.userPass.data());
-return proto.GetAdmins(GetAdminsCallback, NULL) == STG::st_ok;
-}
-
-bool GetAdminFunction(const SGCONF::CONFIG & config,
-                      const std::string & arg,
-                      const std::map<std::string, std::string> & /*options*/)
-{
-STG::ServConf proto(config.server.data(),
-                    config.port.data(),
-                    config.localAddress.data(),
-                    config.localPort.data(),
-                    config.userName.data(),
-                    config.userPass.data());
-// STG currently doesn't support <GetAdmin login="..."/>.
-// So get a list of admins and filter it. 'data' param holds a pointer to 'login'.
-std::string login(arg);
-return proto.GetAdmins(GetAdminCallback, &login) == STG::st_ok;
-}
-
-bool DelAdminFunction(const SGCONF::CONFIG & config,
-                      const std::string & arg,
-                      const std::map<std::string, std::string> & /*options*/)
-{
-STG::ServConf proto(config.server.data(),
-                    config.port.data(),
-                    config.localAddress.data(),
-                    config.localPort.data(),
-                    config.userName.data(),
-                    config.userPass.data());
-return proto.DelAdmin(arg, SimpleCallback, NULL) == STG::st_ok;
-}
-
-bool AddAdminFunction(const SGCONF::CONFIG & config,
-                      const std::string & arg,
-                      const std::map<std::string, std::string> & options)
-{
-STG::AdminConfOpt conf;
-conf.login = arg;
-SGCONF::MaybeSet(options, "priv", conf.priv, ConvPriv);
-SGCONF::MaybeSet(options, "password", conf.password);
-STG::ServConf proto(config.server.data(),
-                    config.port.data(),
-                    config.localAddress.data(),
-                    config.localPort.data(),
-                    config.userName.data(),
-                    config.userPass.data());
-return proto.AddAdmin(arg, conf, SimpleCallback, NULL) == STG::st_ok;
-}
-
-bool ChgAdminFunction(const SGCONF::CONFIG & config,
-                      const std::string & arg,
-                      const std::map<std::string, std::string> & options)
-{
-STG::AdminConfOpt conf;
-conf.login = arg;
-SGCONF::MaybeSet(options, "priv", conf.priv, ConvPriv);
-SGCONF::MaybeSet(options, "password", conf.password);
-STG::ServConf proto(config.server.data(),
-                    config.port.data(),
-                    config.localAddress.data(),
-                    config.localPort.data(),
-                    config.userName.data(),
-                    config.userPass.data());
-return proto.ChgAdmin(conf, SimpleCallback, NULL) == STG::st_ok;
-}
-
-} // namespace anonymous
-
-void SGCONF::AppendAdminsOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks)
-{
-std::vector<API_ACTION::PARAM> params(GetAdminParams());
-blocks.Add("Admin management options")
-      .Add("get-admins", SGCONF::MakeAPIAction(commands, GetAdminsFunction), "\tget admin list")
-      .Add("get-admin", SGCONF::MakeAPIAction(commands, "<login>", GetAdminFunction), "get admin")
-      .Add("add-admin", SGCONF::MakeAPIAction(commands, "<login>", params, AddAdminFunction), "add admin")
-      .Add("del-admin", SGCONF::MakeAPIAction(commands, "<login>", DelAdminFunction), "del admin")
-      .Add("chg-admin", SGCONF::MakeAPIAction(commands, "<login>", params, ChgAdminFunction), "change admin");
-}
diff --git a/sgconf/admins.h b/sgconf/admins.h
deleted file mode 100644 (file)
index 303d6d1..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#pragma once
-
-namespace SGCONF
-{
-
-class OPTION_BLOCKS;
-class COMMANDS;
-
-void AppendAdminsOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks);
-
-} // namespace SGCONF
diff --git a/sgconf/api_action.cpp b/sgconf/api_action.cpp
deleted file mode 100644 (file)
index d5b1e8e..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#include "api_action.h"
-
-#include "actions.h"
-#include "parser_state.h"
-
-SGCONF::PARSER_STATE SGCONF::API_ACTION::Parse(int argc, char ** argv, void * /*data*/)
-{
-PARSER_STATE state(false, argc, argv);
-if (!m_argument.empty())
-    {
-    if (argc == 0 ||
-        argv == NULL ||
-        *argv == NULL)
-        throw ERROR("Missing argument.");
-    m_argument = *argv;
-    --state.argc;
-    ++state.argv;
-    }
-state = m_suboptions.Parse(state.argc, state.argv, &m_params);
-m_commands.Add(m_funPtr, m_argument, m_params);
-return state;
-}
-
-SGCONF::API_ACTION::API_ACTION(COMMANDS & commands,
-                               const std::string & paramDescription,
-                               bool needArgument,
-                               const std::vector<PARAM> & params,
-                               API_FUNCTION funPtr)
-    : m_commands(commands),
-      m_description(paramDescription),
-      m_argument(needArgument ? "1" : ""), // Hack
-      m_funPtr(funPtr)
-{
-std::vector<PARAM>::const_iterator it(params.begin());
-while (it != params.end())
-    {
-    m_suboptions.Add(it->name, MakeKVAction(it->name, it->shortDescr), it->longDescr);
-    ++it;
-    }
-}
diff --git a/sgconf/api_action.h b/sgconf/api_action.h
deleted file mode 100644 (file)
index f27715c..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-#ifndef __STG_SGCONF_API_ACTION_H__
-#define __STG_SGCONF_API_ACTION_H__
-
-#include "action.h"
-
-#include "options.h"
-
-#include <string>
-#include <map>
-#include <vector>
-
-namespace SGCONF
-{
-
-typedef bool (* API_FUNCTION) (const CONFIG &,
-                               const std::string &,
-                               const std::map<std::string, std::string> &);
-
-class COMMAND
-{
-    public:
-        COMMAND(API_FUNCTION funPtr,
-                const std::string & arg,
-                const std::map<std::string, std::string> & options)
-            : m_funPtr(funPtr),
-              m_arg(arg),
-              m_options(options)
-        {}
-        bool Execute(const SGCONF::CONFIG & config) const
-        {
-            return m_funPtr(config, m_arg, m_options);
-        }
-
-    private:
-        API_FUNCTION m_funPtr;
-        std::string m_arg;
-        std::map<std::string, std::string> m_options;
-};
-
-class COMMANDS
-{
-    public:
-        void Add(API_FUNCTION funPtr,
-                 const std::string & arg,
-                 const std::map<std::string, std::string> & options) { m_commands.push_back(COMMAND(funPtr, arg, options)); }
-        bool Execute(const SGCONF::CONFIG & config) const
-        {
-            std::vector<COMMAND>::const_iterator it(m_commands.begin());
-            bool res = true;
-            while (it != m_commands.end() && res)
-            {
-                res = res && it->Execute(config);
-                ++it;
-            }
-            return res;
-        }
-    private:
-        std::vector<COMMAND> m_commands;
-};
-
-class API_ACTION : public ACTION
-{
-    public:
-        struct PARAM
-        {
-            PARAM(const std::string & n,
-                  const std::string & s,
-                  const std::string & l)
-                : name(n),
-                  shortDescr(s),
-                  longDescr(l)
-            {}
-            std::string name;
-            std::string shortDescr;
-            std::string longDescr;
-        };
-
-        API_ACTION(COMMANDS & commands,
-                   const std::string & paramDescription,
-                   bool needArgument,
-                   const std::vector<PARAM> & params,
-                   API_FUNCTION funPtr);
-        API_ACTION(COMMANDS & commands,
-                   const std::string & paramDescription,
-                   bool needArgument,
-                   API_FUNCTION funPtr)
-            : m_commands(commands),
-              m_description(paramDescription),
-              m_argument(needArgument ? "1" : ""), // Hack
-              m_funPtr(funPtr)
-        {}
-
-        virtual ACTION * Clone() const { return new API_ACTION(*this); }
-
-        virtual std::string ParamDescription() const { return m_description; }
-        virtual std::string DefaultDescription() const { return ""; }
-        virtual OPTION_BLOCK & Suboptions() { return m_suboptions; }
-        virtual PARSER_STATE Parse(int argc, char ** argv, void * /*data*/);
-
-    private:
-        COMMANDS & m_commands;
-        std::string m_description;
-        std::string m_argument;
-        OPTION_BLOCK m_suboptions;
-        std::map<std::string, std::string> m_params;
-        API_FUNCTION m_funPtr;
-};
-
-inline
-ACTION * MakeAPIAction(COMMANDS & commands,
-                       const std::string & paramDescription,
-                       const std::vector<API_ACTION::PARAM> & params,
-                       API_FUNCTION funPtr)
-{
-return new API_ACTION(commands, paramDescription, true, params, funPtr);
-}
-
-inline
-ACTION * MakeAPIAction(COMMANDS & commands,
-                       const std::vector<API_ACTION::PARAM> & params,
-                       API_FUNCTION funPtr)
-{
-return new API_ACTION(commands, "", false, params, funPtr);
-}
-
-inline
-ACTION * MakeAPIAction(COMMANDS & commands,
-                       const std::string & paramDescription,
-                       API_FUNCTION funPtr)
-{
-return new API_ACTION(commands, paramDescription, true, funPtr);
-}
-
-inline
-ACTION * MakeAPIAction(COMMANDS & commands,
-                       API_FUNCTION funPtr)
-{
-return new API_ACTION(commands, "", false, funPtr);
-}
-
-}
-
-#endif
diff --git a/sgconf/config.h b/sgconf/config.h
deleted file mode 100644 (file)
index f5313ef..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#pragma once
-
-#include "stg/common.h"
-#include "stg/optional.h"
-
-#include <string>
-#include <cstdint>
-
-namespace SGCONF
-{
-
-struct CONFIG
-{
-    STG::Optional<std::string> configFile;
-    STG::Optional<std::string> server;
-    STG::Optional<uint16_t> port;
-    STG::Optional<std::string> localAddress;
-    STG::Optional<uint16_t> localPort;
-    STG::Optional<std::string> userName;
-    STG::Optional<std::string> userPass;
-    STG::Optional<bool> showConfig;
-
-    CONFIG & operator=(const CONFIG & rhs)
-    {
-    if (!rhs.configFile.empty())
-        configFile = rhs.configFile;
-    if (!rhs.server.empty())
-        server = rhs.server;
-    if (!rhs.port.empty())
-        port = rhs.port;
-    if (!rhs.localAddress.empty())
-        localAddress = rhs.localAddress;
-    if (!rhs.localPort.empty())
-        localPort = rhs.localPort;
-    if (!rhs.userName.empty())
-        userName = rhs.userName;
-    if (!rhs.userPass.empty())
-        userPass = rhs.userPass;
-    if (!rhs.showConfig.empty())
-        showConfig = rhs.showConfig;
-    return *this;
-    }
-
-    std::string Serialize() const
-    {
-    std::string res;
-    if (!configFile.empty())
-        res += "configFile: '" + configFile.data() + "'\n";
-    if (!server.empty())
-        res += "server: '" + server.data() + "'\n";
-    if (!port.empty())
-        res += "port: " + std::to_string(port.data()) + "\n";
-    if (!localAddress.empty())
-        res += "local address: '" + localAddress.data() + "'\n";
-    if (!localPort.empty())
-        res += "local port: " + std::to_string(localPort.data()) + "\n";
-    if (!userName.empty())
-        res += "userName: '" + userName.data() + "'\n";
-    if (!userPass.empty())
-        res += "userPass: '" + userPass.data() + "\n";
-    return res;
-    }
-};
-
-} // namespace SGCONF
diff --git a/sgconf/corps.cpp b/sgconf/corps.cpp
deleted file mode 100644 (file)
index 586ddcd..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-#include "corps.h"
-
-#include "api_action.h"
-#include "options.h"
-#include "config.h"
-#include "utils.h"
-
-#include "stg/servconf.h"
-#include "stg/servconf_types.h"
-#include "stg/corp_conf.h"
-#include "stg/common.h"
-
-#include <iostream>
-#include <string>
-#include <map>
-
-namespace
-{
-
-std::string Indent(size_t level, bool dash = false)
-{
-if (level == 0)
-    return "";
-return dash ? std::string(level * 4 - 2, ' ') + "- " : std::string(level * 4, ' ');
-}
-
-void PrintCorp(const STG::GetCorp::Info & info, size_t level = 0)
-{
-std::cout << Indent(level, true) << "name: " << info.name << "\n"
-          << Indent(level)       << "cash: " << info.cash << "\n";
-}
-
-std::vector<SGCONF::API_ACTION::PARAM> GetCorpParams()
-{
-std::vector<SGCONF::API_ACTION::PARAM> params;
-params.push_back(SGCONF::API_ACTION::PARAM("cash", "<cash>", "\tcorporation's cash"));
-return params;
-}
-
-void SimpleCallback(bool result,
-                    const std::string & reason,
-                    void * /*data*/)
-{
-if (!result)
-    {
-    std::cerr << "Operation failed. Reason: '" << reason << "'." << std::endl;
-    return;
-    }
-std::cout << "Success.\n";
-}
-
-void GetCorpsCallback(bool result,
-                      const std::string & reason,
-                      const std::vector<STG::GetCorp::Info> & info,
-                      void * /*data*/)
-{
-if (!result)
-    {
-    std::cerr << "Failed to get corp list. Reason: '" << reason << "'." << std::endl;
-    return;
-    }
-std::cout << "Corps:\n";
-for (size_t i = 0; i < info.size(); ++i)
-    PrintCorp(info[i], 1);
-}
-
-void GetCorpCallback(bool result,
-                     const std::string & reason,
-                     const STG::GetCorp::Info & info,
-                     void * /*data*/)
-{
-if (!result)
-    {
-    std::cerr << "Failed to get corp. Reason: '" << reason << "'." << std::endl;
-    return;
-    }
-PrintCorp(info);
-}
-
-bool GetCorpsFunction(const SGCONF::CONFIG & config,
-                      const std::string & /*arg*/,
-                      const std::map<std::string, std::string> & /*options*/)
-{
-STG::ServConf proto(config.server.data(),
-                    config.port.data(),
-                    config.localAddress.data(),
-                    config.localPort.data(),
-                    config.userName.data(),
-                    config.userPass.data());
-return proto.GetCorporations(GetCorpsCallback, NULL) == STG::st_ok;
-}
-
-bool GetCorpFunction(const SGCONF::CONFIG & config,
-                     const std::string & arg,
-                     const std::map<std::string, std::string> & /*options*/)
-{
-STG::ServConf proto(config.server.data(),
-                    config.port.data(),
-                    config.localAddress.data(),
-                    config.localPort.data(),
-                    config.userName.data(),
-                    config.userPass.data());
-return proto.GetCorp(arg, GetCorpCallback, NULL) == STG::st_ok;
-}
-
-bool DelCorpFunction(const SGCONF::CONFIG & config,
-                     const std::string & arg,
-                     const std::map<std::string, std::string> & /*options*/)
-{
-STG::ServConf proto(config.server.data(),
-                    config.port.data(),
-                    config.localAddress.data(),
-                    config.localPort.data(),
-                    config.userName.data(),
-                    config.userPass.data());
-return proto.DelCorp(arg, SimpleCallback, NULL) == STG::st_ok;
-}
-
-bool AddCorpFunction(const SGCONF::CONFIG & config,
-                     const std::string & arg,
-                     const std::map<std::string, std::string> & options)
-{
-STG::CorpConfOpt conf;
-conf.name = arg;
-SGCONF::MaybeSet(options, "cash", conf.cash);
-STG::ServConf proto(config.server.data(),
-                    config.port.data(),
-                    config.localAddress.data(),
-                    config.localPort.data(),
-                    config.userName.data(),
-                    config.userPass.data());
-return proto.AddCorp(arg, conf, SimpleCallback, NULL) == STG::st_ok;
-}
-
-bool ChgCorpFunction(const SGCONF::CONFIG & config,
-                     const std::string & arg,
-                     const std::map<std::string, std::string> & options)
-{
-STG::CorpConfOpt conf;
-conf.name = arg;
-SGCONF::MaybeSet(options, "cash", conf.cash);
-STG::ServConf proto(config.server.data(),
-                    config.port.data(),
-                    config.localAddress.data(),
-                    config.localPort.data(),
-                    config.userName.data(),
-                    config.userPass.data());
-return proto.ChgCorp(conf, SimpleCallback, NULL) == STG::st_ok;
-}
-
-} // namespace anonymous
-
-void SGCONF::AppendCorpsOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks)
-{
-std::vector<API_ACTION::PARAM> params(GetCorpParams());
-blocks.Add("Corporation management options")
-      .Add("get-corps", SGCONF::MakeAPIAction(commands, GetCorpsFunction), "\tget corporation list")
-      .Add("get-corp", SGCONF::MakeAPIAction(commands, "<name>", GetCorpFunction), "get corporation")
-      .Add("add-corp", SGCONF::MakeAPIAction(commands, "<name>", params, AddCorpFunction), "add corporation")
-      .Add("del-corp", SGCONF::MakeAPIAction(commands, "<name>", DelCorpFunction), "delete corporation")
-      .Add("chg-corp", SGCONF::MakeAPIAction(commands, "<name>", params, ChgCorpFunction), "change corporation");
-}
diff --git a/sgconf/corps.h b/sgconf/corps.h
deleted file mode 100644 (file)
index 550f453..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#pragma once
-
-namespace SGCONF
-{
-
-class OPTION_BLOCKS;
-class COMMANDS;
-
-void AppendCorpsOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks);
-
-} // namespace SGCONF
diff --git a/sgconf/info.cpp b/sgconf/info.cpp
deleted file mode 100644 (file)
index 421e438..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-#include "info.h"
-
-#include "api_action.h"
-#include "options.h"
-#include "config.h"
-
-#include "stg/servconf.h"
-
-#include <iostream>
-#include <string>
-#include <map>
-
-#include <expat.h>
-
-namespace
-{
-
-void PrintInfo(const STG::ServerInfo::Info& info)
-{
-    std::cout << "Server version: '" << info.version << "'\n"
-              << "Number of tariffs: " << info.tariffNum << "\n"
-              << "Tariff subsystem version: " << info.tariffType << "\n"
-              << "Number of users: " << info.usersNum << "\n"
-              << "UName: '" << info.uname << "\n"
-              << "Number of directions: " << info.dirNum << "\n"
-              << "Dirs:\n";
-    for (size_t i = 0; i < info.dirName.size(); ++i)
-        std::cout << "\t - '" << info.dirName[i] << "'\n";
-}
-
-void InfoCallback(bool result, const std::string & reason, const STG::ServerInfo::Info & info, void * /*data*/)
-{
-if (!result)
-    {
-    std::cerr << "Failed to get server info. Reason: '" << reason << "'." << std::endl;
-    return;
-    }
-PrintInfo(info);
-}
-
-bool InfoFunction(const SGCONF::CONFIG & config,
-                  const std::string& /*arg*/,
-                  const std::map<std::string, std::string> & /*options*/)
-{
-STG::ServConf proto(config.server.data(),
-                    config.port.data(),
-                    config.localAddress.data(),
-                    config.localPort.data(),
-                    config.userName.data(),
-                    config.userPass.data());
-return proto.ServerInfo(InfoCallback, NULL) == STG::st_ok;
-}
-
-}
-
-void SGCONF::AppendServerInfoBlock(COMMANDS & commands, OPTION_BLOCKS & blocks)
-{
-blocks.Add("Server info")
-      .Add("server-info", SGCONF::MakeAPIAction(commands, InfoFunction), "\tget server info");
-}
diff --git a/sgconf/info.h b/sgconf/info.h
deleted file mode 100644 (file)
index 3eb47a4..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#pragma once
-
-namespace SGCONF
-{
-
-class OPTION_BLOCKS;
-class COMMANDS;
-
-void AppendServerInfoBlock(COMMANDS & commands, OPTION_BLOCKS & blocks);
-
-}
diff --git a/sgconf/main.cpp b/sgconf/main.cpp
deleted file mode 100644 (file)
index 9790819..0000000
+++ /dev/null
@@ -1,465 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#include "xml.h"
-#include "admins.h"
-#include "tariffs.h"
-#include "users.h"
-#include "services.h"
-#include "corps.h"
-#include "info.h"
-
-#include "api_action.h"
-#include "options.h"
-#include "actions.h"
-#include "config.h"
-
-#include <string>
-#include <iostream>
-
-#include <cstdlib> // getenv
-#include <cstring> // str*
-
-#include <unistd.h> // access
-#include <libgen.h> // basename
-
-namespace
-{
-
-template <typename T>
-struct nullary_function
-{
-typedef T result_type;
-};
-
-template <typename F>
-class binder0 : public nullary_function<typename F::result_type>
-{
-    public:
-        binder0(const F & func, const typename F::argument_type & arg)
-            : m_func(func), m_arg(arg) {}
-        typename F::result_type operator()() const { return m_func(m_arg); }
-    private:
-        F m_func;
-        typename F::argument_type m_arg;
-};
-
-template <typename F>
-inline
-binder0<F> bind0(const F & func, const typename F::argument_type & arg)
-{
-return binder0<F>(func, arg);
-}
-
-template <typename A, typename R>
-class FUNC1_ADAPTER : public std::unary_function<A, R>
-{
-    public:
-        FUNC1_ADAPTER(R (*func)(A)) : m_func(func) {}
-        const R operator()(A arg) const { return (m_func)(arg); }
-    private:
-        R (*m_func)(A);
-};
-
-template <typename C, typename A, typename R>
-class METHOD1_ADAPTER : public std::unary_function<A, R>
-{
-    public:
-        METHOD1_ADAPTER(R (C::* func)(A), C & obj) : m_func(func), m_obj(obj) {}
-        R operator()(A arg) { return (m_obj.*m_func)(arg); }
-    private:
-        R (C::* m_func)(A);
-        C & m_obj;
-};
-
-template <typename C, typename A, typename R>
-class CONST_METHOD1_ADAPTER : public std::unary_function<A, R>
-{
-    public:
-        CONST_METHOD1_ADAPTER(R (C::* func)(A) const, C & obj) : m_func(func), m_obj(obj) {}
-        R operator()(A arg) const { return (m_obj.*m_func)(arg); }
-    private:
-        R (C::* m_func)(A) const;
-        C & m_obj;
-};
-
-template <typename A, typename R>
-FUNC1_ADAPTER<A, R> Func1Adapt(R (func)(A))
-{
-return FUNC1_ADAPTER<A, R>(func);
-}
-
-template <typename C, typename A, typename R>
-METHOD1_ADAPTER<C, A, R> Method1Adapt(R (C::* func)(A), C & obj)
-{
-return METHOD1_ADAPTER<C, A, R>(func, obj);
-}
-
-template <typename C, typename A, typename R>
-CONST_METHOD1_ADAPTER<C, A, R> Method1Adapt(R (C::* func)(A) const, C & obj)
-{
-return CONST_METHOD1_ADAPTER<C, A, R>(func, obj);
-}
-
-void Version(const std::string & self)
-{
-std::cout << self << ", version: 2.0.0.\n";
-}
-
-void ReadUserConfigFile(SGCONF::OPTION_BLOCK & block)
-{
-std::vector<std::string> paths;
-const char * configHome = getenv("XDG_CONFIG_HOME");
-if (configHome == NULL)
-    {
-    const char * home = getenv("HOME");
-    if (home == NULL)
-        return;
-    paths.push_back(std::string(home) + "/.config/sgconf/sgconf.conf");
-    paths.push_back(std::string(home) + "/.sgconf/sgconf.conf");
-    }
-else
-    paths.push_back(std::string(configHome) + "/sgconf/sgconf.conf");
-for (std::vector<std::string>::const_iterator it = paths.begin(); it != paths.end(); ++it)
-    if (access(it->c_str(), R_OK) == 0)
-        {
-        block.ParseFile(*it);
-        return;
-        }
-}
-
-} // namespace anonymous
-
-namespace SGCONF
-{
-
-class CONFIG_ACTION : public ACTION
-{
-    public:
-        CONFIG_ACTION(SGCONF::CONFIG & config,
-                      const std::string & paramDescription)
-            : m_config(config),
-              m_description(paramDescription)
-        {}
-
-        virtual ACTION * Clone() const { return new CONFIG_ACTION(*this); }
-
-        virtual std::string ParamDescription() const { return m_description; }
-        virtual std::string DefaultDescription() const { return ""; }
-        virtual OPTION_BLOCK & Suboptions() { return m_suboptions; }
-        virtual PARSER_STATE Parse(int argc, char ** argv, void * /*data*/);
-
-    private:
-        SGCONF::CONFIG & m_config;
-        std::string m_description;
-        OPTION_BLOCK m_suboptions;
-
-        void ParseCredentials(const std::string & credentials);
-        void ParseHostAndPort(const std::string & hostAndPort);
-};
-
-
-PARSER_STATE CONFIG_ACTION::Parse(int argc, char ** argv, void * /*data*/)
-{
-if (argc == 0 ||
-    argv == NULL ||
-    *argv == NULL)
-    throw ERROR("Missing argument.");
-char * pos = strchr(*argv, '@');
-if (pos != NULL)
-    {
-    ParseCredentials(std::string(*argv, pos));
-    ParseHostAndPort(std::string(pos + 1));
-    }
-else
-    {
-    ParseHostAndPort(std::string(*argv));
-    }
-return PARSER_STATE(false, --argc, ++argv);
-}
-
-void CONFIG_ACTION::ParseCredentials(const std::string & credentials)
-{
-std::string::size_type pos = credentials.find_first_of(':');
-if (pos != std::string::npos)
-    {
-    m_config.userName = credentials.substr(0, pos);
-    m_config.userPass = credentials.substr(pos + 1);
-    }
-else
-    {
-    m_config.userName = credentials;
-    }
-}
-
-void CONFIG_ACTION::ParseHostAndPort(const std::string & hostAndPort)
-{
-std::string::size_type pos = hostAndPort.find_first_of(':');
-if (pos != std::string::npos)
-    {
-    m_config.server = hostAndPort.substr(0, pos);
-    uint16_t port = 0;
-    if (str2x(hostAndPort.substr(pos + 1), port))
-        throw ERROR("Invalid port value: '" + hostAndPort.substr(pos + 1) + "'");
-    m_config.port = port;
-    }
-else
-    {
-    m_config.server = hostAndPort;
-    }
-}
-
-inline
-CONFIG_ACTION * MakeParamAction(SGCONF::CONFIG & config,
-                                const std::string & paramDescription)
-{
-return new CONFIG_ACTION(config, paramDescription);
-}
-
-} // namespace SGCONF
-
-//-----------------------------------------------------------------------------
-int main(int argc, char **argv)
-{
-std::string self(basename(argv[0]));
-SGCONF::CONFIG config;
-SGCONF::COMMANDS commands;
-
-SGCONF::OPTION_BLOCKS blocks;
-blocks.Add("General options")
-      .Add("c", "config", SGCONF::MakeParamAction(config.configFile, std::string("~/.config/stg/sgconf.conf"), "<config file>"), "override default config file")
-      .Add("h", "help", SGCONF::MakeFunc0Action(bind0(Method1Adapt(&SGCONF::OPTION_BLOCKS::Help, blocks), 0)), "\t\tshow this help and exit")
-      //.Add("help-all", SGCONF::MakeFunc0Action(UsageAll), "\t\tshow full help and exit")
-      .Add("v", "version", SGCONF::MakeFunc0Action(bind0(Func1Adapt(Version), self)), "\t\tshow version information and exit");
-SGCONF::OPTION_BLOCK & block = blocks.Add("Connection options")
-      .Add("s", "server", SGCONF::MakeParamAction(config.server, std::string("localhost"), "<address>"), "\t\thost to connect")
-      .Add("p", "port", SGCONF::MakeParamAction(config.port, uint16_t(5555), "<port>"), "\t\tport to connect")
-      .Add("local-address", SGCONF::MakeParamAction(config.localAddress, std::string(""), "<address>"), "\tlocal address to bind")
-      .Add("local-port", SGCONF::MakeParamAction(config.localPort, uint16_t(0), "<port>"), "\t\tlocal port to bind")
-      .Add("u", "username", SGCONF::MakeParamAction(config.userName, std::string("admin"), "<username>"), "\tadministrative login")
-      .Add("w", "userpass", SGCONF::MakeParamAction(config.userPass, "<password>"), "\tpassword for the administrative login")
-      .Add("a", "address", SGCONF::MakeParamAction(config, "<connection string>"), "connection params as a single string in format: <login>:<password>@<host>:<port>");
-blocks.Add("Debug options")
-      .Add("show-config", SGCONF::MakeParamAction(config.showConfig), "\tshow config and exit");
-SGCONF::AppendXMLOptionBlock(commands, blocks);
-SGCONF::AppendServerInfoBlock(commands, blocks);
-SGCONF::AppendAdminsOptionBlock(commands, blocks);
-SGCONF::AppendTariffsOptionBlock(commands, blocks);
-SGCONF::AppendUsersOptionBlock(commands, blocks);
-SGCONF::AppendServicesOptionBlock(commands, blocks);
-SGCONF::AppendCorpsOptionBlock(commands, blocks);
-
-SGCONF::PARSER_STATE state(false, argc, argv);
-
-try
-{
-state = blocks.Parse(--argc, ++argv); // Skipping self name
-}
-catch (const SGCONF::OPTION::ERROR& ex)
-{
-std::cerr << ex.what() << "\n";
-return -1;
-}
-
-if (state.stop)
-    return 0;
-
-if (state.argc > 0)
-    {
-    std::cerr << "Unknown option: '" << *state.argv << "'\n";
-    return -1;
-    }
-
-try
-{
-SGCONF::CONFIG configOverride(config);
-
-if (config.configFile.empty())
-    {
-    const char * mainConfigFile = "/etc/sgconf/sgconf.conf";
-    if (access(mainConfigFile, R_OK) == 0)
-        block.ParseFile(mainConfigFile);
-    ReadUserConfigFile(block);
-    }
-else
-    {
-    block.ParseFile(config.configFile.data());
-    }
-
-config = configOverride;
-
-if (!config.showConfig.empty() && config.showConfig.data())
-    {
-    std::cout << config.Serialize() << std::endl;
-    return 0;
-    }
-return commands.Execute(config) ? 0 : -1;
-}
-catch (const std::exception& ex)
-{
-std::cerr << ex.what() << "\n";
-return -1;
-}
-}
-//-----------------------------------------------------------------------------
-
-namespace
-{
-
-/*void UsageTariffs(bool full)
-{
-std::cout << "Tariffs management options:\n"
-          << "\t--get-tariffs\t\t\t\tget a list of tariffs (subsequent options will define what to show)\n";
-if (full)
-    std::cout << "\t\t--name\t\t\t\tshow tariff's name\n"
-              << "\t\t--fee\t\t\t\tshow tariff's fee\n"
-              << "\t\t--free\t\t\t\tshow tariff's prepaid traffic in terms of cost\n"
-              << "\t\t--passive-cost\t\t\tshow tariff's cost of \"freeze\"\n"
-              << "\t\t--traff-type\t\t\tshow what type of traffix will be accounted by the tariff\n"
-              << "\t\t--dirs\t\t\t\tshow tarification rules for directions\n\n";
-std::cout << "\t--get-tariff\t\t\t\tget the information about tariff\n";
-if (full)
-    std::cout << "\t\t--name <name>\t\t\tname of the tariff to show\n"
-              << "\t\t--fee\t\t\t\tshow tariff's fee\n"
-              << "\t\t--free\t\t\t\tshow tariff's prepaid traffic in terms of cost\n"
-              << "\t\t--passive-cost\t\t\tshow tariff's cost of \"freeze\"\n"
-              << "\t\t--traff-type\t\t\tshow what type of traffix will be accounted by the tariff\n"
-              << "\t\t--dirs\t\t\t\tshow tarification rules for directions\n\n";
-std::cout << "\t--add-tariff\t\t\t\tadd a new tariff\n";
-if (full)
-    std::cout << "\t\t--name <name>\t\t\tname of the tariff to add\n"
-              << "\t\t--fee <fee>\t\t\tstariff's fee\n"
-              << "\t\t--free <free>\t\t\ttariff's prepaid traffic in terms of cost\n"
-              << "\t\t--passive-cost <cost>\t\ttariff's cost of \"freeze\"\n"
-              << "\t\t--traff-type <type>\t\twhat type of traffi will be accounted by the tariff\n"
-              << "\t\t--times <times>\t\t\tslash-separated list of \"day\" time-spans (in form \"hh:mm-hh:mm\") for each direction\n"
-              << "\t\t--prices-day-a <prices>\t\tslash-separated list of prices for \"day\" traffic before threshold for each direction\n"
-              << "\t\t--prices-night-a <prices>\tslash-separated list of prices for \"night\" traffic before threshold for each direction\n"
-              << "\t\t--prices-day-b <prices>\t\tslash-separated list of prices for \"day\" traffic after threshold for each direction\n"
-              << "\t\t--prices-night-b <prices>\tslash-separated list of prices for \"night\" traffic after threshold for each direction\n"
-              << "\t\t--single-prices <yes|no>\tslash-separated list of \"single price\" flags for each direction\n"
-              << "\t\t--no-discounts <yes|no>\t\tslash-separated list of \"no discount\" flags for each direction\n"
-              << "\t\t--thresholds <thresholds>\tslash-separated list of thresholds (in Mb) for each direction\n\n";
-std::cout << "\t--del-tariff\t\t\t\tdelete an existing tariff\n";
-if (full)
-    std::cout << "\t\t--name <name>\t\t\tname of the tariff to delete\n\n";
-std::cout << "\t--chg-tariff\t\t\t\tchange an existing tariff\n";
-if (full)
-    std::cout << "\t\t--name <name>\t\t\tname of the tariff to change\n"
-              << "\t\t--fee <fee>\t\t\tstariff's fee\n"
-              << "\t\t--free <free>\t\t\ttariff's prepaid traffic in terms of cost\n"
-              << "\t\t--passive-cost <cost>\t\ttariff's cost of \"freeze\"\n"
-              << "\t\t--traff-type <type>\t\twhat type of traffix will be accounted by the tariff\n"
-              << "\t\t--dir <N>\t\t\tnumber of direction data to change\n"
-              << "\t\t\t--time <time>\t\t\"day\" time-span (in form \"hh:mm-hh:mm\")\n"
-              << "\t\t\t--price-day-a <price>\tprice for \"day\" traffic before threshold\n"
-              << "\t\t\t--price-night-a <price>\tprice for \"night\" traffic before threshold\n"
-              << "\t\t\t--price-day-b <price>\tprice for \"day\" traffic after threshold\n"
-              << "\t\t\t--price-night-b <price>\tprice for \"night\" traffic after threshold\n"
-              << "\t\t\t--single-price <yes|no>\t\"single price\" flag\n"
-              << "\t\t\t--no-discount <yes|no>\t\"no discount\" flag\n"
-              << "\t\t\t--threshold <threshold>\tthreshold (in Mb)\n\n";
-}
-//-----------------------------------------------------------------------------
-void UsageUsers(bool full)
-{
-std::cout << "Users management options:\n"
-          << "\t--get-users\t\t\t\tget a list of users (subsequent options will define what to show)\n";
-if (full)
-    std::cout << "\n\n";
-std::cout << "\t--get-user\t\t\t\tget the information about user\n";
-if (full)
-    std::cout << "\n\n";
-std::cout << "\t--add-user\t\t\t\tadd a new user\n";
-if (full)
-    std::cout << "\n\n";
-std::cout << "\t--del-user\t\t\t\tdelete an existing user\n";
-if (full)
-    std::cout << "\n\n";
-std::cout << "\t--chg-user\t\t\t\tchange an existing user\n";
-if (full)
-    std::cout << "\n\n";
-std::cout << "\t--check-user\t\t\t\tcheck credentials is valid\n";
-if (full)
-    std::cout << "\n\n";
-std::cout << "\t--send-message\t\t\t\tsend a message to a user\n";
-if (full)
-    std::cout << "\n\n";
-}
-//-----------------------------------------------------------------------------
-void UsageServices(bool full)
-{
-std::cout << "Services management options:\n"
-          << "\t--get-services\t\t\t\tget a list of services (subsequent options will define what to show)\n";
-if (full)
-    std::cout << "\t\t--name\t\t\t\tshow service's name\n"
-              << "\t\t--comment\t\t\tshow a comment to the service\n"
-              << "\t\t--cost\t\t\t\tshow service's cost\n"
-              << "\t\t--pay-day\t\t\tshow service's pay day\n\n";
-std::cout << "\t--get-service\t\t\t\tget the information about service\n";
-if (full)
-    std::cout << "\t\t--name <name>\t\t\tname of the service to show\n"
-              << "\t\t--comment\t\t\tshow a comment to the service\n"
-              << "\t\t--cost\t\t\t\tshow service's cost\n"
-              << "\t\t--pay-day\t\t\tshow service's pay day\n\n";
-std::cout << "\t--add-service\t\t\t\tadd a new service\n";
-if (full)
-    std::cout << "\t\t--name <name>\t\t\tname of the service to add\n"
-              << "\t\t--comment <comment>\t\ta comment to the service\n"
-              << "\t\t--cost <cost>\t\t\tservice's cost\n"
-              << "\t\t--pay-day <day>\t\t\tservice's pay day\n\n";
-std::cout << "\t--del-service\t\t\t\tdelete an existing service\n";
-if (full)
-    std::cout << "\t\t--name <name>\t\t\tname of the service to delete\n\n";
-std::cout << "\t--chg-service\t\t\t\tchange an existing service\n";
-if (full)
-    std::cout << "\t\t--name <name>\t\t\tname of the service to change\n"
-              << "\t\t--comment <comment>\t\ta comment to the service\n"
-              << "\t\t--cost <cost>\t\t\tservice's cost\n"
-              << "\t\t--pay-day <day>\t\t\tservice's pay day\n\n";
-}
-//-----------------------------------------------------------------------------
-void UsageCorporations(bool full)
-{
-std::cout << "Corporations management options:\n"
-          << "\t--get-corporations\t\t\tget a list of corporations (subsequent options will define what to show)\n";
-if (full)
-    std::cout << "\t\t--name\t\t\t\tshow corporation's name\n"
-              << "\t\t--cash\t\t\t\tshow corporation's cash\n\n";
-std::cout << "\t--get-corp\t\t\t\tget the information about corporation\n";
-if (full)
-    std::cout << "\t\t--name <name>\t\t\tname of the corporation to show\n"
-              << "\t\t--cash\t\t\t\tshow corporation's cash\n\n";
-std::cout << "\t--add-corp\t\t\t\tadd a new corporation\n";
-if (full)
-    std::cout << "\t\t--name <name>\t\t\tname of the corporation to add\n"
-              << "\t\t--cash <cash>\t\t\tinitial corporation's cash (default: \"0\")\n\n";
-std::cout << "\t--del-corp\t\t\t\tdelete an existing corporation\n";
-if (full)
-    std::cout << "\t\t--name <name>\t\t\tname of the corporation to delete\n\n";
-std::cout << "\t--chg-corp\t\t\t\tchange an existing corporation\n";
-if (full)
-    std::cout << "\t\t--name <name>\t\t\tname of the corporation to change\n"
-              << "\t\t--add-cash <amount>[:<message>]\tadd cash to the corporation's account and optional comment message\n"
-              << "\t\t--set-cash <cash>[:<message>]\tnew corporation's cash and optional comment message\n\n";
-}*/
-
-} // namespace anonymous
diff --git a/sgconf/options.cpp b/sgconf/options.cpp
deleted file mode 100644 (file)
index e431bcb..0000000
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#include "options.h"
-
-#include "action.h"
-#include "parser_state.h"
-
-#include "stg/common.h"
-
-#include <fstream>
-#include <sstream>
-#include <iostream>
-#include <functional>
-#include <algorithm>
-
-#include <unistd.h>
-
-namespace
-{
-
-template <class C>
-void ReadConfigFile(const std::string & filePath, void (C::* callback)(const std::string&, const std::string&), C * obj)
-{
-std::ifstream stream(filePath.c_str());
-std::string line;
-size_t num = 0;
-while (std::getline(stream, line))
-    {
-    ++num;
-    line = Trim(line);
-    std::string::size_type pos = line.find_first_of('#');
-    if (pos != std::string::npos)
-        line = line.substr(0, pos);
-    if (line.empty())
-        continue;
-    pos = line.find_first_of('=');
-    if (pos == std::string::npos)
-        {
-        std::ostringstream error;
-        error << "Bad file format, missing '=' in '" << filePath << ":" << num << "'.";
-        throw std::runtime_error(error.str().c_str());
-        }
-    (obj->*callback)(Trim(line.substr(0, pos)), Trim(line.substr(pos + 1, line.length() - pos - 1)));
-    }
-}
-
-} // namespace anonymous
-
-using SGCONF::OPTION;
-using SGCONF::OPTION_BLOCK;
-using SGCONF::OPTION_BLOCKS;
-using SGCONF::ACTION;
-using SGCONF::PARSER_STATE;
-
-OPTION::OPTION(const std::string & shortName,
-               const std::string & longName,
-               ACTION * action,
-               const std::string & description)
-    : m_shortName(shortName),
-      m_longName(longName),
-      m_action(action),
-      m_description(description)
-{
-}
-
-OPTION::OPTION(const std::string & longName,
-               ACTION * action,
-               const std::string & description)
-    : m_longName(longName),
-      m_action(action),
-      m_description(description)
-{
-}
-
-OPTION::OPTION(const OPTION & rhs)
-    : m_shortName(rhs.m_shortName),
-      m_longName(rhs.m_longName),
-      m_action(rhs.m_action->Clone()),
-      m_description(rhs.m_description)
-{
-}
-
-OPTION::~OPTION()
-{
-delete m_action;
-}
-
-OPTION & OPTION::operator=(const OPTION & rhs)
-{
-m_shortName = rhs.m_shortName;
-m_longName = rhs.m_longName;
-m_action = rhs.m_action->Clone();
-m_description = rhs.m_description;
-return *this;
-}
-
-void OPTION::Help(size_t level) const
-{
-if (!m_action)
-    throw ERROR("Option is not defined.");
-std::string indent(level, '\t');
-std::cout << indent;
-if (!m_shortName.empty())
-    std::cout << "-" << m_shortName << ", ";
-std::cout << "--" << m_longName << " " << m_action->ParamDescription()
-          << "\t" << m_description << m_action->DefaultDescription() << "\n";
-m_action->Suboptions().Help(level);
-}
-
-bool OPTION::Check(const char * arg) const
-{
-if (arg == NULL)
-    return false;
-
-if (*arg++ != '-')
-    return false;
-
-if (*arg == '-')
-{
-    return m_longName == arg + 1;
-}
-
-return m_shortName == arg;
-}
-
-PARSER_STATE OPTION::Parse(int argc, char ** argv, void * data)
-{
-if (!m_action)
-    throw ERROR("Option is not defined.");
-try
-    {
-    return m_action->Parse(argc, argv, data);
-    }
-catch (const ACTION::ERROR & ex)
-    {
-    if (m_longName.empty())
-        throw ERROR("-" + m_shortName + ": " + ex.what());
-    else
-        throw m_shortName.empty() ? ERROR("--" + m_longName + ": " + ex.what())
-                                  : ERROR("--" + m_longName + ", -" + m_shortName + ": " + ex.what());
-    }
-}
-
-void OPTION::ParseValue(const std::string & value)
-{
-if (!m_action)
-    throw ERROR("Option is not defined.");
-try
-    {
-    return m_action->ParseValue(value);
-    }
-catch (const ACTION::ERROR & ex)
-    {
-    throw ERROR(m_longName + ": " + ex.what());
-    }
-}
-
-OPTION_BLOCK & OPTION_BLOCK::Add(const std::string & shortName,
-                                 const std::string & longName,
-                                 ACTION * action,
-                                 const std::string & description)
-{
-m_options.push_back(OPTION(shortName, longName, action, description));
-return *this;
-}
-
-OPTION_BLOCK & OPTION_BLOCK::Add(const std::string & longName,
-                                 ACTION * action,
-                                 const std::string & description)
-{
-m_options.push_back(OPTION(longName, action, description));
-return *this;
-}
-
-void OPTION_BLOCK::Help(size_t level) const
-{
-if (m_options.empty())
-    return;
-if (!m_description.empty())
-    std::cout << m_description << ":\n";
-std::for_each(m_options.begin(),
-              m_options.end(),
-              [&level](const auto& opt){ opt.Help(level + 1); });
-}
-
-PARSER_STATE OPTION_BLOCK::Parse(int argc, char ** argv, void * data)
-{
-PARSER_STATE state(false, argc, argv);
-if (state.argc == 0)
-    return state;
-while (state.argc > 0 && !state.stop)
-    {
-    const auto it = std::find_if(m_options.begin(), m_options.end(), [&state](const auto& opt){ return opt.Check(*state.argv); });
-    if (it != m_options.end())
-        state = it->Parse(--state.argc, ++state.argv, data);
-    else
-        break;
-    }
-return state;
-}
-
-void OPTION_BLOCK::ParseFile(const std::string & filePath)
-{
-if (access(filePath.c_str(), R_OK))
-    throw ERROR("File '" + filePath + "' does not exists.");
-ReadConfigFile(filePath, &OPTION_BLOCK::OptionCallback, this);
-}
-
-void OPTION_BLOCK::OptionCallback(const std::string & key, const std::string & value)
-{
-for (std::vector<OPTION>::iterator it = m_options.begin(); it != m_options.end(); ++it)
-    if (it->Name() == key)
-        it->ParseValue(value);
-}
-
-void OPTION_BLOCKS::Help(size_t level) const
-{
-std::list<OPTION_BLOCK>::const_iterator it(m_blocks.begin());
-while (it != m_blocks.end())
-    {
-    it->Help(level);
-    std::cout << "\n";
-    ++it;
-    }
-}
-
-PARSER_STATE OPTION_BLOCKS::Parse(int argc, char ** argv)
-{
-PARSER_STATE state(false, argc, argv);
-std::list<OPTION_BLOCK>::iterator it(m_blocks.begin());
-while (state.argc > 0 && !state.stop && it != m_blocks.end())
-    {
-    state = it->Parse(state.argc, state.argv);
-    ++it;
-    }
-return state;
-}
diff --git a/sgconf/options.h b/sgconf/options.h
deleted file mode 100644 (file)
index c00707b..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#ifndef __STG_SGCONF_OPTIONS_H__
-#define __STG_SGCONF_OPTIONS_H__
-
-#include <string>
-#include <vector>
-#include <list>
-#include <utility>
-#include <stdexcept>
-#include <cstddef> // size_t
-
-namespace SGCONF
-{
-
-class ACTION;
-struct PARSER_STATE;
-
-class OPTION
-{
-    public:
-        OPTION(const std::string & shortName,
-               const std::string & longName,
-               ACTION * action,
-               const std::string & description);
-        OPTION(const std::string & longName,
-               ACTION * action,
-               const std::string & description);
-        OPTION(const OPTION & rhs);
-        ~OPTION();
-
-        OPTION & operator=(const OPTION & rhs);
-
-        void Help(size_t level = 0) const;
-        PARSER_STATE Parse(int argc, char ** argv, void * data);
-        void ParseValue(const std::string & value);
-        bool Check(const char * arg) const;
-        const std::string & Name() const { return m_longName; }
-
-        class ERROR : public std::runtime_error
-        {
-            public:
-                ERROR(const std::string & message)
-                    : std::runtime_error(message.c_str()) {}
-        };
-
-    private:
-        std::string m_shortName;
-        std::string m_longName;
-        ACTION * m_action;
-        std::string m_description;
-};
-
-class OPTION_BLOCK
-{
-    public:
-        OPTION_BLOCK() {}
-        OPTION_BLOCK(const std::string & description)
-            : m_description(description) {}
-        OPTION_BLOCK & Add(const std::string & shortName,
-                           const std::string & longName,
-                           ACTION * action,
-                           const std::string & description);
-        OPTION_BLOCK & Add(const std::string & longName,
-                           ACTION * action,
-                           const std::string & description);
-
-        void Help(size_t level) const;
-
-        PARSER_STATE Parse(int argc, char ** argv, void * data = NULL);
-        void ParseFile(const std::string & filePath);
-
-        class ERROR : public std::runtime_error
-        {
-            public:
-                ERROR(const std::string & message)
-                    : std::runtime_error(message.c_str()) {}
-        };
-
-    private:
-        std::vector<OPTION> m_options;
-        std::string m_description;
-
-        void OptionCallback(const std::string & key, const std::string & value);
-};
-
-class OPTION_BLOCKS
-{
-    public:
-        OPTION_BLOCK & Add(const std::string & description)
-        { m_blocks.push_back(OPTION_BLOCK(description)); return m_blocks.back(); }
-        void Add(const OPTION_BLOCK & block) { m_blocks.push_back(block); }
-        void Help(size_t level) const;
-        PARSER_STATE Parse(int argc, char ** argv);
-
-    private:
-        std::list<OPTION_BLOCK> m_blocks;
-};
-
-} // namespace SGCONF
-
-#endif
diff --git a/sgconf/parser_state.h b/sgconf/parser_state.h
deleted file mode 100644 (file)
index 22ad794..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#ifndef __STG_SGCONF_PARSER_STATE_H__
-#define __STG_SGCONF_PARSER_STATE_H__
-
-namespace SGCONF
-{
-
-struct PARSER_STATE
-{
-    PARSER_STATE(bool s, int c, char ** v) : stop(s), argc(c), argv(v) {}
-    bool stop;
-    int argc;
-    char ** argv;
-};
-
-}
-
-#endif
diff --git a/sgconf/services.cpp b/sgconf/services.cpp
deleted file mode 100644 (file)
index ede820a..0000000
+++ /dev/null
@@ -1,170 +0,0 @@
-#include "services.h"
-
-#include "api_action.h"
-#include "options.h"
-#include "config.h"
-#include "utils.h"
-
-#include "stg/servconf.h"
-#include "stg/servconf_types.h"
-#include "stg/service_conf.h"
-#include "stg/common.h"
-
-#include <iostream>
-#include <string>
-#include <map>
-
-namespace
-{
-
-std::string Indent(size_t level, bool dash = false)
-{
-if (level == 0)
-    return "";
-return dash ? std::string(level * 4 - 2, ' ') + "- " : std::string(level * 4, ' ');
-}
-
-void PrintService(const STG::GetService::Info & info, size_t level = 0)
-{
-std::cout << Indent(level, true) << "name: " << info.name << "\n"
-          << Indent(level)       << "cost: " << info.cost << "\n"
-          << Indent(level)       << "payment day: " << static_cast<unsigned>(info.payDay) << "\n"
-          << Indent(level)       << "comment: " << info.comment << "\n";
-}
-
-std::vector<SGCONF::API_ACTION::PARAM> GetServiceParams()
-{
-std::vector<SGCONF::API_ACTION::PARAM> params;
-params.push_back(SGCONF::API_ACTION::PARAM("cost", "<cost>", "\tcost of the service"));
-params.push_back(SGCONF::API_ACTION::PARAM("pay-day", "<month day>", "payment day"));
-params.push_back(SGCONF::API_ACTION::PARAM("comment", "<text>", "comment"));
-return params;
-}
-
-void SimpleCallback(bool result,
-                    const std::string & reason,
-                    void * /*data*/)
-{
-if (!result)
-    {
-    std::cerr << "Operation failed. Reason: '" << reason << "'." << std::endl;
-    return;
-    }
-std::cout << "Success.\n";
-}
-
-void GetServicesCallback(bool result,
-                         const std::string & reason,
-                         const std::vector<STG::GetService::Info> & info,
-                         void * /*data*/)
-{
-if (!result)
-    {
-    std::cerr << "Failed to get service list. Reason: '" << reason << "'." << std::endl;
-    return;
-    }
-std::cout << "Services:\n";
-for (size_t i = 0; i < info.size(); ++i)
-    PrintService(info[i], 1);
-}
-
-void GetServiceCallback(bool result,
-                        const std::string & reason,
-                        const STG::GetService::Info & info,
-                        void * /*data*/)
-{
-if (!result)
-    {
-    std::cerr << "Failed to get service. Reason: '" << reason << "'." << std::endl;
-    return;
-    }
-PrintService(info);
-}
-
-bool GetServicesFunction(const SGCONF::CONFIG & config,
-                         const std::string & /*arg*/,
-                         const std::map<std::string, std::string> & /*options*/)
-{
-STG::ServConf proto(config.server.data(),
-                    config.port.data(),
-                    config.localAddress.data(),
-                    config.localPort.data(),
-                    config.userName.data(),
-                    config.userPass.data());
-return proto.GetServices(GetServicesCallback, NULL) == STG::st_ok;
-}
-
-bool GetServiceFunction(const SGCONF::CONFIG & config,
-                        const std::string & arg,
-                        const std::map<std::string, std::string> & /*options*/)
-{
-STG::ServConf proto(config.server.data(),
-                    config.port.data(),
-                    config.localAddress.data(),
-                    config.localPort.data(),
-                    config.userName.data(),
-                    config.userPass.data());
-return proto.GetService(arg, GetServiceCallback, NULL) == STG::st_ok;
-}
-
-bool DelServiceFunction(const SGCONF::CONFIG & config,
-                        const std::string & arg,
-                        const std::map<std::string, std::string> & /*options*/)
-{
-STG::ServConf proto(config.server.data(),
-                    config.port.data(),
-                    config.localAddress.data(),
-                    config.localPort.data(),
-                    config.userName.data(),
-                    config.userPass.data());
-return proto.DelService(arg, SimpleCallback, NULL) == STG::st_ok;
-}
-
-bool AddServiceFunction(const SGCONF::CONFIG & config,
-                        const std::string & arg,
-                        const std::map<std::string, std::string> & options)
-{
-STG::ServiceConfOpt conf;
-conf.name = arg;
-SGCONF::MaybeSet(options, "cost", conf.cost);
-SGCONF::MaybeSet(options, "pay-day", conf.payDay);
-SGCONF::MaybeSet(options, "comment", conf.comment);
-STG::ServConf proto(config.server.data(),
-                    config.port.data(),
-                    config.localAddress.data(),
-                    config.localPort.data(),
-                    config.userName.data(),
-                    config.userPass.data());
-return proto.AddService(arg, conf, SimpleCallback, NULL) == STG::st_ok;
-}
-
-bool ChgServiceFunction(const SGCONF::CONFIG & config,
-                        const std::string & arg,
-                        const std::map<std::string, std::string> & options)
-{
-STG::ServiceConfOpt conf;
-conf.name = arg;
-SGCONF::MaybeSet(options, "cost", conf.cost);
-SGCONF::MaybeSet(options, "pay-day", conf.payDay);
-SGCONF::MaybeSet(options, "comment", conf.comment);
-STG::ServConf proto(config.server.data(),
-                    config.port.data(),
-                    config.localAddress.data(),
-                    config.localPort.data(),
-                    config.userName.data(),
-                    config.userPass.data());
-return proto.ChgService(conf, SimpleCallback, NULL) == STG::st_ok;
-}
-
-} // namespace anonymous
-
-void SGCONF::AppendServicesOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks)
-{
-std::vector<API_ACTION::PARAM> params(GetServiceParams());
-blocks.Add("Service management options")
-      .Add("get-services", SGCONF::MakeAPIAction(commands, GetServicesFunction), "\tget service list")
-      .Add("get-service", SGCONF::MakeAPIAction(commands, "<name>", GetServiceFunction), "get service")
-      .Add("add-service", SGCONF::MakeAPIAction(commands, "<name>", params, AddServiceFunction), "add service")
-      .Add("del-service", SGCONF::MakeAPIAction(commands, "<name>", DelServiceFunction), "delete service")
-      .Add("chg-service", SGCONF::MakeAPIAction(commands, "<name>", params, ChgServiceFunction), "change service");
-}
diff --git a/sgconf/services.h b/sgconf/services.h
deleted file mode 100644 (file)
index 4eee2c6..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#pragma once
-
-namespace SGCONF
-{
-
-class OPTION_BLOCKS;
-class COMMANDS;
-
-void AppendServicesOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks);
-
-} // namespace SGCONF
diff --git a/sgconf/tariffs.cpp b/sgconf/tariffs.cpp
deleted file mode 100644 (file)
index 6c5ab3b..0000000
+++ /dev/null
@@ -1,449 +0,0 @@
-#include "tariffs.h"
-
-#include "api_action.h"
-#include "options.h"
-#include "config.h"
-#include "utils.h"
-
-#include "stg/servconf.h"
-#include "stg/servconf_types.h"
-#include "stg/tariff_conf.h"
-#include "stg/common.h"
-
-#include <iostream>
-#include <algorithm>
-#include <sstream>
-#include <string>
-#include <map>
-#include <cstdint>
-#include <cassert>
-
-namespace
-{
-
-std::string Indent(size_t level, bool dash = false)
-{
-if (level == 0)
-    return "";
-return dash ? std::string(level * 4 - 2, ' ') + "- " : std::string(level * 4, ' ');
-}
-
-std::string ChangePolicyToString(STG::Tariff::ChangePolicy changePolicy)
-{
-switch (changePolicy)
-    {
-    case STG::Tariff::ALLOW: return "allow";
-    case STG::Tariff::TO_CHEAP: return "to_cheap";
-    case STG::Tariff::TO_EXPENSIVE: return "to_expensive";
-    case STG::Tariff::DENY: return "deny";
-    }
-return "unknown";
-}
-
-std::string PeriodToString(STG::Tariff::Period period)
-{
-switch (period)
-    {
-    case STG::Tariff::DAY:
-        return "daily";
-    case STG::Tariff::MONTH:
-        return "monthly";
-    }
-return "unknown";
-}
-
-std::string TraffTypeToString(STG::Tariff::TraffType traffType)
-{
-switch (traffType)
-    {
-    case STG::Tariff::TRAFF_UP:
-        return "upload";
-    case STG::Tariff::TRAFF_DOWN:
-        return "download";
-    case STG::Tariff::TRAFF_UP_DOWN:
-        return "upload + download";
-    case STG::Tariff::TRAFF_MAX:
-        return "max(upload, download)";
-    }
-return "unknown";
-}
-
-void ConvPeriod(const std::string & value, STG::Optional<STG::Tariff::Period> & res)
-{
-std::string lowered = ToLower(value);
-if (lowered == "daily")
-    res = STG::Tariff::DAY;
-else if (lowered == "monthly")
-    res = STG::Tariff::MONTH;
-else
-    throw SGCONF::ACTION::ERROR("Period should be 'daily' or 'monthly'. Got: '" + value + "'");
-}
-
-void ConvChangePolicy(const std::string & value, STG::Optional<STG::Tariff::ChangePolicy> & res)
-{
-std::string lowered = ToLower(value);
-if (lowered == "allow")
-    res = STG::Tariff::ALLOW;
-else if (lowered == "to_cheap")
-    res = STG::Tariff::TO_CHEAP;
-else if (lowered == "to_expensive")
-    res = STG::Tariff::TO_EXPENSIVE;
-else if (lowered == "deny")
-    res = STG::Tariff::DENY;
-else
-    throw SGCONF::ACTION::ERROR("Change policy should be 'allow', 'to_cheap', 'to_expensive' or 'deny'. Got: '" + value + "'");
-}
-
-void ConvChangePolicyTimeout(const std::string & value, STG::Optional<time_t> & res)
-{
-struct tm brokenTime;
-if (stg_strptime(value.c_str(), "%Y-%m-%d %H:%M:%S", &brokenTime) == NULL)
-    throw SGCONF::ACTION::ERROR("Credit expiration should be in format 'YYYY-MM-DD HH:MM:SS'. Got: '" + value + "'");
-res = stg_timegm(&brokenTime);
-}
-
-void ConvTraffType(const std::string & value, STG::Optional<STG::Tariff::TraffType> & res)
-{
-std::string lowered = ToLower(value);
-lowered.erase(std::remove(lowered.begin(), lowered.end(), ' '), lowered.end());
-if (lowered == "upload")
-    res = STG::Tariff::TRAFF_UP;
-else if (lowered == "download")
-    res = STG::Tariff::TRAFF_DOWN;
-else if (lowered == "upload+download")
-    res = STG::Tariff::TRAFF_UP_DOWN;
-else if (lowered.substr(0, 3) == "max")
-    res = STG::Tariff::TRAFF_MAX;
-else
-    throw SGCONF::ACTION::ERROR("Traff type should be 'upload', 'download', 'upload + download' or 'max'. Got: '" + value + "'");
-}
-
-STG::DirPriceDataOpt ConvTimeSpan(const std::string & value)
-{
-size_t dashPos = value.find_first_of('-');
-if (dashPos == std::string::npos)
-    throw SGCONF::ACTION::ERROR("Time span should be in format 'hh:mm-hh:mm'. Got: '" + value + "'");
-size_t fromColon = value.find_first_of(':');
-if (fromColon == std::string::npos || fromColon > dashPos)
-    throw SGCONF::ACTION::ERROR("Time span should be in format 'hh:mm-hh:mm'. Got: '" + value + "'");
-size_t toColon = value.find_first_of(':', dashPos);
-if (toColon == std::string::npos)
-    throw SGCONF::ACTION::ERROR("Time span should be in format 'hh:mm-hh:mm'. Got: '" + value + "'");
-STG::DirPriceDataOpt res;
-res.hDay = FromString<int>(value.substr(0, fromColon));
-if (res.hDay.data() < 0 || res.hDay.data() > 23)
-    throw SGCONF::ACTION::ERROR("Invalid 'from' hours. Got: '" + value.substr(0, fromColon) + "'");
-res.mDay = FromString<int>(value.substr(fromColon + 1, dashPos - fromColon - 1));
-if (res.mDay.data() < 0 || res.mDay.data() > 59)
-    throw SGCONF::ACTION::ERROR("Invalid 'from' minutes. Got: '" + value.substr(fromColon + 1, dashPos - fromColon - 1) + "'");
-res.hNight = FromString<int>(value.substr(dashPos + 1, toColon - dashPos - 1));
-if (res.hNight.data() < 0 || res.hNight.data() > 23)
-    throw SGCONF::ACTION::ERROR("Invalid 'to' hours. Got: '" + value.substr(dashPos + 1, toColon - dashPos - 1) + "'");
-res.mNight = FromString<int>(value.substr(toColon + 1, value.length() - toColon));
-if (res.mNight.data() < 0 || res.mNight.data() > 59)
-    throw SGCONF::ACTION::ERROR("Invalid 'to' minutes. Got: '" + value.substr(toColon + 1, value.length() - toColon) + "'");
-return res;
-}
-
-void splice(std::vector<STG::DirPriceDataOpt> & lhs, const std::vector<STG::DirPriceDataOpt> & rhs)
-{
-for (size_t i = 0; i < lhs.size() && i < rhs.size(); ++i)
-    lhs[i].splice(rhs[i]);
-}
-
-void ConvTimes(std::string value, std::vector<STG::DirPriceDataOpt> & res)
-{
-value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
-splice(res, Split<std::vector<STG::DirPriceDataOpt> >(value, ',', ConvTimeSpan));
-}
-
-struct ConvPrice : public std::unary_function<std::string, STG::DirPriceDataOpt>
-{
-    typedef STG::Optional<double> (STG::DirPriceDataOpt::* MemPtr);
-    ConvPrice(MemPtr before, MemPtr after)
-        : m_before(before), m_after(after)
-    {}
-
-    STG::DirPriceDataOpt operator()(const std::string & value)
-    {
-        STG::DirPriceDataOpt res;
-    size_t slashPos = value.find_first_of('/');
-    if (slashPos == std::string::npos)
-        {
-        double price = 0;
-        if (str2x(value, price) < 0)
-            throw SGCONF::ACTION::ERROR("Price should be a floating point number. Got: '" + value + "'");
-        (res.*m_before) = (res.*m_after) = price;
-        res.noDiscount = true;
-        }
-    else
-        {
-        double price = 0;
-        if (str2x(value.substr(0, slashPos), price) < 0)
-            throw SGCONF::ACTION::ERROR("Price should be a floating point number. Got: '" + value.substr(0, slashPos) + "'");
-        (res.*m_before) = price;
-        if (str2x(value.substr(slashPos + 1, value.length() - slashPos), price) < 0)
-            throw SGCONF::ACTION::ERROR("Price should be a floating point number. Got: '" + value.substr(slashPos + 1, value.length() - slashPos) + "'");
-        (res.*m_after) = price;
-        res.noDiscount = false;
-        }
-    return res;
-    }
-
-    MemPtr m_before;
-    MemPtr m_after;
-};
-
-void ConvDayPrices(std::string value, std::vector<STG::DirPriceDataOpt> & res)
-{
-value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
-splice(res, Split<std::vector<STG::DirPriceDataOpt> >(value, ',', ConvPrice(&STG::DirPriceDataOpt::priceDayA, &STG::DirPriceDataOpt::priceDayB)));
-}
-
-void ConvNightPrices(std::string value, std::vector<STG::DirPriceDataOpt> & res)
-{
-value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
-splice(res, Split<std::vector<STG::DirPriceDataOpt> >(value, ',', ConvPrice(&STG::DirPriceDataOpt::priceNightA, &STG::DirPriceDataOpt::priceNightB)));
-}
-
-STG::DirPriceDataOpt ConvThreshold(std::string value)
-{
-    STG::DirPriceDataOpt res;
-double threshold = 0;
-if (str2x(value, threshold) < 0)
-    throw SGCONF::ACTION::ERROR("Threshold should be a floating point value. Got: '" + value + "'");
-res.threshold = threshold;
-return res;
-}
-
-void ConvThresholds(std::string value, std::vector<STG::DirPriceDataOpt> & res)
-{
-value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
-splice(res, Split<std::vector<STG::DirPriceDataOpt> >(value, ',', ConvThreshold));
-}
-
-std::string TimeToString(int h, int m)
-{
-std::ostringstream stream;
-stream << (h < 10 ? "0" : "") << h << ":"
-       << (m < 10 ? "0" : "") << m;
-return stream.str();
-}
-
-void PrintDirPriceData(size_t dir, const STG::DirPriceData & data, size_t level)
-{
-std::string night = TimeToString(data.hNight, data.mNight);
-std::string day = TimeToString(data.hDay, data.mDay);
-std::cout << Indent(level, true) << "dir: " << dir << "\n"
-          << Indent(level)       << "'" << night << "' - '" << day << "': " << data.priceDayA << "/" << data.priceDayB << "\n"
-          << Indent(level)       << "'" << day << "' - '" << night << "': " << data.priceNightA << "/" << data.priceNightB << "\n"
-          << Indent(level)       << "threshold: " << data.threshold << "\n"
-          << Indent(level)       << "single price: " << (data.singlePrice ? "yes" : "no") << "\n"
-          << Indent(level)       << "discount: " << (data.noDiscount ? "no" : "yes") << "\n"; // Attention!
-}
-
-void PrintTariffConf(const STG::TariffConf & conf, size_t level)
-{
-std::cout << Indent(level, true) << "name: " << conf.name << "\n"
-          << Indent(level)       << "fee: " << conf.fee << "\n"
-          << Indent(level)       << "free mb: " << conf.free << "\n"
-          << Indent(level)       << "passive cost: " << conf.passiveCost << "\n"
-          << Indent(level)       << "traff type: " << TraffTypeToString(conf.traffType) << "\n"
-          << Indent(level)       << "period: " << PeriodToString(conf.period) << "\n"
-          << Indent(level)       << "change policy: " << ChangePolicyToString(conf.changePolicy) << "\n"
-          << Indent(level)       << "change policy timeout: " << formatTime(conf.changePolicyTimeout) << "\n";
-}
-
-void PrintTariff(const STG::GetTariff::Info & info, size_t level = 0)
-{
-PrintTariffConf(info.tariffConf, level);
-std::cout << Indent(level) << "dir prices:\n";
-for (size_t i = 0; i < info.dirPrice.size(); ++i)
-    PrintDirPriceData(i, info.dirPrice[i], level + 1);
-}
-
-std::vector<SGCONF::API_ACTION::PARAM> GetTariffParams()
-{
-std::vector<SGCONF::API_ACTION::PARAM> params;
-params.push_back(SGCONF::API_ACTION::PARAM("fee", "<fee>", "\t\ttariff fee"));
-params.push_back(SGCONF::API_ACTION::PARAM("free", "<free mb>", "\tprepaid traffic"));
-params.push_back(SGCONF::API_ACTION::PARAM("passive-cost", "<cost>", "\tpassive cost"));
-params.push_back(SGCONF::API_ACTION::PARAM("traff-type", "<type>", "\ttraffic type (up, down, up+down, max)"));
-params.push_back(SGCONF::API_ACTION::PARAM("period", "<period>", "\ttarification period (daily, monthly)"));
-params.push_back(SGCONF::API_ACTION::PARAM("change-policy", "<policy>", "tariff change policy (allow, to_cheap, to_expensive, deny)"));
-params.push_back(SGCONF::API_ACTION::PARAM("change-policy-timeout", "<yyyy-mm-dd hh:mm:ss>", "tariff change policy timeout"));
-params.push_back(SGCONF::API_ACTION::PARAM("times", "<hh:mm-hh:mm, ...>", "coma-separated day time-spans for each direction"));
-params.push_back(SGCONF::API_ACTION::PARAM("day-prices", "<price/price, ...>", "coma-separated day prices for each direction"));
-params.push_back(SGCONF::API_ACTION::PARAM("night-prices", "<price/price, ...>", "coma-separated night prices for each direction"));
-params.push_back(SGCONF::API_ACTION::PARAM("thresholds", "<threshold, ...>", "coma-separated thresholds for each direction"));
-return params;
-}
-
-void SimpleCallback(bool result,
-                    const std::string & reason,
-                    void * /*data*/)
-{
-if (!result)
-    {
-    std::cerr << "Operation failed. Reason: '" << reason << "'." << std::endl;
-    return;
-    }
-std::cout << "Success.\n";
-}
-
-void GetTariffsCallback(bool result,
-                        const std::string & reason,
-                        const std::vector<STG::GetTariff::Info> & info,
-                        void * /*data*/)
-{
-if (!result)
-    {
-    std::cerr << "Failed to get tariff list. Reason: '" << reason << "'." << std::endl;
-    return;
-    }
-std::cout << "Tariffs:\n";
-for (size_t i = 0; i < info.size(); ++i)
-    PrintTariff(info[i], 1);
-}
-
-void GetTariffCallback(bool result,
-                       const std::string & reason,
-                       const std::vector<STG::GetTariff::Info> & info,
-                       void * data)
-{
-assert(data != NULL && "Expecting pointer to std::string with the tariff's name.");
-const std::string & name = *static_cast<const std::string *>(data);
-if (!result)
-    {
-    std::cerr << "Failed to get tariff. Reason: '" << reason << "'." << std::endl;
-    return;
-    }
-for (size_t i = 0; i < info.size(); ++i)
-    if (info[i].tariffConf.name == name)
-        PrintTariff(info[i]);
-}
-
-bool GetTariffsFunction(const SGCONF::CONFIG & config,
-                        const std::string & /*arg*/,
-                        const std::map<std::string, std::string> & /*options*/)
-{
-STG::ServConf proto(config.server.data(),
-                    config.port.data(),
-                    config.localAddress.data(),
-                    config.localPort.data(),
-                    config.userName.data(),
-                    config.userPass.data());
-return proto.GetTariffs(GetTariffsCallback, NULL) == STG::st_ok;
-}
-
-bool GetTariffFunction(const SGCONF::CONFIG & config,
-                       const std::string & arg,
-                       const std::map<std::string, std::string> & /*options*/)
-{
-STG::ServConf proto(config.server.data(),
-                    config.port.data(),
-                    config.localAddress.data(),
-                    config.localPort.data(),
-                    config.userName.data(),
-                    config.userPass.data());
-// STG currently doesn't support <GetTariff name="..."/>.
-// So get a list of tariffs and filter it. 'data' param holds a pointer to 'name'.
-std::string name(arg);
-return proto.GetTariffs(GetTariffCallback, &name) == STG::st_ok;
-}
-
-bool DelTariffFunction(const SGCONF::CONFIG & config,
-                       const std::string & arg,
-                       const std::map<std::string, std::string> & /*options*/)
-{
-STG::ServConf proto(config.server.data(),
-                    config.port.data(),
-                    config.localAddress.data(),
-                    config.localPort.data(),
-                    config.userName.data(),
-                    config.userPass.data());
-return proto.DelTariff(arg, SimpleCallback, NULL) == STG::st_ok;
-}
-
-bool AddTariffFunction(const SGCONF::CONFIG & config,
-                       const std::string & arg,
-                       const std::map<std::string, std::string> & options)
-{
-STG::TariffDataOpt conf;
-conf.tariffConf.name = arg;
-SGCONF::MaybeSet(options, "fee", conf.tariffConf.fee);
-SGCONF::MaybeSet(options, "free", conf.tariffConf.free);
-SGCONF::MaybeSet(options, "passive-cost", conf.tariffConf.passiveCost);
-SGCONF::MaybeSet(options, "traff-type", conf.tariffConf.traffType, ConvTraffType);
-SGCONF::MaybeSet(options, "period", conf.tariffConf.period, ConvPeriod);
-SGCONF::MaybeSet(options, "change-policy", conf.tariffConf.changePolicy, ConvChangePolicy);
-SGCONF::MaybeSet(options, "change-policy-timeout", conf.tariffConf.changePolicyTimeout, ConvChangePolicyTimeout);
-SGCONF::MaybeSet(options, "times", conf.dirPrice, ConvTimes);
-SGCONF::MaybeSet(options, "day-prices", conf.dirPrice, ConvDayPrices);
-SGCONF::MaybeSet(options, "night-prices", conf.dirPrice, ConvNightPrices);
-SGCONF::MaybeSet(options, "thresholds", conf.dirPrice, ConvThresholds);
-for (size_t i = 0; i < conf.dirPrice.size(); ++i)
-    {
-    if (!conf.dirPrice[i].priceDayA.empty() &&
-        !conf.dirPrice[i].priceNightA.empty() &&
-        !conf.dirPrice[i].priceDayB.empty() &&
-        !conf.dirPrice[i].priceNightB.empty())
-        conf.dirPrice[i].singlePrice = conf.dirPrice[i].priceDayA.data() == conf.dirPrice[i].priceNightA.data() &&
-                                       conf.dirPrice[i].priceDayB.data() == conf.dirPrice[i].priceNightB.data();
-    }
-STG::ServConf proto(config.server.data(),
-                    config.port.data(),
-                    config.localAddress.data(),
-                    config.localPort.data(),
-                    config.userName.data(),
-                    config.userPass.data());
-return proto.AddTariff(arg, conf, SimpleCallback, NULL) == STG::st_ok;
-}
-
-bool ChgTariffFunction(const SGCONF::CONFIG & config,
-                       const std::string & arg,
-                       const std::map<std::string, std::string> & options)
-{
-STG::TariffDataOpt conf;
-conf.tariffConf.name = arg;
-SGCONF::MaybeSet(options, "fee", conf.tariffConf.fee);
-SGCONF::MaybeSet(options, "free", conf.tariffConf.free);
-SGCONF::MaybeSet(options, "passive-cost", conf.tariffConf.passiveCost);
-SGCONF::MaybeSet(options, "traff-type", conf.tariffConf.traffType, ConvTraffType);
-SGCONF::MaybeSet(options, "period", conf.tariffConf.period, ConvPeriod);
-SGCONF::MaybeSet(options, "change-policy", conf.tariffConf.changePolicy, ConvChangePolicy);
-SGCONF::MaybeSet(options, "change-policy-timeout", conf.tariffConf.changePolicyTimeout, ConvChangePolicyTimeout);
-SGCONF::MaybeSet(options, "times", conf.dirPrice, ConvTimes);
-SGCONF::MaybeSet(options, "day-prices", conf.dirPrice, ConvDayPrices);
-SGCONF::MaybeSet(options, "night-prices", conf.dirPrice, ConvNightPrices);
-SGCONF::MaybeSet(options, "thresholds", conf.dirPrice, ConvThresholds);
-for (size_t i = 0; i < conf.dirPrice.size(); ++i)
-    {
-    if (!conf.dirPrice[i].priceDayA.empty() &&
-        !conf.dirPrice[i].priceNightA.empty() &&
-        !conf.dirPrice[i].priceDayB.empty() &&
-        !conf.dirPrice[i].priceNightB.empty())
-        conf.dirPrice[i].singlePrice = conf.dirPrice[i].priceDayA.data() == conf.dirPrice[i].priceNightA.data() &&
-                                       conf.dirPrice[i].priceDayB.data() == conf.dirPrice[i].priceNightB.data();
-    }
-STG::ServConf proto(config.server.data(),
-                    config.port.data(),
-                    config.localAddress.data(),
-                    config.localPort.data(),
-                    config.userName.data(),
-                    config.userPass.data());
-return proto.ChgTariff(conf, SimpleCallback, NULL) == STG::st_ok;
-}
-
-} // namespace anonymous
-
-void SGCONF::AppendTariffsOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks)
-{
-std::vector<API_ACTION::PARAM> params(GetTariffParams());
-blocks.Add("Tariff management options")
-      .Add("get-tariffs", SGCONF::MakeAPIAction(commands, GetTariffsFunction), "\tget tariff list")
-      .Add("get-tariff", SGCONF::MakeAPIAction(commands, "<name>", GetTariffFunction), "get tariff")
-      .Add("add-tariff", SGCONF::MakeAPIAction(commands, "<name>", params, AddTariffFunction), "add tariff")
-      .Add("del-tariff", SGCONF::MakeAPIAction(commands, "<name>", DelTariffFunction), "delete tariff")
-      .Add("chg-tariff", SGCONF::MakeAPIAction(commands, "<name>", params, ChgTariffFunction), "change tariff");
-}
diff --git a/sgconf/tariffs.h b/sgconf/tariffs.h
deleted file mode 100644 (file)
index b6b896d..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#pragma once
-
-namespace SGCONF
-{
-
-class OPTION_BLOCKS;
-class COMMANDS;
-
-void AppendTariffsOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks);
-
-} // namespace SGCONF
diff --git a/sgconf/users.cpp b/sgconf/users.cpp
deleted file mode 100644 (file)
index 3bf5caa..0000000
+++ /dev/null
@@ -1,469 +0,0 @@
-#include "users.h"
-
-#include "api_action.h"
-#include "options.h"
-#include "config.h"
-#include "utils.h"
-
-#include "stg/servconf.h"
-#include "stg/servconf_types.h"
-#include "stg/user_conf.h"
-#include "stg/user_stat.h"
-#include "stg/user_ips.h"
-#include "stg/common.h"
-
-#include <iostream>
-#include <algorithm>
-#include <string>
-#include <map>
-
-namespace
-{
-
-std::string Indent(size_t level, bool dash = false)
-{
-if (level == 0)
-    return "";
-return dash ? std::string(level * 4 - 2, ' ') + "- " : std::string(level * 4, ' ');
-}
-
-void PrintUser(const STG::GetUser::Info & info, size_t level = 0)
-{
-std::cout << Indent(level, true) << "login: " << info.login << "\n"
-          << Indent(level)       << "password: " << info.password << "\n"
-          << Indent(level)       << "cash: " << info.cash << "\n"
-          << Indent(level)       << "credit: " << info.credit << "\n"
-          << Indent(level)       << "credit expire: " << TimeToString(info.creditExpire) << "\n"
-          << Indent(level)       << "last cash add: " << info.lastCashAdd << "\n"
-          << Indent(level)       << "last cash add time: " << TimeToString(info.lastCashAddTime) << "\n"
-          << Indent(level)       << "prepaid traffic: " << info.prepaidTraff << "\n"
-          << Indent(level)       << "disabled: " << (info.disabled ? "t" : "f") << "\n"
-          << Indent(level)       << "passive: " << (info.passive ? "t" : "f") << "\n"
-          << Indent(level)       << "disabled detail stat: " << (info.disableDetailStat ? "t" : "f") << "\n"
-          << Indent(level)       << "connected: " << (info.connected ? "t" : "f") << "\n"
-          << Indent(level)       << "always on-line: " << (info.alwaysOnline ? "t" : "f") << "\n"
-          << Indent(level)       << "IP: " << inet_ntostring(info.ip) << "\n"
-          << Indent(level)       << "IPs: " << info.ips << "\n"
-          << Indent(level)       << "tariff: " << info.tariff << "\n"
-          << Indent(level)       << "group: " << info.group << "\n"
-          << Indent(level)       << "note: " << info.note << "\n"
-          << Indent(level)       << "email: " << info.email << "\n"
-          << Indent(level)       << "name: " << info.name << "\n"
-          << Indent(level)       << "address: " << info.address << "\n"
-          << Indent(level)       << "phone: " << info.phone << "\n"
-          << Indent(level)       << "corporation: " << info.corp << "\n"
-          << Indent(level)       << "last ping time: " << TimeToString(info.pingTime) << "\n"
-          << Indent(level)       << "last activity time: " << TimeToString(info.lastActivityTime) << "\n"
-          << Indent(level)       << "traffic:\n";
-for (size_t i = 0; i < DIR_NUM; ++i)
-    {
-    std::cout << Indent(level + 1, true) << "dir: " << i << "\n"
-              << Indent(level + 1)       << "session upload: " << info.stat.su[i] << "\n"
-              << Indent(level + 1)       << "session download: " << info.stat.sd[i] << "\n"
-              << Indent(level + 1)       << "month upload: " << info.stat.mu[i] << "\n"
-              << Indent(level + 1)       << "month download: " << info.stat.md[i] << "\n";
-    }
-std::cout << Indent(level)       << "user data:\n";
-for (size_t i = 0; i < USERDATA_NUM; ++i)
-    std::cout << Indent(level + 1, true) << "user data " << i << ": " << info.userData[i] << "\n";
-if (!info.services.empty())
-    {
-    std::cout << Indent(level) << "services:\n";
-    for (size_t i = 0; i < info.services.size(); ++i)
-        std::cout << Indent(level + 1, true) << info.services[i] << "\n";
-    }
-if (!info.authBy.empty())
-    {
-    std::cout << Indent(level) << "auth by:\n";
-    for (size_t i = 0; i < info.authBy.size(); ++i)
-        std::cout << Indent(level + 1, true) << info.authBy[i] << "\n";
-    }
-}
-
-std::vector<SGCONF::API_ACTION::PARAM> GetUserParams()
-{
-std::vector<SGCONF::API_ACTION::PARAM> params;
-params.push_back(SGCONF::API_ACTION::PARAM("password", "<password>", "\tuser's password"));
-params.push_back(SGCONF::API_ACTION::PARAM("cash-add", "<cash[:message]>", "cash to add (with optional comment)"));
-params.push_back(SGCONF::API_ACTION::PARAM("cash-set", "<cash[:message]>", "cash to set (with optional comment)"));
-params.push_back(SGCONF::API_ACTION::PARAM("credit", "<amount>", "\tuser's credit"));
-params.push_back(SGCONF::API_ACTION::PARAM("credit-expire", "<date>", "\tcredit expiration"));
-params.push_back(SGCONF::API_ACTION::PARAM("free", "<free mb>", "\tprepaid traffic"));
-params.push_back(SGCONF::API_ACTION::PARAM("disabled", "<flag>", "\tdisable user (y|n)"));
-params.push_back(SGCONF::API_ACTION::PARAM("passive", "<flag>", "\tmake user passive (y|n)"));
-params.push_back(SGCONF::API_ACTION::PARAM("disable-detail-stat", "<flag>", "disable detail stat (y|n)"));
-params.push_back(SGCONF::API_ACTION::PARAM("always-online", "<flag>", "\tmake user always online (y|n)"));
-params.push_back(SGCONF::API_ACTION::PARAM("ips", "<ips>", "\t\tcoma-separated list of ips"));
-params.push_back(SGCONF::API_ACTION::PARAM("tariff", "<tariff name>", "\tcurrent tariff"));
-params.push_back(SGCONF::API_ACTION::PARAM("next-tariff", "<tariff name>", "tariff starting from the next month"));
-params.push_back(SGCONF::API_ACTION::PARAM("group", "<group>", "\t\tuser's group"));
-params.push_back(SGCONF::API_ACTION::PARAM("note", "<note>", "\t\tuser's note"));
-params.push_back(SGCONF::API_ACTION::PARAM("email", "<email>", "\t\tuser's email"));
-params.push_back(SGCONF::API_ACTION::PARAM("name", "<real name>", "\tuser's real name"));
-params.push_back(SGCONF::API_ACTION::PARAM("address", "<address>", "\tuser's postal address"));
-params.push_back(SGCONF::API_ACTION::PARAM("phone", "<phone>", "\t\tuser's phone number"));
-params.push_back(SGCONF::API_ACTION::PARAM("corp", "<corp name>", "\tcorporation name"));
-params.push_back(SGCONF::API_ACTION::PARAM("session-traffic", "<up/dn, ...>", "coma-separated session upload and download"));
-params.push_back(SGCONF::API_ACTION::PARAM("month-traffic", "<up/dn, ...>", "coma-separated month upload and download"));
-params.push_back(SGCONF::API_ACTION::PARAM("user-data", "<value, ...>", "coma-separated user data values"));
-return params;
-}
-
-std::vector<SGCONF::API_ACTION::PARAM> GetCheckParams()
-{
-std::vector<SGCONF::API_ACTION::PARAM> params;
-params.push_back(SGCONF::API_ACTION::PARAM("password", "<password>", "\tuser's password"));
-return params;
-}
-
-std::vector<SGCONF::API_ACTION::PARAM> GetMessageParams()
-{
-std::vector<SGCONF::API_ACTION::PARAM> params;
-params.push_back(SGCONF::API_ACTION::PARAM("logins", "<login, ...>", "\tlist of logins to send a message"));
-params.push_back(SGCONF::API_ACTION::PARAM("text", "<text>", "\t\tmessage text"));
-return params;
-}
-
-void ConvBool(const std::string & value, STG::Optional<int> & res)
-{
-res = !value.empty() && value[0] == 'y';
-}
-
-void Splice(std::vector<STG::Optional<std::string> > & lhs, const std::vector<STG::Optional<std::string> > & rhs)
-{
-for (size_t i = 0; i < lhs.size() && i < rhs.size(); ++i)
-    lhs[i].splice(rhs[i]);
-}
-
-STG::Optional<std::string> ConvString(const std::string & value)
-{
-return STG::Optional<std::string>(value);
-}
-
-void ConvStringList(std::string value, std::vector<STG::Optional<std::string> > & res)
-{
-Splice(res, Split<std::vector<STG::Optional<std::string> > >(value, ',', ConvString));
-}
-
-void ConvServices(std::string value, STG::Optional<std::vector<std::string> > & res)
-{
-value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
-res = Split<std::vector<std::string> >(value, ',');
-}
-
-void ConvCreditExpire(const std::string & value, STG::Optional<time_t> & res)
-{
-struct tm brokenTime;
-if (stg_strptime(value.c_str(), "%Y-%m-%d %H:%M:%S", &brokenTime) == NULL)
-    throw SGCONF::ACTION::ERROR("Credit expiration should be in format 'YYYY-MM-DD HH:MM:SS'. Got: '" + value + "'");
-res = stg_timegm(&brokenTime);
-}
-
-void ConvIPs(const std::string & value, STG::Optional<STG::UserIPs> & res)
-{
-res = STG::UserIPs::parse(value);
-}
-
-struct TRAFF
-{
-    uint64_t up;
-    uint64_t down;
-};
-
-TRAFF ConvTraff(const std::string & value)
-{
-TRAFF res;
-size_t slashPos = value.find_first_of('/');
-if (slashPos == std::string::npos)
-    throw SGCONF::ACTION::ERROR("Traffic record should be in format 'upload/download'. Got: '" + value + "'");
-
-if (str2x(value.substr(0, slashPos), res.up) < 0)
-    throw SGCONF::ACTION::ERROR("Traffic value should be an integer. Got: '" + value.substr(0, slashPos) + "'");
-if (str2x(value.substr(slashPos + 1, value.length() - slashPos), res.down) < 0)
-    throw SGCONF::ACTION::ERROR("Traffic value should be an integer. Got: '" + value.substr(slashPos + 1, value.length() - slashPos) + "'");
-return res;
-}
-
-void ConvSessionTraff(std::string value, STG::UserStatOpt & res)
-{
-value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
-std::vector<TRAFF> traff(Split<std::vector<TRAFF> >(value, ',', ConvTraff));
-if (traff.size() != DIR_NUM)
-    throw SGCONF::ACTION::ERROR("There should be prcisely " + std::to_string(DIR_NUM) + " records of session traffic.");
-for (size_t i = 0; i < DIR_NUM; ++i)
-    {
-    res.sessionUp[i] = traff[i].up;
-    res.sessionDown[i] = traff[i].down;
-    }
-}
-
-void ConvMonthTraff(std::string value, STG::UserStatOpt & res)
-{
-value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
-std::vector<TRAFF> traff(Split<std::vector<TRAFF> >(value, ',', ConvTraff));
-if (traff.size() != DIR_NUM)
-    throw SGCONF::ACTION::ERROR("There should be prcisely " + std::to_string(DIR_NUM) + " records of month traffic.");
-for (size_t i = 0; i < DIR_NUM; ++i)
-    {
-    res.monthUp[i] = traff[i].up;
-    res.monthDown[i] = traff[i].down;
-    }
-}
-
-void ConvCashInfo(const std::string & value, STG::Optional<STG::CashInfo> & res)
-{
-STG::CashInfo info;
-size_t pos = value.find_first_of(':');
-if (pos == std::string::npos)
-    {
-    if (str2x(value, info.first) < 0)
-        throw SGCONF::ACTION::ERROR("Cash should be a double value. Got: '" + value + "'");
-    }
-else
-    {
-    if (str2x(value.substr(0, pos), info.first) < 0)
-        throw SGCONF::ACTION::ERROR("Cash should be a double value. Got: '" + value + "'");
-    info.second = value.substr(pos + 1);
-    }
-res = info;
-}
-
-void SimpleCallback(bool result,
-                    const std::string & reason,
-                    void * /*data*/)
-{
-if (!result)
-    {
-    std::cerr << "Operation failed. Reason: '" << reason << "'." << std::endl;
-    return;
-    }
-std::cout << "Success.\n";
-}
-
-void GetUsersCallback(bool result,
-                      const std::string & reason,
-                      const std::vector<STG::GetUser::Info> & info,
-                      void * /*data*/)
-{
-if (!result)
-    {
-    std::cerr << "Failed to get user list. Reason: '" << reason << "'." << std::endl;
-    return;
-    }
-std::cout << "Users:\n";
-for (size_t i = 0; i < info.size(); ++i)
-    PrintUser(info[i], 1);
-}
-
-void GetUserCallback(bool result,
-                     const std::string & reason,
-                     const STG::GetUser::Info & info,
-                     void * /*data*/)
-{
-if (!result)
-    {
-    std::cerr << "Failed to get user. Reason: '" << reason << "'." << std::endl;
-    return;
-    }
-PrintUser(info);
-}
-
-void AuthByCallback(bool result,
-                    const std::string & reason,
-                    const std::vector<std::string> & info,
-                    void * /*data*/)
-{
-if (!result)
-    {
-    std::cerr << "Failed to get authorizer list. Reason: '" << reason << "'." << std::endl;
-    return;
-    }
-std::cout << "Authorized by:\n";
-for (size_t i = 0; i < info.size(); ++i)
-    std::cout << Indent(1, true) << info[i] << "\n";
-}
-
-bool GetUsersFunction(const SGCONF::CONFIG & config,
-                      const std::string & /*arg*/,
-                      const std::map<std::string, std::string> & /*options*/)
-{
-STG::ServConf proto(config.server.data(),
-                    config.port.data(),
-                    config.localAddress.data(),
-                    config.localPort.data(),
-                    config.userName.data(),
-                    config.userPass.data());
-return proto.GetUsers(GetUsersCallback, NULL) == STG::st_ok;
-}
-
-bool GetUserFunction(const SGCONF::CONFIG & config,
-                     const std::string & arg,
-                     const std::map<std::string, std::string> & /*options*/)
-{
-STG::ServConf proto(config.server.data(),
-                    config.port.data(),
-                    config.localAddress.data(),
-                    config.localPort.data(),
-                    config.userName.data(),
-                    config.userPass.data());
-return proto.GetUser(arg, GetUserCallback, NULL) == STG::st_ok;
-}
-
-bool DelUserFunction(const SGCONF::CONFIG & config,
-                     const std::string & arg,
-                     const std::map<std::string, std::string> & /*options*/)
-{
-STG::ServConf proto(config.server.data(),
-                    config.port.data(),
-                    config.localAddress.data(),
-                    config.localPort.data(),
-                    config.userName.data(),
-                    config.userPass.data());
-return proto.DelUser(arg, SimpleCallback, NULL) == STG::st_ok;
-}
-
-bool AddUserFunction(const SGCONF::CONFIG & config,
-                     const std::string & arg,
-                     const std::map<std::string, std::string> & options)
-{
-STG::UserConfOpt conf;
-SGCONF::MaybeSet(options, "password", conf.password);
-SGCONF::MaybeSet(options, "passive", conf.passive, ConvBool);
-SGCONF::MaybeSet(options, "disabled", conf.disabled, ConvBool);
-SGCONF::MaybeSet(options, "disable-detail-stat", conf.disabledDetailStat, ConvBool);
-SGCONF::MaybeSet(options, "always-online", conf.alwaysOnline, ConvBool);
-SGCONF::MaybeSet(options, "tariff", conf.tariffName);
-SGCONF::MaybeSet(options, "address", conf.address);
-SGCONF::MaybeSet(options, "phone", conf.phone);
-SGCONF::MaybeSet(options, "email", conf.email);
-SGCONF::MaybeSet(options, "note", conf.note);
-SGCONF::MaybeSet(options, "name", conf.realName);
-SGCONF::MaybeSet(options, "corp", conf.corp);
-SGCONF::MaybeSet(options, "services", conf.services, ConvServices);
-SGCONF::MaybeSet(options, "group", conf.group);
-SGCONF::MaybeSet(options, "credit", conf.credit);
-SGCONF::MaybeSet(options, "next-tariff", conf.nextTariff);
-SGCONF::MaybeSet(options, "user-data", conf.userdata, ConvStringList);
-SGCONF::MaybeSet(options, "credit-expire", conf.creditExpire, ConvCreditExpire);
-SGCONF::MaybeSet(options, "ips", conf.ips, ConvIPs);
-STG::UserStatOpt stat;
-SGCONF::MaybeSet(options, "cash-set", stat.cashSet, ConvCashInfo);
-SGCONF::MaybeSet(options, "free", stat.freeMb);
-SGCONF::MaybeSet(options, "session-traffic", stat, ConvSessionTraff);
-SGCONF::MaybeSet(options, "month-traffic", stat, ConvMonthTraff);
-STG::ServConf proto(config.server.data(),
-                    config.port.data(),
-                    config.localAddress.data(),
-                    config.localPort.data(),
-                    config.userName.data(),
-                    config.userPass.data());
-return proto.AddUser(arg, conf, stat, SimpleCallback, NULL) == STG::st_ok;
-}
-
-bool ChgUserFunction(const SGCONF::CONFIG & config,
-                     const std::string & arg,
-                     const std::map<std::string, std::string> & options)
-{
-STG::UserConfOpt conf;
-SGCONF::MaybeSet(options, "password", conf.password);
-SGCONF::MaybeSet(options, "passive", conf.passive, ConvBool);
-SGCONF::MaybeSet(options, "disabled", conf.disabled, ConvBool);
-SGCONF::MaybeSet(options, "disable-detail-stat", conf.disabledDetailStat, ConvBool);
-SGCONF::MaybeSet(options, "always-online", conf.alwaysOnline, ConvBool);
-SGCONF::MaybeSet(options, "tariff", conf.tariffName);
-SGCONF::MaybeSet(options, "address", conf.address);
-SGCONF::MaybeSet(options, "phone", conf.phone);
-SGCONF::MaybeSet(options, "email", conf.email);
-SGCONF::MaybeSet(options, "note", conf.note);
-SGCONF::MaybeSet(options, "name", conf.realName);
-SGCONF::MaybeSet(options, "corp", conf.corp);
-SGCONF::MaybeSet(options, "services", conf.services, ConvServices);
-SGCONF::MaybeSet(options, "group", conf.group);
-SGCONF::MaybeSet(options, "credit", conf.credit);
-SGCONF::MaybeSet(options, "next-tariff", conf.nextTariff);
-SGCONF::MaybeSet(options, "user-data", conf.userdata, ConvStringList);
-SGCONF::MaybeSet(options, "credit-expire", conf.creditExpire, ConvCreditExpire);
-SGCONF::MaybeSet(options, "ips", conf.ips, ConvIPs);
-STG::UserStatOpt stat;
-SGCONF::MaybeSet(options, "cash-add", stat.cashAdd, ConvCashInfo);
-SGCONF::MaybeSet(options, "cash-set", stat.cashSet, ConvCashInfo);
-SGCONF::MaybeSet(options, "free", stat.freeMb);
-SGCONF::MaybeSet(options, "session-traffic", stat, ConvSessionTraff);
-SGCONF::MaybeSet(options, "month-traffic", stat, ConvMonthTraff);
-STG::ServConf proto(config.server.data(),
-                    config.port.data(),
-                    config.localAddress.data(),
-                    config.localPort.data(),
-                    config.userName.data(),
-                    config.userPass.data());
-return proto.ChgUser(arg, conf, stat, SimpleCallback, NULL) == STG::st_ok;
-}
-
-bool CheckUserFunction(const SGCONF::CONFIG & config,
-                       const std::string & arg,
-                       const std::map<std::string, std::string> & options)
-{
-std::map<std::string, std::string>::const_iterator it(options.find("password"));
-if (it == options.end())
-    throw SGCONF::ACTION::ERROR("Password is not specified.");
-STG::ServConf proto(config.server.data(),
-                    config.port.data(),
-                    config.localAddress.data(),
-                    config.localPort.data(),
-                    config.userName.data(),
-                    config.userPass.data());
-return proto.CheckUser(arg, it->second, SimpleCallback, NULL) == STG::st_ok;
-}
-
-bool SendMessageFunction(const SGCONF::CONFIG & config,
-                         const std::string & /*arg*/,
-                         const std::map<std::string, std::string> & options)
-{
-std::map<std::string, std::string>::const_iterator it(options.find("logins"));
-if (it == options.end())
-    throw SGCONF::ACTION::ERROR("Logins are not specified.");
-std::string logins = it->second;
-for (size_t i = 0; i < logins.length(); ++i)
-    if (logins[i] == ',')
-        logins[i] = ':';
-it = options.find("text");
-if (it == options.end())
-    throw SGCONF::ACTION::ERROR("Message text is not specified.");
-std::string text = it->second;
-STG::ServConf proto(config.server.data(),
-                    config.port.data(),
-                    config.localAddress.data(),
-                    config.localPort.data(),
-                    config.userName.data(),
-                    config.userPass.data());
-return proto.SendMessage(logins, text, SimpleCallback, NULL) == STG::st_ok;
-}
-
-bool AuthByFunction(const SGCONF::CONFIG & config,
-                    const std::string & arg,
-                    const std::map<std::string, std::string> & /*options*/)
-{
-STG::ServConf proto(config.server.data(),
-                    config.port.data(),
-                    config.localAddress.data(),
-                    config.localPort.data(),
-                    config.userName.data(),
-                    config.userPass.data());
-return proto.AuthBy(arg, AuthByCallback, NULL) == STG::st_ok;
-}
-
-} // namespace anonymous
-
-void SGCONF::AppendUsersOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks)
-{
-std::vector<API_ACTION::PARAM> params(GetUserParams());
-blocks.Add("User management options")
-      .Add("get-users", SGCONF::MakeAPIAction(commands, GetUsersFunction), "\tget user list")
-      .Add("get-user", SGCONF::MakeAPIAction(commands, "<login>", GetUserFunction), "get user")
-      .Add("add-user", SGCONF::MakeAPIAction(commands, "<login>", params, AddUserFunction), "add user")
-      .Add("del-user", SGCONF::MakeAPIAction(commands, "<login>", DelUserFunction), "delete user")
-      .Add("chg-user", SGCONF::MakeAPIAction(commands, "<login>", params, ChgUserFunction), "change user")
-      .Add("check-user", SGCONF::MakeAPIAction(commands, "<login>", GetCheckParams(), CheckUserFunction), "check user existance and credentials")
-      .Add("send-message", SGCONF::MakeAPIAction(commands, GetMessageParams(), SendMessageFunction), "send message")
-      .Add("auth-by", SGCONF::MakeAPIAction(commands, "<login>", AuthByFunction), "a list of authorizers user authorized by");
-}
diff --git a/sgconf/users.h b/sgconf/users.h
deleted file mode 100644 (file)
index 01bc6db..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#pragma once
-
-namespace SGCONF
-{
-
-class OPTION_BLOCKS;
-class COMMANDS;
-
-void AppendUsersOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks);
-
-}
diff --git a/sgconf/utils.h b/sgconf/utils.h
deleted file mode 100644 (file)
index 6168cbf..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-#pragma once
-
-#include "stg/common.h"
-#include "stg/optional.h"
-
-#include <string>
-#include <map>
-
-namespace SGCONF
-{
-
-template <typename T>
-inline
-void MaybeSet(const std::map<std::string, std::string> & options, const std::string & name, STG::Optional<T> & res)
-{
-std::map<std::string, std::string>::const_iterator it(options.find(name));
-if (it == options.end())
-    return;
-T value;
-if (str2x(it->second, value) < 0)
-    return;
-res = value;
-}
-
-template <typename T, typename F>
-inline
-void MaybeSet(const std::map<std::string, std::string> & options, const std::string & name, T & res, F conv)
-{
-std::map<std::string, std::string>::const_iterator it(options.find(name));
-if (it == options.end())
-    return;
-conv(it->second, res);
-}
-
-template <>
-inline
-void MaybeSet<std::string>(const std::map<std::string, std::string> & options, const std::string & name, STG::Optional<std::string> & res)
-{
-std::map<std::string, std::string>::const_iterator it(options.find(name));
-if (it == options.end())
-    return;
-res = it->second;
-}
-
-} // namespace SGCONF
diff --git a/sgconf/xml.cpp b/sgconf/xml.cpp
deleted file mode 100644 (file)
index 61587a1..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-#include "xml.h"
-
-#include "api_action.h"
-#include "options.h"
-#include "config.h"
-
-#include "stg/servconf.h"
-
-#include <iostream>
-#include <string>
-#include <map>
-
-#include <expat.h>
-
-namespace
-{
-
-struct ParserState
-{
-size_t level;
-};
-
-std::string Indent(size_t level)
-{
-return std::string(level * 4, ' ');
-}
-
-std::string PrintAttr(const char ** attr)
-{
-std::string res;
-if (attr == NULL)
-    return res;
-while (*attr)
-    {
-    if (*(attr + 1) == NULL)
-        return res;
-    res += std::string(" ") + *attr + "=\"" + *(attr + 1) + "\"";
-    ++attr; ++attr;
-    }
-return res;
-}
-
-void Start(void * data, const char * el, const char ** attr)
-{
-ParserState * state = static_cast<ParserState *>(data);
-if (el != NULL)
-    std::cout << Indent(state->level) << "<" << el << PrintAttr(attr) << ">\n";
-++state->level;
-}
-
-void End(void * data, const char * el)
-{
-ParserState * state = static_cast<ParserState *>(data);
---state->level;
-if (el != NULL)
-    std::cout << Indent(state->level) << "</" << el << ">\n";
-}
-
-void PrintXML(const std::string& xml)
-{
-ParserState state = { 0 };
-
-XML_Parser parser = XML_ParserCreate(NULL);
-XML_ParserReset(parser, NULL);
-XML_SetElementHandler(parser, Start, End);
-XML_SetUserData(parser, &state);
-
-if (XML_Parse(parser, xml.c_str(), xml.length(), true) == XML_STATUS_ERROR)
-    std::cerr << "XML parse error at line " << XML_GetCurrentLineNumber(parser)
-              << ": '" << XML_ErrorString(XML_GetErrorCode(parser)) << "'"
-              << std::endl;
-
-XML_ParserFree(parser);
-}
-
-void RawXMLCallback(bool result, const std::string & reason, const std::string & response, void * /*data*/)
-{
-if (!result)
-    {
-    std::cerr << "Failed to get raw XML response. Reason: '" << reason << "'." << std::endl;
-    return;
-    }
-PrintXML(response);
-}
-
-bool RawXMLFunction(const SGCONF::CONFIG & config,
-                    const std::string & arg,
-                    const std::map<std::string, std::string> & /*options*/)
-{
-STG::ServConf proto(config.server.data(),
-                    config.port.data(),
-                    config.localAddress.data(),
-                    config.localPort.data(),
-                    config.userName.data(),
-                    config.userPass.data());
-return proto.RawXML(arg, RawXMLCallback, NULL) == STG::st_ok;
-}
-
-}
-
-void SGCONF::AppendXMLOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks)
-{
-blocks.Add("Raw XML")
-      .Add("r", "raw", SGCONF::MakeAPIAction(commands, "<xml>", RawXMLFunction), "\tmake raw XML request");
-}
diff --git a/sgconf/xml.h b/sgconf/xml.h
deleted file mode 100644 (file)
index d00d441..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#pragma once
-
-namespace SGCONF
-{
-
-class OPTION_BLOCKS;
-class COMMANDS;
-
-void AppendXMLOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks);
-
-}
diff --git a/stargazer/BUGS b/stargazer/BUGS
deleted file mode 100644 (file)
index 139597f..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
diff --git a/stargazer/CHANGES b/stargazer/CHANGES
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/stargazer/CMakeLists.txt b/stargazer/CMakeLists.txt
deleted file mode 100644 (file)
index 073c716..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-set ( CPP_FILES main.cpp
-                admins_impl.cpp
-                users_impl.cpp
-                tariffs_impl.cpp
-                corps_impl.cpp
-                services_impl.cpp
-                user_impl.cpp
-                tariff_impl.cpp
-                eventloop.cpp
-                pidfile.cpp
-                plugin_runner.cpp
-                plugin_mgr.cpp
-                settings_impl.cpp
-                stg_timer.cpp
-                store_loader.cpp
-                traffcounter_impl.cpp
-                user_property.cpp )
-
-set ( THREADS_PREFER_PTHREAD_FLAG ON )
-find_package ( Threads REQUIRED )
-
-add_executable ( stargazer ${CPP_FILES} )
-
-target_link_libraries ( stargazer scriptexecuter dotconfpp logger common Threads::Threads ${CMAKE_DL_LIBS} )
-
-add_subdirectory ( plugins )
-
-# TODO: install
diff --git a/stargazer/README b/stargazer/README
deleted file mode 100644 (file)
index 21ede00..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-Инсталяция и запуск.
-1. > ./build
-2. > make install
-3. Правка конфигурационных файлов
-4. > stargazer
-
diff --git a/stargazer/TODO b/stargazer/TODO
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/stargazer/actions.h b/stargazer/actions.h
deleted file mode 100644 (file)
index eea72b7..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-#ifndef __ACTIONS_H__
-#define __ACTIONS_H__
-
-// Usage:
-//
-// ACTIONS_LIST actionsList;
-// CLASS myClass;
-// DATA1 myData1;
-// DATA2 myData2;
-//
-// actionsList.Enqueue(myClass, &CLASS::myMethod1, myData1);
-// actionsList.Enqueue(myClass, &CLASS::myMethod2, myData2);
-//
-// actionsList.InvokeAll();
-
-#include <pthread.h>
-#include <vector>
-#include <functional>
-
-// Generalized actor type - a method of some class with one argument
-template <class ACTIVE_CLASS, typename DATA_TYPE>
-struct ACTOR
-{
-typedef void (ACTIVE_CLASS::*TYPE)(DATA_TYPE);
-};
-
-// Abstract base action class for polymorphic action invocation
-class BASE_ACTION
-{
-public:
-    virtual ~BASE_ACTION() {}
-    virtual void Invoke() = 0;
-};
-
-// Concrete generalized action type - an actor with it's data and owner
-template <class ACTIVE_CLASS, typename DATA_TYPE>
-class ACTION : public BASE_ACTION,
-               public std::unary_function<ACTIVE_CLASS &, void>
-{
-public:
-    ACTION(ACTIVE_CLASS & ac,
-           typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE a,
-           DATA_TYPE d)
-        : activeClass(ac), actor(a), data(d) {}
-    void Invoke();
-private:
-    ACTION(const ACTION<ACTIVE_CLASS, DATA_TYPE> & rvalue);
-    ACTION<ACTIVE_CLASS, DATA_TYPE> & operator=(const ACTION<ACTIVE_CLASS, DATA_TYPE> & rvalue);
-
-    ACTIVE_CLASS & activeClass;
-    typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE actor;
-    DATA_TYPE data;
-};
-
-// A list of an actions
-// All methods are thread-safe
-class ACTIONS_LIST : private std::vector<BASE_ACTION *>
-{
-public:
-    // Just a typedef for parent class
-    typedef std::vector<BASE_ACTION *> parent;
-
-    // Initialize mutex
-    ACTIONS_LIST();
-    // Delete actions and destroy mutex
-    virtual ~ACTIONS_LIST();
-
-    parent::iterator begin();
-    parent::iterator end();
-    parent::const_iterator begin() const;
-    parent::const_iterator end() const;
-
-    bool empty() const;
-    size_t size() const;
-    void swap(ACTIONS_LIST & list);
-
-    // Add an action to list
-    template <class ACTIVE_CLASS, typename DATA_TYPE>
-    void Enqueue(ACTIVE_CLASS & ac,
-                 typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE a,
-                 DATA_TYPE d);
-    // Invoke all actions in the list
-    void InvokeAll();
-private:
-    mutable pthread_mutex_t mutex;
-};
-
-#include "actions.inl.h"
-
-#endif
diff --git a/stargazer/actions.inl.h b/stargazer/actions.inl.h
deleted file mode 100644 (file)
index 1b713f1..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-#ifndef __ACTIONS_INL_H__
-#define __ACTIONS_INL_H__
-
-#include <algorithm>
-
-#include "stg/locker.h"
-
-// Polymorphick action invocation
-template <class ACTIVE_CLASS, typename DATA_TYPE>
-inline
-void ACTION<ACTIVE_CLASS, DATA_TYPE>::Invoke()
-{
-(activeClass.*actor)(data);
-}
-
-inline
-ACTIONS_LIST::ACTIONS_LIST()
-    : mutex()
-{
-pthread_mutex_init(&mutex, NULL);
-}
-
-// Delete all actions before deleting list
-inline
-ACTIONS_LIST::~ACTIONS_LIST()
-{
-
-    {
-    STG_LOCKER lock(&mutex);
-
-    parent::iterator it(parent::begin());
-    while (it != parent::end())
-        {
-        delete *it++;
-        }
-    }
-
-pthread_mutex_destroy(&mutex);
-}
-
-inline
-ACTIONS_LIST::parent::iterator ACTIONS_LIST::begin()
-{
-STG_LOCKER lock(&mutex);
-return parent::begin();
-}
-
-inline
-ACTIONS_LIST::parent::iterator ACTIONS_LIST::end()
-{
-STG_LOCKER lock(&mutex);
-return parent::end();
-}
-
-inline
-ACTIONS_LIST::parent::const_iterator ACTIONS_LIST::begin() const
-{
-STG_LOCKER lock(&mutex);
-return parent::begin();
-}
-
-inline
-ACTIONS_LIST::parent::const_iterator ACTIONS_LIST::end() const
-{
-STG_LOCKER lock(&mutex);
-return parent::end();
-}
-
-inline
-bool ACTIONS_LIST::empty() const
-{
-STG_LOCKER lock(&mutex);
-return parent::empty();
-}
-
-inline
-size_t ACTIONS_LIST::size() const
-{
-STG_LOCKER lock(&mutex);
-return parent::size();
-}
-
-inline
-void ACTIONS_LIST::swap(ACTIONS_LIST & list)
-{
-STG_LOCKER lock(&mutex);
-parent::swap(list);
-}
-
-template <class ACTIVE_CLASS, typename DATA_TYPE>
-inline
-void ACTIONS_LIST::Enqueue(ACTIVE_CLASS & ac,
-                           typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE a,
-                           DATA_TYPE d)
-{
-STG_LOCKER lock(&mutex);
-push_back(new ACTION<ACTIVE_CLASS, DATA_TYPE>(ac, a, d));
-}
-
-inline
-void ACTIONS_LIST::InvokeAll()
-{
-STG_LOCKER lock(&mutex);
-std::for_each(
-        parent::begin(),
-        parent::end(),
-        [](auto action){ action->Invoke(); });
-}
-
-#endif
diff --git a/stargazer/admins_impl.cpp b/stargazer/admins_impl.cpp
deleted file mode 100644 (file)
index 1e59736..0000000
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Date: 27.10.2002
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- */
-
-#include "admins_impl.h"
-
-#include "stg/common.h"
-
-using STG::AdminsImpl;
-
-//-----------------------------------------------------------------------------
-AdminsImpl::AdminsImpl(Store& st)
-    : m_stg(Priv(0xFFFF), "@stargazer", ""),
-      m_noAdmin(Priv(0xFFFF), "NO-ADMIN", ""),
-      m_store(st),
-      WriteServLog(Logger::get())
-{
-    read();
-}
-//-----------------------------------------------------------------------------
-int AdminsImpl::add(const std::string& login, const Admin& admin)
-{
-    if (!admin.priv().adminChg)
-    {
-        const std::string s = admin.logStr() + " Add administrator \'" + login + "\'. Access denied.";
-        m_strError = "Access denied.";
-        WriteServLog(s.c_str());
-        return -1;
-    }
-
-    std::lock_guard<std::mutex> lock(m_mutex);
-    const auto it = find(login);
-
-    if (it != m_data.end())
-    {
-        m_strError = "Administrator \'" + login + "\' cannot not be added. Administrator already exists.";
-        WriteServLog("%s %s", admin.logStr().c_str(), m_strError.c_str());
-        return -1;
-    }
-
-    m_data.push_back(Admin(Priv(0), login, {}));
-
-    if (m_store.AddAdmin(login) == 0)
-    {
-        WriteServLog("%s Administrator \'%s\' added.",
-                     admin.logStr().c_str(), login.c_str());
-        return 0;
-    }
-
-    m_strError = "Administrator \'" + login + "\' was not added. Error: " + m_store.GetStrError();
-    WriteServLog("%s %s", admin.logStr().c_str(), m_strError.c_str());
-
-    return -1;
-}
-//-----------------------------------------------------------------------------
-int AdminsImpl::del(const std::string& login, const Admin& admin)
-{
-    if (!admin.priv().adminChg)
-    {
-        const std::string s = admin.logStr() + " Delete administrator \'" + login + "\'. Access denied.";
-        m_strError = "Access denied.";
-        WriteServLog(s.c_str());
-        return -1;
-    }
-
-    std::lock_guard<std::mutex> lock(m_mutex);
-    const auto it = find(login);
-
-    if (it == m_data.end())
-    {
-        m_strError = "Administrator \'" + login + "\' cannot be deleted. Administrator does not exist.";
-        WriteServLog("%s %s", admin.logStr().c_str(), m_strError.c_str());
-        return -1;
-    }
-
-    m_data.erase(it);
-    if (m_store.DelAdmin(login) < 0)
-    {
-        m_strError = "Administrator \'" + login + "\' was not deleted. Error: " + m_store.GetStrError();
-        WriteServLog("%s %s", admin.logStr().c_str(), m_strError.c_str());
-
-        return -1;
-    }
-
-    WriteServLog("%s Administrator \'%s\' deleted.", admin.logStr().c_str(), login.c_str());
-    return 0;
-}
-//-----------------------------------------------------------------------------
-int AdminsImpl::change(const AdminConf& ac, const Admin& admin)
-{
-    if (!admin.priv().adminChg)
-    {
-        const std::string s = admin.logStr() + " Change administrator \'" + ac.login + "\'. Access denied.";
-        m_strError = "Access denied.";
-        WriteServLog(s.c_str());
-        return -1;
-    }
-
-    std::lock_guard<std::mutex> lock(m_mutex);
-    const auto it = find(ac.login);
-
-    if (it == m_data.end())
-    {
-        m_strError = "Administrator \'" + ac.login + "\' cannot be changed " + ". Administrator does not exist.";
-        WriteServLog("%s %s", admin.logStr().c_str(), m_strError.c_str());
-        return -1;
-    }
-
-    *it = ac;
-    if (m_store.SaveAdmin(ac))
-    {
-        WriteServLog("Cannot write admin %s.", ac.login.c_str());
-        WriteServLog("%s", m_store.GetStrError().c_str());
-        return -1;
-    }
-
-    WriteServLog("%s Administrator \'%s\' changed.",
-                 admin.logStr().c_str(), ac.login.c_str());
-
-    return 0;
-}
-//-----------------------------------------------------------------------------
-void AdminsImpl::read()
-{
-    std::vector<std::string> logins;
-    if (m_store.GetAdminsList(&logins) < 0)
-    {
-        WriteServLog(m_store.GetStrError().c_str());
-        return;
-    }
-
-    std::vector<Admin> admins;
-    for (const auto& login : logins)
-    {
-        AdminConf ac(Priv(0), login, "");
-
-        if (m_store.RestoreAdmin(&ac, login))
-        {
-            WriteServLog(m_store.GetStrError().c_str());
-            return;
-        }
-
-        m_data.push_back(Admin(ac));
-    }
-
-    std::lock_guard<std::mutex> lock(m_mutex);
-    m_data.swap(admins);
-}
-//-----------------------------------------------------------------------------
-bool AdminsImpl::find(const std::string& login, Admin** admin)
-{
-    std::lock_guard<std::mutex> lock(m_mutex);
-    if (m_data.empty())
-    {
-        printfd(__FILE__, "No admin in system!\n");
-        if (admin != nullptr)
-            *admin = &m_noAdmin;
-        return false;
-    }
-
-    auto it = find(login);
-
-    if (it != m_data.end())
-    {
-        if (admin != nullptr)
-            *admin = &(*it);
-        return false;
-    }
-
-    return true;
-}
-//-----------------------------------------------------------------------------
-bool AdminsImpl::exists(const std::string& login) const
-{
-    std::lock_guard<std::mutex> lock(m_mutex);
-    if (m_data.empty())
-    {
-        printfd(__FILE__, "No admin in system!\n");
-        return true;
-    }
-
-    return find(login) != m_data.end();
-}
-//-----------------------------------------------------------------------------
-bool AdminsImpl::correct(const std::string& login, const std::string& password, Admin** admin)
-{
-    std::lock_guard<std::mutex> lock(m_mutex);
-    if (m_data.empty())
-    {
-        printfd(__FILE__, "No admin in system!\n");
-        return true;
-    }
-
-    const auto it = find(login);
-
-    if (it == m_data.end() || it->password() != password)
-        return false;
-
-    if (admin != nullptr)
-        *admin = &(*it);
-
-    return true;
-}
diff --git a/stargazer/admins_impl.h b/stargazer/admins_impl.h
deleted file mode 100644 (file)
index 9c443a7..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Date: 27.10.2002
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- */
-
-#pragma once
-
-#include "stg/admins.h"
-#include "stg/admin.h"
-#include "stg/store.h"
-#include "stg/logger.h"
-
-#include <vector>
-#include <string>
-#include <algorithm>
-#include <mutex>
-
-namespace STG
-{
-
-class AdminsImpl : public Admins
-{
-    public:
-        explicit AdminsImpl(Store& st);
-
-        AdminsImpl(const AdminsImpl&) = delete;
-        AdminsImpl& operator=(const AdminsImpl&) = delete;
-
-        int          add(const std::string& login, const Admin& admin) override;
-        int          del(const std::string& login, const Admin& admin) override;
-        int          change(const AdminConf& ac, const Admin& admin) override;
-        const Admin& sysAdmin() const override { return m_stg; }
-        const Admin& noAdmin() const override { return m_noAdmin; }
-        bool         find(const std::string& login, Admin** admin) override;
-        bool         exists(const std::string& login) const override;
-        bool         correct(const std::string& login,
-                             const std::string& password,
-                             Admin** admin) override;
-
-        const std::string& strError() const override { return m_strError; }
-
-        size_t       count() const override { return m_data.size(); }
-
-        void fmap(std::function<void (const Admin&)> callback) const
-        {
-            for (const auto& admin : m_data)
-                callback(admin);
-        }
-
-    private:
-        void         read();
-        auto         find(const std::string& login) { return std::find(m_data.begin(), m_data.end(), Admin(Priv(0), login, "")); }
-        auto         find(const std::string& login) const { return std::find(m_data.begin(), m_data.end(), Admin(Priv(0), login, "")); }
-
-        Admin              m_stg;
-        Admin              m_noAdmin;
-        std::vector<Admin> m_data;
-        Store&             m_store;
-        Logger&            WriteServLog;
-        mutable std::mutex m_mutex;
-        std::string        m_strError;
-};
-
-}
diff --git a/stargazer/corps_impl.cpp b/stargazer/corps_impl.cpp
deleted file mode 100644 (file)
index b41b455..0000000
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#include "corps_impl.h"
-
-#include "stg/admin.h"
-#include "stg/admin_conf.h"
-#include "stg/store.h"
-#include "stg/common.h"
-
-#include <algorithm>
-#include <cassert>
-
-using STG::CorporationsImpl;
-
-//-----------------------------------------------------------------------------
-CorporationsImpl::CorporationsImpl(Store * st)
-    : store(st),
-      WriteServLog(Logger::get()),
-      handle(0)
-{
-Read();
-}
-//-----------------------------------------------------------------------------
-int CorporationsImpl::Add(const CorpConf & corp, const Admin * admin)
-{
-std::lock_guard<std::mutex> lock(mutex);
-const auto& priv = admin->priv();
-
-if (!priv.corpChg)
-    {
-    std::string s = admin->logStr() + " Add corporation \'" + corp.name + "\'. Access denied.";
-    strError = "Access denied.";
-    WriteServLog(s.c_str());
-    return -1;
-    }
-
-crp_iter si(find(data.begin(), data.end(), corp));
-
-if (si != data.end())
-    {
-    strError = "Corporation \'" + corp.name + "\' cannot not be added. Corporation already exist.";
-    WriteServLog("%s %s", admin->logStr().c_str(), strError.c_str());
-
-    return -1;
-    }
-
-data.push_back(corp);
-
-if (store->AddCorp(corp.name) == 0)
-    {
-    WriteServLog("%s Corporation \'%s\' added.",
-                 admin->logStr().c_str(), corp.name.c_str());
-    return 0;
-    }
-
-strError = "Corporation \'" + corp.name + "\' was not added. Error: " + store->GetStrError();
-WriteServLog("%s %s", admin->logStr().c_str(), strError.c_str());
-
-return -1;
-}
-//-----------------------------------------------------------------------------
-int CorporationsImpl::Del(const std::string & name, const Admin * admin)
-{
-std::lock_guard<std::mutex> lock(mutex);
-const auto& priv = admin->priv();
-
-if (!priv.corpChg)
-    {
-    std::string s = admin->logStr() + " Delete corporation \'" + name + "\'. Access denied.";
-    strError = "Access denied.";
-    WriteServLog(s.c_str());
-    return -1;
-    }
-
-crp_iter si(find(data.begin(), data.end(), CorpConf(name)));
-
-if (si == data.end())
-    {
-    strError = "Corporation \'" + name + "\' cannot be deleted. Corporation does not exist.";
-    WriteServLog("%s %s", admin->logStr().c_str(), strError.c_str());
-    return -1;
-    }
-
-std::map<int, const_crp_iter>::iterator csi;
-csi = searchDescriptors.begin();
-while (csi != searchDescriptors.end())
-    {
-    if (csi->second == si)
-        (csi->second)++;
-    ++csi;
-    }
-
-data.erase(si);
-if (store->DelCorp(name) < 0)
-    {
-    strError = "Corporation \'" + name + "\' was not deleted. Error: " + store->GetStrError();
-    WriteServLog("%s %s", admin->logStr().c_str(), strError.c_str());
-
-    return -1;
-    }
-
-WriteServLog("%s Corporation \'%s\' deleted.", admin->logStr().c_str(), name.c_str());
-return 0;
-}
-//-----------------------------------------------------------------------------
-int CorporationsImpl::Change(const CorpConf & corp, const Admin * admin)
-{
-std::lock_guard<std::mutex> lock(mutex);
-const auto& priv = admin->priv();
-
-if (!priv.corpChg)
-    {
-    std::string s = admin->logStr() + " Change corporation \'" + corp.name + "\'. Access denied.";
-    strError = "Access denied.";
-    WriteServLog(s.c_str());
-    return -1;
-    }
-
-crp_iter si(find(data.begin(), data.end(), corp));
-
-if (si == data.end())
-    {
-    strError = "Corporation \'" + corp.name + "\' cannot be changed " + ". Corporation does not exist.";
-    WriteServLog("%s %s", admin->logStr().c_str(), strError.c_str());
-    return -1;
-    }
-
-*si = corp;
-if (store->SaveCorp(corp))
-    {
-    WriteServLog("Cannot write corporation %s.", corp.name.c_str());
-    WriteServLog("%s", store->GetStrError().c_str());
-    return -1;
-    }
-
-WriteServLog("%s Corporation \'%s\' changed.",
-             admin->logStr().c_str(), corp.name.c_str());
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-bool CorporationsImpl::Read()
-{
-std::lock_guard<std::mutex> lock(mutex);
-std::vector<std::string> corpsList;
-if (store->GetCorpsList(&corpsList) < 0)
-    {
-    WriteServLog(store->GetStrError().c_str());
-    return true;
-    }
-
-for (size_t i = 0; i < corpsList.size(); i++)
-    {
-    CorpConf corp;
-
-    if (store->RestoreCorp(&corp, corpsList[i]))
-        {
-        WriteServLog(store->GetStrError().c_str());
-        return true;
-        }
-
-    data.push_back(corp);
-    }
-return false;
-}
-//-----------------------------------------------------------------------------
-bool CorporationsImpl::Find(const std::string & name, CorpConf * corp)
-{
-assert(corp != NULL && "Pointer to corporation is not null");
-
-std::lock_guard<std::mutex> lock(mutex);
-if (data.empty())
-    return false;
-
-crp_iter si(find(data.begin(), data.end(), CorpConf(name)));
-
-if (si != data.end())
-    {
-    *corp = *si;
-    return false;
-    }
-
-return true;
-}
-//-----------------------------------------------------------------------------
-bool CorporationsImpl::Exists(const std::string & name) const
-{
-std::lock_guard<std::mutex> lock(mutex);
-if (data.empty())
-    {
-    printfd(__FILE__, "no corporations in system!\n");
-    return true;
-    }
-
-const_crp_iter si(find(data.begin(), data.end(), CorpConf(name)));
-
-if (si != data.end())
-    return true;
-
-return false;
-}
-//-----------------------------------------------------------------------------
-int CorporationsImpl::OpenSearch() const
-{
-std::lock_guard<std::mutex> lock(mutex);
-handle++;
-searchDescriptors[handle] = data.begin();
-return handle;
-}
-//-----------------------------------------------------------------------------
-int CorporationsImpl::SearchNext(int h, CorpConf * corp) const
-{
-std::lock_guard<std::mutex> lock(mutex);
-if (searchDescriptors.find(h) == searchDescriptors.end())
-    {
-    WriteServLog("CORPORATIONS. Incorrect search handle.");
-    return -1;
-    }
-
-if (searchDescriptors[h] == data.end())
-    return -1;
-
-*corp = *searchDescriptors[h]++;
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int CorporationsImpl::CloseSearch(int h) const
-{
-std::lock_guard<std::mutex> lock(mutex);
-if (searchDescriptors.find(h) != searchDescriptors.end())
-    {
-    searchDescriptors.erase(searchDescriptors.find(h));
-    return 0;
-    }
-
-WriteServLog("CORPORATIONS. Incorrect search handle.");
-return -1;
-}
-//-----------------------------------------------------------------------------
diff --git a/stargazer/corps_impl.h b/stargazer/corps_impl.h
deleted file mode 100644 (file)
index 43bcb5d..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#pragma once
-
-#include "stg/corporations.h"
-#include "stg/corp_conf.h"
-#include "stg/locker.h"
-#include "stg/logger.h"
-
-#include <vector>
-#include <map>
-#include <string>
-#include <mutex>
-
-namespace STG
-{
-
-struct Admin;
-struct Store;
-
-class CorporationsImpl : public Corporations {
-public:
-    explicit CorporationsImpl(Store* st);
-
-    int Add(const CorpConf& corp, const Admin* admin) override;
-    int Del(const std::string& name, const Admin* admin) override;
-    int Change(const CorpConf& corp, const Admin* admin) override;
-    bool Find(const std::string& name, CorpConf* corp) override;
-    bool Exists(const std::string& name) const override;
-    const std::string& GetStrError() const override { return strError; }
-
-    size_t Count() const override { return data.size(); }
-
-    int OpenSearch() const override;
-    int SearchNext(int, CorpConf* corp) const override;
-    int CloseSearch(int) const override;
-
-private:
-    typedef std::vector<CorpConf>::iterator       crp_iter;
-    typedef std::vector<CorpConf>::const_iterator const_crp_iter;
-
-    bool Read();
-
-    std::vector<CorpConf> data;
-    Store* store;
-    Logger& WriteServLog;
-    mutable std::map<int, const_crp_iter> searchDescriptors;
-    mutable unsigned int handle;
-    mutable std::mutex mutex;
-    std::string strError;
-};
-
-}
diff --git a/stargazer/eventloop.cpp b/stargazer/eventloop.cpp
deleted file mode 100644 (file)
index 36a77e9..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-#include <csignal>
-#include <cerrno>
-#include <cstring>
-
-#include "stg/locker.h"
-#include "stg/common.h"
-#include "eventloop.h"
-
-EVENT_LOOP::EVENT_LOOP()
-    : ACTIONS_LIST(),
-      _running(false),
-      _stopped(true),
-      _tid(),
-      _mutex(),
-      _condition()
-{
-pthread_mutex_init(&_mutex, NULL);
-pthread_cond_init(&_condition, NULL);
-}
-
-EVENT_LOOP::~EVENT_LOOP()
-{
-pthread_cond_destroy(&_condition);
-pthread_mutex_destroy(&_mutex);
-}
-
-bool EVENT_LOOP::Start()
-{
-_running = true;
-if (pthread_create(&_tid, NULL, Run, this))
-    {
-    printfd(__FILE__, "EVENT_LOOP::Start - Failed to create thread: '%s'\n", strerror(errno));
-    return true;
-    }
-return false;
-}
-
-bool EVENT_LOOP::Stop()
-{
-_running = false;
-// Wake up thread
-pthread_cond_signal(&_condition);
-// Wait until thread exit
-pthread_join(_tid, NULL);
-return false;
-}
-
-void * EVENT_LOOP::Run(void * self)
-{
-EVENT_LOOP * ev = static_cast<EVENT_LOOP *>(self);
-ev->Runner();
-return NULL;
-}
-
-void EVENT_LOOP::Runner()
-{
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-_stopped = false;
-printfd(__FILE__, "EVENT_LOOP::Runner - Before start\n");
-while (_running)
-    {
-        {
-        STG_LOCKER lock(&_mutex);
-        // Check for any actions...
-        if (empty())
-            {
-            // ... and sleep until new actions added
-            printfd(__FILE__, "EVENT_LOOP::Runner - Sleeping until new actions arrived\n");
-            pthread_cond_wait(&_condition, &_mutex);
-            }
-        // Check for running after wake up
-        if (!_running)
-            {
-            // Don't process any actions if stopping
-            break;
-            }
-        }
-    // Create new empty actions list
-    ACTIONS_LIST local;
-    // Fast swap with current
-    swap(local);
-    // Invoke all current actions
-    printfd(__FILE__, "EVENT_LOOP::Runner - Invoke %d actions\n", local.size());
-    local.InvokeAll();
-    }
-printfd(__FILE__, "EVENT_LOOP::Runner - Before stop\n");
-_stopped = true;
-}
-
-namespace {
-
-pthread_mutex_t singletonMutex;
-
-}
-
-EVENT_LOOP & EVENT_LOOP_SINGLETON::GetInstance()
-{
-// Double-checking technique
-if (!_instance)
-    {
-    STG_LOCKER lock(&singletonMutex);
-    if (!_instance)
-        {
-        CreateInstance();
-        }
-    }
-return *_instance;
-}
-
-void EVENT_LOOP_SINGLETON::CreateInstance()
-{
-static EVENT_LOOP loop;
-_instance = &loop;
-}
-
-EVENT_LOOP * EVENT_LOOP_SINGLETON::_instance = NULL;
diff --git a/stargazer/eventloop.h b/stargazer/eventloop.h
deleted file mode 100644 (file)
index 0e79814..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-#ifndef __EVENT_LOOP_H__
-#define __EVENT_LOOP_H__
-
-#include <pthread.h>
-
-#include "stg/noncopyable.h"
-#include "actions.h"
-
-class EVENT_LOOP : private NONCOPYABLE,
-                   private ACTIONS_LIST
-{
-    public:
-        bool Start();
-        bool Stop();
-        bool IsRunning() const { return _running; }
-
-        template <class ACTIVE_CLASS, typename DATA_TYPE>
-        void Enqueue(ACTIVE_CLASS & ac,
-                     typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE a,
-                     DATA_TYPE d);
-
-    private:
-        bool _running;
-        bool _stopped;
-        pthread_t _tid;
-        pthread_mutex_t _mutex;
-        pthread_cond_t _condition;
-
-        EVENT_LOOP();
-        virtual ~EVENT_LOOP();
-
-        static void * Run(void *);
-        void Runner();
-
-        friend class EVENT_LOOP_SINGLETON;
-};
-
-class EVENT_LOOP_SINGLETON : private NONCOPYABLE
-{
-    public:
-        static EVENT_LOOP & GetInstance();
-
-    private:
-        static EVENT_LOOP * _instance;
-        static void CreateInstance();
-
-        EVENT_LOOP_SINGLETON() {}
-        ~EVENT_LOOP_SINGLETON() {}
-};
-
-template <class ACTIVE_CLASS, typename DATA_TYPE>
-void EVENT_LOOP::Enqueue(ACTIVE_CLASS & ac,
-                         typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE a,
-                         DATA_TYPE d)
-{
-STG_LOCKER lock(&_mutex);
-// Add new action
-ACTIONS_LIST::Enqueue(ac, a, d);
-// Signal about new action
-pthread_cond_signal(&_condition);
-}
-
-#endif
diff --git a/stargazer/inst/freebsd/etc/stargazer/OnChange b/stargazer/inst/freebsd/etc/stargazer/OnChange
deleted file mode 100755 (executable)
index 8cb1096..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#! /bin/sh
-
-login=$1
-param=$2
-oldValue=$3
-newValue=$4
-
-#echo "User: '$login'. Parameter $param changed from '$oldValue' to '$newValue'" >> /var/stargazer/users.chg.log
\ No newline at end of file
diff --git a/stargazer/inst/freebsd/etc/stargazer/OnConnect b/stargazer/inst/freebsd/etc/stargazer/OnConnect
deleted file mode 100755 (executable)
index 912ed7d..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-#! /bin/sh
-
-#Этот скрипт вызывается в момент, когда пользователь
-#успешно прошел авторизацию на сервере. Задача скрипта - перестроить 
-#файрвол так, что бы пользователь получил доступ в интернет
-
-# Login
-LOGIN=$1
-
-#user IP
-IP=$2
-
-#cash
-CASH=$3
-
-#user ID
-ID=$4
-
-#Selected dirs to connect
-DIRS=$5
-
-
-#echo "C `date +%Y.%m.%d-%H.%M.%S` $IP $CASH" >> /var/stargazer/users/$LOGIN/connect.log
-
diff --git a/stargazer/inst/freebsd/etc/stargazer/OnDisconnect b/stargazer/inst/freebsd/etc/stargazer/OnDisconnect
deleted file mode 100755 (executable)
index 6169ddc..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-#! /bin/sh
-
-# Этот скрипт вызывается в момент, когда пользователь
-# желает отключится от интернета или вышел таймаут у пользователя
-# и сервер сам отключает пользователя
-# Задача скрипта подобна задаче скрипта OnConnect - перестроить 
-# файрвол так, что бы пользователю закрыть доступ в интернет
-
-# Login
-LOGIN=$1
-
-#user IP
-IP=$2
-
-#cash
-CASH=$3
-
-#user ID
-ID=$4
-
-#Selected dirs to disconnect
-DIRS=$5
-
-#echo "D `date +%Y.%m.%d-%H.%M.%S` $IP $CASH" >> /var/stargazer/users/$LOGIN/connect.log
diff --git a/stargazer/inst/freebsd/etc/stargazer/OnUserAdd b/stargazer/inst/freebsd/etc/stargazer/OnUserAdd
deleted file mode 100755 (executable)
index 22d321c..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#! /bin/sh
-
-# Использование (неиспользование) этого скрипта дело вкуса.
-# Он не выполняет критических функций. Его задача автматизировать
-# действия характерные при добавлении пользователя сети, например добавлекние 
-# пользователю почты
-
-# Login
-login=$1
-
-#echo "added user $login" >> /var/stargazer/add_del.log
-
-
-
diff --git a/stargazer/inst/freebsd/etc/stargazer/OnUserDel b/stargazer/inst/freebsd/etc/stargazer/OnUserDel
deleted file mode 100755 (executable)
index 248e5b3..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#! /bin/sh
-
-# Login
-login=$1
-
-#echo "deleted user $login" >> /var/stargazer/add_del.log
-
diff --git a/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_ao.conf b/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_ao.conf
deleted file mode 100644 (file)
index 62c0dc7..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-# Enable the authorization module Always Online "mod_auth_ao.so"
-<Module auth_ao>
-</Module>
\ No newline at end of file
diff --git a/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_cap_bpf.conf b/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_cap_bpf.conf
deleted file mode 100644 (file)
index 4a6c626..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-# Enable the traffic capture module "mod_cap_ipq.so" using Berkeley Packet Filter
-<Module cap_bpf>
-   # Define interface(s) for traffic capture
-   iface = rl0
-   iface = rl1
-   iface = dc0
-</Module>
\ No newline at end of file
diff --git a/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_cap_divert.conf b/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_cap_divert.conf
deleted file mode 100644 (file)
index acd15e0..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-# Enable the traffic capture module "mod_cap_divert.so" using Divert-sockets
-<Module cap_divert>
-   # Port for traffic
-   # Parameter: optional
-   # Value: 1 ... 65535
-   # Default: 15701
-   Port = 15701
-
-   # Disable packet forwarding
-   # Parameter: optional
-   # Value: yes, no
-   # Default: no
-   DisableForwarding = no
-</Module>
diff --git a/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_cap_nf.conf b/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_cap_nf.conf
deleted file mode 100644 (file)
index 948674c..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-# Enable the traffic capture module "mod_cap_ipq.so" using NetFlow protocol
-<Module cap_nf>
-    # Port for TCP connections
-    # Note: Parameters TCPPort and UDPPort can be equal
-    # Parameter: optional
-    # Value: 1 ... 65535
-    # Default: 9996
-    #TCPPort = 9996
-
-    # Port for UDP connections
-    # Note: Parameters TCPPort and UDPPort can be equal
-    # Parameter: optional
-    # Value: 1 ... 65535
-    # Default: 9996
-    UDPPort = 9996
-</Module>
diff --git a/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_ia.conf b/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_ia.conf
deleted file mode 100644 (file)
index df170dd..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-# Enable the authorization module InetAccess "mod_auth_ia.so"
-<Module auth_ia>
-    # Port on which the server interacts with authorizator
-    # Parameter: required
-    # Value: 1 ... 65535
-    # Default: 5555
-    Port = 5555
-
-    # The time interval between sending an alive query to the user
-    # and updating statistics
-    # Parameter: required
-    # Values: 5 ... 600 (seconds)
-    # Default: 60
-    UserDelay = 60
-
-    # User timeout. If authorizer does not respond during this time,
-    # the user will be disconnected
-    # Parameter: required
-    # Values: 5 ... 600
-    # Default: 60
-    UserTimeout = 65
-
-    # Define which information will be transmitted from the server to InetAccess
-    # as a residue of prepaid traffic
-    # FreeMb = 0 — amount of free megabytes in terms of cost of zero direction
-    # FreeMb = 1 — amount of free megabytes in terms of cost of the first direction
-    # FreeMb = 1 — amount of free megabytes in terms of cost of the first direction
-    # FreeMb = 2 — amount of free megabytes in terms of cost of the second direction
-    # ........................
-    # FreeMb = 9 — amount of free megabytes in terms of cost of the ninth direction
-    # FreeMb = cash - amount of money for which the user can download for free
-    # FreeMb = none - no transfer
-    # Default: cash
-    # Parameter: required
-    # Values: different, see above
-    # Default: cash
-    FreeMb = cash
-
-    # Enable protocol errors logging
-    # Parameter: optional
-    # Values: yes, no
-    # Default: no
-    # LogProtocolErrors = no
-</Module>
diff --git a/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_ping.conf b/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_ping.conf
deleted file mode 100644 (file)
index 7402219..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# Enable the module that pings users "mod_ping.so"
-<Module ping>
-    # The time interval between pings
-    # Parameter: required
-    # Value: 10 ... 3600 (seconds)
-    # Default: 15
-    PingDelay = 15
-</Module>
\ No newline at end of file
diff --git a/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_radius.conf b/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_radius.conf
deleted file mode 100644 (file)
index edc94d5..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-# Enable the interaction module for FreeRADIUS "mod_radius.so"
-<Module radius>
-    # FreeRADIUS password
-    # Parameter: required
-    # Values: any, supported by software
-    # Default: 123456
-    Password = 123456
-
-    # FreeRADIUS server
-    # Parameter: required
-    # Values: IP address or DNS name
-    # Default: 127.0.0.1
-    ServerIP = 127.0.0.1
-
-    # FreeRADIUS port
-    # Parameter: required
-    # Value: 1 ... 65535
-    # Default: 6666
-    Port = 6666
-
-    # List of services for which will be carried out FreeRADIUS authentication 
-    # Note: Parameter can be blank
-    # Parameter: required
-    # Value: any, supported by software
-    # Default: Login-User
-    AuthServices = Login-User
-
-    # List of services for which will be carried out FreeRADIUS Accounting
-    # Note: Parameter can be blank
-    # Parameter: required
-    # Value: any, supported by software
-    # Default: Framed-User
-    AcctServices = Framed-User
-</Module>
\ No newline at end of file
diff --git a/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_remote_script.conf b/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_remote_script.conf
deleted file mode 100644 (file)
index a71350c..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-# Enable the module for remote execution of scripts OnConnect and OnDisconnect "mod_remote_script.so"
-<Module remote_script>
-    # The time interval between sending confirmations that the user is online
-    # Parametr: required
-    # Values: 10 ... 600 (seconds)
-    # Default: 60
-    SendPeriod = 15
-
-    # Define mapping between subnet(s) and remote server(s)
-    # File format: <subnet> <Router1> <Router2> ...
-    # Example:
-    # 192.168.1.0/24 192.168.1.7 192.168.1.8
-    # 192.168.2.0/24 192.168.2.5 192.168.2.6 192.168.2.7
-    # 192.168.3.0/24 192.168.3.5
-    # 192.168.4.0/24 192.168.4.5
-    # Parametr: required
-    # Values: file path
-    # Default: subnets
-    SubnetFile = subnets
-
-    # The password to encrypt packets between the stg-server and remote server
-    # Parameter: required
-    # Values: any
-    # Default: 123456
-    Password = 123456
-
-    # Define which user parameters are transferred to a remote server in addition to
-    # other parameters that transfered by default (ID, IP, Login, Cash, Dirs).
-    # Note: Parameter can be blank. 
-    # Parameter: required  
-    # Values: Cash, FreeMb, Passive, Disabled, AlwaysOnline, TariffName, 
-    # NextTariff, Address, Note, Group, Email, RealName, Credit, EnabledDirs, 
-    # Userdata0...Userdata9
-    # Default: Cash Tariff EnabledDirs
-    UserParams = Cash Tariff EnabledDirs
-
-    # Port on which the server interacts with remote server
-    # Parameter: required
-    # Value: 1...65535
-    # Default: 9999
-    Port = 9999
-</Module>
diff --git a/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_rpc.conf b/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_rpc.conf
deleted file mode 100644 (file)
index b05695a..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-# Enable the configuration module ConfRPC "mod_conf_rpc.so"
-<Module conf_rpc>
-    # Port on which the server interacts with configurator
-    # Parameter: required
-    # Value: 1...65535
-    # Default:
-    Port = 8080
-
-    # Session timeout in seconds
-    # Parameter: required
-    # Value: positive integer
-    # Default: 1800
-    CookieTimeout = 1800
-</Module>
diff --git a/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_sg.conf b/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_sg.conf
deleted file mode 100644 (file)
index 610a312..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# Enable the configuration module SgConfig "mod_conf_sg.so"
-<Module conf_sg>
-    # Port on which the server interacts with configurator
-    # Parameter: required
-    # Value: 1...65535
-    # Default: 5555
-    Port = 5555
-</Module>
\ No newline at end of file
diff --git a/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_smux.conf b/stargazer/inst/freebsd/etc/stargazer/conf-available.d/mod_smux.conf
deleted file mode 100644 (file)
index 84ce24b..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-# Enables SMUX-peer for SNMPd.
-<Module smux>
-    # IP-address of a server to connect to
-    # Parameter: required
-    # Value: X.X.X.X
-    # Default: 127.0.0.1
-    Server = 127.0.0.1
-
-    # Port number on a server to connect to
-    # Parameter: required
-    # Value: 1 ... 65535
-    # Default: 199
-    Port = 199
-
-    # Password for authentication on a server
-    # Parameter: required
-    # Value: any text
-    Password =
-</Module>
diff --git a/stargazer/inst/freebsd/etc/stargazer/conf-available.d/store_files.conf b/stargazer/inst/freebsd/etc/stargazer/conf-available.d/store_files.conf
deleted file mode 100644 (file)
index f7e0f23..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-# Enables plain file backend.
-<StoreModule store_files>
-
-    # Working server directory, provides data on tariffs, users, administrators.
-    # Parameter: required
-    # Value: directory path
-    WorkDir = /var/stargazer
-
-    # Owner, group and permissions of the files of user statistics (stat)
-    # Parameter: required
-    # Values: any, supported by OS
-    ConfOwner = root
-    ConfGroup = root
-    ConfMode = 640
-
-    # Owner, group and permissions on user configuration files (conf)
-    # Parameter: required
-    # Values: any, supported by OS
-    StatOwner = root
-    StatGroup = root
-    StatMode = 640
-
-    # Owner, group and permissions for user log files (log)
-    # Parameter: required
-    # Values: any, supported by OS
-    UserLogOwner = root
-    UserLogGroup = root
-    UserLogMode = 640
-
-</StoreModule>
diff --git a/stargazer/inst/freebsd/etc/stargazer/conf-available.d/store_firebird.conf b/stargazer/inst/freebsd/etc/stargazer/conf-available.d/store_firebird.conf
deleted file mode 100644 (file)
index 39e4ad3..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-# Enables Firebird backend.
-<StoreModule store_firebird>
-    # Database server address
-    # Parameter: optional
-    # Value: IP address or DNS name
-    # Default: localhost
-    # Server = localhost
-
-    # Path to the database on the server or its alias
-    # Parameter: optional
-    # Value: file path
-    # Default: /var/stg/stargazer.fdb
-    # Database = /var/stg/stargazer.fdb
-
-    # Database username
-    # Parameter: optional
-    # Value: any, supported by database
-    # Default: stg
-    # User = stg
-
-    # Database password
-    # Parameter: optional
-    # Value: any, supported by database
-    # Default: 123456
-    # Password = 123456
-
-    # The transaction isolation level
-    # Parameter: optional
-    # Values: concurrency, dirtyread, readcommitted, consistency
-    # Defalt: concurrency
-    # IsolationLevel = concurrency
-
-    # Responding to lock (optional, defaults to wait):
-    # Parameter: optional
-    # Values: wait, nowait
-    # Defalt: wait
-    # LockResolution = wait
-</StoreModule>
diff --git a/stargazer/inst/freebsd/etc/stargazer/conf-available.d/store_mysql.conf b/stargazer/inst/freebsd/etc/stargazer/conf-available.d/store_mysql.conf
deleted file mode 100644 (file)
index a5b2126..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-# Enables MySQL backend.
-<StoreModule store_mysql>
-    # Database server address
-    # Parameter: required
-    # Value: IP address or DNS name
-    # Default: localhost
-    Server = localhost
-
-    # Database name
-    # Parameter: required
-    # Value: any, supported by database
-    # Default: stg
-    Database = stg
-
-    # Database username
-    # Parameter: required
-    # Value: any, supported by database
-    # Default: stg
-    User = stg
-
-    # Database password
-    # Parameter: required
-    # Value: any, supported by database
-    # Default: 123456
-    Password = 123456
-</StoreModule>
diff --git a/stargazer/inst/freebsd/etc/stargazer/conf-available.d/store_postgresql.conf b/stargazer/inst/freebsd/etc/stargazer/conf-available.d/store_postgresql.conf
deleted file mode 100644 (file)
index 8a52c75..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-# Enables PostgreSQL backend.
-<StoreModule store_postgresql>
-    # Database server address
-    # Parameter: optional
-    # Value: IP address or DNS name
-    # Default: localhost
-    # Server = localhost
-
-    # Database name
-    # Parameter: optional
-    # Value: any, supported by database
-    # Default: stargazer
-    # Database = stargazer
-
-    # Database username
-    # Parameter: optional
-    # Value: any, supported by database
-    # Default: stg
-    # User = stg
-
-    # Database password
-    # Parameter: optional
-    # Value: any, supported by database
-    # Default: 123456
-    # Password = 123456
-
-    # Number of tries to reconnect
-    # Parameter: optional
-    # Value: positive integer
-    # Default: 3
-    # Retries = 3
-</StoreModule>
diff --git a/stargazer/inst/freebsd/etc/stargazer/conf-enabled.d/mod_ao.conf b/stargazer/inst/freebsd/etc/stargazer/conf-enabled.d/mod_ao.conf
deleted file mode 120000 (symlink)
index fe7a6f5..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../conf-available.d/mod_ao.conf
\ No newline at end of file
diff --git a/stargazer/inst/freebsd/etc/stargazer/conf-enabled.d/mod_cap_bpf.conf b/stargazer/inst/freebsd/etc/stargazer/conf-enabled.d/mod_cap_bpf.conf
deleted file mode 120000 (symlink)
index d9ec552..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../conf-available.d/mod_cap_bpf.conf
\ No newline at end of file
diff --git a/stargazer/inst/freebsd/etc/stargazer/conf-enabled.d/mod_ia.conf b/stargazer/inst/freebsd/etc/stargazer/conf-enabled.d/mod_ia.conf
deleted file mode 120000 (symlink)
index 3dea06d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../conf-available.d/mod_ia.conf
\ No newline at end of file
diff --git a/stargazer/inst/freebsd/etc/stargazer/conf-enabled.d/mod_ping.conf b/stargazer/inst/freebsd/etc/stargazer/conf-enabled.d/mod_ping.conf
deleted file mode 120000 (symlink)
index 0d6db18..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../conf-available.d/mod_ping.conf
\ No newline at end of file
diff --git a/stargazer/inst/freebsd/etc/stargazer/conf-enabled.d/mod_sg.conf b/stargazer/inst/freebsd/etc/stargazer/conf-enabled.d/mod_sg.conf
deleted file mode 120000 (symlink)
index 7ab2476..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../conf-available.d/mod_sg.conf
\ No newline at end of file
diff --git a/stargazer/inst/freebsd/etc/stargazer/conf-enabled.d/store_files.conf b/stargazer/inst/freebsd/etc/stargazer/conf-enabled.d/store_files.conf
deleted file mode 120000 (symlink)
index cb4e4da..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../conf-available.d/store_files.conf
\ No newline at end of file
diff --git a/stargazer/inst/freebsd/etc/stargazer/rules b/stargazer/inst/freebsd/etc/stargazer/rules
deleted file mode 100644 (file)
index 1042010..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-ALL     192.168.0.0/16  DIR1
-ALL     10.0.0.0/8      DIR2
-ALL     0.0.0.0/0       DIR0
\ No newline at end of file
diff --git a/stargazer/inst/freebsd/etc/stargazer/stargazer.conf b/stargazer/inst/freebsd/etc/stargazer/stargazer.conf
deleted file mode 100644 (file)
index bb8ee7c..0000000
+++ /dev/null
@@ -1,231 +0,0 @@
-################################################################################
-#                        Stargazer Configuration file                          #
-################################################################################
-
-# LOG file name
-# Parameter: required
-# Value: file path
-# Default: /var/log/stargazer.log
-LogFile = /var/log/stargazer.log
-
-# PID file name
-# Parameter: optional
-# Value: file path
-# Default: /var/run/stargazer.pid
-PIDFile = /var/run/stargazer.pid
-
-# Traffic classification rules
-# Parameter: required
-# Value: file path
-# Default: /etc/stargazer/rules
-Rules = /etc/stargazer/rules
-
-# The time interval between writing detailed user's statistics into the database
-# Note: With a large number of users this value should be increased,
-# since writting into the database can take a long time.
-# Parameter: required
-# Values: 1 (hourly), 1/2 (every half hour), 1/4 (every 15 m), 1/6 (every 10 m)
-# Default: 1/2
-DetailStatWritePeriod = 1/2
-
-# The time interval between writing summary user's statistics into the database
-# Parameter: optional
-# Value: 1 ... 1440 (minutes)
-# Default: 10
-StatWritePeriod = 10
-
-# Day of charging fee
-# Note: 0 - The last day of the month
-# Parameter: required
-# Value: 0 ... 31
-# Default: 1
-DayFee = 1
-
-# When set to 'no' Stargazer will continue reading database after error and show all of them.
-# Parameter: optional
-# Values: yes, no
-# Default: yes
-# StopOnError = yes
-
-# Fee charged at the last (yes) or first (no) day of tariffication period.
-# Defines how the fee will be charged in the transition to the new tariff.
-# User has tariff A with fee 100. Changing it to tariff B with fee 200
-# will result in charging user's account at 100 if DayFeeIsLastDay = yes 
-# and at 200, if DayFeeIsLastDay = no
-# Parameter: required
-# Values: yes, no
-# Default: no
-DayFeeIsLastDay = no
-
-# Day of changing delayed tariffs and resetting summary user's statistics.
-# Defines the edge of the tariffication period.
-# Parameter: required
-# Value: 0 ... 31. 0 - The last day of the month
-# Default: 1
-DayResetTraff = 1
-
-# Defines whether to charge fee daily (yes) or monthly (no)
-# Parameter: required
-# Values: yes, no
-# Default: no
-SpreadFee = no
-
-# Defines whether the user can access the internet if it has no cash,
-# but remained prepaid traffic
-# Parameter: required
-# Values: yes, no
-# Default: no
-FreeMbAllowInet = no
-
-# Defines what will be written in the traffic cost in detail_stat.
-# If user still has the prepaid traffic and WriteFreeMbTraffCost = no,
-# then the traffic cost willn't be written in detail_stat.
-# If user doestn't have prepaid traffic and WriteFreeMbTraffCost = no, 
-# then the traffic cost will be written in detail_stat.
-# When WriteFreeMbTraffCost = yes the traffic cost will be recorded in any case.
-# Parameter: required
-# Values: yes, no
-# Default: yes
-WriteFreeMbTraffCost = yes
-
-# Charge a full monthly fee even if user was "frozen" a part 
-# of the tariffication period
-# Parameter: optional
-# Values: yes, no
-# Default: no
-FullFee = no
-
-# Allow user to see and use a full cash (yes) or hide a part of it (no) 
-# for the next fee charge
-# Parameter: optional
-# Values: yes, no
-# Default: yes
-# ShowFeeInCash=yes
-
-# The names of directions. Direction without names will not appear in
-# authorizer and configurator.
-# Note: Names consisting of several words should be quoted
-# Parameter: optional
-# Values:
-<DirNames>
-    DirName0 = Internet
-    DirName1 =
-    DirName2 =
-    DirName3 =
-    DirName4 =
-    DirName5 =
-    DirName6 =
-    DirName7 =
-    DirName8 =
-    DirName9 =
-</DirNames>
-
-# Amount of stg-exec processes.
-# These processes are responsible for the execution of scripts OnConnect, 
-# OnDisconnect, etc. 
-# Amount of processes means how many scripts can be executed simultaneously.
-# Recommend to leave 1 to avoid errors when executing scripts
-# Parameter: optional
-# Value: 1 ... 1024
-# Default: 1
-ExecutersNum = 1
-
-# Message queue identifier for the script executer.
-# It may be changed if there're a needs to run multiple copies of stargazer.
-# Warning: If you do not understand it, do not touch this setting!
-# Parameter: optional
-# Value: 0 ... 2 ^ 32
-# Default: 5555
-# ExecMsgKey = 5555
-
-# The path to directory with server modules
-# Parameter: required
-# Value: directory path
-# Default: /usr/lib/stg
-ModulesPath = /usr/lib/stg
-
-# Directory where the "monitor" files are located.
-# A blank files will be created in this directory. The modification time of such
-# files will be changed about once a minute. If server crashes or some of server 
-# component hang, the files will stop refreshing, and on this basis we can define
-# the failure of the server and if necessary restart. 
-# If option is omitted or blank, the monitoring is not performed.
-# Parameter: optional
-# Value: file path
-# Default: /var/stargazer/monitor
-#MonitorDir=/var/stargazer/monitor
-
-# Defines message maximum lifetime
-# Note: 0 - unlimited
-# Parameter: optional
-# Value: any numeric
-# Default: 0 (day)
-# MessagesTimeout = 0
-
-# Defines fee charging rules.
-# 0 - classic rules, allow fee charge even cash is negative;
-# 1 - disallow fee charge if cash value is negative;
-# 2 - disallow fee charge if there is not enought cash (cash < fee).
-# Parameter: optional
-# Value: 0 ... 2
-# Default: 0 (classic)
-# FeeChargeType = 0
-
-# Enable or disable reconnect on tariff change
-# Parameter: optional
-# Values: yes, no
-# Default: no
-# ReconnectOnTariffChange = no
-
-# Definest set of parameters passed to OnConnect and OnDisconnect scripts
-# This set is added to the end of the default param list, which are, respectively:
-# login, ip, cash, id, dirs
-# Valid parameter names: "cash", "upload", "download", "lastCashAdd", "passiveTime",
-# "lastCashAddTime", "freeMb", "lastActivityTime", "password", "passive", "disabled",
-# "disabledDetailStat", "alwaysOnline", "tariffName", "nextTariff", "address",
-# "note", "group", "email", "phone", "realName", "credit", "creditExpire", "ips",
-# "userdata0" ... "userdata9".
-# Parameter: optional
-# Values: parameter names, case insensitive
-# Default:
-# ScriptParams =
-
-# Enable or disable writing session log
-# Parameter: optional
-# Values: yes, no
-# Default: no (session log is enabled)
-# DisableSessionLog = no
-
-# Filter for logging parameter changes
-# Defines which parameters will be logged to parameter log in database. Allows
-# to specify multiuple parameter names or asterisk (*), which means "log all params".
-# Valid parameter names: "cash", "upload", "download", "lastCashAdd", "passiveTime",
-# "lastCashAddTime", "freeMb", "lastActivityTime", "password", "passive", "disabled",
-# "disabledDetailStat", "alwaysOnline", "tariffName", "nextTariff", "address",
-# "note", "group", "email", "phone", "realName", "credit", "creditExpire", "ips",
-# "userdata0" ... "userdata9".
-# Parameter: optional
-# Values: parameter names, case insensitive, or "*"
-# Default: *
-# FilterParamsLog = *
-
-################################################################################
-# Store module
-# Configure the module that works with the database server
-
-# Warning: Only one store module could be used at the same time!
-
-<IncludeFile "conf-enabled.d/store_*.conf">
-</IncludeFile>
-
-
-################################################################################
-# Other modules
-
-<Modules>
-
-    <IncludeFile "conf-enabled.d/mod_*.conf">
-    </IncludeFile>
-
-</Modules>
-################################################################################
diff --git a/stargazer/inst/linux/etc/init.d/stargazer.gentoo b/stargazer/inst/linux/etc/init.d/stargazer.gentoo
deleted file mode 100755 (executable)
index daa0fd6..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/sbin/runscript
-
-extra_commands="reload"
-
-DAEMON=/usr/sbin/stargazer
-STARGAZER_OPTS=""
-PIDFILE=/var/run/stargazer.pid
-
-depend() {
-       need net
-       use postgresql firebird mysql
-       provide stargazer
-}
-
-start() {
-       ebegin "Starting stargazer"
-       start-stop-daemon --start --quiet --pidfile ${PIDFILE} --exec ${DAEMON} -- ${STARGAZER_OPTS}
-       eend $?
-}
-
-stop() {
-       ebegin "Stopping stargazer"
-       start-stop-daemon --stop --quiet --pidfile ${PIDFILE} --retry=INT/120/KILL/5
-       rm -f ${PIDFILE}
-       eend $?
-}
-
-reload() {
-       ebegin "Reloading stargazer rules"
-       start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE
-       return 0
-       eend $?
-}
diff --git a/stargazer/inst/linux/etc/init.d/stargazer.suse.9.3 b/stargazer/inst/linux/etc/init.d/stargazer.suse.9.3
deleted file mode 100755 (executable)
index 49a50da..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/bin/bash
-#
-# processname: stargazer
-# config: /etc/stargazer/stargazer.conf
-# pidfile: /var/run/stargazer.pid
-
-# Source function library.
-. /etc/init.d/functions
-
-# Source networking configuration.
-. /etc/sysconfig/network
-
-# Source stargazer configureation.
-DAEMON=yes
-QUEUE=1h
-
-# Check that networking is up.
-[ ${NETWORKING} = "no" ] && exit 0
-
-[ -f /sbin/stargazer ] || exit 0
-
-RETVAL=0
-prog="stargazer"
-
-start() {
-       # Start daemons.
-
-       echo -n $"Starting $prog: "
-       /etc/stargazer/first 2> /dev/null
-       daemon /sbin/stargazer
-       RETVAL=$?
-       /etc/stargazer/last 2> /dev/null
-       echo
-       [ $RETVAL -eq 0 ] && touch /var/lock/subsys/stargazer
-       return $RETVAL
-}
-
-stop() {
-       # Stop daemons.
-       echo -n $"Shutting down $prog: "
-       killproc stargazer
-       RETVAL=$?
-       echo
-       [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/stargazer
-       return $RETVAL
-}
-
-# See how we were called.
-case "$1" in
-  start)
-       start
-       ;;
-  stop)
-       stop
-       ;;
-  restart|reload)
-       stop
-       start
-       RETVAL=$?
-       ;;
-  status)
-       status stargazer
-       RETVAL=$?
-       ;;
-  *)
-       echo $"Usage: $0 {start|stop|restart|status}"
-       exit 1
-esac
-
-exit $RETVAL
diff --git a/stargazer/inst/linux/etc/init.d/stargazer.ubuntu.7.10 b/stargazer/inst/linux/etc/init.d/stargazer.ubuntu.7.10
deleted file mode 100755 (executable)
index a5ed971..0000000
+++ /dev/null
@@ -1,152 +0,0 @@
-#! /bin/sh
-### BEGIN INIT INFO
-# Provides:          stargazer
-# Required-Start:    $local_fs $remote_fs
-# Required-Stop:     $local_fs $remote_fs
-# Default-Start:     2 3 4 5
-# Default-Stop:      S 0 1 6
-# Short-Description: Stargazer initscript
-# Description:       This file should be used to start and stop stargazer daemon
-### END INIT INFO
-
-# Author: Boris Mikhailenko <stg34@stg.dp.ua>
-
-# Do NOT "set -e"
-
-# PATH should only include /usr/* if it runs after the mountnfs.sh script
-PATH=/usr/sbin:/usr/bin:/sbin:/bin
-DESC="Billing system"
-NAME=stargazer
-DAEMON=/usr/sbin/$NAME
-DAEMON_ARGS=""
-PIDFILE=/var/run/$NAME.pid
-SCRIPTNAME=/etc/init.d/$NAME
-
-# Exit if the package is not installed
-[ -x "$DAEMON" ] || exit 0
-
-# Read configuration variable file if it is present
-[ -r /etc/default/$NAME ] && . /etc/default/$NAME
-
-# Load the VERBOSE setting and other rcS variables
-[ -f /etc/default/rcS ] && . /etc/default/rcS
-
-# Define LSB log_* functions.
-# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
-. /lib/lsb/init-functions
-
-#
-# Function that starts the daemon/service
-#
-do_start()
-{
-       # Return
-       #   0 if daemon has been started
-       #   1 if daemon was already running
-       #   2 if daemon could not be started
-       start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
-               || return 1
-               
-       # ps x | grep $DAEMON | grep -v grep | cut -f1 -d" " > $PIDFILE
-               
-       start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
-               $DAEMON_ARGS \
-               || return 2
-       
-       # ps x | grep $DAEMON | grep -v grep | cut -f1 -d" " > $PIDFILE
-       # Add code here, if necessary, that waits for the process to be ready
-       # to handle requests from services started subsequently which depend
-       # on this one.  As a last resort, sleep for some time.
-}
-
-#
-# Function that stops the daemon/service
-#
-do_stop()
-{
-       # Return
-       #   0 if daemon has been stopped
-       #   1 if daemon was already stopped
-       #   2 if daemon could not be stopped
-       #   other if a failure occurred
-       start-stop-daemon --stop --quiet --retry=INT/60/KILL/5 --pidfile $PIDFILE --name $NAME
-       RETVAL="$?"
-       [ "$RETVAL" = 2 ] && return 2
-       # Wait for children to finish too if this is a daemon that forks
-       # and if the daemon is only ever run from this initscript.
-       # If the above conditions are not satisfied then add some other code
-       # that waits for the process to drop all resources that could be
-       # needed by services started subsequently.  A last resort is to
-       # sleep for some time.
-       start-stop-daemon --stop --quiet --oknodo --retry=0/60/KILL/5 --exec $DAEMON
-       [ "$?" = 2 ] && return 2
-       # Many daemons don't delete their pidfiles when they exit.
-       rm -f $PIDFILE
-       return "$RETVAL"
-}
-
-#
-# Function that sends a SIGHUP to the daemon/service
-#
-do_reload() {
-       # If the daemon can reload its configuration without
-       # restarting (for example, when it is sent a SIGHUP),
-       # then implement that here.
-       start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
-       return 0
-}
-
-case "$1" in
-  start)
-       [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
-       do_start
-       case "$?" in
-               0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
-               2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
-       esac
-       ;;
-  stop)
-       [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
-       do_stop
-       case "$?" in
-               0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
-               2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
-       esac
-       ;;
-  reload)
-       # If do_reload() is not implemented then leave this commented out
-       # and leave 'force-reload' as an alias for 'restart'.
-       log_daemon_msg "Reloading $DESC" "$NAME"
-       do_reload
-       log_end_msg $?
-       ;;
-  restart)
-       #
-       # If the "reload" option is implemented then remove the
-       # 'force-reload' alias
-       #
-       log_daemon_msg "Restarting $DESC" "$NAME"
-       do_stop
-       case "$?" in
-         0|1)
-               do_start
-               case "$?" in
-                       0) log_end_msg 0 ;;
-                       1) log_end_msg 1 ;; # Old process is still running
-                       *) log_end_msg 1 ;; # Failed to start
-               esac
-               ;;
-         *)
-               # Failed to stop
-               log_end_msg 1
-               ;;
-       esac
-       ;;
-  *)
-       #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
-       echo "Usage: $SCRIPTNAME {start|stop|restart|reload}" >&2
-       exit 3
-       ;;
-esac
-
-:
diff --git a/stargazer/inst/linux/etc/stargazer/OnChange b/stargazer/inst/linux/etc/stargazer/OnChange
deleted file mode 100755 (executable)
index c1ad6a6..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#! /bin/sh
-
-# About: This script is called when user account is changed.
-# Common Task: Notify about various events.
-# Priority: optional
-
-# User login
-LOGIN=$1
-
-# User parameter
-PARAMETER=$2
-
-# User parameter old value
-OLDVALUE=$3
-
-# User parameter new value
-NEWVALUE=$4
-
-# Usage examples:
-#echo "User: '$LOGIN'. Parameter $PARAMETER changed from '$OLDVALUE' to '$NEWVALUE'" >> /var/stargazer/user.change.log
\ No newline at end of file
diff --git a/stargazer/inst/linux/etc/stargazer/OnConnect b/stargazer/inst/linux/etc/stargazer/OnConnect
deleted file mode 100755 (executable)
index cb1f64f..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#! /bin/sh
-
-# About: This script is called when the user successfully authenticated on the server.
-# Common Task: Rebuild firewall to allow user to access the Internet.
-# Priority: required
-
-# User login
-LOGIN=$1
-
-# User IP
-IP=$2
-
-# User cash
-CASH=$3
-
-# User ID
-ID=$4
-
-# Selected DIRs (from rules file) to connect
-DIRS=$5
-
-# Usage examples:
-#echo "Connected `date +%Y.%m.%d-%H.%M.%S` $IP $CASH" >> /var/stargazer/users/$LOGIN/connect.log
\ No newline at end of file
diff --git a/stargazer/inst/linux/etc/stargazer/OnDisconnect b/stargazer/inst/linux/etc/stargazer/OnDisconnect
deleted file mode 100755 (executable)
index 64a6c51..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#! /bin/sh
-
-# About: This script is called when the user wants to disconnect or authorization timeout has passed.
-# Common task: Rebuild firewall to disallow user to access the Internet.
-# Priority: required
-
-# User login
-LOGIN=$1
-
-# User IP
-IP=$2
-
-# User cash
-CASH=$3
-
-# User ID
-ID=$4
-
-# Selected DIRs (from rules file) to disconnect
-DIRS=$5
-
-# Usage examples:
-#echo "Disconnected `date +%Y.%m.%d-%H.%M.%S` $IP $CASH" >> /var/stargazer/users/$LOGIN/connect.log
diff --git a/stargazer/inst/linux/etc/stargazer/OnUserAdd b/stargazer/inst/linux/etc/stargazer/OnUserAdd
deleted file mode 100755 (executable)
index 2dcc056..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#! /bin/sh
-
-# About: This script is called when the user is added to the Stargazer.
-# Common task: Automate typical actions on adding user to the network,
-#              such as creating email or IM account.
-# Priority: optional
-
-# User login
-LOGIN=$1
-
-# Usage examples:
-#echo "Added user $login" >> /var/stargazer/add_del.log
\ No newline at end of file
diff --git a/stargazer/inst/linux/etc/stargazer/OnUserDel b/stargazer/inst/linux/etc/stargazer/OnUserDel
deleted file mode 100755 (executable)
index a72da15..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#! /bin/sh
-
-# About: This script is called when the user is removed from the Stargazer.
-# Common task: Automate typical actions on removing user from the network,
-#              such as removing email or IM account.
-# Priority: optional
-
-# User login
-LOGIN=$1
-
-# Usage examples:
-#echo "Deleted user $LOGIN" >> /var/stargazer/add_del.log
-
diff --git a/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_ao.conf b/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_ao.conf
deleted file mode 100644 (file)
index 62c0dc7..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-# Enable the authorization module Always Online "mod_auth_ao.so"
-<Module auth_ao>
-</Module>
\ No newline at end of file
diff --git a/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_cap_ether.conf b/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_cap_ether.conf
deleted file mode 100644 (file)
index 677ed5a..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-# Enable the traffic capture module "mod_cap_ether.so" using Packet-sockets
-<Module cap_ether>
-</Module>
\ No newline at end of file
diff --git a/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_cap_ipq.conf b/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_cap_ipq.conf
deleted file mode 100644 (file)
index 6b4b3c0..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-# Enable the traffic capture module "mod_cap_ipq.so" using mechanism of IP Queueing
-<Module cap_ipq>
-</Module>
\ No newline at end of file
diff --git a/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_cap_nf.conf b/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_cap_nf.conf
deleted file mode 100644 (file)
index 948674c..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-# Enable the traffic capture module "mod_cap_ipq.so" using NetFlow protocol
-<Module cap_nf>
-    # Port for TCP connections
-    # Note: Parameters TCPPort and UDPPort can be equal
-    # Parameter: optional
-    # Value: 1 ... 65535
-    # Default: 9996
-    #TCPPort = 9996
-
-    # Port for UDP connections
-    # Note: Parameters TCPPort and UDPPort can be equal
-    # Parameter: optional
-    # Value: 1 ... 65535
-    # Default: 9996
-    UDPPort = 9996
-</Module>
diff --git a/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_ia.conf b/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_ia.conf
deleted file mode 100644 (file)
index df170dd..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-# Enable the authorization module InetAccess "mod_auth_ia.so"
-<Module auth_ia>
-    # Port on which the server interacts with authorizator
-    # Parameter: required
-    # Value: 1 ... 65535
-    # Default: 5555
-    Port = 5555
-
-    # The time interval between sending an alive query to the user
-    # and updating statistics
-    # Parameter: required
-    # Values: 5 ... 600 (seconds)
-    # Default: 60
-    UserDelay = 60
-
-    # User timeout. If authorizer does not respond during this time,
-    # the user will be disconnected
-    # Parameter: required
-    # Values: 5 ... 600
-    # Default: 60
-    UserTimeout = 65
-
-    # Define which information will be transmitted from the server to InetAccess
-    # as a residue of prepaid traffic
-    # FreeMb = 0 — amount of free megabytes in terms of cost of zero direction
-    # FreeMb = 1 — amount of free megabytes in terms of cost of the first direction
-    # FreeMb = 1 — amount of free megabytes in terms of cost of the first direction
-    # FreeMb = 2 — amount of free megabytes in terms of cost of the second direction
-    # ........................
-    # FreeMb = 9 — amount of free megabytes in terms of cost of the ninth direction
-    # FreeMb = cash - amount of money for which the user can download for free
-    # FreeMb = none - no transfer
-    # Default: cash
-    # Parameter: required
-    # Values: different, see above
-    # Default: cash
-    FreeMb = cash
-
-    # Enable protocol errors logging
-    # Parameter: optional
-    # Values: yes, no
-    # Default: no
-    # LogProtocolErrors = no
-</Module>
diff --git a/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_ping.conf b/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_ping.conf
deleted file mode 100644 (file)
index 7402219..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# Enable the module that pings users "mod_ping.so"
-<Module ping>
-    # The time interval between pings
-    # Parameter: required
-    # Value: 10 ... 3600 (seconds)
-    # Default: 15
-    PingDelay = 15
-</Module>
\ No newline at end of file
diff --git a/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_radius.conf b/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_radius.conf
deleted file mode 100644 (file)
index edc94d5..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-# Enable the interaction module for FreeRADIUS "mod_radius.so"
-<Module radius>
-    # FreeRADIUS password
-    # Parameter: required
-    # Values: any, supported by software
-    # Default: 123456
-    Password = 123456
-
-    # FreeRADIUS server
-    # Parameter: required
-    # Values: IP address or DNS name
-    # Default: 127.0.0.1
-    ServerIP = 127.0.0.1
-
-    # FreeRADIUS port
-    # Parameter: required
-    # Value: 1 ... 65535
-    # Default: 6666
-    Port = 6666
-
-    # List of services for which will be carried out FreeRADIUS authentication 
-    # Note: Parameter can be blank
-    # Parameter: required
-    # Value: any, supported by software
-    # Default: Login-User
-    AuthServices = Login-User
-
-    # List of services for which will be carried out FreeRADIUS Accounting
-    # Note: Parameter can be blank
-    # Parameter: required
-    # Value: any, supported by software
-    # Default: Framed-User
-    AcctServices = Framed-User
-</Module>
\ No newline at end of file
diff --git a/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_remote_script.conf b/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_remote_script.conf
deleted file mode 100644 (file)
index a71350c..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-# Enable the module for remote execution of scripts OnConnect and OnDisconnect "mod_remote_script.so"
-<Module remote_script>
-    # The time interval between sending confirmations that the user is online
-    # Parametr: required
-    # Values: 10 ... 600 (seconds)
-    # Default: 60
-    SendPeriod = 15
-
-    # Define mapping between subnet(s) and remote server(s)
-    # File format: <subnet> <Router1> <Router2> ...
-    # Example:
-    # 192.168.1.0/24 192.168.1.7 192.168.1.8
-    # 192.168.2.0/24 192.168.2.5 192.168.2.6 192.168.2.7
-    # 192.168.3.0/24 192.168.3.5
-    # 192.168.4.0/24 192.168.4.5
-    # Parametr: required
-    # Values: file path
-    # Default: subnets
-    SubnetFile = subnets
-
-    # The password to encrypt packets between the stg-server and remote server
-    # Parameter: required
-    # Values: any
-    # Default: 123456
-    Password = 123456
-
-    # Define which user parameters are transferred to a remote server in addition to
-    # other parameters that transfered by default (ID, IP, Login, Cash, Dirs).
-    # Note: Parameter can be blank. 
-    # Parameter: required  
-    # Values: Cash, FreeMb, Passive, Disabled, AlwaysOnline, TariffName, 
-    # NextTariff, Address, Note, Group, Email, RealName, Credit, EnabledDirs, 
-    # Userdata0...Userdata9
-    # Default: Cash Tariff EnabledDirs
-    UserParams = Cash Tariff EnabledDirs
-
-    # Port on which the server interacts with remote server
-    # Parameter: required
-    # Value: 1...65535
-    # Default: 9999
-    Port = 9999
-</Module>
diff --git a/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_rpc.conf b/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_rpc.conf
deleted file mode 100644 (file)
index b05695a..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-# Enable the configuration module ConfRPC "mod_conf_rpc.so"
-<Module conf_rpc>
-    # Port on which the server interacts with configurator
-    # Parameter: required
-    # Value: 1...65535
-    # Default:
-    Port = 8080
-
-    # Session timeout in seconds
-    # Parameter: required
-    # Value: positive integer
-    # Default: 1800
-    CookieTimeout = 1800
-</Module>
diff --git a/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_sg.conf b/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_sg.conf
deleted file mode 100644 (file)
index 610a312..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# Enable the configuration module SgConfig "mod_conf_sg.so"
-<Module conf_sg>
-    # Port on which the server interacts with configurator
-    # Parameter: required
-    # Value: 1...65535
-    # Default: 5555
-    Port = 5555
-</Module>
\ No newline at end of file
diff --git a/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_smux.conf b/stargazer/inst/linux/etc/stargazer/conf-available.d/mod_smux.conf
deleted file mode 100644 (file)
index 84ce24b..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-# Enables SMUX-peer for SNMPd.
-<Module smux>
-    # IP-address of a server to connect to
-    # Parameter: required
-    # Value: X.X.X.X
-    # Default: 127.0.0.1
-    Server = 127.0.0.1
-
-    # Port number on a server to connect to
-    # Parameter: required
-    # Value: 1 ... 65535
-    # Default: 199
-    Port = 199
-
-    # Password for authentication on a server
-    # Parameter: required
-    # Value: any text
-    Password =
-</Module>
diff --git a/stargazer/inst/linux/etc/stargazer/conf-available.d/store_files.conf b/stargazer/inst/linux/etc/stargazer/conf-available.d/store_files.conf
deleted file mode 100644 (file)
index f7e0f23..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-# Enables plain file backend.
-<StoreModule store_files>
-
-    # Working server directory, provides data on tariffs, users, administrators.
-    # Parameter: required
-    # Value: directory path
-    WorkDir = /var/stargazer
-
-    # Owner, group and permissions of the files of user statistics (stat)
-    # Parameter: required
-    # Values: any, supported by OS
-    ConfOwner = root
-    ConfGroup = root
-    ConfMode = 640
-
-    # Owner, group and permissions on user configuration files (conf)
-    # Parameter: required
-    # Values: any, supported by OS
-    StatOwner = root
-    StatGroup = root
-    StatMode = 640
-
-    # Owner, group and permissions for user log files (log)
-    # Parameter: required
-    # Values: any, supported by OS
-    UserLogOwner = root
-    UserLogGroup = root
-    UserLogMode = 640
-
-</StoreModule>
diff --git a/stargazer/inst/linux/etc/stargazer/conf-available.d/store_firebird.conf b/stargazer/inst/linux/etc/stargazer/conf-available.d/store_firebird.conf
deleted file mode 100644 (file)
index 39e4ad3..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-# Enables Firebird backend.
-<StoreModule store_firebird>
-    # Database server address
-    # Parameter: optional
-    # Value: IP address or DNS name
-    # Default: localhost
-    # Server = localhost
-
-    # Path to the database on the server or its alias
-    # Parameter: optional
-    # Value: file path
-    # Default: /var/stg/stargazer.fdb
-    # Database = /var/stg/stargazer.fdb
-
-    # Database username
-    # Parameter: optional
-    # Value: any, supported by database
-    # Default: stg
-    # User = stg
-
-    # Database password
-    # Parameter: optional
-    # Value: any, supported by database
-    # Default: 123456
-    # Password = 123456
-
-    # The transaction isolation level
-    # Parameter: optional
-    # Values: concurrency, dirtyread, readcommitted, consistency
-    # Defalt: concurrency
-    # IsolationLevel = concurrency
-
-    # Responding to lock (optional, defaults to wait):
-    # Parameter: optional
-    # Values: wait, nowait
-    # Defalt: wait
-    # LockResolution = wait
-</StoreModule>
diff --git a/stargazer/inst/linux/etc/stargazer/conf-available.d/store_mysql.conf b/stargazer/inst/linux/etc/stargazer/conf-available.d/store_mysql.conf
deleted file mode 100644 (file)
index a5b2126..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-# Enables MySQL backend.
-<StoreModule store_mysql>
-    # Database server address
-    # Parameter: required
-    # Value: IP address or DNS name
-    # Default: localhost
-    Server = localhost
-
-    # Database name
-    # Parameter: required
-    # Value: any, supported by database
-    # Default: stg
-    Database = stg
-
-    # Database username
-    # Parameter: required
-    # Value: any, supported by database
-    # Default: stg
-    User = stg
-
-    # Database password
-    # Parameter: required
-    # Value: any, supported by database
-    # Default: 123456
-    Password = 123456
-</StoreModule>
diff --git a/stargazer/inst/linux/etc/stargazer/conf-available.d/store_postgresql.conf b/stargazer/inst/linux/etc/stargazer/conf-available.d/store_postgresql.conf
deleted file mode 100644 (file)
index 8a52c75..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-# Enables PostgreSQL backend.
-<StoreModule store_postgresql>
-    # Database server address
-    # Parameter: optional
-    # Value: IP address or DNS name
-    # Default: localhost
-    # Server = localhost
-
-    # Database name
-    # Parameter: optional
-    # Value: any, supported by database
-    # Default: stargazer
-    # Database = stargazer
-
-    # Database username
-    # Parameter: optional
-    # Value: any, supported by database
-    # Default: stg
-    # User = stg
-
-    # Database password
-    # Parameter: optional
-    # Value: any, supported by database
-    # Default: 123456
-    # Password = 123456
-
-    # Number of tries to reconnect
-    # Parameter: optional
-    # Value: positive integer
-    # Default: 3
-    # Retries = 3
-</StoreModule>
diff --git a/stargazer/inst/linux/etc/stargazer/conf-enabled.d/mod_ao.conf b/stargazer/inst/linux/etc/stargazer/conf-enabled.d/mod_ao.conf
deleted file mode 120000 (symlink)
index fe7a6f5..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../conf-available.d/mod_ao.conf
\ No newline at end of file
diff --git a/stargazer/inst/linux/etc/stargazer/conf-enabled.d/mod_cap_ether.conf b/stargazer/inst/linux/etc/stargazer/conf-enabled.d/mod_cap_ether.conf
deleted file mode 120000 (symlink)
index b929151..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../conf-available.d/mod_cap_ether.conf
\ No newline at end of file
diff --git a/stargazer/inst/linux/etc/stargazer/conf-enabled.d/mod_ia.conf b/stargazer/inst/linux/etc/stargazer/conf-enabled.d/mod_ia.conf
deleted file mode 120000 (symlink)
index 3dea06d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../conf-available.d/mod_ia.conf
\ No newline at end of file
diff --git a/stargazer/inst/linux/etc/stargazer/conf-enabled.d/mod_ping.conf b/stargazer/inst/linux/etc/stargazer/conf-enabled.d/mod_ping.conf
deleted file mode 120000 (symlink)
index 0d6db18..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../conf-available.d/mod_ping.conf
\ No newline at end of file
diff --git a/stargazer/inst/linux/etc/stargazer/conf-enabled.d/mod_sg.conf b/stargazer/inst/linux/etc/stargazer/conf-enabled.d/mod_sg.conf
deleted file mode 120000 (symlink)
index 7ab2476..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../conf-available.d/mod_sg.conf
\ No newline at end of file
diff --git a/stargazer/inst/linux/etc/stargazer/conf-enabled.d/store_files.conf b/stargazer/inst/linux/etc/stargazer/conf-enabled.d/store_files.conf
deleted file mode 120000 (symlink)
index cb4e4da..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../conf-available.d/store_files.conf
\ No newline at end of file
diff --git a/stargazer/inst/linux/etc/stargazer/rules b/stargazer/inst/linux/etc/stargazer/rules
deleted file mode 100644 (file)
index 1042010..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-ALL     192.168.0.0/16  DIR1
-ALL     10.0.0.0/8      DIR2
-ALL     0.0.0.0/0       DIR0
\ No newline at end of file
diff --git a/stargazer/inst/linux/etc/stargazer/stargazer.conf b/stargazer/inst/linux/etc/stargazer/stargazer.conf
deleted file mode 100644 (file)
index bb8ee7c..0000000
+++ /dev/null
@@ -1,231 +0,0 @@
-################################################################################
-#                        Stargazer Configuration file                          #
-################################################################################
-
-# LOG file name
-# Parameter: required
-# Value: file path
-# Default: /var/log/stargazer.log
-LogFile = /var/log/stargazer.log
-
-# PID file name
-# Parameter: optional
-# Value: file path
-# Default: /var/run/stargazer.pid
-PIDFile = /var/run/stargazer.pid
-
-# Traffic classification rules
-# Parameter: required
-# Value: file path
-# Default: /etc/stargazer/rules
-Rules = /etc/stargazer/rules
-
-# The time interval between writing detailed user's statistics into the database
-# Note: With a large number of users this value should be increased,
-# since writting into the database can take a long time.
-# Parameter: required
-# Values: 1 (hourly), 1/2 (every half hour), 1/4 (every 15 m), 1/6 (every 10 m)
-# Default: 1/2
-DetailStatWritePeriod = 1/2
-
-# The time interval between writing summary user's statistics into the database
-# Parameter: optional
-# Value: 1 ... 1440 (minutes)
-# Default: 10
-StatWritePeriod = 10
-
-# Day of charging fee
-# Note: 0 - The last day of the month
-# Parameter: required
-# Value: 0 ... 31
-# Default: 1
-DayFee = 1
-
-# When set to 'no' Stargazer will continue reading database after error and show all of them.
-# Parameter: optional
-# Values: yes, no
-# Default: yes
-# StopOnError = yes
-
-# Fee charged at the last (yes) or first (no) day of tariffication period.
-# Defines how the fee will be charged in the transition to the new tariff.
-# User has tariff A with fee 100. Changing it to tariff B with fee 200
-# will result in charging user's account at 100 if DayFeeIsLastDay = yes 
-# and at 200, if DayFeeIsLastDay = no
-# Parameter: required
-# Values: yes, no
-# Default: no
-DayFeeIsLastDay = no
-
-# Day of changing delayed tariffs and resetting summary user's statistics.
-# Defines the edge of the tariffication period.
-# Parameter: required
-# Value: 0 ... 31. 0 - The last day of the month
-# Default: 1
-DayResetTraff = 1
-
-# Defines whether to charge fee daily (yes) or monthly (no)
-# Parameter: required
-# Values: yes, no
-# Default: no
-SpreadFee = no
-
-# Defines whether the user can access the internet if it has no cash,
-# but remained prepaid traffic
-# Parameter: required
-# Values: yes, no
-# Default: no
-FreeMbAllowInet = no
-
-# Defines what will be written in the traffic cost in detail_stat.
-# If user still has the prepaid traffic and WriteFreeMbTraffCost = no,
-# then the traffic cost willn't be written in detail_stat.
-# If user doestn't have prepaid traffic and WriteFreeMbTraffCost = no, 
-# then the traffic cost will be written in detail_stat.
-# When WriteFreeMbTraffCost = yes the traffic cost will be recorded in any case.
-# Parameter: required
-# Values: yes, no
-# Default: yes
-WriteFreeMbTraffCost = yes
-
-# Charge a full monthly fee even if user was "frozen" a part 
-# of the tariffication period
-# Parameter: optional
-# Values: yes, no
-# Default: no
-FullFee = no
-
-# Allow user to see and use a full cash (yes) or hide a part of it (no) 
-# for the next fee charge
-# Parameter: optional
-# Values: yes, no
-# Default: yes
-# ShowFeeInCash=yes
-
-# The names of directions. Direction without names will not appear in
-# authorizer and configurator.
-# Note: Names consisting of several words should be quoted
-# Parameter: optional
-# Values:
-<DirNames>
-    DirName0 = Internet
-    DirName1 =
-    DirName2 =
-    DirName3 =
-    DirName4 =
-    DirName5 =
-    DirName6 =
-    DirName7 =
-    DirName8 =
-    DirName9 =
-</DirNames>
-
-# Amount of stg-exec processes.
-# These processes are responsible for the execution of scripts OnConnect, 
-# OnDisconnect, etc. 
-# Amount of processes means how many scripts can be executed simultaneously.
-# Recommend to leave 1 to avoid errors when executing scripts
-# Parameter: optional
-# Value: 1 ... 1024
-# Default: 1
-ExecutersNum = 1
-
-# Message queue identifier for the script executer.
-# It may be changed if there're a needs to run multiple copies of stargazer.
-# Warning: If you do not understand it, do not touch this setting!
-# Parameter: optional
-# Value: 0 ... 2 ^ 32
-# Default: 5555
-# ExecMsgKey = 5555
-
-# The path to directory with server modules
-# Parameter: required
-# Value: directory path
-# Default: /usr/lib/stg
-ModulesPath = /usr/lib/stg
-
-# Directory where the "monitor" files are located.
-# A blank files will be created in this directory. The modification time of such
-# files will be changed about once a minute. If server crashes or some of server 
-# component hang, the files will stop refreshing, and on this basis we can define
-# the failure of the server and if necessary restart. 
-# If option is omitted or blank, the monitoring is not performed.
-# Parameter: optional
-# Value: file path
-# Default: /var/stargazer/monitor
-#MonitorDir=/var/stargazer/monitor
-
-# Defines message maximum lifetime
-# Note: 0 - unlimited
-# Parameter: optional
-# Value: any numeric
-# Default: 0 (day)
-# MessagesTimeout = 0
-
-# Defines fee charging rules.
-# 0 - classic rules, allow fee charge even cash is negative;
-# 1 - disallow fee charge if cash value is negative;
-# 2 - disallow fee charge if there is not enought cash (cash < fee).
-# Parameter: optional
-# Value: 0 ... 2
-# Default: 0 (classic)
-# FeeChargeType = 0
-
-# Enable or disable reconnect on tariff change
-# Parameter: optional
-# Values: yes, no
-# Default: no
-# ReconnectOnTariffChange = no
-
-# Definest set of parameters passed to OnConnect and OnDisconnect scripts
-# This set is added to the end of the default param list, which are, respectively:
-# login, ip, cash, id, dirs
-# Valid parameter names: "cash", "upload", "download", "lastCashAdd", "passiveTime",
-# "lastCashAddTime", "freeMb", "lastActivityTime", "password", "passive", "disabled",
-# "disabledDetailStat", "alwaysOnline", "tariffName", "nextTariff", "address",
-# "note", "group", "email", "phone", "realName", "credit", "creditExpire", "ips",
-# "userdata0" ... "userdata9".
-# Parameter: optional
-# Values: parameter names, case insensitive
-# Default:
-# ScriptParams =
-
-# Enable or disable writing session log
-# Parameter: optional
-# Values: yes, no
-# Default: no (session log is enabled)
-# DisableSessionLog = no
-
-# Filter for logging parameter changes
-# Defines which parameters will be logged to parameter log in database. Allows
-# to specify multiuple parameter names or asterisk (*), which means "log all params".
-# Valid parameter names: "cash", "upload", "download", "lastCashAdd", "passiveTime",
-# "lastCashAddTime", "freeMb", "lastActivityTime", "password", "passive", "disabled",
-# "disabledDetailStat", "alwaysOnline", "tariffName", "nextTariff", "address",
-# "note", "group", "email", "phone", "realName", "credit", "creditExpire", "ips",
-# "userdata0" ... "userdata9".
-# Parameter: optional
-# Values: parameter names, case insensitive, or "*"
-# Default: *
-# FilterParamsLog = *
-
-################################################################################
-# Store module
-# Configure the module that works with the database server
-
-# Warning: Only one store module could be used at the same time!
-
-<IncludeFile "conf-enabled.d/store_*.conf">
-</IncludeFile>
-
-
-################################################################################
-# Other modules
-
-<Modules>
-
-    <IncludeFile "conf-enabled.d/mod_*.conf">
-    </IncludeFile>
-
-</Modules>
-################################################################################
diff --git a/stargazer/inst/var/00-alter-01.postgresql.sql b/stargazer/inst/var/00-alter-01.postgresql.sql
deleted file mode 100644 (file)
index 7fd8111..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- *  DB migration from v00 to v01 (postgres)
- */
-
-ALTER TABLE tb_sessions_log ADD free_mb dm_money;
-ALTER TABLE tb_sessions_log ADD reason TEXT;
-
-DROP FUNCTION sp_add_session_log_entry ( dm_name, timestamp without time zone, dm_session_event_type, inet, dm_money);
-
-CREATE FUNCTION sp_add_session_log_entry(_login dm_name,
-                                         _event_time TIMESTAMP,
-                                         _event_type dm_session_event_type,
-                                         _ip INET,
-                                         _cash dm_money,
-                                         _free_mb dm_money,
-                                         _reason TEXT)
-RETURNS INTEGER
-AS $$
-DECLARE
-    _pk_user INTEGER;
-    _pk_session_log INTEGER;
-BEGIN
-    SELECT pk_user INTO _pk_user
-        FROM tb_users
-        WHERE name = _login;
-    IF _pk_user IS NULL THEN
-        RAISE EXCEPTION 'User % not found', _login;
-        RETURN -1;
-    END IF;
-    
-    INSERT INTO tb_sessions_log
-        (fk_user,
-         event_time,
-         event_type,
-         ip,
-         cash,
-         free_mb,
-         reason)
-    VALUES
-        (_pk_user,
-         _event_time,
-         _event_type,
-         _ip,
-         _cash,
-         _free_mb,
-         _reason);
-
-    SELECT CURRVAL('tb_sessions_log_pk_session_log_seq') INTO _pk_session_log;
-
-    RETURN _pk_session_log;
-END;
-$$ LANGUAGE plpgsql;
-
-UPDATE tb_info SET version = 6;
diff --git a/stargazer/inst/var/00-alter-01.sql b/stargazer/inst/var/00-alter-01.sql
deleted file mode 100644 (file)
index f76ae5f..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- *  DB migration from v00 to v01 (firebird)
- */
-
-alter table tb_users add disabled_detail_stat dm_bool;
-
-drop procedure sp_add_user;
-
-set term !! ;
-create procedure sp_add_user(name varchar(32), dirs integer)                             
-as  
-declare variable pk_user integer;
-declare variable pk_stat integer;                                                        
-begin                                                                                    
-    pk_user = gen_id(gn_pk_user, 1);                                                     
-    insert into tb_users(pk_user, fk_tariff, fk_tariff_change, fk_corporation, address, always_online, credit, credit_expire, disabled, disabled_detail_stat, email, grp, note, passive, passwd, phone, name, real_name) values (:pk_user, NULL, NULL, NULL, '', 0, 0, 'now', 0, 0, '', '_', '', 0, '', '', :name, '');
-    pk_stat = gen_id(gn_pk_stat, 1);                                                     
-    insert into tb_stats values (:pk_stat, :pk_user, 0, 0, 'now', 0, 'now', 0, 'now');   
-    while (dirs > 0) do
-    begin
-        insert into tb_stats_traffic (fk_stat, dir_num, upload, download) values (:pk_stat, :dirs - 1, 0, 0);
-        dirs = dirs - 1;
-    end
-end!!
-set term ; !!
diff --git a/stargazer/inst/var/00-base-00.postgresql.sql b/stargazer/inst/var/00-base-00.postgresql.sql
deleted file mode 100644 (file)
index 6b48d75..0000000
+++ /dev/null
@@ -1,644 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *****************************************************************************
- *
- * Скрипт генерации структуры базы для хранения данных Stargazer-a
- *
- * Примечание.
- *      * dm_permission_flag. Представляет собой битовую маску - rw.
- *          r - чтение, w - изменение параметра.
- *          0 - дествие запрещено, 1 - действие разрешено
- *
- *      * dm_traff_type. Число определяющее тип подсчета трафика:
- *          0 - up - считается по upload
- *          1 - down - считается по download
- *          2 - max - считается по максимальному среди upload/download
- *          3 - up+down - считается по сумме upload и download
- *
- *      * dm_session_event_type. Указывает тип записи в логе о сессии.
- *        'c' - connect, 'd' - disconnect.
- *
- *****************************************************************************
- */
-
-/*
- *  $Revision: 1.12 $
- *  $Date: 2009/08/20 14:58:43 $
- */
-
-
-/*
- *****************************************************************************
- * -= Создание типов и доменов =-
- *****************************************************************************
- */
-
-CREATE DOMAIN dm_name AS VARCHAR(32) NOT NULL;
-CREATE DOMAIN dm_password AS VARCHAR(64) NOT NULL;
-CREATE DOMAIN dm_permission_flag AS SMALLINT NOT NULL
-    CHECK ( value BETWEEN 0 AND 3 );
-CREATE DOMAIN dm_money AS NUMERIC(12, 4) NOT NULL DEFAULT 0;
-CREATE DOMAIN dm_traff_type AS SMALLINT NOT NULL
-    CHECK ( value BETWEEN 0 AND 3 );
-CREATE DOMAIN dm_day AS SMALLINT NOT NULL
-    CHECK ( value BETWEEN 0 AND 31 )
-    DEFAULT 0;
-CREATE DOMAIN dm_session_event_type AS CHAR(1) NOT NULL
-    CHECK ( value = 'c' OR value = 'd' );
-
-/*
- *****************************************************************************
- * -= Создание таблиц =-
- *****************************************************************************
- */
-
-CREATE TABLE tb_info
-(
-    version INTEGER NOT NULL
-);
-
-CREATE TABLE tb_admins
-(
-    pk_admin SERIAL PRIMARY KEY,
-    login dm_name UNIQUE,
-    passwd dm_password NOT NULL,
-    chg_conf dm_permission_flag,
-    chg_password dm_permission_flag,
-    chg_stat dm_permission_flag,
-    chg_cash dm_permission_flag,
-    usr_add_del dm_permission_flag,
-    chg_tariff dm_permission_flag,
-    chg_admin dm_permission_flag,
-    chg_service dm_permission_flag,
-    chg_corporation dm_permission_flag
-);
-
-CREATE TABLE tb_tariffs
-(
-    pk_tariff SERIAL PRIMARY KEY,
-    name dm_name UNIQUE,
-    fee dm_money,
-    free dm_money,
-    passive_cost dm_money,
-    traff_type dm_traff_type
-);
-
-CREATE TABLE tb_tariffs_params
-(
-    pk_tariff_param SERIAL PRIMARY KEY,
-    fk_tariff INTEGER NOT NULL,
-    dir_num SMALLINT NOT NULL,
-    price_day_a dm_money,
-    price_day_b dm_money,
-    price_night_a dm_money,
-    price_night_b dm_money,
-    threshold INTEGER NOT NULL,
-    time_day_begins TIME NOT NULL,
-    time_day_ends TIME NOT NULL,
-
-    FOREIGN KEY (fk_tariff)
-        REFERENCES tb_tariffs (pk_tariff)
-        ON DELETE CASCADE
-);
-
-CREATE TABLE tb_corporations
-(
-    pk_corporation SERIAL PRIMARY KEY,
-    name dm_name UNIQUE,
-    cash dm_money
-);
-
-CREATE TABLE tb_users
-(
-    pk_user SERIAL PRIMARY KEY,
-    fk_tariff INTEGER,
-    fk_tariff_change INTEGER,
-    fk_corporation INTEGER,
-    address VARCHAR(256) NOT NULL,
-    always_online BOOLEAN NOT NULL,
-    credit dm_money,
-    credit_expire TIMESTAMP NOT NULL,
-    disabled BOOLEAN NOT NULL,
-    disabled_detail_stat BOOLEAN NOT NULL,
-    email VARCHAR(256) NOT NULL,
-    grp dm_name,
-    note TEXT NOT NULL,
-    passive BOOLEAN NOT NULL,
-    passwd dm_password,
-    phone VARCHAR(256) NOT NULL,
-    name dm_name UNIQUE,
-    real_name VARCHAR(256) NOT NULL,
-    cash dm_money,
-    free_mb dm_money,
-    last_activity_time TIMESTAMP NOT NULL,
-    last_cash_add dm_money,
-    last_cash_add_time TIMESTAMP NOT NULL,
-    passive_time INTEGER NOT NULL,
-
-    FOREIGN KEY (fk_tariff)
-        REFERENCES tb_tariffs (pk_tariff)
-        ON DELETE CASCADE,
-    FOREIGN KEY (fk_tariff_change)
-        REFERENCES tb_tariffs (pk_tariff)
-        ON DELETE CASCADE,
-    FOREIGN KEY (fk_corporation)
-        REFERENCES tb_corporations (pk_corporation)
-        ON DELETE CASCADE
-);
-
-CREATE TABLE tb_detail_stats
-(
-    pk_detail_stat BIGSERIAL PRIMARY KEY,
-    fk_user INTEGER NOT NULL,
-    dir_num SMALLINT NOT NULL,
-    ip INET NOT NULL,
-    download BIGINT NOT NULL,
-    upload BIGINT NOT NULL,
-    cost dm_money,
-    from_time TIMESTAMP NOT NULL,
-    till_time TIMESTAMP NOT NULL,
-
-    FOREIGN KEY (fk_user)
-        REFERENCES tb_users (pk_user)
-        ON DELETE CASCADE
-);
-
-CREATE TABLE tb_services
-(
-    pk_service SERIAL PRIMARY KEY,
-    name dm_name UNIQUE,
-    comment TEXT NOT NULL,
-    cost dm_money,
-    pay_day dm_day
-);
-
-CREATE TABLE tb_users_services
-(
-    pk_user_service SERIAL PRIMARY KEY,
-    fk_user INTEGER NOT NULL,
-    fk_service INTEGER NOT NULL,
-
-    FOREIGN KEY (fk_user)
-        REFERENCES tb_users (pk_user)
-        ON DELETE CASCADE,
-    FOREIGN KEY (fk_service)
-        REFERENCES tb_services (pk_service)
-);
-
-CREATE TABLE tb_messages
-(
-    pk_message SERIAL PRIMARY KEY,
-    fk_user INTEGER NOT NULL,
-    ver SMALLINT NOT NULL,
-    msg_type SMALLINT NOT NULL,
-    last_send_time TIMESTAMP NOT NULL,
-    creation_time TIMESTAMP NOT NULL,
-    show_time INTEGER NOT NULL,
-    repeat SMALLINT NOT NULL,
-    repeat_period INTEGER NOT NULL,
-    msg_text TEXT NOT NULL,
-
-    FOREIGN KEY (fk_user)
-        REFERENCES tb_users (pk_user)
-        ON DELETE CASCADE
-);
-
-CREATE TABLE tb_stats_traffic
-(
-    pk_stat_traffic BIGSERIAL PRIMARY KEY,
-    fk_user INTEGER NOT NULL,
-    stats_date DATE NOT NULL,
-    dir_num SMALLINT NOT NULL,
-    download BIGINT NOT NULL,
-    upload BIGINT NOT NULL,
-
-    FOREIGN KEY (fk_user)
-        REFERENCES tb_users (pk_user)
-        ON DELETE CASCADE,
-    UNIQUE (fk_user, stats_date, dir_num)
-);
-
-CREATE TABLE tb_users_data
-(
-    pk_user_data SERIAL PRIMARY KEY,
-    fk_user INTEGER NOT NULL,
-    num SMALLINT NOT NULL,
-    data VARCHAR(256) NOT NULL,
-
-    FOREIGN KEY (fk_user)
-        REFERENCES tb_users (pk_user)
-        ON DELETE CASCADE
-);
-
-CREATE TABLE tb_allowed_ip
-(
-    pk_allowed_ip SERIAL PRIMARY KEY,
-    fk_user INTEGER NOT NULL,
-    ip INET NOT NULL,
-
-    FOREIGN KEY (fk_user)
-        REFERENCES tb_users (pk_user)
-        ON DELETE CASCADE
-);
-
-CREATE TABLE tb_sessions_log
-(
-    pk_session_log SERIAL PRIMARY KEY,
-    fk_user INTEGER NOT NULL,
-    event_time TIMESTAMP NOT NULL,
-    event_type dm_session_event_type,
-    ip INET NOT NULL,
-    cash dm_money,
-
-    FOREIGN KEY (fk_user)
-        REFERENCES tb_users (pk_user)
-        ON DELETE CASCADE
-);
-
-CREATE TABLE tb_sessions_data
-(
-    pk_session_data SERIAL PRIMARY KEY,
-    fk_session_log INTEGER NOT NULL,
-    dir_num SMALLINT NOT NULL,
-    session_upload BIGINT NOT NULL,
-    session_download BIGINT NOT NULL,
-    month_upload BIGINT NOT NULL,
-    month_download BIGINT NOT NULL,
-
-    FOREIGN KEY (fk_session_log)
-        REFERENCES tb_sessions_log (pk_session_log)
-        ON DELETE CASCADE
-);
-
-CREATE TABLE tb_parameters
-(
-    pk_parameter SERIAL PRIMARY KEY,
-    name dm_name UNIQUE
-);
-
-CREATE TABLE tb_params_log
-(
-    pk_param_log SERIAL PRIMARY KEY,
-    fk_user INTEGER NOT NULL,
-    fk_parameter INTEGER NOT NULL,
-    fk_admin INTEGER NOT NULL,
-    ip INET NOT NULL,
-    event_time TIMESTAMP NOT NULL,
-    from_val VARCHAR(256),
-    to_val VARCHAR(256),
-    comment TEXT,
-
-    FOREIGN KEY (fk_user)
-        REFERENCES tb_users (pk_user)
-        ON DELETE CASCADE,
-    FOREIGN KEY (fk_parameter)
-        REFERENCES tb_parameters (pk_parameter),
-    FOREIGN KEY (fk_admin)
-        REFERENCES tb_admins (pk_admin)
-        ON DELETE CASCADE
-);
-
-/*
- *****************************************************************************
- * -= Создание хранимых процедур =-
- *****************************************************************************
- */
-
-CREATE FUNCTION sp_add_message(_login dm_name,
-                               _ver SMALLINT,
-                               _msg_type SMALLINT,
-                               _last_send_time TIMESTAMP,
-                               _creation_time TIMESTAMP,
-                               _show_time INTEGER,
-                               _repeat SMALLINT,
-                               _repeat_period INTEGER,
-                               _msg_text TEXT)
-RETURNS INTEGER
-AS $$
-DECLARE
-    _pk_user INTEGER;
-BEGIN
-    SELECT pk_user INTO _pk_user
-        FROM tb_users
-        WHERE name = _login;
-    IF _pk_user IS NULL THEN
-        RAISE EXCEPTION 'User % not found', _login;
-        RETURN -1;
-    END IF;
-    INSERT INTO tb_messages
-        (fk_user,
-         ver,
-         msg_type,
-         last_send_time,
-         creation_time,
-         show_time,
-         repeat,
-         repeat_period,
-         msg_text)
-    VALUES
-        (_pk_user,
-         _ver,
-         _msg_type,
-         _last_send_time,
-         _creation_time,
-         _show_time,
-         _repeat,
-         _repeat_period,
-         _msg_text);
-    RETURN CURRVAL('tb_messages_pk_message_seq');
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE FUNCTION sp_add_tariff(_name dm_name, _dirs INTEGER)
-RETURNS INTEGER
-AS $$
-DECLARE
-    pk_tariff INTEGER;
-BEGIN
-    INSERT INTO tb_tariffs
-        (name,
-         fee,
-         free,
-         passive_cost,
-         traff_type)
-    VALUES
-        (_name,
-         0, 0, 0, 0);
-    SELECT CURRVAL('tb_tariffs_pk_tariff_seq') INTO pk_tariff;
-    FOR i IN 1.._dirs LOOP
-        INSERT INTO tb_tariffs_params
-            (fk_tariff,
-             dir_num,
-             price_day_a,
-             price_day_b,
-             price_night_a,
-             price_night_b,
-             threshold,
-             time_day_begins,
-             time_day_ends)
-        VALUES
-            (pk_tariff,
-             i - 1,
-             0, 0, 0, 0, 0,
-             CAST('1970-01-01 00:00:00+00' AS TIMESTAMP),
-             CAST('1970-01-01 00:00:00+00' AS TIMESTAMP));
-    END LOOP;
-    RETURN pk_tariff;
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE FUNCTION sp_add_user(_name dm_name)
-RETURNS INTEGER
-AS $$
-DECLARE
-    pk_user INTEGER;
-BEGIN
-    INSERT INTO tb_users
-        (fk_tariff,
-         fk_tariff_change,
-         fk_corporation,
-         address,
-         always_online,
-         credit,
-         credit_expire,
-         disabled,
-         disabled_detail_stat,
-         email,
-         grp,
-         note,
-         passive,
-         passwd,
-         phone,
-         name,
-         real_name,
-         cash,
-         free_mb,
-         last_activity_time,
-         last_cash_add,
-         last_cash_add_time,
-         passive_time)
-    VALUES
-        (NULL, NULL, NULL, '', FALSE, 0, CAST('now' AS TIMESTAMP),
-         FALSE, FALSE, '', '', '', FALSE, '', '', _name, '', 0, 0,
-         CAST('now' AS TIMESTAMP), 0, CAST('now' AS TIMESTAMP), 0);
-    SELECT CURRVAL('tb_users_pk_user_seq') INTO pk_user;
-    RETURN pk_user;
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE FUNCTION sp_add_stats_traffic (_login dm_name,
-                                      _stats_date DATE,
-                                      _dir_num SMALLINT,
-                                      _upload BIGINT,
-                                      _download BIGINT)
-RETURNS INTEGER
-AS $$
-DECLARE
-    _pk_user INTEGER;
-BEGIN
-    SELECT pk_user INTO _pk_user
-        FROM tb_users
-        WHERE name = _login;
-
-    IF _pk_user IS NULL THEN
-        RAISE EXCEPTION 'User % not found', _login;
-        RETURN -1;
-    END IF;
-
-    UPDATE tb_stats_traffic SET
-        upload = _upload,
-        download = _download
-    WHERE fk_user = _pk_user AND
-          dir_num = _dir_num AND
-          stats_date = _stats_date;
-
-    IF NOT FOUND THEN
-        INSERT INTO tb_stats_traffic
-            (fk_user,
-             dir_num,
-             stats_date,
-             upload,
-             download)
-        VALUES
-            (_pk_user,
-             _dir_num,
-             _stats_date,
-             _upload,
-             _download);
-    END IF;
-
-    RETURN 1;
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE FUNCTION sp_set_user_data (_pk_user INTEGER,
-                                  _num SMALLINT,
-                                  _data VARCHAR(256))
-RETURNS INTEGER
-AS $$
-BEGIN
-    UPDATE tb_users_data SET
-        data = _data
-    WHERE fk_user = _pk_user AND num = _num;
-
-    IF NOT FOUND THEN
-        INSERT INTO tb_users_data
-            (fk_user,
-             num,
-             data)
-        VALUES
-            (_pk_user,
-             _num,
-             _data);
-    END IF;
-
-    RETURN 1;
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE FUNCTION sp_add_param_log_entry(_login dm_name,
-                                       _admin_login dm_name,
-                                       _ip INET,
-                                       _param_name dm_name,
-                                       _event_time TIMESTAMP,
-                                       _from VARCHAR(256),
-                                       _to VARCHAR(256),
-                                       _comment TEXT)
-RETURNS INTEGER
-AS $$
-DECLARE
-    _pk_user INTEGER;
-    _pk_admin INTEGER;
-    _pk_param INTEGER;
-BEGIN
-    SELECT pk_user INTO _pk_user
-        FROM tb_users
-        WHERE name = _login;
-    IF _pk_user IS NULL THEN
-        RAISE EXCEPTION 'User % not found', _login;
-        RETURN -1;
-    END IF;
-
-    SELECT pk_admin INTO _pk_admin
-        FROM tb_admins
-        WHERE login = _admin_login;
-    IF _pk_admin IS NULL THEN
-        RAISE EXCEPTION 'Admin % not found', _admin_login;
-        RETURN -1;
-    END IF;
-
-    SELECT pk_parameter INTO _pk_param
-        FROM tb_parameters
-        WHERE name = _param_name;
-
-    IF NOT FOUND THEN
-        INSERT INTO tb_parameters (name) VALUES (_param_name);
-        SELECT CURRVAL('tb_parameters_pk_parameter_seq') INTO _pk_param;
-    END IF;
-
-    INSERT INTO tb_params_log
-        (fk_user,
-         fk_parameter,
-         fk_admin,
-         ip,
-         event_time,
-         from_val,
-         to_val,
-         comment)
-    VALUES
-        (_pk_user,
-         _pk_param,
-         _pk_admin,
-         _ip,
-         _event_time,
-         _from,
-         _to,
-         _comment);
-
-    RETURN 1;
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE FUNCTION sp_add_session_log_entry(_login dm_name,
-                                         _event_time TIMESTAMP,
-                                         _event_type dm_session_event_type,
-                                         _ip INET,
-                                         _cash dm_money)
-RETURNS INTEGER
-AS $$
-DECLARE
-    _pk_user INTEGER;
-    _pk_session_log INTEGER;
-BEGIN
-    SELECT pk_user INTO _pk_user
-        FROM tb_users
-        WHERE name = _login;
-    IF _pk_user IS NULL THEN
-        RAISE EXCEPTION 'User % not found', _login;
-        RETURN -1;
-    END IF;
-    
-    INSERT INTO tb_sessions_log
-        (fk_user,
-         event_time,
-         event_type,
-         ip,
-         cash)
-    VALUES
-        (_pk_user,
-         _event_time,
-         _event_type,
-         _ip,
-         _cash);
-
-    SELECT CURRVAL('tb_sessions_log_pk_session_log_seq') INTO _pk_session_log;
-
-    RETURN _pk_session_log;
-END;
-$$ LANGUAGE plpgsql;
-
-/*
- *****************************************************************************
- * -= Создание администратора =-
- *
- * Двоичные права доступа пока не поддерживаются, по этому используются флаги
- *****************************************************************************
- */
-INSERT INTO tb_admins
-    (login, passwd,
-     chg_conf, chg_password, chg_stat,
-     chg_cash, usr_add_del, chg_tariff,
-     chg_admin, chg_service, chg_corporation)
-VALUES
-    ('admin',
-     'geahonjehjfofnhammefahbbbfbmpkmkmmefahbbbfbmpkmkmmefahbbbfbmpkmk',
-     1, 1, 1, 1, 1, 1, 1, 1, 1);
-INSERT INTO tb_admins
-    (login, passwd,
-     chg_conf, chg_password, chg_stat,
-     chg_cash, usr_add_del, chg_tariff,
-     chg_admin, chg_service, chg_corporation)
-VALUES
-    ('@stargazer',
-     '',
-     0, 0, 0, 0, 0, 0, 0, 0, 0);
-
-INSERT INTO tb_info
-    (version)
-VALUES
-    (5);
diff --git a/stargazer/inst/var/00-base-00.sql b/stargazer/inst/var/00-base-00.sql
deleted file mode 100644 (file)
index a452d81..0000000
+++ /dev/null
@@ -1,677 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *****************************************************************************
- *
- * Скрипт генерации структуры базы для хранения данных Stargazer-a
- *
- * $Id: 00-base-00.sql,v 1.7 2010/01/06 14:41:13 faust Exp $
- *
- * Примечание.
- *      * dm_permission_flag. Представляет собой битовую маску - rw.
- *          r - чтение, w - изменение параметра.
- *          0 - дествие запрещено, 1 - действие разрешено
- *
- *      * dm_traff_type. Число определяющее тип подсчета трафика:
- *          0 - up - считается по upload
- *          1 - down - считается по download
- *          2 - max - считается по максимальному среди upload/download
- *          3 - up+down - считается по сумме upload и download
- *
- *      * dm_ip. IP адресс в виде четырех байтового целого числа со знаком.
- *        Выполнять приведение к знаковуму целому при занесении IP в БД!!!
- *
- *      * dm_period. Задает периодичность показа сообщения пользователю.
- *        Период задается целым числом (int16). Если значение равно 0 то
- *        сообщение показывается только при подключении пользователя.
- *        Также этот домен определяет промежуток времени в течении которого
- *        сообщение показывается пользователю.
- *
- *      * dm_session_event_type. Указывает тип записи в логе о сессии.
- *        'c' - connect, 'd' - disconnect.
- *
- *****************************************************************************
- */
-
-/*
- * CONNECT 'localhost:/var/stg/stargazer.fdb' USER 'stg' PASSWORD '123456';
- * DROP DATABASE;
- *
- * CREATE DATABASE 'localhost:/var/stg/stargazer.fdb' USER 'stg' PASSWORD '123456' DEFAULT CHARACTER SET UTF8;
- */
-
-
-/*
- *****************************************************************************
- * -= Создание ДОМЕНОВ =-
- *****************************************************************************
- */
-
-CREATE DOMAIN dm_id AS INTEGER NOT NULL;
-CREATE DOMAIN dm_null_id AS INTEGER;
-CREATE DOMAIN dm_login AS VARCHAR(32) NOT NULL;
-CREATE DOMAIN dm_tariff_name AS VARCHAR(32) NOT NULL;
-CREATE DOMAIN dm_group_name AS VARCHAR(32);
-CREATE DOMAIN dm_corporation_name AS VARCHAR(32);
-CREATE DOMAIN dm_parameter_name AS VARCHAR(32);
-
-CREATE DOMAIN dm_password AS VARCHAR(64) NOT NULL;
-/* bitmask - rw => Read, Write */
-CREATE DOMAIN dm_permission_flag AS SMALLINT NOT NULL
-    CHECK ( VALUE BETWEEN 0 AND 3 );
-CREATE DOMAIN dm_money AS NUMERIC(10,6) NOT NULL;
-/* (0, 1, 2, 3) => (up, down, max, up+down) */
-CREATE DOMAIN dm_traff_type AS SMALLINT NOT NULL
-    CHECK ( VALUE BETWEEN 0 AND 3 );
-CREATE DOMAIN dm_dir_num AS SMALLINT NOT NULL;
-CREATE DOMAIN dm_num AS SMALLINT NOT NULL;
-CREATE DOMAIN dm_traffic_mb AS INTEGER NOT NULL;
-CREATE DOMAIN dm_traffic_byte AS BIGINT NOT NULL;
-CREATE DOMAIN dm_time AS TIME NOT NULL;
-CREATE DOMAIN dm_moment AS TIMESTAMP NOT NULL;
-CREATE DOMAIN dm_credit_moment AS TIMESTAMP;
-CREATE DOMAIN dm_ip AS INTEGER NOT NULL;
-CREATE DOMAIN dm_mask AS INTEGER NOT NULL;
-CREATE DOMAIN dm_user_address AS VARCHAR(256) DEFAULT '';
-CREATE DOMAIN dm_bool AS CHAR(1) NOT NULL
-    CHECK ( VALUE IN ('0', '1', 't', 'f', 'T', 'F') );
-CREATE DOMAIN dm_email AS VARCHAR(256) DEFAULT '';
-CREATE DOMAIN dm_note AS VARCHAR(256) DEFAULT '';
-CREATE DOMAIN dm_phone AS VARCHAR(256) DEFAULT '';
-CREATE DOMAIN dm_user_name AS VARCHAR(256) DEFAULT '';
-CREATE DOMAIN dm_service_comment AS VARCHAR(256) DEFAULT '';
-CREATE DOMAIN dm_service_name AS VARCHAR(32) DEFAULT '';
-
-CREATE DOMAIN dm_pay_day AS SMALLINT NOT NULL
-    CHECK ( VALUE BETWEEN 0 AND 31 );
-CREATE DOMAIN dm_period AS INTEGER NOT NULL;
-CREATE DOMAIN dm_counter AS SMALLINT NOT NULL;
-
-CREATE DOMAIN dm_message_ver AS INTEGER NOT NULL;
-CREATE DOMAIN dm_message_type AS INTEGER NOT NULL;
-
-CREATE DOMAIN dm_message AS VARCHAR(256) NOT NULL;
-CREATE DOMAIN dm_user_data AS VARCHAR(256) NOT NULL;
-CREATE DOMAIN dm_session_event_type AS CHAR(1) NOT NULL
-    CHECK ( VALUE IN ('c', 'd') );
-CREATE DOMAIN dm_char_value AS VARCHAR(64) NOT NULL;
-CREATE DOMAIN dm_date AS DATE NOT NULL;
-
-
-
-/*
- *****************************************************************************
- * -= Создание ТАБЛИЦ =-
- *****************************************************************************
- */
-
-CREATE TABLE tb_admins
-(
-    pk_admin dm_id PRIMARY KEY,
-    login dm_login UNIQUE,
-    passwd dm_password,
-    chg_conf dm_permission_flag,
-    chg_password dm_permission_flag,
-    chg_stat dm_permission_flag,
-    chg_cash dm_permission_flag,
-    usr_add_del dm_permission_flag,
-    chg_tariff dm_permission_flag,
-    chg_admin dm_permission_flag,
-    chg_service dm_permission_flag,
-    chg_corporation dm_permission_flag
-);
-
-CREATE TABLE tb_tariffs
-(
-    pk_tariff dm_id PRIMARY KEY,
-    name dm_tariff_name UNIQUE,
-    fee dm_money,
-    free dm_money,
-    passive_cost dm_money,
-    traff_type dm_traff_type
-);
-
-CREATE TABLE tb_tariffs_params
-(
-    pk_tariff_param dm_id PRIMARY KEY,
-    fk_tariff dm_id,
-    dir_num dm_dir_num,
-    price_day_a dm_money,
-    price_day_b dm_money,
-    price_night_a dm_money,
-    price_night_b dm_money,
-    threshold dm_traffic_mb,
-    time_day_begins dm_time,
-    time_day_ends dm_time,
-
-    FOREIGN KEY (fk_tariff) REFERENCES tb_tariffs (pk_tariff)
-);
-
-CREATE TABLE tb_corporations
-(
-    pk_corporation dm_id PRIMARY KEY,
-    name dm_corporation_name UNIQUE,
-    cash dm_money
-);
-
-CREATE TABLE tb_users
-(
-    pk_user dm_id PRIMARY KEY,
-    fk_tariff dm_null_id,
-    fk_tariff_change dm_null_id,
-    fk_corporation dm_null_id,
-    address dm_user_address,
-    always_online dm_bool,
-    credit dm_money,
-    credit_expire dm_credit_moment,
-    disabled dm_bool,
-    disabled_detail_stat dm_bool,
-    email dm_email,
-    grp dm_group_name,
-    note dm_note,
-    passive dm_bool,
-    passwd dm_password,
-    phone dm_phone,
-    name dm_login UNIQUE,
-    real_name dm_user_name,
-
-    FOREIGN KEY (fk_tariff) REFERENCES tb_tariffs (pk_tariff),
-    FOREIGN KEY (fk_tariff_change) REFERENCES tb_tariffs (pk_tariff),
-    FOREIGN KEY (fk_corporation) REFERENCES tb_corporations (pk_corporation)
-);
-
-CREATE TABLE tb_detail_stats
-(
-    pk_detail_stat dm_id PRIMARY KEY,
-    fk_user dm_id,
-    dir_num dm_dir_num,
-    ip dm_ip,
-    download dm_traffic_byte,
-    upload dm_traffic_byte,
-    cost dm_money,
-    from_time dm_moment,
-    till_time dm_moment,
-
-    FOREIGN KEY (fk_user) REFERENCES tb_users (pk_user)
-);
-
-CREATE TABLE tb_services
-(
-    pk_service dm_id PRIMARY KEY,
-    name dm_service_name UNIQUE,
-    comment dm_service_comment,
-    cost dm_money,
-    pay_day dm_pay_day
-);
-
-CREATE TABLE tb_users_services
-(
-    pk_user_service dm_id PRIMARY KEY,
-    fk_user dm_id,
-    fk_service dm_id,
-
-    FOREIGN KEY (fk_user) REFERENCES tb_users (pk_user),
-    FOREIGN KEY (fk_service) REFERENCES tb_services (pk_service)
-);
-
-CREATE TABLE tb_messages
-(
-    pk_message dm_id PRIMARY KEY,
-    fk_user dm_id,
-    ver dm_message_ver,
-    msg_type dm_message_type,
-    last_send_time dm_period,
-    creation_time dm_period,
-    show_time dm_period,
-    repeat dm_counter,
-    repeat_period dm_period,
-    msg_text dm_message,
-
-    FOREIGN KEY (fk_user) REFERENCES tb_users (pk_user)
-);
-
-CREATE TABLE tb_stats
-(
-    pk_stat dm_id PRIMARY KEY,
-    fk_user dm_id,
-    cash dm_money,
-    free_mb dm_money,
-    last_activity_time dm_moment,
-    last_cash_add dm_money,
-    last_cash_add_time dm_moment,
-    passive_time dm_period,
-    stats_date dm_date,
-
-    FOREIGN KEY (fk_user) REFERENCES tb_users (pk_user)
-);
-
-CREATE TABLE tb_stats_traffic
-(
-    pk_stat_traffic dm_id PRIMARY KEY,
-    fk_stat dm_id,
-    dir_num dm_dir_num,
-    download dm_traffic_byte,
-    upload dm_traffic_byte,
-
-    FOREIGN KEY (fk_stat) REFERENCES tb_stats (pk_stat)
-);
-
-CREATE TABLE tb_users_data
-(
-    pk_user_data dm_id PRIMARY KEY,
-    fk_user dm_id,
-    num dm_num,
-    data dm_user_data,
-
-    FOREIGN KEY (fk_user) REFERENCES tb_users (pk_user)
-);
-
-CREATE TABLE tb_allowed_ip
-(
-    pk_allowed_ip dm_id PRIMARY KEY,
-    fk_user dm_id,
-    ip dm_ip,
-    mask dm_mask,
-
-    FOREIGN KEY (fk_user) REFERENCES tb_users (pk_user)
-);
-
-CREATE TABLE tb_sessions_log
-(
-    pk_session_log dm_id PRIMARY KEY,
-    fk_user dm_id,
-    event_time dm_moment,
-    event_type dm_session_event_type,
-    ip dm_ip,
-
-    FOREIGN KEY (fk_user) REFERENCES tb_users (pk_user)
-);
-
-CREATE TABLE tb_sessions_data
-(
-    pk_session_data dm_id PRIMARY KEY,
-    fk_session_log dm_id,
-    dir_num dm_dir_num,
-    session_upload dm_traffic_byte,
-    session_download dm_traffic_byte,
-    month_upload dm_traffic_byte,
-    month_download dm_traffic_byte,
-
-    FOREIGN KEY (fk_session_log) REFERENCES tb_sessions_log (pk_session_log)
-);
-
-CREATE TABLE tb_parameters
-(
-    pk_parameter dm_id PRIMARY KEY,
-    name dm_parameter_name UNIQUE
-);
-
-CREATE TABLE tb_params_log
-(
-    pk_param_log dm_id PRIMARY KEY,
-    fk_user dm_id,
-    fk_parameter dm_id,
-    event_time dm_moment,
-    from_val dm_char_value,
-    to_val dm_char_value,
-    comment dm_service_comment,
-
-    FOREIGN KEY (fk_user) REFERENCES tb_users (pk_user),
-    FOREIGN KEY (fk_parameter) REFERENCES tb_parameters (pk_parameter)
-);
-
-
-/*
- *****************************************************************************
- * -= Создание ИНДЕКСОВ =-
- *****************************************************************************
- */
-
-
-
-/*
- *****************************************************************************
- * -= Создание ГЕНЕРАТОРОВ =-
- *****************************************************************************
- */
-
-CREATE  GENERATOR gn_pk_admin;
-SET     GENERATOR gn_pk_admin           TO 0;
-CREATE  GENERATOR gn_pk_tariff;
-SET     GENERATOR gn_pk_tariff          TO 0;
-CREATE  GENERATOR gn_pk_tariff_param;
-SET     GENERATOR gn_pk_tariff_param    TO 0;
-CREATE  GENERATOR gn_pk_corporation;
-SET     GENERATOR gn_pk_corporation     TO 0;
-CREATE  GENERATOR gn_pk_user;
-SET     GENERATOR gn_pk_user            TO 0;
-CREATE  GENERATOR gn_pk_detail_stat;
-SET     GENERATOR gn_pk_detail_stat     TO 0;
-CREATE  GENERATOR gn_pk_service;
-SET     GENERATOR gn_pk_service         TO 0;
-CREATE  GENERATOR gn_pk_user_service;
-SET     GENERATOR gn_pk_user_service    TO 0;
-CREATE  GENERATOR gn_pk_message;
-SET     GENERATOR gn_pk_message         TO 0;
-CREATE  GENERATOR gn_pk_stat;
-SET     GENERATOR gn_pk_stat            TO 0;
-CREATE  GENERATOR gn_pk_stat_traffic;
-SET     GENERATOR gn_pk_stat_traffic    TO 0;
-CREATE  GENERATOR gn_pk_user_data;
-SET     GENERATOR gn_pk_user_data       TO 0;
-CREATE  GENERATOR gn_pk_allowed_ip;
-SET     GENERATOR gn_pk_allowed_ip      TO 0;
-CREATE  GENERATOR gn_pk_session;
-SET     GENERATOR gn_pk_session         TO 0;
-CREATE  GENERATOR gn_pk_session_log;
-SET     GENERATOR gn_pk_session_log     TO 0;
-CREATE  GENERATOR gn_pk_session_data;
-SET     GENERATOR gn_pk_session_data    TO 0;
-CREATE  GENERATOR gn_pk_parameter;
-SET     GENERATOR gn_pk_parameter       TO 0;
-CREATE  GENERATOR gn_pk_param_log;
-SET     GENERATOR gn_pk_param_log       TO 0;
-
-
-/*
- *****************************************************************************
- * -= Создание ТРИГГЕРОВ =-
- *****************************************************************************
- */
-
-SET TERM !! ;
-CREATE TRIGGER tr_admin_bi FOR tb_admins
-ACTIVE BEFORE INSERT POSITION 0
-AS
-BEGIN
-    IF (new.pk_admin IS NULL)
-    THEN new.pk_admin = GEN_ID(gn_pk_admin, 1);
-END !!
-SET TERM ; !!
-
-set term !! ;
-create trigger tr_tariff_param_bi for tb_tariffs_params active
-before insert position 0
-as
-begin
-    if (new.pk_tariff_param is null)
-    then new.pk_tariff_param = gen_id(gn_pk_tariff_param, 1);
-end !!
-set term ; !!
-
-set term !! ;
-create trigger tr_corporation_bi for tb_corporations active
-before insert position 0
-as
-begin
-    if (new.pk_corporation is null)
-    then new.pk_corporation = gen_id(gn_pk_corporation, 1);
-end !!
-set term ; !!
-
-set term !! ;
-create trigger tr_detail_stat_bi for tb_detail_stats active
-before insert position 0
-as
-begin
-    if (new.pk_detail_stat is null)
-    then new.pk_detail_stat = gen_id(gn_pk_detail_stat, 1);
-end !!
-set term ; !!
-
-set term !! ;
-create trigger tr_service_bi for tb_services active
-before insert position 0
-as
-begin
-    if (new.pk_service is null)
-    then new.pk_service = gen_id(gn_pk_service, 1);
-end !!
-set term ; !!
-
-set term !! ;
-create trigger tr_user_service_bi for tb_users_services active
-before insert position 0
-as
-begin
-    if (new.pk_user_service is null)
-    then new.pk_user_service = gen_id(gn_pk_user_service, 1);
-end !!
-set term ; !!
-
-set term !! ;
-create trigger tr_stat_traffic_bi for tb_stats_traffic active
-before insert position 0
-as
-begin
-    if (new.pk_stat_traffic is null)
-    then new.pk_stat_traffic = gen_id(gn_pk_stat_traffic, 1);
-end !!
-set term ; !!
-
-set term !! ;
-create trigger tr_user_data_bi for tb_users_data active
-before insert position 0
-as
-begin
-    if (new.pk_user_data is null)
-    then new.pk_user_data = gen_id(gn_pk_user_data, 1);
-end !!
-set term ; !!
-
-set term !! ;
-create trigger tr_allowed_ip_bi for tb_allowed_ip active
-before insert position 0
-as
-begin
-    if (new.pk_allowed_ip is null)
-    then new.pk_allowed_ip = gen_id(gn_pk_allowed_ip, 1);
-end !!
-set term ; !!
-
-set term !! ;
-create trigger tr_session_data_bi for tb_sessions_data active
-before insert position 0
-as
-begin
-    if (new.pk_session_data is null)
-    then new.pk_session_data = gen_id(gn_pk_session_data, 1);
-end !!
-set term ; !!
-
-set term !! ;
-create trigger tr_parameter_bi for tb_parameters active
-before insert position 0
-as
-begin
-    if (new.pk_parameter is null)
-    then new.pk_parameter = gen_id(gn_pk_parameter, 1);
-end !!
-set term ; !!
-
-set term !! ;
-create trigger tr_param_log_bi for tb_params_log active
-before insert position 0
-as
-begin
-    if (new.pk_param_log is null)
-    then new.pk_param_log = gen_id(gn_pk_param_log, 1);
-end !!
-set term ; !!
-
-/*
- *****************************************************************************
- * -= Создание stored procedure =-
- *****************************************************************************
- */
-
-/*
- * Add a message returning it's ID
- */
-set term !! ;
-create procedure sp_add_message(pk_message integer, login varchar(32), ver integer, msg_type integer, last_send_time integer, creation_time integer, show_time integer, repeat integer, repeat_period integer, msg_text varchar(256))
-returns(res integer)
-as  
-begin
-    if (:pk_message is null) then
-    begin
-       pk_message = gen_id(gn_pk_message, 1);
-       insert into tb_messages values (:pk_message,
-                                       (select pk_user from tb_users where name = :login),
-                                       :ver,
-                                       :msg_type,
-                                       :last_send_time,
-                                       :creation_time, 
-                                       :show_time,
-                                       :repeat,
-                                       :repeat_period,
-                                       :msg_text);
-    end
-    else
-    begin
-       update tb_messages set fk_user = (select pk_user from tb_users where name = :login),
-                              ver = :ver,
-                              msg_type = :msg_type,
-                              last_send_time = :last_send_time,
-                              creation_time = :creation_time,
-                              show_time = :show_time,
-                              repeat = :repeat_period,
-                              repeat_period = :repeat_period,
-                              msg_text = :msg_text
-                          where pk_message = :pk_message;
-    end
-    res = :pk_message;
-end !!
-set term ; !!
-
-set term !! ;
-create procedure sp_delete_service(name varchar(32))
-as
-declare variable pk_service integer;
-begin
-    select pk_service from tb_services where name = :name into pk_service;
-    if (pk_service is  not null) then
-    begin
-       delete from tb_users_services where fk_service = :pk_service;
-       delete from tb_services where pk_service = :pk_service;
-    end
-end !!
-set term ; !!
-
-set term !! ;
-create procedure sp_add_tariff(name varchar(32), dirs integer)
-as
-declare variable pk_tariff integer;
-begin
-    pk_tariff = gen_id(gn_pk_tariff, 1);
-    insert into tb_tariffs (pk_tariff, name, fee, free, passive_cost, traff_type) values (:pk_tariff, :name, 0, 0, 0, 0);
-    while (dirs > 0) do
-    begin
-        insert into tb_tariffs_params (fk_tariff, dir_num, price_day_a, 
-                                       price_day_b, price_night_a, price_night_b, 
-                                       threshold, time_day_begins, time_day_ends)
-                   values (:pk_tariff, :dirs - 1, 0, 0, 0, 0, 0, '0:0', '0:0');
-       dirs = dirs - 1;
-    end
-end !!
-set term ; !!
-
-set term !! ;
-create procedure sp_delete_tariff(name varchar(32))
-as
-declare variable pk_tariff integer;
-begin
-    select pk_tariff from tb_tariffs where name = :name into pk_tariff;
-    if (pk_tariff is not null) then
-    begin
-       delete from tb_tariffs_params where fk_tariff = :pk_tariff;
-       delete from tb_tariffs where pk_tariff = :pk_tariff;
-    end
-end !!
-set term ; !!
-
-set term !! ;
-create procedure sp_add_user(name varchar(32), dirs integer)
-as
-declare variable pk_user integer;
-declare variable pk_stat integer;
-begin
-    pk_user = gen_id(gn_pk_user, 1);
-    insert into tb_users(pk_user, fk_tariff, fk_tariff_change, fk_corporation, address, always_online, credit, credit_expire, disabled, disabled_detail_stat, email, grp, note, passive, passwd, phone, name, real_name) values (:pk_user, NULL, NULL, NULL, '', 0, 0, 'now', 0, 0, '', '_', '', 0, '', '', :name, '');
-    pk_stat = gen_id(gn_pk_stat, 1);
-    insert into tb_stats values (:pk_stat, :pk_user, 0, 0, 'now', 0, 'now', 0, 'now');
-    while (dirs > 0) do
-    begin
-       insert into tb_stats_traffic (fk_stat, dir_num, upload, download) values (:pk_stat, :dirs - 1, 0, 0);
-       dirs = dirs - 1;
-    end
-end!!
-set term ; !!
-
-set term !! ;
-create procedure sp_delete_user(name varchar(32))
-as
-declare variable pk_user integer;
-begin
-    select pk_user from tb_users where name = :name into pk_user;
-    if (pk_user is not null) then
-    begin
-       delete from tb_users_services where fk_user = :pk_user;
-       delete from tb_params_log where fk_user = :pk_user;
-       delete from tb_detail_stats where fk_user = :pk_user;
-       delete from tb_stats_traffic where fk_stat in (select pk_stat from tb_stats where fk_user = :pk_user);
-       delete from tb_stats where fk_user = :pk_user;
-       delete from tb_sessions_data where fk_session_log in (select pk_session_log from tb_sessions_log where fk_user = :pk_user);
-       delete from tb_sessions_log where fk_user = :pk_user;
-       delete from tb_allowed_ip where fk_user = :pk_user;
-       delete from tb_users_data where fk_user = :pk_user;
-       delete from tb_messages where fk_user = :pk_user;
-       delete from tb_users where pk_user = :pk_user;
-    end
-end !!
-set term ; !!
-
-set term !! ;
-create procedure sp_append_session_log(name varchar(32), event_time timestamp, event_type char(1), ip integer)
-returns(pk_session_log integer)
-as
-begin
-    pk_session_log = gen_id(gn_pk_session_log, 1);
-    insert into tb_sessions_log (pk_session_log, fk_user, event_time, event_type, ip) values (:pk_session_log, (select pk_user from tb_users where name = :name), :event_time, :event_type, :ip);
-end !!
-set term ; !!
-
-set term !! ;
-create procedure sp_add_stat(name varchar(32), cash numeric(10,6), free_mb numeric(10,6), last_activity_time timestamp, last_cash_add numeric(10,6), last_cash_add_time timestamp, passive_time integer, stats_date date)
-returns(pk_stat integer)
-as
-begin
-    pk_stat = gen_id(gn_pk_stat, 1);
-    insert into tb_stats (pk_stat, fk_user, cash, free_mb, last_activity_time, last_cash_add, last_cash_add_time, passive_time, stats_date) values (:pk_stat, (select pk_user from tb_users where name = :name), :cash, :free_mb, :last_activity_time, :last_cash_add, :last_cash_add_time, :passive_time, :stats_date);
-end !!
-set term ; !!
-
-/*
- *****************************************************************************
- * -= Создание администратора =-
- *****************************************************************************
- */
-
-insert into tb_admins values(0, 'admin', 'geahonjehjfofnhammefahbbbfbmpkmkmmefahbbbfbmpkmkmmefahbbbfbmpkmk', 1, 1, 1, 1, 1, 1, 1, 1, 1);
-
-/* EOF */
diff --git a/stargazer/inst/var/00-mysql-01.sql b/stargazer/inst/var/00-mysql-01.sql
deleted file mode 100644 (file)
index 253738a..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-/*
- *  DB migration from v00 to v01 (mysql)
- */
-
-ALTER TABLE users ADD DisabledDetailStat INT(3) DEFAULT 0;
diff --git a/stargazer/inst/var/01-alter-02.mysql.sql b/stargazer/inst/var/01-alter-02.mysql.sql
deleted file mode 100644 (file)
index 1f1b044..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- *  DB migration from v01 to v02 (mysql)
- */
-
-ALTER TABLE tariffs ADD period VARCHAR(32) NOT NULL DEFAULT 'month';
-
-CREATE TABLE info
-(
-    version INTEGER NOT NULL
-);
-
-INSERT INTO info VALUES (1);
diff --git a/stargazer/inst/var/01-alter-02.postgresql.sql b/stargazer/inst/var/01-alter-02.postgresql.sql
deleted file mode 100644 (file)
index ef6a98c..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- *  DB migration from v01 to v02 (postgres)
- */
-BEGIN;
-
-CREATE DOMAIN DM_TARIFF_PERIOD AS TEXT NOT NULL
-    CONSTRAINT valid_value CHECK (VALUE = 'month' OR VALUE = 'day');
-
-ALTER TABLE tb_tariffs ADD period DM_TARIFF_PERIOD DEFAULT 'month';
-
-UPDATE tb_info SET version = 7;
-
-COMMIT;
diff --git a/stargazer/inst/var/01-alter-02.sql b/stargazer/inst/var/01-alter-02.sql
deleted file mode 100644 (file)
index 628a016..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- *  DB migration from v01 to v02 (firebird)
- */
-
-CREATE DOMAIN DM_TARIFF_PERIOD AS VARCHAR(32) NOT NULL
-    CHECK (VALUE = 'month' OR VALUE = 'day');
-
-ALTER TABLE tb_tariffs ADD period DM_TARIFF_PERIOD DEFAULT 'month';
-
-CREATE TABLE tb_info
-(
-    version INTEGER NOT NULL
-);
-
-INSERT INTO tb_info VALUES (1);
diff --git a/stargazer/inst/var/02-alter-03.postgresql.sql b/stargazer/inst/var/02-alter-03.postgresql.sql
deleted file mode 100644 (file)
index e8b248b..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- *  DB migration from v02 to v03 (postgres)
- */
-BEGIN;
-
-CREATE DOMAIN DM_TARIFF_CHANGE_POLICY AS TEXT NOT NULL
-    CONSTRAINT valid_value CHECK (VALUE IN ('allow', 'to_cheap', 'to_expensive', 'deny'));
-
-ALTER TABLE tb_tariffs ADD change_policy DM_TARIFF_CHANGE_POLICY DEFAULT 'allow';
-ALTER TABLE tb_tariffs ADD change_policy_timeout TIMESTAMP NOT NULL DEFAULT '1970-01-01 00:00:00';
-ALTER TABLE tb_tariffs ALTER COLUMN change_policy DROP DEFAULT;
-ALTER TABLE tb_tariffs ALTER COLUMN change_policy_timeout DROP DEFAULT;
-
-UPDATE tb_info SET version = 8;
-
-COMMIT;
diff --git a/stargazer/inst/var/02-alter-03.sql b/stargazer/inst/var/02-alter-03.sql
deleted file mode 100644 (file)
index d274520..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- *  DB migration from v02 to v03 (firebird)
- */
-
-CREATE DOMAIN DM_TARIFF_CHANGE_POLICY AS  VARCHAR(32) NOT NULL
-    CHECK (VALUE IN ('allow', 'to_cheap', 'to_expensive', 'deny'));
-
-ALTER TABLE tb_tariffs ADD change_policy DM_TARIFF_CHANGE_POLICY DEFAULT 'allow';
-ALTER TABLE tb_tariffs ADD change_policy_timeout DM_MOMENT DEFAULT '1970-01-01 00:00:00';
-
-UPDATE tb_tariffs SET change_policy = 'allow', change_policy_timeout = '1970-01-01 00:00:00';
-
-ALTER TABLE tb_tariffs ALTER COLUMN change_policy DROP DEFAULT;
-ALTER TABLE tb_tariffs ALTER COLUMN change_policy_timeout DROP DEFAULT;
-
-UPDATE tb_info SET version = 2;
diff --git a/stargazer/inst/var/base.dia b/stargazer/inst/var/base.dia
deleted file mode 100644 (file)
index a3d09fa..0000000
Binary files a/stargazer/inst/var/base.dia and /dev/null differ
diff --git a/stargazer/inst/var/stargazer/admins/admin.adm b/stargazer/inst/var/stargazer/admins/admin.adm
deleted file mode 100644 (file)
index bfc6cde..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-password=geahonjehjfofnhammefahbbbfbmpkmkmmefahbbbfbmpkmkmmefahbbbfbmpkmkaa
-ChgConf=1
-ChgPassword=1
-ChgStat=1
-ChgCash=1
-UsrAddDel=1
-ChgTariff=1
-ChgAdmin=1
diff --git a/stargazer/inst/var/stargazer/tariffs/tariff.tf b/stargazer/inst/var/stargazer/tariffs/tariff.tf
deleted file mode 100644 (file)
index 8eb1deb..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-Fee=10.000000
-Free=0
-NoDiscount0=1
-NoDiscount1=1
-NoDiscount2=1
-NoDiscount3=1
-NoDiscount4=1
-NoDiscount5=1
-NoDiscount6=1
-NoDiscount7=1
-NoDiscount8=1
-NoDiscount9=1
-PassiveCost=0.000000
-PriceDayA0=0.000000
-PriceDayA1=0.750000
-PriceDayA2=0.000000
-PriceDayA3=0.000000
-PriceDayA4=0.000000
-PriceDayA5=0.000000
-PriceDayA6=0.000000
-PriceDayA7=0.000000
-PriceDayA8=0.000000
-PriceDayA9=0.000000
-PriceDayB0=0.000000
-PriceDayB1=0.750000
-PriceDayB2=0.000000
-PriceDayB3=0.000000
-PriceDayB4=0.000000
-PriceDayB5=0.000000
-PriceDayB6=0.000000
-PriceDayB7=0.000000
-PriceDayB8=0.000000
-PriceDayB9=0.000000
-PriceNightA0=1.000000
-PriceNightA1=0.000000
-PriceNightA2=0.000000
-PriceNightA3=0.000000
-PriceNightA4=0.000000
-PriceNightA5=0.000000
-PriceNightA6=0.000000
-PriceNightA7=0.000000
-PriceNightA8=0.000000
-PriceNightA9=0.000000
-PriceNightB0=1.000000
-PriceNightB1=0.000000
-PriceNightB2=0.000000
-PriceNightB3=0.000000
-PriceNightB4=0.000000
-PriceNightB5=0.000000
-PriceNightB6=0.000000
-PriceNightB7=0.000000
-PriceNightB8=0.000000
-PriceNightB9=0.000000
-SinglePrice0=1
-SinglePrice1=1
-SinglePrice2=0
-SinglePrice3=0
-SinglePrice4=0
-SinglePrice5=0
-SinglePrice6=0
-SinglePrice7=0
-SinglePrice8=0
-SinglePrice9=0
-Threshold0=0
-Threshold1=0
-Threshold2=0
-Threshold3=0
-Threshold4=0
-Threshold5=0
-Threshold6=0
-Threshold7=0
-Threshold8=0
-Threshold9=0
-Time0=0:0-0:0
-Time1=0:0-0:0
-Time2=0:0-0:0
-Time3=0:0-0:0
-Time4=0:0-0:0
-Time5=0:0-0:0
-Time6=0:0-0:0
-Time7=0:0-0:0
-Time8=0:0-0:0
-Time9=0:0-0:0
-TraffType=up+down
diff --git a/stargazer/inst/var/stargazer/users/test/conf b/stargazer/inst/var/stargazer/users/test/conf
deleted file mode 100644 (file)
index 16fff5e..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-Address=
-AlwaysOnline=0
-CreationTime=1123487395
-Credit=0.000000
-CreditExpire=0
-Down=0
-Email=
-Group=
-Iface=eth1
-IP=192.168.1.1
-Note=
-Passive=0
-Password=123456
-Phone=
-RealName=
-Tariff=tariff
-TariffChange=
-Userdata0=
-Userdata1=
diff --git a/stargazer/inst/var/stargazer/users/test/stat b/stargazer/inst/var/stargazer/users/test/stat
deleted file mode 100644 (file)
index 8aa33e0..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-Cash=10.000000
-D0=0
-D1=0
-D2=0
-D3=0
-D4=0
-D5=0
-D6=0
-D7=0
-D8=0
-D9=0
-FreeMb=0.000000
-LastActivityTime=0
-LastCashAdd=0
-LastCashAddTime=0
-PassiveTime=0
-U0=0
-U1=0
-U2=0
-U3=0
-U4=0
-U5=0
-U6=0
-U7=0
-U8=0
-U9=0
diff --git a/stargazer/main.cpp b/stargazer/main.cpp
deleted file mode 100644 (file)
index 825cba5..0000000
+++ /dev/null
@@ -1,405 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- */
-
-#include "store_loader.h"
-#include "plugin_mgr.h"
-#include "plugin_runner.h"
-#include "users_impl.h"
-#include "admins_impl.h"
-#include "tariffs_impl.h"
-#include "services_impl.h"
-#include "corps_impl.h"
-#include "traffcounter_impl.h"
-#include "settings_impl.h"
-#include "pidfile.h"
-#include "eventloop.h"
-#include "stg_timer.h"
-
-#include "stg/user.h"
-#include "stg/common.h"
-#include "stg/plugin.h"
-#include "stg/logger.h"
-#include "stg/scriptexecuter.h"
-#include "stg/version.h"
-
-#include <fstream>
-#include <vector>
-#include <set>
-#include <csignal>
-#include <cerrno>
-#include <cstdio>
-#include <cstdlib> // srandom, exit
-
-#include <unistd.h>
-#include <sys/ipc.h>
-#include <sys/msg.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/stat.h> // S_IRUSR
-#include <fcntl.h> // create
-
-#ifdef DEBUG
-    #define NO_DAEMON  (1)
-#endif
-
-#define START_FILE "/._ST_ART_ED_"
-
-using STG::SettingsImpl;
-using STG::AdminsImpl;
-using STG::TraffCounterImpl;
-using STG::UsersImpl;
-using STG::TariffsImpl;
-using STG::ServicesImpl;
-using STG::CorporationsImpl;
-using STG::StoreLoader;
-
-namespace
-{
-std::set<pid_t> executers;
-
-void StartTimer();
-int StartScriptExecuter(char* procName, int msgKey, int* msgID);
-int ForkAndWait(const std::string& confDir);
-void KillExecuters();
-
-//-----------------------------------------------------------------------------
-void StartTimer()
-{
-    auto& WriteServLog = STG::Logger::get();
-
-    if (RunStgTimer())
-    {
-        WriteServLog("Cannot start timer. Fatal.");
-        exit(1);
-    }
-    else
-        WriteServLog("Timer thread started successfully.");
-}
-//-----------------------------------------------------------------------------
-#if defined(LINUX) || defined(DARWIN)
-int StartScriptExecuter(char* procName, int msgKey, int* msgID)
-#else
-int StartScriptExecuter(char*, int msgKey, int* msgID)
-#endif
-{
-    auto& WriteServLog = STG::Logger::get();
-
-    if (*msgID == -11)   // If msgID == -11 - first call. Create queue
-    {
-        for (int i = 0; i < 2; i++)
-        {
-            *msgID = msgget(msgKey, IPC_CREAT | IPC_EXCL | 0600);
-
-            if (*msgID == -1)
-            {
-                *msgID = msgget(msgKey, 0);
-                if (*msgID == -1)
-                {
-                    WriteServLog("Message queue not created.");
-                    return -1;
-                }
-                else
-                    msgctl(*msgID, IPC_RMID, NULL);
-            }
-            else
-            {
-                WriteServLog("Message queue created successfully. msgKey=%d msgID=%d", msgKey, *msgID);
-                break;
-            }
-        }
-    }
-
-    const auto pid = fork();
-
-    switch (pid)
-    {
-        case -1:
-            WriteServLog("Fork error!");
-            return -1;
-
-        case 0:
-#if defined(LINUX) || defined(DARWIN)
-            Executer(*msgID, pid, procName);
-#else
-            Executer(*msgID, pid);
-#endif
-            return 1;
-
-        default:
-            if (executers.empty()) {
-#if defined(LINUX) || defined(DARWIN)
-                Executer(*msgID, pid, NULL);
-#else
-                Executer(*msgID, pid);
-#endif
-            }
-            executers.insert(pid);
-    }
-    return 0;
-}
-//-----------------------------------------------------------------------------
-#ifndef NO_DAEMON
-int ForkAndWait(const std::string& confDir)
-#else
-int ForkAndWait(const std::string&)
-#endif
-{
-#ifndef NO_DAEMON
-    const auto pid = fork();
-    const auto startFile = confDir + START_FILE;
-    unlink(startFile.c_str());
-
-    switch (pid)
-    {
-        case -1:
-            return -1;
-            break;
-
-        case 0:
-            close(1);
-            close(2);
-            setsid();
-            break;
-
-        default:
-            struct timespec ts = {0, 200000000};
-            for (int i = 0; i < 120 * 5; i++)
-            {
-                if (access(startFile.c_str(), F_OK) == 0)
-                {
-                    unlink(startFile.c_str());
-                    exit(0);
-                }
-
-                nanosleep(&ts, NULL);
-            }
-            unlink(startFile.c_str());
-            exit(1);
-            break;
-    }
-#endif
-    return 0;
-}
-//-----------------------------------------------------------------------------
-void KillExecuters()
-{
-    auto pid = executers.begin();
-    while (pid != executers.end())
-    {
-        printfd(__FILE__, "KillExecuters pid=%d\n", *pid);
-        kill(*pid, SIGUSR1);
-        ++pid;
-    }
-}
-//-----------------------------------------------------------------------------
-} // namespace anonymous
-//-----------------------------------------------------------------------------
-int main(int argc, char* argv[])
-{
-    int msgID = -11;
-
-    STG::Logger::get().setFileName("/var/log/stargazer.log");
-
-    if (getuid())
-    {
-        printf("You must be root. Exit.\n");
-        return 1;
-    }
-
-    SettingsImpl settings(argc == 2 ? argv[1] : "");
-
-    if (settings.ReadSettings())
-    {
-        auto& WriteServLog = STG::Logger::get();
-
-        if (settings.GetLogFileName() != "")
-            WriteServLog.setFileName(settings.GetLogFileName());
-
-        WriteServLog("ReadSettings error. %s", settings.GetStrError().c_str());
-        return -1;
-    }
-
-#ifndef NO_DAEMON
-    const auto startFile = settings.GetConfDir() + START_FILE;
-#endif
-
-    if (ForkAndWait(settings.GetConfDir()) < 0)
-    {
-        STG::Logger::get()("Fork error!");
-        return -1;
-    }
-
-    auto& WriteServLog = STG::Logger::get();
-    WriteServLog.setFileName(settings.GetLogFileName());
-    WriteServLog("Stg v. %s", SERVER_VERSION);
-
-    for (size_t i = 0; i < settings.GetExecutersNum(); i++)
-    {
-        auto ret = StartScriptExecuter(argv[0], settings.GetExecMsgKey(), &msgID);
-        if (ret < 0)
-        {
-            STG::Logger::get()("Start Script Executer error!");
-            return -1;
-        }
-        if (ret == 1)
-            return 0;
-    }
-
-    PIDFile pidFile(settings.GetPIDFileName());
-
-    struct sigaction sa;
-    memset(&sa, 0, sizeof(sa));
-    sa.sa_handler = SIG_DFL;
-    sigaction(SIGHUP, &sa, NULL); // Apparently FreeBSD ignores SIGHUP by default when launched from rc.d at bot time.
-
-    sigset_t signalSet;
-    sigfillset(&signalSet);
-    pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-    StartTimer();
-    WaitTimer();
-    if (!IsStgTimerRunning())
-    {
-        printfd(__FILE__, "Timer thread not started in 1 sec!\n");
-        WriteServLog("Timer thread not started in 1 sec!");
-        return -1;
-    }
-
-    auto& loop = EVENT_LOOP_SINGLETON::GetInstance();
-
-    StoreLoader storeLoader(settings);
-    if (storeLoader.load())
-    {
-        printfd(__FILE__, "Storage plugin: '%s'\n", storeLoader.GetStrError().c_str());
-        WriteServLog("Storage plugin: '%s'", storeLoader.GetStrError().c_str());
-        return -1;
-    }
-
-    if (loop.Start())
-    {
-        printfd(__FILE__, "Event loop not started.\n");
-        WriteServLog("Event loop not started.");
-        return -1;
-    }
-
-    auto& store = storeLoader.get();
-    WriteServLog("Storage plugin: %s. Loading successfull.", store.GetVersion().c_str());
-
-    AdminsImpl admins(store);
-    TariffsImpl tariffs(&store);
-    ServicesImpl services(&store);
-    CorporationsImpl corps(&store);
-    UsersImpl users(&settings, &store, &tariffs, services, admins.sysAdmin());
-    TraffCounterImpl traffCnt(&users, settings.GetRulesFileName());
-    traffCnt.SetMonitorDir(settings.GetMonitorDir());
-
-    if (users.Start())
-        return -1;
-
-    WriteServLog("Users started successfully.");
-
-    if (traffCnt.Start())
-        return -1;
-
-    WriteServLog("Traffcounter started successfully.");
-
-    STG::PluginManager manager(settings, store, admins, tariffs, services, corps, users, traffCnt);
-
-    srandom(static_cast<unsigned int>(stgTime));
-
-    WriteServLog("Stg started successfully.");
-    WriteServLog("+++++++++++++++++++++++++++++++++++++++++++++");
-
-#ifndef NO_DAEMON
-    creat(startFile.c_str(), S_IRUSR);
-#endif
-
-    bool running = true;
-    while (running)
-    {
-        sigfillset(&signalSet);
-        int sig = 0;
-        sigwait(&signalSet, &sig);
-        int status;
-        switch (sig)
-        {
-            case SIGHUP:
-            {
-                SettingsImpl newSettings(settings);
-                if (newSettings.ReadSettings())
-                    WriteServLog("ReadSettings error. %s", newSettings.GetStrError().c_str());
-                else
-                    settings = newSettings;
-                WriteServLog.setFileName(settings.GetLogFileName());
-                traffCnt.Reload();
-                manager.reload(settings);
-                break;
-            }
-            case SIGTERM:
-                running = false;
-                break;
-            case SIGINT:
-                running = false;
-                break;
-            case SIGPIPE:
-                WriteServLog("Broken pipe!");
-                break;
-            case SIGCHLD:
-                executers.erase(waitpid(-1, &status, WNOHANG));
-                if (executers.empty())
-                    running = false;
-                break;
-            default:
-                WriteServLog("Ignore signal %d", sig);
-                break;
-        }
-    }
-
-    WriteServLog("+++++++++++++++++++++++++++++++++++++++++++++");
-
-    manager.stop();
-
-    if (loop.Stop())
-        WriteServLog("Event loop not stopped.");
-
-    if (!traffCnt.Stop())
-        WriteServLog("Traffcounter: Stop successfull.");
-
-    if (!users.Stop())
-        WriteServLog("Users: Stop successfull.");
-
-    sleep(1);
-    int res = msgctl(msgID, IPC_RMID, NULL);
-    if (res)
-        WriteServLog("Queue was not removed. id=%d", msgID);
-    else
-        WriteServLog("Queue removed successfully.");
-
-    KillExecuters();
-
-    StopStgTimer();
-    WriteServLog("StgTimer: Stop successfull.");
-
-    WriteServLog("Stg stopped successfully.");
-    WriteServLog("---------------------------------------------");
-
-    return 0;
-}
-//-----------------------------------------------------------------------------
diff --git a/stargazer/pidfile.cpp b/stargazer/pidfile.cpp
deleted file mode 100644 (file)
index 0f47a25..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-/*
- $Revision: 1.2 $
- $Date: 2009/06/09 09:07:32 $
- $Author: faust $
- */
-
-/*
- *  An implementation of RAII pid-file writer
- */
-
-#include <fstream>
-#include <unistd.h>
-
-#include "pidfile.h"
-
-PIDFile::PIDFile(const std::string & fn)
-    : fileName(fn)
-{
-if (fileName != "")
-    {
-    std::ofstream pf(fileName.c_str());
-    pf << getpid() << std::endl;
-    pf.close();
-    }
-}
-
-PIDFile::~PIDFile()
-{
-if (fileName != "")
-    {
-    unlink(fileName.c_str());
-    }
-}
diff --git a/stargazer/pidfile.h b/stargazer/pidfile.h
deleted file mode 100644 (file)
index 2600f7f..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-/*
- *  Header file for RAII pid-file writer
- */
-
-/*
- $Revision: 1.2 $
- $Date: 2009/06/09 09:07:32 $
- $Author: faust $
- */
-
-#ifndef __PID_FILE_H__
-#define __PID_FILE_H__
-
-#include <string>
-
-class PIDFile {
-public:
-    explicit PIDFile(const std::string & fn);
-    ~PIDFile();
-private:
-    std::string fileName;
-};
-
-#endif
diff --git a/stargazer/plugin_mgr.cpp b/stargazer/plugin_mgr.cpp
deleted file mode 100644 (file)
index 9d0f136..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#include "plugin_mgr.h"
-
-#include "plugin_runner.h"
-
-#include "admins_impl.h"
-#include "tariffs_impl.h"
-#include "services_impl.h"
-#include "corps_impl.h"
-#include "users_impl.h"
-#include "traffcounter_impl.h"
-#include "settings_impl.h"
-
-#include "stg/logger.h"
-
-using STG::PluginManager;
-using STG::PluginRunner;
-
-namespace
-{
-
-bool StartModCmp(const PluginRunner * lhs, const PluginRunner * rhs)
-{
-    return lhs->GetStartPosition() < rhs->GetStartPosition();
-}
-
-bool StopModCmp(const PluginRunner * lhs, const PluginRunner * rhs)
-{
-    return lhs->GetStopPosition() > rhs->GetStopPosition();
-}
-
-} // namespace anonymous
-
-PluginManager::PluginManager(const SettingsImpl& settings,
-                             Store& store, AdminsImpl& admins, TariffsImpl& tariffs,
-                             ServicesImpl& services, CorporationsImpl& corporations,
-                             UsersImpl& users, TraffCounterImpl& traffcounter)
-    : m_log(Logger::get())
-{
-    std::string basePath = settings.GetModulesPath();
-    const std::vector<ModuleSettings> & modSettings(settings.GetModulesSettings());
-    for (size_t i = 0; i < modSettings.size(); i++)
-    {
-        std::string moduleName = modSettings[i].moduleName;
-        std::string modulePath = basePath + "/mod_" + moduleName + ".so";
-        printfd(__FILE__, "Module: %s\n", modulePath.c_str());
-        try
-        {
-            m_modules.push_back(
-                new PluginRunner(modulePath, moduleName, modSettings[i], admins, tariffs,
-                                  users, services, corporations, traffcounter,
-                                  store, settings)
-            );
-        }
-        catch (const PluginRunner::Error & ex)
-        {
-            m_log(ex.what());
-            printfd(__FILE__, "%s\n", ex.what());
-            // TODO: React
-        }
-    }
-    std::sort(m_modules.begin(), m_modules.end(), StartModCmp);
-    for (size_t i = 0; i < m_modules.size(); ++i)
-    {
-        auto& plugin = m_modules[i]->GetPlugin();
-        if (m_modules[i]->Start())
-        {
-            m_log("Failed to start module '%s': '%s'", plugin.GetVersion().c_str(),
-                                                       plugin.GetStrError().c_str());
-            printfd(__FILE__, "Failed to start module '%s': '%s'\n", plugin.GetVersion().c_str(),
-                                                                   plugin.GetStrError().c_str());
-        }
-        else
-        {
-            m_log("Module '%s' started successfully.", plugin.GetVersion().c_str());
-            printfd(__FILE__, "Module '%s' started successfully.\n", plugin.GetVersion().c_str());
-        }
-    }
-}
-
-PluginManager::~PluginManager()
-{
-    stop();
-    for (size_t i = 0; i < m_modules.size(); ++i)
-        delete m_modules[i];
-}
-
-void PluginManager::reload(const SettingsImpl& settings)
-{
-    const std::vector<ModuleSettings> & modSettings(settings.GetModulesSettings());
-    for (size_t i = 0; i < m_modules.size(); ++i)
-    {
-        for (size_t j = 0; j < modSettings.size(); j++)
-        {
-            if (modSettings[j].moduleName == m_modules[i]->GetName())
-            {
-                auto& plugin = m_modules[i]->GetPlugin();
-                if (m_modules[i]->Reload(modSettings[j]))
-                {
-                    m_log("Error reloading module '%s': '%s'", plugin.GetVersion().c_str(),
-                                                               plugin.GetStrError().c_str());
-                    printfd(__FILE__, "Error reloading module '%s': '%s'\n", plugin.GetVersion().c_str(),
-                                                                             plugin.GetStrError().c_str());
-                }
-                break;
-            }
-        }
-    }
-}
-
-void PluginManager::stop()
-{
-    std::sort(m_modules.begin(), m_modules.end(), StopModCmp);
-    for (size_t i = 0; i < m_modules.size(); ++i)
-    {
-        if (!m_modules[i]->IsRunning())
-            continue;
-        auto& plugin = m_modules[i]->GetPlugin();
-        if (m_modules[i]->Stop())
-        {
-            m_log("Failed to stop module '%s': '%s'", plugin.GetVersion().c_str(),
-                                                      plugin.GetStrError().c_str());
-            printfd(__FILE__, "Failed to stop module '%s': '%s'\n", plugin.GetVersion().c_str(),
-                                                                    plugin.GetStrError().c_str());
-        }
-        else
-        {
-            m_log("Module '%s' stopped successfully.", plugin.GetVersion().c_str());
-            printfd(__FILE__, "Module '%s' stopped successfully.\n", plugin.GetVersion().c_str());
-        }
-    }
-}
diff --git a/stargazer/plugin_mgr.h b/stargazer/plugin_mgr.h
deleted file mode 100644 (file)
index 1d402eb..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#pragma once
-
-#include "stg/module_settings.h"
-
-#include <vector>
-
-namespace STG
-{
-
-class SettingsImpl;
-class PluginRunner;
-struct Store;
-class AdminsImpl;
-class TariffsImpl;
-class ServicesImpl;
-class CorporationsImpl;
-class UsersImpl;
-class TraffCounterImpl;
-class Logger;
-
-class PluginManager
-{
-    public:
-        PluginManager(const SettingsImpl& settings,
-                      Store& store, AdminsImpl& admins, TariffsImpl& tariffs,
-                      ServicesImpl& services, CorporationsImpl& corporations,
-                      UsersImpl& users, TraffCounterImpl& traffcounter);
-        ~PluginManager();
-
-        void reload(const SettingsImpl& settings);
-        void stop();
-
-    private:
-        std::vector<PluginRunner*> m_modules;
-        Logger & m_log;
-};
-
-}
diff --git a/stargazer/plugin_runner.cpp b/stargazer/plugin_runner.cpp
deleted file mode 100644 (file)
index 8938950..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#include "plugin_runner.h"
-
-#include "stg/common.h"
-
-#include <dlfcn.h>
-#include <unistd.h>
-
-using STG::PluginRunner;
-using STG::Plugin;
-
-//-----------------------------------------------------------------------------
-PluginRunner::PluginRunner(const std::string& fileName,
-                           const std::string& name,
-                           const ModuleSettings& ms,
-                           Admins& admins,
-                           Tariffs& tariffs,
-                           Users& users,
-                           Services& services,
-                           Corporations& corporations,
-                           TraffCounter& traffcounter,
-                           Store& store,
-                           const Settings& settings)
-    : pluginFileName(fileName),
-      pluginName(name),
-      libHandle(NULL),
-      m_plugin(load(ms, admins, tariffs, users, services, corporations,
-                    traffcounter, store, settings))
-{
-}
-//-----------------------------------------------------------------------------
-PluginRunner::~PluginRunner()
-{
-    delete &m_plugin;
-    if (dlclose(libHandle))
-    {
-        errorStr = "Failed to unload plugin '" + pluginFileName + "': " + dlerror();
-        printfd(__FILE__, "PluginRunner::Unload() - %s", errorStr.c_str());
-    }
-}
-//-----------------------------------------------------------------------------
-int PluginRunner::Start()
-{
-    int res = m_plugin.Start();
-    errorStr = m_plugin.GetStrError();
-    return res;
-}
-//-----------------------------------------------------------------------------
-int PluginRunner::Stop()
-{
-    int res = m_plugin.Stop();
-    errorStr = m_plugin.GetStrError();
-    return res;
-}
-//-----------------------------------------------------------------------------
-int PluginRunner::Reload(const ModuleSettings& ms)
-{
-    int res = m_plugin.Reload(ms);
-    errorStr = m_plugin.GetStrError();
-    return res;
-}
-//-----------------------------------------------------------------------------
-Plugin & PluginRunner::load(const ModuleSettings& ms,
-                            Admins& admins,
-                            Tariffs& tariffs,
-                            Users& users,
-                            Services& services,
-                            Corporations& corporations,
-                            TraffCounter& traffcounter,
-                            Store& store,
-                            const Settings& settings)
-{
-    if (pluginFileName.empty())
-    {
-        const std::string msg = "Empty plugin file name.";
-        printfd(__FILE__, "PluginRunner::load() - %s\n", msg.c_str());
-        throw Error(msg);
-    }
-
-    if (access(pluginFileName.c_str(), R_OK))
-    {
-        const std::string msg = "Plugin file '" + pluginFileName + "' is missing or inaccessible.";
-        printfd(__FILE__, "PluginRunner::load() - %s\n", msg.c_str());
-        throw Error(msg);
-    }
-
-    libHandle = dlopen(pluginFileName.c_str(), RTLD_NOW);
-
-    if (!libHandle)
-    {
-        std::string msg = "Error loading plugin '" + pluginFileName + "'";
-        const char* error = dlerror();
-        if (error)
-            msg = msg + ": '" + error + "'";
-        printfd(__FILE__, "PluginRunner::load() - %s\n", msg.c_str());
-        throw Error(msg);
-    }
-
-    using Getter = Plugin* (*)();
-    auto GetPlugin = reinterpret_cast<Getter>(dlsym(libHandle, "GetPlugin"));
-    if (!GetPlugin)
-    {
-        const std::string msg = "Plugin '" + pluginFileName + "' does not have GetPlugin() function. ";
-        printfd(__FILE__, "PluginRunner::load() - %s\n", msg.c_str());
-        throw Error(msg);
-    }
-
-    Plugin* plugin = GetPlugin();
-
-    if (!plugin)
-    {
-        const std::string msg = "Failed to create an instance of plugin '" + pluginFileName + "'.";
-        printfd(__FILE__, "PluginRunner::load() - %s\n", msg.c_str());
-        throw Error(msg);
-    }
-
-    plugin->SetSettings(ms);
-    plugin->SetTariffs(&tariffs);
-    plugin->SetAdmins(&admins);
-    plugin->SetUsers(&users);
-    plugin->SetServices(&services);
-    plugin->SetCorporations(&corporations);
-    plugin->SetTraffcounter(&traffcounter);
-    plugin->SetStore(&store);
-    plugin->SetStgSettings(&settings);
-
-    if (plugin->ParseSettings())
-    {
-        const std::string msg = "Plugin '" + pluginFileName + "' is unable to parse settings. " + plugin->GetStrError();
-        printfd(__FILE__, "PluginRunner::load() - %s\n", msg.c_str());
-        throw Error(msg);
-    }
-
-    return *plugin;
-}
diff --git a/stargazer/plugin_runner.h b/stargazer/plugin_runner.h
deleted file mode 100644 (file)
index 1c8bf42..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#pragma once
-
-#include "stg/plugin.h"
-
-#include <string>
-#include <stdexcept>
-#include <cstdint>
-
-namespace STG
-{
-
-struct ModuleSettings;
-struct Settings;
-struct Admins;
-struct Tariffs;
-struct Users;
-struct Services;
-struct Corporations;
-struct TraffCounter;
-struct Store;
-
-//-----------------------------------------------------------------------------
-class PluginRunner {
-public:
-    struct Error : public std::runtime_error {
-        explicit Error(const std::string & msg) : runtime_error(msg) {}
-    };
-
-    PluginRunner(const std::string& pluginFileName,
-                 const std::string& pluginName,
-                 const ModuleSettings& ms,
-                 Admins& admins,
-                 Tariffs& tariffs,
-                 Users& users,
-                 Services& services,
-                 Corporations& corporations,
-                 TraffCounter& traffcounter,
-                 Store& store,
-                 const Settings & settings);
-    ~PluginRunner();
-
-    int             Start();
-    int             Stop();
-    int             Reload(const ModuleSettings& ms);
-    int             Restart();
-    bool            IsRunning() { return m_plugin.IsRunning(); }
-
-    const std::string& GetStrError() const { return errorStr; }
-    Plugin& GetPlugin() { return m_plugin; }
-    const std::string& GetFileName() const { return pluginFileName; }
-    const std::string& GetName() const { return pluginName; }
-
-    uint16_t        GetStartPosition() const { return m_plugin.GetStartPosition(); }
-    uint16_t        GetStopPosition() const { return m_plugin.GetStopPosition(); }
-
-private:
-    Plugin & load(const ModuleSettings& ms,
-                  Admins& admins,
-                  Tariffs& tariffs,
-                  Users& users,
-                  Services& services,
-                  Corporations& corporations,
-                  TraffCounter& traffcounter,
-                  Store& store,
-                  const Settings& settings);
-
-    std::string pluginFileName;
-    std::string pluginName;
-    void*       libHandle;
-
-    Plugin&     m_plugin;
-    std::string errorStr;
-};
-//-----------------------------------------------------------------------------
-}
diff --git a/stargazer/plugins/CMakeLists.txt b/stargazer/plugins/CMakeLists.txt
deleted file mode 100644 (file)
index a8958c4..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-if ( BUILD_MOD_AO )
-    add_library ( mod_auth_ao MODULE authorization/ao/ao.cpp )
-    target_link_libraries ( mod_auth_ao scriptexecuter logger common )
-    set_target_properties ( mod_auth_ao PROPERTIES PREFIX "" )
-endif ( BUILD_MOD_AO )
-
-if ( BUILD_MOD_IA )
-    add_library ( mod_auth_ia MODULE authorization/inetaccess/inetaccess.cpp )
-    target_link_libraries ( mod_auth_ia scriptexecuter crypto logger common )
-    set_target_properties ( mod_auth_ia PROPERTIES PREFIX "" )
-    if ( ${CMAKE_SYSTEM_NAME} STREQUAL "Darwin" )
-        set_target_properties ( mod_auth_ia PROPERTIES LINK_FLAGS "-undefined dynamic_lookup" )
-    endif ( ${CMAKE_SYSTEM_NAME} STREQUAL "Darwin" )
-endif ( BUILD_MOD_IA )
-
-if ( BUILD_MOD_CAP_NF )
-    add_library ( mod_cap_nf MODULE capture/cap_nf/cap_nf.cpp )
-    target_link_libraries ( mod_cap_nf logger common )
-    set_target_properties ( mod_cap_nf PROPERTIES PREFIX "" )
-endif ( BUILD_MOD_CAP_NF )
-
-if ( BUILD_MOD_CAP_DIVERT )
-    add_library ( mod_cap_divert MODULE capture/divert_freebsd/divert_cap.cpp )
-    target_link_libraries ( mod_cap_divert logger common )
-    set_target_properties ( mod_cap_divert PROPERTIES PREFIX "" )
-endif ( BUILD_MOD_CAP_DIVERT )
-
-if ( BUILD_MOD_CAP_ETHER_FREEBSD )
-    add_library ( mod_cap_bpf MODULE capture/ether_freebsd/ether_cap.cpp )
-    target_link_libraries ( mod_cap_bpf logger common )
-    set_target_properties ( mod_cap_bpf PROPERTIES PREFIX "" )
-endif ( BUILD_MOD_CAP_ETHER_FREEBSD )
-
-if ( BUILD_MOD_CAP_ETHER_LINUX )
-    add_library ( mod_cap_ether MODULE capture/ether_linux/ether_cap.cpp )
-    target_link_libraries ( mod_cap_ether logger common )
-    set_target_properties ( mod_cap_ether PROPERTIES PREFIX "" )
-endif ( BUILD_MOD_CAP_ETHER_LINUX )
-
-if ( BUILD_MOD_CAP_PCAP )
-    find_package ( PCap REQUIRED )
-    add_library ( mod_cap_pcap MODULE capture/pcap/pcap_cap.cpp )
-    target_link_libraries ( mod_cap_pcap logger common PCap::PCap )
-    set_target_properties ( mod_cap_pcap PROPERTIES PREFIX "" )
-endif ( BUILD_MOD_CAP_PCAP )
-
-if ( BUILD_MOD_CAP_NFQUEUE )
-    find_package ( NFQueue REQUIRED )
-    find_package ( NFNetLink REQUIRED )
-    find_package ( MNL REQUIRED )
-    add_library ( mod_cap_nfqueue MODULE capture/nfqueue/nfqueue.cpp )
-    target_link_libraries ( mod_cap_nfqueue logger common NF::Queue NF::NetLink MNL::MNL )
-    set_target_properties ( mod_cap_nfqueue PROPERTIES PREFIX "" )
-endif ( BUILD_MOD_CAP_NFQUEUE )
-
-if ( BUILD_MOD_SGCONFIG )
-    find_package ( EXPAT REQUIRED )
-    add_library ( mod_conf_sg MODULE configuration/sgconfig/stgconfig.cpp
-                                     configuration/sgconfig/conn.cpp
-                                     configuration/sgconfig/configproto.cpp
-                                     configuration/sgconfig/parser.cpp
-                                     configuration/sgconfig/parser_tariffs.cpp
-                                     configuration/sgconfig/parser_admins.cpp
-                                     configuration/sgconfig/parser_users.cpp
-                                     configuration/sgconfig/parser_services.cpp
-                                     configuration/sgconfig/parser_message.cpp
-                                     configuration/sgconfig/parser_auth_by.cpp
-                                     configuration/sgconfig/parser_user_info.cpp
-                                     configuration/sgconfig/parser_server_info.cpp )
-    target_link_libraries ( mod_conf_sg scriptexecuter crypto logger common EXPAT::EXPAT )
-    set_target_properties ( mod_conf_sg PROPERTIES PREFIX "" )
-    if ( ${CMAKE_SYSTEM_NAME} STREQUAL "Darwin" )
-        set_target_properties ( mod_conf_sg PROPERTIES LINK_FLAGS "-undefined dynamic_lookup" )
-    endif ( ${CMAKE_SYSTEM_NAME} STREQUAL "Darwin" )
-endif ( BUILD_MOD_SGCONFIG )
-
-if ( BUILD_MOD_RPCCONFIG )
-    find_package ( XMLRPC REQUIRED c++ abyss-server )
-    include_directories ( ${XMLRPC_INCLUDE_DIRS} )
-    add_library ( mod_conf_rpc MODULE configuration/rpcconfig/rpcconfig.cpp
-                                      configuration/rpcconfig/user_helper.cpp
-                                      configuration/rpcconfig/tariff_helper.cpp
-                                      configuration/rpcconfig/info_methods.cpp
-                                      configuration/rpcconfig/users_methods.cpp
-                                      configuration/rpcconfig/tariffs_methods.cpp
-                                      configuration/rpcconfig/admins_methods.cpp
-                                      configuration/rpcconfig/messages_methods.cpp )
-                              target_link_libraries ( mod_conf_rpc scriptexecuter logger common ${XMLRPC_LIBRARIES} )
-    set_target_properties ( mod_conf_rpc PROPERTIES PREFIX "" )
-endif ( BUILD_MOD_RPCCONFIG )
-
-if ( BUILD_MOD_PING )
-    add_library ( mod_ping MODULE other/ping/ping.cpp )
-    target_link_libraries ( mod_ping scriptexecuter logger pinger common )
-    set_target_properties ( mod_ping PROPERTIES PREFIX "" )
-endif ( BUILD_MOD_PING )
-
-if ( BUILD_MOD_RSCRYPT )
-    add_library ( mod_remote_script MODULE other/rscript/rscript.cpp other/rscript/nrmap_parser.cpp )
-    target_link_libraries ( mod_remote_script crypto scriptexecuter logger common )
-    set_target_properties ( mod_remote_script PROPERTIES PREFIX "" )
-    if ( ${CMAKE_SYSTEM_NAME} STREQUAL "Darwin" )
-        set_target_properties ( mod_remote_script PROPERTIES LINK_FLAGS "-undefined dynamic_lookup" )
-    endif ( ${CMAKE_SYSTEM_NAME} STREQUAL "Darwin" )
-endif ( BUILD_MOD_RSCRYPT )
-
-if ( BUILD_MOD_SMUX )
-    add_library ( mod_smux MODULE other/smux/smux.cpp
-                                  other/smux/sensors.cpp
-                                  other/smux/tables.cpp
-                                  other/smux/handlers.cpp
-                                  other/smux/utils.cpp
-                                  other/smux/types.cpp )
-    target_link_libraries ( mod_smux scriptexecuter logger smux common )
-    set_target_properties ( mod_smux PROPERTIES PREFIX "" )
-endif ( BUILD_MOD_SMUX )
-
-if ( BUILD_MOD_STORE_FILES )
-    add_library ( mod_store_files MODULE store/files/file_store.cpp )
-    target_link_libraries ( mod_store_files crypto conffiles logger common )
-    set_target_properties ( mod_store_files PROPERTIES PREFIX "" )
-endif ( BUILD_MOD_STORE_FILES )
-
-if ( BUILD_MOD_STORE_FIREBIRD )
-    find_package ( FBClient REQUIRED )
-    add_library ( mod_store_firebird MODULE store/firebird/firebird_store.cpp
-                                            store/firebird/firebird_store_admins.cpp
-                                            store/firebird/firebird_store_corporations.cpp
-                                            store/firebird/firebird_store_messages.cpp
-                                            store/firebird/firebird_store_services.cpp
-                                            store/firebird/firebird_store_tariffs.cpp
-                                            store/firebird/firebird_store_users.cpp
-                                            store/firebird/firebird_store_utils.cpp )
-    target_link_libraries ( mod_store_firebird crypto common logger ibpp FBClient::FBClient )
-    set_target_properties ( mod_store_firebird PROPERTIES PREFIX "" )
-endif ( BUILD_MOD_STORE_FIREBIRD )
-
-if ( BUILD_MOD_STORE_MYSQL )
-    find_package ( MySQLConnector REQUIRED )
-    add_library ( mod_store_mysql MODULE store/mysql/mysql_store.cpp )
-    target_link_libraries ( mod_store_mysql crypto logger common MySQL::Connector )
-    set_target_properties ( mod_store_mysql PROPERTIES PREFIX "" )
-endif ( BUILD_MOD_STORE_MYSQL )
-
-if ( BUILD_MOD_STORE_POSTGRESQL )
-    find_package ( PostgreSQL REQUIRED )
-    include_directories ( ${PostgreSQL_INCLUDE_DIRS} )
-    add_library ( mod_store_postgresql MODULE store/postgresql/postgresql_store.cpp
-                                              store/postgresql/postgresql_store_admins.cpp
-                                              store/postgresql/postgresql_store_corporations.cpp
-                                              store/postgresql/postgresql_store_messages.cpp
-                                              store/postgresql/postgresql_store_services.cpp
-                                              store/postgresql/postgresql_store_tariffs.cpp
-                                              store/postgresql/postgresql_store_users.cpp
-                                              store/postgresql/postgresql_store_utils.cpp )
-                                      target_link_libraries ( mod_store_postgresql crypto logger common ${PostgreSQL_LIBRARIES} )
-    set_target_properties ( mod_store_postgresql PROPERTIES PREFIX "" )
-endif ( BUILD_MOD_STORE_POSTGRESQL )
diff --git a/stargazer/plugins/authorization/ao/ao.cpp b/stargazer/plugins/authorization/ao/ao.cpp
deleted file mode 100644 (file)
index 7b6f129..0000000
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- */
-
-#include "ao.h"
-
-#include "stg/user.h"
-#include "stg/users.h"
-#include "stg/user_property.h"
-#include "stg/common.h"
-
-#include <algorithm> // for_each
-#include <functional> // mem_fun_ref
-#include <csignal>
-#include <cassert>
-
-#include <unistd.h>
-
-extern "C" STG::Plugin* GetPlugin()
-{
-    static AUTH_AO plugin;
-    return &plugin;
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-std::string AUTH_AO::GetVersion() const
-{
-return "Always Online authorizator v.1.0";
-}
-//-----------------------------------------------------------------------------
-AUTH_AO::AUTH_AO()
-    : users(NULL),
-      isRunning(false),
-      onAddUserNotifier(*this),
-      onDelUserNotifier(*this),
-      logger(STG::PluginLogger::get("auth_ao"))
-{
-}
-//-----------------------------------------------------------------------------
-int AUTH_AO::Start()
-{
-printfd(__FILE__, "AUTH_AO::Start()\n");
-GetUsers();
-
-users->AddNotifierUserAdd(&onAddUserNotifier);
-users->AddNotifierUserDel(&onDelUserNotifier);
-
-std::for_each(userList.begin(), userList.end(), [this](auto user){ UpdateUserAuthorization(user); });
-
-isRunning = true;
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int AUTH_AO::Stop()
-{
-printfd(__FILE__, "AUTH_AO::Stop()\n");
-if (!isRunning)
-    return 0;
-
-users->DelNotifierUserAdd(&onAddUserNotifier);
-users->DelNotifierUserDel(&onDelUserNotifier);
-
-auto it = userList.begin();
-while (it != userList.end())
-    {
-    if ((*it)->IsAuthorizedBy(this))
-        users->Unauthorize((*it)->GetLogin(), this);
-    UnSetUserNotifiers(*it);
-    ++it;
-    }
-isRunning = false;
-return 0;
-}
-//-----------------------------------------------------------------------------
-void AUTH_AO::SetUserNotifiers(UserPtr u)
-{
-// ---------- AlwaysOnline -------------------
-CHG_BEFORE_NOTIFIER<int> BeforeChgAONotifier(*this, u);
-CHG_AFTER_NOTIFIER<int>  AfterChgAONotifier(*this, u);
-
-BeforeChgAONotifierList.push_front(BeforeChgAONotifier);
-AfterChgAONotifierList.push_front(AfterChgAONotifier);
-
-u->GetProperties().alwaysOnline.AddBeforeNotifier(&BeforeChgAONotifierList.front());
-u->GetProperties().alwaysOnline.AddAfterNotifier(&AfterChgAONotifierList.front());
-// ---------- AlwaysOnline end ---------------
-
-// ---------- IP -------------------
-CHG_BEFORE_NOTIFIER<STG::UserIPs> BeforeChgIPNotifier(*this, u);
-CHG_AFTER_NOTIFIER<STG::UserIPs>  AfterChgIPNotifier(*this, u);
-
-BeforeChgIPNotifierList.push_front(BeforeChgIPNotifier);
-AfterChgIPNotifierList.push_front(AfterChgIPNotifier);
-
-u->GetProperties().ips.AddBeforeNotifier(&BeforeChgIPNotifierList.front());
-u->GetProperties().ips.AddAfterNotifier(&AfterChgIPNotifierList.front());
-// ---------- IP end ---------------
-}
-//-----------------------------------------------------------------------------
-void AUTH_AO::UnSetUserNotifiers(UserPtr u)
-{
-// ---      AlwaysOnline        ---
-auto aoBIter = find_if(BeforeChgAONotifierList.begin(),
-                       BeforeChgAONotifierList.end(),
-                       [u](auto notifier){ return notifier.GetUser() == u; });
-
-if (aoBIter != BeforeChgAONotifierList.end())
-    {
-    aoBIter->GetUser()->GetProperties().alwaysOnline.DelBeforeNotifier(&(*aoBIter));
-    BeforeChgAONotifierList.erase(aoBIter);
-    }
-
-auto aoAIter = find_if(AfterChgAONotifierList.begin(),
-                       AfterChgAONotifierList.end(),
-                       [u](auto notifier){ return notifier.GetUser() == u; });
-
-if (aoAIter != AfterChgAONotifierList.end())
-    {
-    aoAIter->GetUser()->GetProperties().alwaysOnline.DelAfterNotifier(&(*aoAIter));
-    AfterChgAONotifierList.erase(aoAIter);
-    }
-// ---      AlwaysOnline end    ---
-
-// ---          IP              ---
-auto ipBIter = std::find_if(BeforeChgIPNotifierList.begin(),
-                            BeforeChgIPNotifierList.end(),
-                            [u](auto notifier){ return notifier.GetUser() == u; });
-
-if (ipBIter != BeforeChgIPNotifierList.end())
-    {
-    ipBIter->GetUser()->GetProperties().ips.DelBeforeNotifier(&(*ipBIter));
-    BeforeChgIPNotifierList.erase(ipBIter);
-    }
-
-auto ipAIter = find_if(AfterChgIPNotifierList.begin(),
-                       AfterChgIPNotifierList.end(),
-                       [u](auto notifier){ return notifier.GetUser() == u; });
-
-if (ipAIter != AfterChgIPNotifierList.end())
-    {
-    ipAIter->GetUser()->GetProperties().ips.DelAfterNotifier(&(*ipAIter));
-    AfterChgIPNotifierList.erase(ipAIter);
-    }
-// ---          IP end          ---
-}
-//-----------------------------------------------------------------------------
-void AUTH_AO::GetUsers()
-{
-UserPtr u;
-int h = users->OpenSearch();
-assert(h && "USERS::OpenSearch is always correct");
-
-while (!users->SearchNext(h, &u))
-    {
-    userList.push_back(u);
-    SetUserNotifiers(u);
-    }
-
-users->CloseSearch(h);
-}
-//-----------------------------------------------------------------------------
-void AUTH_AO::UpdateUserAuthorization(ConstUserPtr u) const
-{
-if (u->GetProperties().alwaysOnline)
-    {
-    auto ips = u->GetProperties().ips.get();
-    if (ips.onlyOneIP())
-        {
-        users->Authorize(u->GetLogin(), ips[0].ip, 0xFFffFFff, this);
-        }
-    }
-}
-//-----------------------------------------------------------------------------
-void AUTH_AO::AddUser(UserPtr u)
-{
-SetUserNotifiers(u);
-userList.push_back(u);
-UpdateUserAuthorization(u);
-}
-//-----------------------------------------------------------------------------
-void AUTH_AO::DelUser(UserPtr u)
-{
-if (u->IsAuthorizedBy(this))
-    users->Unauthorize(u->GetLogin(), this);
-UnSetUserNotifiers(u);
-userList.erase(std::remove(userList.begin(), userList.end(), u), userList.end());
-}
-//-----------------------------------------------------------------------------
-int AUTH_AO::SendMessage(const STG::Message &, uint32_t) const
-{
-errorStr = "Authorization modele \'AlwaysOnline\' does not support sending messages";
-return -1;
-}
-//-----------------------------------------------------------------------------
-template <typename varParamType>
-void CHG_BEFORE_NOTIFIER<varParamType>::Notify(const varParamType &, const varParamType &)
-{
-//EVENT_LOOP_SINGLETON::GetInstance().Enqueue(auth, &AUTH_AO::Unauthorize, user);
-if (user->IsAuthorizedBy(&auth))
-    auth.users->Unauthorize(user->GetLogin(), &auth);
-}
-//-----------------------------------------------------------------------------
-template <typename varParamType>
-void CHG_AFTER_NOTIFIER<varParamType>::Notify(const varParamType &, const varParamType &)
-{
-//EVENT_LOOP_SINGLETON::GetInstance().Enqueue(auth, &AUTH_AO::UpdateUserAuthorization, user);
-auth.UpdateUserAuthorization(user);
-}
-//-----------------------------------------------------------------------------
diff --git a/stargazer/plugins/authorization/ao/ao.h b/stargazer/plugins/authorization/ao/ao.h
deleted file mode 100644 (file)
index dbb2993..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- */
-
-#pragma once
-
-#include "stg/auth.h"
-#include "stg/module_settings.h"
-#include "stg/store.h"
-#include "stg/notifer.h"
-#include "stg/user_ips.h"
-#include "stg/user.h"
-#include "stg/logger.h"
-
-#include <string>
-#include <vector>
-#include <list>
-
-#include <pthread.h>
-
-namespace STG
-{
-struct Users;
-}
-
-class AUTH_AO;
-
-using UserPtr = STG::User*;
-using ConstUserPtr = const STG::User*;
-
-template <typename T>
-class CHG_BEFORE_NOTIFIER : public STG::PropertyNotifierBase<T> {
-public:
-                CHG_BEFORE_NOTIFIER(AUTH_AO & a, UserPtr u)
-                    : user(u), auth(a) {}
-                CHG_BEFORE_NOTIFIER(const CHG_BEFORE_NOTIFIER<T> & rvalue)
-                    : user(rvalue.user), auth(rvalue.auth) {}
-    void        Notify(const T & oldValue, const T & newValue);
-    UserPtr    GetUser() const { return user; }
-
-private:
-    CHG_BEFORE_NOTIFIER<T> & operator=(const CHG_BEFORE_NOTIFIER<T> & rvalue);
-
-    UserPtr        user;
-    const AUTH_AO & auth;
-};
-//-----------------------------------------------------------------------------
-template <typename T>
-class CHG_AFTER_NOTIFIER : public STG::PropertyNotifierBase<T> {
-public:
-                CHG_AFTER_NOTIFIER(AUTH_AO & a, UserPtr u)
-                    : user(u), auth(a) {}
-                CHG_AFTER_NOTIFIER(const CHG_AFTER_NOTIFIER<T> & rvalue)
-                    : user(rvalue.user), auth(rvalue.auth) {}
-    void        Notify(const T & oldValue, const T & newValue);
-    UserPtr    GetUser() const { return user; }
-
-private:
-    CHG_AFTER_NOTIFIER<T> & operator=(const CHG_AFTER_NOTIFIER<T> & rvalue);
-
-    UserPtr        user;
-    const AUTH_AO & auth;
-};
-//-----------------------------------------------------------------------------
-class AUTH_AO : public STG::Auth {
-public:
-    AUTH_AO();
-
-    void                SetUsers(STG::Users * u) override { users = u; }
-
-    int                 Start() override;
-    int                 Stop() override;
-    int                 Reload(const STG::ModuleSettings & /*ms*/) override { return 0; }
-    bool                IsRunning() override { return isRunning; }
-    void                SetSettings(const STG::ModuleSettings &) override {}
-    int                 ParseSettings() override { return 0; }
-    const std::string & GetStrError() const override { return errorStr; }
-    std::string         GetVersion() const override;
-    uint16_t            GetStartPosition() const override { return 30; }
-    uint16_t            GetStopPosition() const override { return 30; }
-
-    int                 SendMessage(const STG::Message & msg, uint32_t ip) const override;
-
-private:
-    AUTH_AO(const AUTH_AO & rvalue);
-    AUTH_AO & operator=(const AUTH_AO & rvalue);
-
-    void                AddUser(UserPtr u);
-    void                DelUser(UserPtr u);
-
-    void                GetUsers();
-    void                SetUserNotifiers(UserPtr u);
-    void                UnSetUserNotifiers(UserPtr u);
-    void                UpdateUserAuthorization(ConstUserPtr u) const;
-
-    mutable std::string errorStr;
-    STG::Users *             users;
-    std::vector<UserPtr> userList;
-    bool                isRunning;
-    STG::ModuleSettings     settings;
-
-    std::list<CHG_BEFORE_NOTIFIER<int> >      BeforeChgAONotifierList;
-    std::list<CHG_AFTER_NOTIFIER<int> >       AfterChgAONotifierList;
-
-    std::list<CHG_BEFORE_NOTIFIER<STG::UserIPs> > BeforeChgIPNotifierList;
-    std::list<CHG_AFTER_NOTIFIER<STG::UserIPs> >  AfterChgIPNotifierList;
-
-    class ADD_USER_NONIFIER: public STG::NotifierBase<UserPtr> {
-    public:
-        explicit ADD_USER_NONIFIER(AUTH_AO & a) : auth(a) {}
-        virtual ~ADD_USER_NONIFIER() {}
-        void Notify(const UserPtr & user) { auth.AddUser(user); }
-
-    private:
-        ADD_USER_NONIFIER(const ADD_USER_NONIFIER & rvalue);
-        ADD_USER_NONIFIER & operator=(const ADD_USER_NONIFIER & rvalue);
-
-        AUTH_AO & auth;
-    } onAddUserNotifier;
-
-    class DEL_USER_NONIFIER: public STG::NotifierBase<UserPtr> {
-    public:
-        explicit DEL_USER_NONIFIER(AUTH_AO & a) : auth(a) {}
-        virtual ~DEL_USER_NONIFIER() {}
-        void Notify(const UserPtr & user) { auth.DelUser(user); }
-
-    private:
-        DEL_USER_NONIFIER(const DEL_USER_NONIFIER & rvalue);
-        DEL_USER_NONIFIER & operator=(const DEL_USER_NONIFIER & rvalue);
-
-        AUTH_AO & auth;
-    } onDelUserNotifier;
-
-    STG::PluginLogger logger;
-
-    friend class CHG_BEFORE_NOTIFIER<int>;
-    friend class CHG_AFTER_NOTIFIER<int>;
-    friend class CHG_BEFORE_NOTIFIER<STG::UserIPs>;
-    friend class CHG_AFTER_NOTIFIER<STG::UserIPs>;
-
-};
diff --git a/stargazer/plugins/authorization/inetaccess/inetaccess.cpp b/stargazer/plugins/authorization/inetaccess/inetaccess.cpp
deleted file mode 100644 (file)
index b824d59..0000000
+++ /dev/null
@@ -1,1702 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- */
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#include "inetaccess.h"
-
-#include "stg/common.h"
-#include "stg/locker.h"
-#include "stg/tariff.h"
-#include "stg/settings.h"
-
-#include <algorithm>
-#include <csignal>
-#include <cstdlib>
-#include <cstdio> // snprintf
-#include <cerrno>
-#include <cmath>
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <unistd.h> // close
-
-#define IA_PROTO_VER    (6)
-
-extern volatile time_t stgTime;
-
-extern "C" STG::Plugin* GetPlugin()
-{
-    static AUTH_IA plugin;
-    return &plugin;
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-AUTH_IA_SETTINGS::AUTH_IA_SETTINGS()
-    : userDelay(0),
-      userTimeout(0),
-      port(0),
-      freeMbShowType(freeMbCash),
-      logProtocolErrors(false)
-{
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA_SETTINGS::ParseSettings(const STG::ModuleSettings & s)
-{
-int p;
-STG::ParamValue pv;
-std::vector<STG::ParamValue>::const_iterator pvi;
-///////////////////////////
-pv.param = "Port";
-pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-if (pvi == s.moduleParams.end() || pvi->value.empty())
-    {
-    errorStr = "Parameter \'Port\' not found.";
-    printfd(__FILE__, "Parameter 'Port' not found\n");
-    return -1;
-    }
-if (ParseIntInRange(pvi->value[0], 2, 65535, &p))
-    {
-    errorStr = "Cannot parse parameter \'Port\': " + errorStr;
-    printfd(__FILE__, "Cannot parse parameter 'Port'\n");
-    return -1;
-    }
-port = static_cast<uint16_t>(p);
-///////////////////////////
-pv.param = "UserDelay";
-pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-if (pvi == s.moduleParams.end() || pvi->value.empty())
-    {
-    errorStr = "Parameter \'UserDelay\' not found.";
-    printfd(__FILE__, "Parameter 'UserDelay' not found\n");
-    return -1;
-    }
-
-if (ParseIntInRange(pvi->value[0], 5, 600, &userDelay))
-    {
-    errorStr = "Cannot parse parameter \'UserDelay\': " + errorStr;
-    printfd(__FILE__, "Cannot parse parameter 'UserDelay'\n");
-    return -1;
-    }
-///////////////////////////
-pv.param = "UserTimeout";
-pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-if (pvi == s.moduleParams.end() || pvi->value.empty())
-    {
-    errorStr = "Parameter \'UserTimeout\' not found.";
-    printfd(__FILE__, "Parameter 'UserTimeout' not found\n");
-    return -1;
-    }
-
-if (ParseIntInRange(pvi->value[0], 15, 1200, &userTimeout))
-    {
-    errorStr = "Cannot parse parameter \'UserTimeout\': " + errorStr;
-    printfd(__FILE__, "Cannot parse parameter 'UserTimeout'\n");
-    return -1;
-    }
-///////////////////////////
-pv.param = "LogProtocolErrors";
-pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-if (pvi == s.moduleParams.end() || pvi->value.empty())
-    logProtocolErrors = false;
-else if (ParseYesNo(pvi->value[0], &logProtocolErrors))
-    {
-    errorStr = "Cannot parse parameter \'LogProtocolErrors\': " + errorStr;
-    printfd(__FILE__, "Cannot parse parameter 'LogProtocolErrors'\n");
-    return -1;
-    }
-/////////////////////////////////////////////////////////////
-std::string freeMbType;
-int n = 0;
-pv.param = "FreeMb";
-pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-if (pvi == s.moduleParams.end() || pvi->value.empty())
-    {
-    errorStr = "Parameter \'FreeMb\' not found.";
-    printfd(__FILE__, "Parameter 'FreeMb' not found\n");
-    return -1;
-    }
-freeMbType = pvi->value[0];
-
-if (strcasecmp(freeMbType.c_str(), "cash") == 0)
-    {
-    freeMbShowType = freeMbCash;
-    }
-else if (strcasecmp(freeMbType.c_str(), "none") == 0)
-    {
-    freeMbShowType = freeMbNone;
-    }
-else if (!str2x(freeMbType.c_str(), n))
-    {
-    if (n < 0 || n >= DIR_NUM)
-        {
-        errorStr = "Incorrect parameter \'" + freeMbType + "\'.";
-        printfd(__FILE__, "%s\n", errorStr.c_str());
-        return -1;
-        }
-    freeMbShowType = (FREEMB)(freeMb0 + n);
-    }
-else
-    {
-    errorStr = "Incorrect parameter \'" + freeMbType + "\'.";
-    printfd(__FILE__, "%s\n", errorStr.c_str());
-    return -1;
-    }
-/////////////////////////////////////////////////////////////
-return 0;
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-#ifdef IA_PHASE_DEBUG
-IA_PHASE::IA_PHASE()
-    : phase(1),
-      flog(NULL)
-{
-gettimeofday(&phaseTime, NULL);
-}
-#else
-IA_PHASE::IA_PHASE()
-    : phase(1)
-{
-gettimeofday(&phaseTime, NULL);
-}
-#endif
-//-----------------------------------------------------------------------------
-IA_PHASE::~IA_PHASE()
-{
-#ifdef IA_PHASE_DEBUG
-flog = fopen(log.c_str(), "at");
-if (flog)
-    {
-    fprintf(flog, "IA %s D\n", login.c_str());
-    fclose(flog);
-    }
-#endif
-}
-//-----------------------------------------------------------------------------
-#ifdef IA_PHASE_DEBUG
-void IA_PHASE::SetLogFileName(const string & logFileName)
-{
-log = logFileName + ".ia.log";
-}
-//-----------------------------------------------------------------------------
-void IA_PHASE::SetUserLogin(const string & login)
-{
-IA_PHASE::login = login;
-}
-//-----------------------------------------------------------------------------
-void IA_PHASE::WritePhaseChange(int newPhase)
-{
-UTIME newPhaseTime;
-gettimeofday(&newPhaseTime, NULL);
-flog = fopen(log.c_str(), "at");
-if (flog)
-    {
-    string action = newPhase == phase ? "U" : "C";
-    double delta = newPhaseTime.GetSec() - phaseTime.GetSec();
-    delta += (newPhaseTime.GetUSec() - phaseTime.GetUSec()) * 1.0e-6;
-    fprintf(flog, "IA %s %s oldPhase = %d, newPhase = %d. dt = %.6f\n",
-            login.c_str(),
-            action.c_str(),
-            phase,
-            newPhase,
-            delta);
-    fclose(flog);
-    }
-}
-#endif
-//-----------------------------------------------------------------------------
-void IA_PHASE::SetPhase1()
-{
-#ifdef IA_PHASE_DEBUG
-WritePhaseChange(1);
-#endif
-phase = 1;
-gettimeofday(&phaseTime, NULL);
-}
-//-----------------------------------------------------------------------------
-void IA_PHASE::SetPhase2()
-{
-#ifdef IA_PHASE_DEBUG
-WritePhaseChange(2);
-#endif
-phase = 2;
-gettimeofday(&phaseTime, NULL);
-}
-//-----------------------------------------------------------------------------
-void IA_PHASE::SetPhase3()
-{
-#ifdef IA_PHASE_DEBUG
-WritePhaseChange(3);
-#endif
-phase = 3;
-gettimeofday(&phaseTime, NULL);
-}
-//-----------------------------------------------------------------------------
-void IA_PHASE::SetPhase4()
-{
-#ifdef IA_PHASE_DEBUG
-WritePhaseChange(4);
-#endif
-phase = 4;
-gettimeofday(&phaseTime, NULL);
-}
-//-----------------------------------------------------------------------------
-int IA_PHASE::GetPhase() const
-{
-return phase;
-}
-//-----------------------------------------------------------------------------
-void IA_PHASE::UpdateTime()
-{
-#ifdef IA_PHASE_DEBUG
-WritePhaseChange(phase);
-#endif
-gettimeofday(&phaseTime, NULL);
-}
-//-----------------------------------------------------------------------------
-const UTIME & IA_PHASE::GetTime() const
-{
-return phaseTime;
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-AUTH_IA::AUTH_IA()
-    : nonstop(false),
-      isRunningRun(false),
-      isRunningRunTimeouter(false),
-      users(NULL),
-      stgSettings(NULL),
-      listenSocket(-1),
-      enabledDirs(0xFFffFFff),
-      onDelUserNotifier(*this),
-      logger(STG::PluginLogger::get("auth_ia"))
-{
-InitContext("pr7Hhen", 7, &ctxS);
-
-pthread_mutexattr_t attr;
-pthread_mutexattr_init(&attr);
-pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
-pthread_mutex_init(&mutex, &attr);
-
-memset(&connSynAck6, 0, sizeof(CONN_SYN_ACK_6));
-memset(&connSynAck8, 0, sizeof(CONN_SYN_ACK_8));
-memset(&disconnSynAck6, 0, sizeof(DISCONN_SYN_ACK_6));
-memset(&disconnSynAck8, 0, sizeof(DISCONN_SYN_ACK_8));
-memset(&aliveSyn6, 0, sizeof(ALIVE_SYN_6));
-memset(&aliveSyn8, 0, sizeof(ALIVE_SYN_8));
-memset(&fin6, 0, sizeof(FIN_6));
-memset(&fin8, 0, sizeof(FIN_8));
-
-printfd(__FILE__, "sizeof(CONN_SYN_6) = %d %d\n",           sizeof(CONN_SYN_6),     Min8(sizeof(CONN_SYN_6)));
-printfd(__FILE__, "sizeof(CONN_SYN_8) = %d %d\n",           sizeof(CONN_SYN_8),     Min8(sizeof(CONN_SYN_8)));
-printfd(__FILE__, "sizeof(CONN_SYN_ACK_6) = %d %d\n",       sizeof(CONN_SYN_ACK_6), Min8(sizeof(CONN_SYN_ACK_6)));
-printfd(__FILE__, "sizeof(CONN_SYN_ACK_8) = %d %d\n",       sizeof(CONN_SYN_ACK_8), Min8(sizeof(CONN_SYN_ACK_8)));
-printfd(__FILE__, "sizeof(CONN_ACK_6) = %d %d\n",           sizeof(CONN_ACK_6),     Min8(sizeof(CONN_ACK_6)));
-printfd(__FILE__, "sizeof(ALIVE_SYN_6) = %d %d\n",          sizeof(ALIVE_SYN_6),    Min8(sizeof(ALIVE_SYN_6)));
-printfd(__FILE__, "sizeof(ALIVE_SYN_8) = %d %d\n",          sizeof(ALIVE_SYN_8),    Min8(sizeof(ALIVE_SYN_8)));
-printfd(__FILE__, "sizeof(ALIVE_ACK_6) = %d %d\n",          sizeof(ALIVE_ACK_6),    Min8(sizeof(ALIVE_ACK_6)));
-printfd(__FILE__, "sizeof(DISCONN_SYN_6) = %d %d\n",        sizeof(DISCONN_SYN_6),  Min8(sizeof(DISCONN_SYN_6)));
-printfd(__FILE__, "sizeof(DISCONN_SYN_ACK_6) = %d %d\n",    sizeof(DISCONN_SYN_ACK_6), Min8(sizeof(DISCONN_SYN_ACK_6)));
-printfd(__FILE__, "sizeof(DISCONN_SYN_ACK_8) = %d %d\n",    sizeof(DISCONN_SYN_ACK_8), Min8(sizeof(DISCONN_SYN_ACK_8)));
-printfd(__FILE__, "sizeof(DISCONN_ACK_6) = %d %d\n",        sizeof(DISCONN_ACK_6),  Min8(sizeof(DISCONN_ACK_6)));
-printfd(__FILE__, "sizeof(FIN_6) = %d %d\n",                sizeof(FIN_6),          Min8(sizeof(FIN_6)));
-printfd(__FILE__, "sizeof(FIN_8) = %d %d\n",                sizeof(FIN_8),          Min8(sizeof(FIN_8)));
-printfd(__FILE__, "sizeof(ERR) = %d %d\n",                  sizeof(ERR),            Min8(sizeof(ERR)));
-printfd(__FILE__, "sizeof(INFO_6) = %d %d\n",               sizeof(INFO_6),         Min8(sizeof(INFO_6)));
-printfd(__FILE__, "sizeof(INFO_7) = %d %d\n",               sizeof(INFO_7),         Min8(sizeof(INFO_7)));
-printfd(__FILE__, "sizeof(INFO_8) = %d %d\n",               sizeof(INFO_8),         Min8(sizeof(INFO_8)));
-
-packetTypes["CONN_SYN"] = CONN_SYN_N;
-packetTypes["CONN_SYN_ACK"] = CONN_SYN_ACK_N;
-packetTypes["CONN_ACK"] = CONN_ACK_N;
-packetTypes["ALIVE_SYN"] = ALIVE_SYN_N;
-packetTypes["ALIVE_ACK"] = ALIVE_ACK_N;
-packetTypes["DISCONN_SYN"] = DISCONN_SYN_N;
-packetTypes["DISCONN_SYN_ACK"] = DISCONN_SYN_ACK_N;
-packetTypes["DISCONN_ACK"] = DISCONN_ACK_N;
-packetTypes["FIN"] = FIN_N;
-packetTypes["ERR"] = ERROR_N;
-}
-//-----------------------------------------------------------------------------
-AUTH_IA::~AUTH_IA()
-{
-pthread_mutex_destroy(&mutex);
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Start()
-{
-users->AddNotifierUserDel(&onDelUserNotifier);
-nonstop = true;
-
-if (PrepareNet())
-    {
-    return -1;
-    }
-
-if (!isRunningRun)
-    {
-    if (pthread_create(&recvThread, NULL, Run, this))
-        {
-        errorStr = "Cannot create thread.";
-        printfd(__FILE__, "Cannot create recv thread\n");
-        logger("Cannot create recv thread.");
-        return -1;
-        }
-    }
-
-if (!isRunningRunTimeouter)
-    {
-    if (pthread_create(&timeouterThread, NULL, RunTimeouter, this))
-        {
-        errorStr = "Cannot create thread.";
-        printfd(__FILE__, "Cannot create timeouter thread\n");
-        logger("Cannot create timeouter thread.");
-        return -1;
-        }
-    }
-errorStr = "";
-return 0;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Stop()
-{
-if (!IsRunning())
-    return 0;
-
-nonstop = false;
-
-std::for_each(
-        ip2user.begin(),
-        ip2user.end(),
-        UnauthorizeUser(this)
-        );
-
-if (isRunningRun)
-    {
-    //5 seconds to thread stops itself
-    for (int i = 0; i < 25 && isRunningRun; i++)
-        {
-        struct timespec ts = {0, 200000000};
-        nanosleep(&ts, NULL);
-        }
-    }
-
-FinalizeNet();
-
-if (isRunningRunTimeouter)
-    {
-    //5 seconds to thread stops itself
-    for (int i = 0; i < 25 && isRunningRunTimeouter; i++)
-        {
-        struct timespec ts = {0, 200000000};
-        nanosleep(&ts, NULL);
-        }
-    }
-
-users->DelNotifierUserDel(&onDelUserNotifier);
-
-if (isRunningRun || isRunningRunTimeouter)
-    return -1;
-
-printfd(__FILE__, "AUTH_IA::Stoped successfully.\n");
-return 0;
-}
-//-----------------------------------------------------------------------------
-void * AUTH_IA::Run(void * d)
-{
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-AUTH_IA * ia = static_cast<AUTH_IA *>(d);
-
-ia->isRunningRun = true;
-
-char buffer[512];
-
-time_t touchTime = stgTime - MONITOR_TIME_DELAY_SEC;
-
-while (ia->nonstop)
-    {
-    ia->RecvData(buffer, sizeof(buffer));
-    if ((touchTime + MONITOR_TIME_DELAY_SEC <= stgTime) && ia->stgSettings->GetMonitoring())
-        {
-        touchTime = stgTime;
-        std::string monFile = ia->stgSettings->GetMonitorDir() + "/inetaccess_r";
-        TouchFile(monFile);
-        }
-    }
-
-ia->isRunningRun = false;
-return NULL;
-}
-//-----------------------------------------------------------------------------
-void * AUTH_IA::RunTimeouter(void * d)
-{
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-AUTH_IA * ia = static_cast<AUTH_IA *>(d);
-
-ia->isRunningRunTimeouter = true;
-
-int a = -1;
-std::string monFile = ia->stgSettings->GetMonitorDir() + "/inetaccess_t";
-while (ia->nonstop)
-    {
-    struct timespec ts = {0, 20000000};
-    nanosleep(&ts, NULL);
-    ia->Timeouter();
-    // TODO change counter to timer and MONITOR_TIME_DELAY_SEC
-    if (++a % (50 * 60) == 0 && ia->stgSettings->GetMonitoring())
-        {
-        TouchFile(monFile);
-        }
-    }
-
-ia->isRunningRunTimeouter = false;
-return NULL;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::ParseSettings()
-{
-int ret = iaSettings.ParseSettings(settings);
-if (ret)
-    errorStr = iaSettings.GetStrError();
-return ret;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Reload(const STG::ModuleSettings & ms)
-{
-AUTH_IA_SETTINGS newIaSettings;
-if (newIaSettings.ParseSettings(ms))
-    {
-    printfd(__FILE__, "AUTH_IA::Reload() - Failed to reload InetAccess.\n");
-    logger("AUTH_IA: Cannot reload InetAccess. Errors found.");
-    return -1;
-    }
-
-printfd(__FILE__, "AUTH_IA::Reload() -  Reloaded InetAccess successfully.\n");
-logger("AUTH_IA: Reloaded InetAccess successfully.");
-iaSettings = newIaSettings;
-return 0;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::PrepareNet()
-{
-struct sockaddr_in listenAddr;
-
-listenSocket = socket(AF_INET, SOCK_DGRAM, 0);
-
-if (listenSocket < 0)
-    {
-    errorStr = "Cannot create socket.";
-    logger("Cannot create a socket: %s", strerror(errno));
-    return -1;
-    }
-
-listenAddr.sin_family = AF_INET;
-listenAddr.sin_port = htons(static_cast<uint16_t>(iaSettings.GetUserPort()));
-listenAddr.sin_addr.s_addr = inet_addr("0.0.0.0");
-
-if (bind(listenSocket, (struct sockaddr*)&listenAddr, sizeof(listenAddr)) < 0)
-    {
-    errorStr = "AUTH_IA: Bind failed.";
-    logger("Cannot bind the socket: %s", strerror(errno));
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::FinalizeNet()
-{
-close(listenSocket);
-return 0;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::RecvData(char * buffer, int bufferSize)
-{
-if (!WaitPackets(listenSocket)) // Timeout
-    {
-    return 0;
-    }
-
-struct sockaddr_in outerAddr;
-socklen_t outerAddrLen(sizeof(outerAddr));
-ssize_t dataLen = recvfrom(listenSocket, buffer, bufferSize, 0, (struct sockaddr *)&outerAddr, &outerAddrLen);
-
-if (!dataLen) // EOF
-    {
-    return 0;
-    }
-
-if (dataLen <= 0) // Error
-    {
-    if (errno != EINTR)
-        {
-        printfd(__FILE__, "recvfrom res=%d, error: '%s'\n", dataLen, strerror(errno));
-        logger("recvfrom error: %s", strerror(errno));
-        return -1;
-        }
-    return 0;
-    }
-
-if (dataLen > 256)
-    return -1;
-
-uint32_t sip = outerAddr.sin_addr.s_addr;
-uint16_t sport = htons(outerAddr.sin_port);
-
-int protoVer;
-if (CheckHeader(buffer, sip, &protoVer))
-    return -1;
-
-char login[PASSWD_LEN];  //TODO why PASSWD_LEN ?
-memset(login, 0, PASSWD_LEN);
-
-DecryptString(login, buffer + 8, PASSWD_LEN, &ctxS);
-
-UserPtr user;
-if (users->FindByName(login, &user))
-    {
-    logger("User's connect failed: user '%s' not found. IP %s",
-           login,
-           inet_ntostring(sip).c_str());
-    printfd(__FILE__, "User '%s' NOT found!\n", login);
-    SendError(sip, sport, protoVer, IconvString("Неправильный логин.", "utf8", "koi8-ru"));
-    return -1;
-    }
-
-printfd(__FILE__, "User '%s' FOUND!\n", user->GetLogin().c_str());
-
-if (user->GetProperties().disabled.Get())
-    {
-    logger("Cannont authorize '%s', user is disabled.", login);
-    SendError(sip, sport, protoVer, IconvString("Учетная запись заблокирована.", "utf8", "koi8-ru"));
-    return 0;
-    }
-
-if (user->GetProperties().passive.Get())
-    {
-    logger("Cannont authorize '%s', user is passive.", login);
-    SendError(sip, sport, protoVer, IconvString("Учетная запись заморожена.", "utf8", "koi8-ru"));
-    return 0;
-    }
-
-if (!user->GetProperties().ips.Get().find(sip))
-    {
-    printfd(__FILE__, "User %s. IP address is incorrect. IP %s\n",
-            user->GetLogin().c_str(), inet_ntostring(sip).c_str());
-    logger("User %s. IP address is incorrect. IP %s",
-           user->GetLogin().c_str(), inet_ntostring(sip).c_str());
-    SendError(sip, sport, protoVer, IconvString("Пользователь не опознан. Проверьте IP-адрес.", "utf8", "koi8-ru"));
-    return 0;
-    }
-
-return PacketProcessor(buffer, dataLen, sip, sport, protoVer, user);
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::CheckHeader(const char * buffer, uint32_t sip, int * protoVer)
-{
-if (strncmp(IA_ID, buffer, strlen(IA_ID)) != 0)
-    {
-    printfd(__FILE__, "update needed - IA_ID\n");
-    if (iaSettings.LogProtocolErrors())
-        logger("IP: %s. Header: invalid packed signature.", inet_ntostring(sip).c_str());
-    return -1;
-    }
-
-if (buffer[6] != 0) //proto[0] shoud be 0
-    {
-    printfd(__FILE__, "update needed - PROTO major: %d\n", buffer[6]);
-    if (iaSettings.LogProtocolErrors())
-        logger("IP: %s. Header: invalid protocol major version: %d.", inet_ntostring(sip).c_str(), buffer[6]);
-    return -1;
-    }
-
-if (buffer[7] < 6)
-    {
-    // need update
-    printfd(__FILE__, "update needed - PROTO minor: %d\n", buffer[7]);
-    if (iaSettings.LogProtocolErrors())
-        logger("IP: %s. Header: invalid protocol minor version: %d.", inet_ntostring(sip).c_str(), buffer[7]);
-    return -1;
-    }
-else
-    {
-    *protoVer = buffer[7];
-    }
-return 0;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Timeouter()
-{
-STG_LOCKER lock(&mutex);
-
-std::map<uint32_t, IA_USER>::iterator it;
-it = ip2user.begin();
-
-while (it != ip2user.end())
-    {
-    uint32_t sip = it->first;
-
-    static UTIME currTime;
-    gettimeofday(&currTime, NULL);
-
-    if ((it->second.phase.GetPhase() == 2)
-        && (currTime - it->second.phase.GetTime()) > iaSettings.GetUserDelay())
-        {
-        if (iaSettings.LogProtocolErrors())
-            logger("User '%s'. Protocol version: %d. Phase 2: connect request timeout (%f > %d).", it->second.login.c_str(), it->second.protoVer, (currTime - it->second.phase.GetTime()).AsDouble(), iaSettings.GetUserDelay().GetSec());
-        it->second.phase.SetPhase1();
-        printfd(__FILE__, "Phase changed from 2 to 1. Reason: timeout\n");
-        ip2user.erase(it++);
-        continue;
-        }
-
-    if (it->second.phase.GetPhase() == 3)
-        {
-        if (!it->second.messagesToSend.empty())
-            {
-            if (it->second.protoVer == 6)
-                RealSendMessage6(*it->second.messagesToSend.begin(), sip, it->second);
-
-            if (it->second.protoVer == 7)
-                RealSendMessage7(*it->second.messagesToSend.begin(), sip, it->second);
-
-            if (it->second.protoVer == 8)
-                RealSendMessage8(*it->second.messagesToSend.begin(), sip, it->second);
-
-            it->second.messagesToSend.erase(it->second.messagesToSend.begin());
-            }
-
-        if((currTime - it->second.lastSendAlive) > iaSettings.GetUserDelay())
-            {
-            switch (it->second.protoVer)
-                {
-                case 6:
-                    Send_ALIVE_SYN_6(&(it->second), sip);
-                    break;
-                case 7:
-                    Send_ALIVE_SYN_7(&(it->second), sip);
-                    break;
-                case 8:
-                    Send_ALIVE_SYN_8(&(it->second), sip);
-                    break;
-                }
-
-            gettimeofday(&it->second.lastSendAlive, NULL);
-            }
-
-        if ((currTime - it->second.phase.GetTime()) > iaSettings.GetUserTimeout())
-            {
-            if (iaSettings.LogProtocolErrors())
-                logger("User '%s'. Protocol version: %d. Phase 3: alive timeout (%f > %d).", it->second.login.c_str(), it->second.protoVer, (currTime - it->second.phase.GetTime()).AsDouble(), iaSettings.GetUserTimeout().GetSec());
-            users->Unauthorize(it->second.user->GetLogin(), this);
-            ip2user.erase(it++);
-            continue;
-            }
-        }
-
-    if ((it->second.phase.GetPhase() == 4)
-        && ((currTime - it->second.phase.GetTime()) > iaSettings.GetUserDelay()))
-        {
-        if (iaSettings.LogProtocolErrors())
-            logger("User '%s'. Protocol version: %d. Phase 4: disconnect request timeout (%f > %d).", it->second.login.c_str(), it->second.protoVer, (currTime - it->second.phase.GetTime()).AsDouble(), iaSettings.GetUserDelay().GetSec());
-        it->second.phase.SetPhase3();
-        printfd(__FILE__, "Phase changed from 4 to 3. Reason: timeout\n");
-        }
-
-    ++it;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::PacketProcessor(void * buff, size_t dataLen, uint32_t sip, uint16_t sport, int protoVer, UserPtr user)
-{
-std::string login(user->GetLogin());
-const size_t offset = LOGIN_LEN + 2 + 6; // LOGIN_LEN + sizeOfMagic + sizeOfVer;
-
-STG_LOCKER lock(&mutex);
-std::map<uint32_t, IA_USER>::iterator it(ip2user.find(sip));
-
-if (it == ip2user.end())
-    {
-    UserPtr userPtr;
-    if (!users->FindByIPIdx(sip, &userPtr))
-        {
-        if (userPtr->GetID() != user->GetID())
-            {
-            printfd(__FILE__, "IP address already in use by user '%s'. IP %s, login: '%s'\n",
-                    userPtr->GetLogin().c_str(),
-                    inet_ntostring(sip).c_str(),
-                   login.c_str());
-            logger("IP address is already in use by user '%s'. IP %s, login: '%s'",
-                   userPtr->GetLogin().c_str(),
-                   inet_ntostring(sip).c_str(),
-                   login.c_str());
-            SendError(sip, sport, protoVer, IconvString("IP-адрес уже сипользуется.", "utf8", "koi8-ru"));
-            return 0;
-            }
-        }
-
-    printfd(__FILE__, "Add new user '%s' from ip %s\n",
-            login.c_str(), inet_ntostring(sip).c_str());
-    std::pair<std::map<uint32_t, IA_USER>::iterator, bool> res;
-    res = ip2user.insert(std::make_pair(sip, IA_USER(login, user, sport, protoVer)));
-    it = res.first;
-    #ifdef IA_PHASE_DEBUG
-    it->second.phase.SetLogFileName(stgSettings->GetLogFileName());
-    it->second.phase.SetUserLogin(login);
-    #endif
-    }
-else if (user->GetID() != it->second.user->GetID())
-    {
-    printfd(__FILE__, "IP address already in use by user '%s'. IP %s, login: '%s'\n",
-            it->second.user->GetLogin().c_str(),
-            inet_ntostring(sip).c_str(),
-            user->GetLogin().c_str());
-    logger("IP address is already in use by user '%s'. IP %s, login: '%s'",
-           it->second.user->GetLogin().c_str(),
-           inet_ntostring(sip).c_str(),
-           user->GetLogin().c_str());
-    SendError(sip, sport, protoVer, IconvString("IP-адрес уже используется.", "utf8", "koi8-ru"));
-    return 0;
-    }
-
-IA_USER * iaUser = &(it->second);
-
-if (iaUser->password != user->GetProperties().password.Get())
-    {
-    const std::string & password = user->GetProperties().password.Get();
-    InitContext(password.c_str(), password.length(), &iaUser->ctx);
-    iaUser->password = user->GetProperties().password.Get();
-    }
-
-DecryptString(static_cast<char *>(buff) + offset, static_cast<char *>(buff) + offset, (dataLen - offset), &iaUser->ctx);
-
-char packetName[IA_MAX_TYPE_LEN];
-strncpy(packetName,  static_cast<char *>(buff) + offset + 4, IA_MAX_TYPE_LEN);
-packetName[IA_MAX_TYPE_LEN - 1] = 0;
-
-std::map<std::string, int>::iterator pi(packetTypes.find(packetName));
-if (pi == packetTypes.end())
-    {
-    SendError(sip, sport, protoVer, IconvString("Неправильный логин или пароль.", "utf8", "koi8-ru"));
-    printfd(__FILE__, "Login or password is wrong!\n");
-    logger("User's connect failed. User: '%s', ip %s. Wrong login or password",
-           login.c_str(),
-           inet_ntostring(sip).c_str());
-    ip2user.erase(it);
-    return 0;
-    }
-
-if (user->IsAuthorizedBy(this) && user->GetCurrIP() != sip)
-    {
-    printfd(__FILE__, "Login %s already in use from ip %s. IP %s\n",
-            login.c_str(), inet_ntostring(user->GetCurrIP()).c_str(),
-            inet_ntostring(sip).c_str());
-    logger("Login '%s' is already in use from ip %s. IP %s",
-           login.c_str(),
-           inet_ntostring(user->GetCurrIP()).c_str(),
-           inet_ntostring(sip).c_str());
-    SendError(sip, sport, protoVer, IconvString("Логин уже используется.", "utf8", "koi8-ru"));
-    ip2user.erase(it);
-    return 0;
-    }
-
-switch (pi->second)
-    {
-    case CONN_SYN_N:
-        switch (protoVer)
-            {
-            case 6:
-                if (Process_CONN_SYN_6(static_cast<CONN_SYN_6 *>(buff), &(it->second), sip))
-                    return -1;
-                return Send_CONN_SYN_ACK_6(iaUser, sip);
-            case 7:
-                if (Process_CONN_SYN_7(static_cast<CONN_SYN_7 *>(buff), &(it->second), sip))
-                    return -1;
-                return Send_CONN_SYN_ACK_7(iaUser, sip);
-            case 8:
-                if (Process_CONN_SYN_8(static_cast<CONN_SYN_8 *>(buff), &(it->second), sip))
-                    return -1;
-                return Send_CONN_SYN_ACK_8(iaUser, sip);
-            }
-        break;
-
-    case CONN_ACK_N:
-        switch (protoVer)
-            {
-            case 6:
-                if (Process_CONN_ACK_6(static_cast<CONN_ACK_6 *>(buff), iaUser, sip))
-                    return -1;
-                return Send_ALIVE_SYN_6(iaUser, sip);
-            case 7:
-                if (Process_CONN_ACK_7(static_cast<CONN_ACK_6 *>(buff), iaUser, sip))
-                    return -1;
-                return Send_ALIVE_SYN_7(iaUser, sip);
-            case 8:
-                if (Process_CONN_ACK_8(static_cast<CONN_ACK_8 *>(buff), iaUser, sip))
-                    return -1;
-                return Send_ALIVE_SYN_8(iaUser, sip);
-            }
-        break;
-
-    case ALIVE_ACK_N:
-        switch (protoVer)
-            {
-            case 6:
-                return Process_ALIVE_ACK_6(static_cast<ALIVE_ACK_6 *>(buff), iaUser, sip);
-            case 7:
-                return Process_ALIVE_ACK_7(static_cast<ALIVE_ACK_6 *>(buff), iaUser, sip);
-            case 8:
-                return Process_ALIVE_ACK_8(static_cast<ALIVE_ACK_8 *>(buff), iaUser, sip);
-            }
-        break;
-
-    case DISCONN_SYN_N:
-        switch (protoVer)
-            {
-            case 6:
-                if (Process_DISCONN_SYN_6(static_cast<DISCONN_SYN_6 *>(buff), iaUser, sip))
-                    return -1;
-                return Send_DISCONN_SYN_ACK_6(iaUser, sip);
-            case 7:
-                if (Process_DISCONN_SYN_7(static_cast<DISCONN_SYN_6 *>(buff), iaUser, sip))
-                    return -1;
-                return Send_DISCONN_SYN_ACK_7(iaUser, sip);
-            case 8:
-                if (Process_DISCONN_SYN_8(static_cast<DISCONN_SYN_8 *>(buff), iaUser, sip))
-                    return -1;
-                return Send_DISCONN_SYN_ACK_8(iaUser, sip);
-            }
-        break;
-
-    case DISCONN_ACK_N:
-        switch (protoVer)
-            {
-            case 6:
-                if (Process_DISCONN_ACK_6(static_cast<DISCONN_ACK_6 *>(buff), iaUser, sip, it))
-                    return -1;
-                return Send_FIN_6(iaUser, sip, it);
-            case 7:
-                if (Process_DISCONN_ACK_7(static_cast<DISCONN_ACK_6 *>(buff), iaUser, sip, it))
-                    return -1;
-                return Send_FIN_7(iaUser, sip, it);
-            case 8:
-                if (Process_DISCONN_ACK_8(static_cast<DISCONN_ACK_8 *>(buff), iaUser, sip, it))
-                    return -1;
-                return Send_FIN_8(iaUser, sip, it);
-            }
-        break;
-    }
-
-return -1;
-}
-//-----------------------------------------------------------------------------
-void AUTH_IA::DelUser(UserPtr u)
-{
-
-uint32_t ip = u->GetCurrIP();
-
-if (!ip)
-    return;
-
-std::map<uint32_t, IA_USER>::iterator it;
-
-STG_LOCKER lock(&mutex);
-it = ip2user.find(ip);
-if (it == ip2user.end())
-    {
-    //Nothing to delete
-    printfd(__FILE__, "Nothing to delete\n");
-    return;
-    }
-
-if (it->second.user == u)
-    {
-    printfd(__FILE__, "User removed!\n");
-    users->Unauthorize(u->GetLogin(), this);
-    ip2user.erase(it);
-    }
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::SendError(uint32_t ip, uint16_t port, int protoVer, const std::string & text)
-{
-struct sockaddr_in sendAddr;
-ssize_t res;
-switch (protoVer)
-    {
-    case 6:
-    case 7:
-        ERR err;
-        memset(&err, 0, sizeof(ERR));
-
-        sendAddr.sin_family = AF_INET;
-        sendAddr.sin_port = htons(port);
-        sendAddr.sin_addr.s_addr = ip;
-
-        err.len = 1;
-        strncpy((char*)err.type, "ERR", 16);
-        strncpy((char*)err.text, text.c_str(), MAX_MSG_LEN);
-
-        #ifdef ARCH_BE
-        SwapBytes(err.len);
-        #endif
-
-        res = sendto(listenSocket, &err, sizeof(err), 0, (struct sockaddr*)&sendAddr, sizeof(sendAddr));
-        printfd(__FILE__, "SendError %d bytes sent\n", res);
-        break;
-
-    case 8:
-        ERR_8 err8;
-        memset(&err8, 0, sizeof(ERR_8));
-
-        sendAddr.sin_family = AF_INET;
-        sendAddr.sin_port = htons(port);
-        sendAddr.sin_addr.s_addr = ip;
-
-        err8.len = 256;
-        strncpy((char*)err8.type, "ERR", 16);
-        strncpy((char*)err8.text, text.c_str(), MAX_MSG_LEN);
-
-        #ifdef ARCH_BE
-        SwapBytes(err8.len);
-        #endif
-
-        res = sendto(listenSocket, &err8, sizeof(err8), 0, (struct sockaddr*)&sendAddr, sizeof(sendAddr));
-        printfd(__FILE__, "SendError_8 %d bytes sent\n", res);
-        break;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Send(uint32_t ip, uint16_t port, const char * buffer, size_t len)
-{
-struct sockaddr_in sendAddr;
-
-sendAddr.sin_family = AF_INET;
-sendAddr.sin_port = htons(port);
-sendAddr.sin_addr.s_addr = ip;
-
-if (sendto(listenSocket, buffer, len, 0, (struct sockaddr*)&sendAddr, sizeof(sendAddr)) == static_cast<ssize_t>(len))
-    return 0;
-
-return -1;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::SendMessage(const STG::Message & msg, uint32_t ip) const
-{
-printfd(__FILE__, "SendMessage userIP=%s\n", inet_ntostring(ip).c_str());
-
-std::map<uint32_t, IA_USER>::iterator it;
-
-STG_LOCKER lock(&mutex);
-it = ip2user.find(ip);
-if (it == ip2user.end())
-    {
-    errorStr = "Unknown user.";
-    return -1;
-    }
-it->second.messagesToSend.push_back(msg);
-return 0;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::RealSendMessage6(const STG::Message & msg, uint32_t ip, IA_USER & user)
-{
-printfd(__FILE__, "RealSendMessage 6 user=%s\n", user.login.c_str());
-
-INFO_6 info;
-memset(&info, 0, sizeof(INFO_6));
-
-info.len = 256;
-strncpy((char*)info.type, "INFO", 16);
-info.infoType = 'I';
-strncpy((char*)info.text, msg.text.c_str(), 235);
-info.text[234] = 0;
-
-size_t len = info.len;
-#ifdef ARCH_BE
-SwapBytes(info.len);
-#endif
-
-char buffer[256];
-memcpy(buffer, &info, sizeof(INFO_6));
-EncryptString(buffer, buffer, len, &user.ctx);
-return Send(ip, iaSettings.GetUserPort(), buffer, len);
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::RealSendMessage7(const STG::Message & msg, uint32_t ip, IA_USER & user)
-{
-printfd(__FILE__, "RealSendMessage 7 user=%s\n", user.login.c_str());
-
-INFO_7 info;
-memset(&info, 0, sizeof(INFO_7));
-
-info.len = 264;
-strncpy((char*)info.type, "INFO_7", 16);
-info.infoType = static_cast<int8_t>(msg.header.type);
-info.showTime = static_cast<int8_t>(msg.header.showTime);
-info.sendTime = msg.header.creationTime;
-
-size_t len = info.len;
-#ifdef ARCH_BE
-SwapBytes(info.len);
-SwapBytes(info.sendTime);
-#endif
-
-strncpy((char*)info.text, msg.text.c_str(), MAX_MSG_LEN - 1);
-info.text[MAX_MSG_LEN - 1] = 0;
-
-char buffer[300];
-memcpy(buffer, &info, sizeof(INFO_7));
-
-EncryptString(buffer, buffer, len, &user.ctx);
-return Send(ip, iaSettings.GetUserPort(), buffer, len);
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::RealSendMessage8(const STG::Message & msg, uint32_t ip, IA_USER & user)
-{
-printfd(__FILE__, "RealSendMessage 8 user=%s\n", user.login.c_str());
-
-INFO_8 info;
-memset(&info, 0, sizeof(INFO_8));
-
-info.len = 1056;
-strncpy((char*)info.type, "INFO_8", 16);
-info.infoType = static_cast<int8_t>(msg.header.type);
-info.showTime = static_cast<int8_t>(msg.header.showTime);
-info.sendTime = msg.header.creationTime;
-
-strncpy((char*)info.text, msg.text.c_str(), IA_MAX_MSG_LEN_8 - 1);
-info.text[IA_MAX_MSG_LEN_8 - 1] = 0;
-
-size_t len = info.len;
-#ifdef ARCH_BE
-SwapBytes(info.len);
-SwapBytes(info.sendTime);
-#endif
-
-char buffer[1500];
-memcpy(buffer, &info, sizeof(INFO_8));
-
-EncryptString(buffer, buffer, len, &user.ctx);
-return Send(ip, user.port, buffer, len);
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Process_CONN_SYN_6(CONN_SYN_6 *, IA_USER * iaUser, uint32_t)
-{
-if (!(iaUser->phase.GetPhase() == 1 || iaUser->phase.GetPhase() == 3))
-    return -1;
-
-enabledDirs = 0xFFffFFff;
-
-iaUser->phase.SetPhase2();
-printfd(__FILE__, "Phase changed from %d to 2. Reason: CONN_SYN_6\n", iaUser->phase.GetPhase());
-return 0;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Process_CONN_SYN_7(CONN_SYN_7 * connSyn, IA_USER * iaUser, uint32_t sip)
-{
-return Process_CONN_SYN_6(connSyn, iaUser, sip);
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Process_CONN_SYN_8(CONN_SYN_8 * connSyn, IA_USER * iaUser, uint32_t sip)
-{
-#ifdef ARCH_BE
-SwapBytes(connSyn->dirs);
-#endif
-int ret = Process_CONN_SYN_6(reinterpret_cast<CONN_SYN_6 *>(connSyn), iaUser, sip);
-enabledDirs = connSyn->dirs;
-return ret;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Process_CONN_ACK_6(CONN_ACK_6 * connAck, IA_USER * iaUser, uint32_t sip)
-{
-#ifdef ARCH_BE
-SwapBytes(connAck->len);
-SwapBytes(connAck->rnd);
-#endif
-printfd( __FILE__, "CONN_ACK_6 %s\n", connAck->type);
-
-if ((iaUser->phase.GetPhase() == 2) && (connAck->rnd == iaUser->rnd + 1))
-    {
-    iaUser->phase.UpdateTime();
-
-    iaUser->lastSendAlive = iaUser->phase.GetTime();
-    if (users->Authorize(iaUser->login, sip, enabledDirs, this))
-        {
-        iaUser->phase.SetPhase3();
-        printfd(__FILE__, "Phase changed from 2 to 3. Reason: CONN_ACK_6\n");
-        return 0;
-        }
-    else
-        {
-        errorStr = iaUser->user->GetStrError();
-        if (iaSettings.LogProtocolErrors())
-            logger("IP: %s. User '%s'. Protocol version: %d. CONN_ACK: phase 2, authorization error ('%s').", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, errorStr.c_str());
-        iaUser->phase.SetPhase1();
-        ip2user.erase(sip);
-        printfd(__FILE__, "Phase changed from 2 to 1. Reason: failed to authorize user\n");
-        return -1;
-        }
-    }
-printfd(__FILE__, "Invalid phase or control number. Phase: %d. Control number: %d, expected: %d\n", iaUser->phase.GetPhase(), connAck->rnd, iaUser->rnd + 1);
-if (iaSettings.LogProtocolErrors())
-    {
-    if (iaUser->phase.GetPhase() != 2)
-        logger("IP: %s. User '%s'. Protocol version: %d. CONN_ACK: invalid phase, expected 2, got %d.", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, iaUser->phase.GetPhase());
-    if (connAck->rnd != iaUser->rnd + 1)
-        logger("IP: %s. User '%s'. Protocol version: %d. CONN_ACK: invalid control number, expected %d, got %d.", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, (iaUser->rnd + 1), connAck->rnd);
-    }
-return -1;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Process_CONN_ACK_7(CONN_ACK_7 * connAck, IA_USER * iaUser, uint32_t sip)
-{
-return Process_CONN_ACK_6(connAck, iaUser, sip);
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Process_CONN_ACK_8(CONN_ACK_8 * connAck, IA_USER * iaUser, uint32_t sip)
-{
-#ifdef ARCH_BE
-SwapBytes(connAck->len);
-SwapBytes(connAck->rnd);
-#endif
-printfd( __FILE__, "CONN_ACK_8 %s\n", connAck->type);
-
-if ((iaUser->phase.GetPhase() == 2) && (connAck->rnd == iaUser->rnd + 1))
-    {
-    iaUser->phase.UpdateTime();
-    iaUser->lastSendAlive = iaUser->phase.GetTime();
-    if (users->Authorize(iaUser->login, sip, enabledDirs, this))
-        {
-        iaUser->phase.SetPhase3();
-        printfd(__FILE__, "Phase changed from 2 to 3. Reason: CONN_ACK_8\n");
-        return 0;
-        }
-    else
-        {
-        errorStr = iaUser->user->GetStrError();
-        if (iaSettings.LogProtocolErrors())
-            logger("IP: %s. User '%s'. Protocol version: %d. CONN_ACK: phase 2, authorization error ('%s').", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, errorStr.c_str());
-        iaUser->phase.SetPhase1();
-        ip2user.erase(sip);
-        printfd(__FILE__, "Phase changed from 2 to 1. Reason: failed to authorize user\n");
-        return -1;
-        }
-    }
-printfd(__FILE__, "Invalid phase or control number. Phase: %d. Control number: %d, expected: %d\n", iaUser->phase.GetPhase(), connAck->rnd, iaUser->rnd + 1);
-if (iaSettings.LogProtocolErrors())
-    {
-    if (iaUser->phase.GetPhase() != 2)
-        logger("IP: %s. User '%s'. Protocol version: %d. CONN_ACK: invalid phase, expected 2, got %d.", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, iaUser->phase.GetPhase());
-    if (connAck->rnd != iaUser->rnd + 1)
-        logger("IP: %s. User '%s'. Protocol version: %d. CONN_ACK: invalid control number, expected %d, got %d.", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, (iaUser->rnd + 1), connAck->rnd);
-    }
-return -1;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Process_ALIVE_ACK_6(ALIVE_ACK_6 * aliveAck, IA_USER * iaUser, uint32_t)
-{
-#ifdef ARCH_BE
-SwapBytes(aliveAck->len);
-SwapBytes(aliveAck->rnd);
-#endif
-printfd(__FILE__, "ALIVE_ACK_6\n");
-if ((iaUser->phase.GetPhase() == 3) && (aliveAck->rnd == iaUser->rnd + 1))
-    {
-    iaUser->phase.UpdateTime();
-    #ifdef IA_DEBUG
-    iaUser->aliveSent = false;
-    #endif
-    }
-return 0;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Process_ALIVE_ACK_7(ALIVE_ACK_7 * aliveAck, IA_USER * iaUser, uint32_t sip)
-{
-return Process_ALIVE_ACK_6(aliveAck, iaUser, sip);
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Process_ALIVE_ACK_8(ALIVE_ACK_8 * aliveAck, IA_USER * iaUser, uint32_t)
-{
-#ifdef ARCH_BE
-SwapBytes(aliveAck->len);
-SwapBytes(aliveAck->rnd);
-#endif
-printfd(__FILE__, "ALIVE_ACK_8\n");
-if ((iaUser->phase.GetPhase() == 3) && (aliveAck->rnd == iaUser->rnd + 1))
-    {
-    iaUser->phase.UpdateTime();
-    #ifdef IA_DEBUG
-    iaUser->aliveSent = false;
-    #endif
-    }
-return 0;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Process_DISCONN_SYN_6(DISCONN_SYN_6 *, IA_USER * iaUser, uint32_t sip)
-{
-printfd(__FILE__, "DISCONN_SYN_6\n");
-if (iaUser->phase.GetPhase() != 3)
-    {
-    if (iaSettings.LogProtocolErrors())
-        logger("IP: %s. User '%s'. Protocol version: %d. DISCONN_SYN: invalid phase, expected 3, got %d.", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, iaUser->phase.GetPhase());
-    printfd(__FILE__, "Invalid phase. Expected 3, actual %d\n", iaUser->phase.GetPhase());
-    errorStr = "Incorrect request DISCONN_SYN";
-    return -1;
-    }
-
-iaUser->phase.SetPhase4();
-printfd(__FILE__, "Phase changed from 3 to 4. Reason: DISCONN_SYN_6\n");
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Process_DISCONN_SYN_7(DISCONN_SYN_7 * disconnSyn, IA_USER * iaUser, uint32_t sip)
-{
-return Process_DISCONN_SYN_6(disconnSyn, iaUser, sip);
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Process_DISCONN_SYN_8(DISCONN_SYN_8 *, IA_USER * iaUser, uint32_t sip)
-{
-if (iaUser->phase.GetPhase() != 3)
-    {
-    if (iaSettings.LogProtocolErrors())
-        logger("IP: %s. User '%s'. Protocol version: %d. DISCONN_SYN: invalid phase, expected 3, got %d.", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, iaUser->phase.GetPhase());
-    errorStr = "Incorrect request DISCONN_SYN";
-    printfd(__FILE__, "Invalid phase. Expected 3, actual %d\n", iaUser->phase.GetPhase());
-    return -1;
-    }
-
-iaUser->phase.SetPhase4();
-printfd(__FILE__, "Phase changed from 3 to 4. Reason: DISCONN_SYN_6\n");
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Process_DISCONN_ACK_6(DISCONN_ACK_6 * disconnAck,
-                                   IA_USER * iaUser,
-                                   uint32_t sip,
-                                   std::map<uint32_t, IA_USER>::iterator)
-{
-#ifdef ARCH_BE
-SwapBytes(disconnAck->len);
-SwapBytes(disconnAck->rnd);
-#endif
-printfd(__FILE__, "DISCONN_ACK_6\n");
-if (!((iaUser->phase.GetPhase() == 4) && (disconnAck->rnd == iaUser->rnd + 1)))
-    {
-    if (iaSettings.LogProtocolErrors())
-        {
-        if (iaUser->phase.GetPhase() != 4)
-            logger("IP: %s. User '%s'. Protocol version: %d. DISCONN_ACK: invalid phase, expected 4, got %d.", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, iaUser->phase.GetPhase());
-        if (disconnAck->rnd != iaUser->rnd + 1)
-            logger("IP: %s. User '%s'. Protocol version: %d. DISCONN_ACK: invalid control number, expected %d, got %d.", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, (iaUser->rnd + 1), disconnAck->rnd);
-        }
-    printfd(__FILE__, "Invalid phase or control number. Phase: %d. Control number: %d\n", iaUser->phase.GetPhase(), disconnAck->rnd);
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Process_DISCONN_ACK_7(DISCONN_ACK_7 * disconnAck, IA_USER * iaUser, uint32_t sip, std::map<uint32_t, IA_USER>::iterator it)
-{
-return Process_DISCONN_ACK_6(disconnAck, iaUser, sip, it);
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Process_DISCONN_ACK_8(DISCONN_ACK_8 * disconnAck, IA_USER * iaUser, uint32_t sip, std::map<uint32_t, IA_USER>::iterator)
-{
-#ifdef ARCH_BE
-SwapBytes(disconnAck->len);
-SwapBytes(disconnAck->rnd);
-#endif
-printfd(__FILE__, "DISCONN_ACK_8\n");
-if (!((iaUser->phase.GetPhase() == 4) && (disconnAck->rnd == iaUser->rnd + 1)))
-    {
-    if (iaSettings.LogProtocolErrors())
-        {
-        if (iaUser->phase.GetPhase() != 4)
-            logger("IP: %s. User '%s'. Protocol version: %d. DISCONN_ACK: invalid phase, expected 4, got %d.", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, iaUser->phase.GetPhase());
-        if (disconnAck->rnd != iaUser->rnd + 1)
-            logger("IP: %s. User '%s'. Protocol version: %d. DISCONN_ACK: invalid control number, expected %d, got %d.", inet_ntostring(sip).c_str(), iaUser->login.c_str(), iaUser->protoVer, (iaUser->rnd + 1), disconnAck->rnd);
-        }
-    printfd(__FILE__, "Invalid phase or control number. Phase: %d. Control number: %d\n", iaUser->phase.GetPhase(), disconnAck->rnd);
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Send_CONN_SYN_ACK_6(IA_USER * iaUser, uint32_t sip)
-{
-//+++ Fill static data in connSynAck +++
-// TODO Move this code. It must be executed only once
-connSynAck6.len = Min8(sizeof(CONN_SYN_ACK_6));
-strcpy((char*)connSynAck6.type, "CONN_SYN_ACK");
-for (int j = 0; j < DIR_NUM; j++)
-    {
-    strncpy((char*)connSynAck6.dirName[j],
-            stgSettings->GetDirName(j).c_str(),
-            sizeof(string16));
-
-    connSynAck6.dirName[j][sizeof(string16) - 1] = 0;
-    }
-//--- Fill static data in connSynAck ---
-
-iaUser->rnd = static_cast<uint32_t>(random());
-connSynAck6.rnd = iaUser->rnd;
-
-printfd(__FILE__, "Sending CONN_SYN_ACK with control number %d.\n", iaUser->rnd);
-
-connSynAck6.userTimeOut = iaSettings.GetUserTimeout().GetSec();
-connSynAck6.aliveDelay = iaSettings.GetUserDelay().GetSec();
-
-#ifdef ARCH_BE
-SwapBytes(connSynAck6.len);
-SwapBytes(connSynAck6.rnd);
-SwapBytes(connSynAck6.userTimeOut);
-SwapBytes(connSynAck6.aliveDelay);
-#endif
-
-EncryptString((char*)&connSynAck6, (char*)&connSynAck6, Min8(sizeof(CONN_SYN_ACK_6)), &iaUser->ctx);
-return Send(sip, iaSettings.GetUserPort(), (char*)&connSynAck6, Min8(sizeof(CONN_SYN_ACK_6)));;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Send_CONN_SYN_ACK_7(IA_USER * iaUser, uint32_t sip)
-{
-return Send_CONN_SYN_ACK_6(iaUser, sip);
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Send_CONN_SYN_ACK_8(IA_USER * iaUser, uint32_t sip)
-{
-strcpy((char*)connSynAck8.hdr.magic, IA_ID);
-connSynAck8.hdr.protoVer[0] = 0;
-connSynAck8.hdr.protoVer[1] = 8;
-
-//+++ Fill static data in connSynAck +++
-// TODO Move this code. It must be executed only once
-connSynAck8.len = Min8(sizeof(CONN_SYN_ACK_8));
-strcpy((char*)connSynAck8.type, "CONN_SYN_ACK");
-for (int j = 0; j < DIR_NUM; j++)
-    {
-    strncpy((char*)connSynAck8.dirName[j],
-            stgSettings->GetDirName(j).c_str(),
-            sizeof(string16));
-
-    connSynAck8.dirName[j][sizeof(string16) - 1] = 0;
-    }
-//--- Fill static data in connSynAck ---
-
-iaUser->rnd = static_cast<uint32_t>(random());
-connSynAck8.rnd = iaUser->rnd;
-
-printfd(__FILE__, "Sending CONN_SYN_ACK with control number %d.\n", iaUser->rnd);
-
-connSynAck8.userTimeOut = iaSettings.GetUserTimeout().GetSec();
-connSynAck8.aliveDelay = iaSettings.GetUserDelay().GetSec();
-
-#ifdef ARCH_BE
-SwapBytes(connSynAck8.len);
-SwapBytes(connSynAck8.rnd);
-SwapBytes(connSynAck8.userTimeOut);
-SwapBytes(connSynAck8.aliveDelay);
-#endif
-
-EncryptString((char*)&connSynAck8, (char*)&connSynAck8, Min8(sizeof(CONN_SYN_ACK_8)), &iaUser->ctx);
-return Send(sip, iaUser->port, (char*)&connSynAck8, Min8(sizeof(CONN_SYN_ACK_8)));
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Send_ALIVE_SYN_6(IA_USER * iaUser, uint32_t sip)
-{
-aliveSyn6.len = Min8(sizeof(ALIVE_SYN_6));
-aliveSyn6.rnd = iaUser->rnd = static_cast<uint32_t>(random());
-
-strcpy((char*)aliveSyn6.type, "ALIVE_SYN");
-
-for (int i = 0; i < DIR_NUM; i++)
-    {
-    aliveSyn6.md[i] = iaUser->user->GetProperties().down.Get()[i];
-    aliveSyn6.mu[i] = iaUser->user->GetProperties().up.Get()[i];
-
-    aliveSyn6.sd[i] = iaUser->user->GetSessionDownload()[i];
-    aliveSyn6.su[i] = iaUser->user->GetSessionUpload()[i];
-    }
-
-//TODO
-int dn = iaSettings.GetFreeMbShowType();
-const auto tf = iaUser->user->GetTariff();
-
-if (dn < DIR_NUM)
-    {
-    double p = tf->GetPriceWithTraffType(aliveSyn6.mu[dn],
-                                         aliveSyn6.md[dn],
-                                         dn,
-                                         stgTime);
-    p *= 1024 * 1024;
-    if (std::fabs(p) < 1.0e-3)
-        {
-        snprintf((char*)aliveSyn6.freeMb, IA_FREEMB_LEN, "---");
-        }
-    else
-        {
-        double fmb = iaUser->user->GetProperties().freeMb;
-        fmb = fmb < 0 ? 0 : fmb;
-        snprintf((char*)aliveSyn6.freeMb, IA_FREEMB_LEN, "%.3f", fmb / p);
-        }
-    }
-else
-    {
-    if (freeMbNone == iaSettings.GetFreeMbShowType())
-        {
-        aliveSyn6.freeMb[0] = 0;
-        }
-    else
-        {
-        double fmb = iaUser->user->GetProperties().freeMb;
-        fmb = fmb < 0 ? 0 : fmb;
-        snprintf((char*)aliveSyn6.freeMb, IA_FREEMB_LEN, "C%.3f", fmb);
-        }
-    }
-
-#ifdef IA_DEBUG
-if (iaUser->aliveSent)
-    {
-    printfd(__FILE__, "========= ALIVE_ACK_6(7) TIMEOUT !!! %s =========\n", iaUser->login.c_str());
-    }
-iaUser->aliveSent = true;
-#endif
-
-aliveSyn6.cash =(int64_t) (iaUser->user->GetProperties().cash.Get() * 1000.0);
-if (!stgSettings->GetShowFeeInCash())
-    aliveSyn6.cash -= (int64_t)(tf->GetFee() * 1000.0);
-
-#ifdef ARCH_BE
-SwapBytes(aliveSyn6.len);
-SwapBytes(aliveSyn6.rnd);
-SwapBytes(aliveSyn6.cash);
-for (int i = 0; i < DIR_NUM; ++i)
-    {
-    SwapBytes(aliveSyn6.mu[i]);
-    SwapBytes(aliveSyn6.md[i]);
-    SwapBytes(aliveSyn6.su[i]);
-    SwapBytes(aliveSyn6.sd[i]);
-    }
-#endif
-
-EncryptString((char*)&aliveSyn6, (char*)&aliveSyn6, Min8(sizeof(aliveSyn6)), &iaUser->ctx);
-return Send(sip, iaSettings.GetUserPort(), (char*)&aliveSyn6, Min8(sizeof(aliveSyn6)));
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Send_ALIVE_SYN_7(IA_USER * iaUser, uint32_t sip)
-{
-return Send_ALIVE_SYN_6(iaUser, sip);
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Send_ALIVE_SYN_8(IA_USER * iaUser, uint32_t sip)
-{
-strcpy((char*)aliveSyn8.hdr.magic, IA_ID);
-aliveSyn8.hdr.protoVer[0] = 0;
-aliveSyn8.hdr.protoVer[1] = 8;
-
-aliveSyn8.len = Min8(sizeof(ALIVE_SYN_8));
-aliveSyn8.rnd = iaUser->rnd = static_cast<uint32_t>(random());
-
-strcpy((char*)aliveSyn8.type, "ALIVE_SYN");
-
-for (int i = 0; i < DIR_NUM; i++)
-    {
-    aliveSyn8.md[i] = iaUser->user->GetProperties().down.Get()[i];
-    aliveSyn8.mu[i] = iaUser->user->GetProperties().up.Get()[i];
-
-    aliveSyn8.sd[i] = iaUser->user->GetSessionDownload()[i];
-    aliveSyn8.su[i] = iaUser->user->GetSessionUpload()[i];
-    }
-
-//TODO
-int dn = iaSettings.GetFreeMbShowType();
-
-if (dn < DIR_NUM)
-    {
-    const auto tf = iaUser->user->GetTariff();
-    double p = tf->GetPriceWithTraffType(aliveSyn8.mu[dn],
-                                         aliveSyn8.md[dn],
-                                         dn,
-                                         stgTime);
-    p *= 1024 * 1024;
-    if (std::fabs(p) < 1.0e-3)
-        {
-        snprintf((char*)aliveSyn8.freeMb, IA_FREEMB_LEN, "---");
-        }
-    else
-        {
-        double fmb = iaUser->user->GetProperties().freeMb;
-        fmb = fmb < 0 ? 0 : fmb;
-        snprintf((char*)aliveSyn8.freeMb, IA_FREEMB_LEN, "%.3f", fmb / p);
-        }
-    }
-else
-    {
-    if (freeMbNone == iaSettings.GetFreeMbShowType())
-        {
-        aliveSyn8.freeMb[0] = 0;
-        }
-    else
-        {
-        double fmb = iaUser->user->GetProperties().freeMb;
-        fmb = fmb < 0 ? 0 : fmb;
-        snprintf((char*)aliveSyn8.freeMb, IA_FREEMB_LEN, "C%.3f", fmb);
-        }
-    }
-
-#ifdef IA_DEBUG
-if (iaUser->aliveSent)
-    {
-    printfd(__FILE__, "========= ALIVE_ACK_8 TIMEOUT !!! =========\n");
-    }
-iaUser->aliveSent = true;
-#endif
-
-const auto tf = iaUser->user->GetTariff();
-
-aliveSyn8.cash =(int64_t) (iaUser->user->GetProperties().cash.Get() * 1000.0);
-if (!stgSettings->GetShowFeeInCash())
-    aliveSyn8.cash -= (int64_t)(tf->GetFee() * 1000.0);
-
-#ifdef ARCH_BE
-SwapBytes(aliveSyn8.len);
-SwapBytes(aliveSyn8.rnd);
-SwapBytes(aliveSyn8.cash);
-SwapBytes(aliveSyn8.status);
-for (int i = 0; i < DIR_NUM; ++i)
-    {
-    SwapBytes(aliveSyn8.mu[i]);
-    SwapBytes(aliveSyn8.md[i]);
-    SwapBytes(aliveSyn8.su[i]);
-    SwapBytes(aliveSyn8.sd[i]);
-    }
-#endif
-
-EncryptString((char*)&aliveSyn8, (char*)&aliveSyn8, Min8(sizeof(aliveSyn8)), &iaUser->ctx);
-return Send(sip, iaUser->port, (char*)&aliveSyn8, Min8(sizeof(aliveSyn8)));
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Send_DISCONN_SYN_ACK_6(IA_USER * iaUser, uint32_t sip)
-{
-disconnSynAck6.len = Min8(sizeof(DISCONN_SYN_ACK_6));
-strcpy((char*)disconnSynAck6.type, "DISCONN_SYN_ACK");
-disconnSynAck6.rnd = iaUser->rnd = static_cast<uint32_t>(random());
-
-#ifdef ARCH_BE
-SwapBytes(disconnSynAck6.len);
-SwapBytes(disconnSynAck6.rnd);
-#endif
-
-EncryptString((char*)&disconnSynAck6, (char*)&disconnSynAck6, Min8(sizeof(disconnSynAck6)), &iaUser->ctx);
-return Send(sip, iaSettings.GetUserPort(), (char*)&disconnSynAck6, Min8(sizeof(disconnSynAck6)));
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Send_DISCONN_SYN_ACK_7(IA_USER * iaUser, uint32_t sip)
-{
-return Send_DISCONN_SYN_ACK_6(iaUser, sip);
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Send_DISCONN_SYN_ACK_8(IA_USER * iaUser, uint32_t sip)
-{
-strcpy((char*)disconnSynAck8.hdr.magic, IA_ID);
-disconnSynAck8.hdr.protoVer[0] = 0;
-disconnSynAck8.hdr.protoVer[1] = 8;
-
-disconnSynAck8.len = Min8(sizeof(DISCONN_SYN_ACK_8));
-strcpy((char*)disconnSynAck8.type, "DISCONN_SYN_ACK");
-disconnSynAck8.rnd = iaUser->rnd = static_cast<uint32_t>(random());
-
-#ifdef ARCH_BE
-SwapBytes(disconnSynAck8.len);
-SwapBytes(disconnSynAck8.rnd);
-#endif
-
-EncryptString((char*)&disconnSynAck8, (char*)&disconnSynAck8, Min8(sizeof(disconnSynAck8)), &iaUser->ctx);
-return Send(sip, iaUser->port, (char*)&disconnSynAck8, Min8(sizeof(disconnSynAck8)));
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Send_FIN_6(IA_USER * iaUser, uint32_t sip, std::map<uint32_t, IA_USER>::iterator it)
-{
-fin6.len = Min8(sizeof(FIN_6));
-strcpy((char*)fin6.type, "FIN");
-strcpy((char*)fin6.ok, "OK");
-
-#ifdef ARCH_BE
-SwapBytes(fin6.len);
-#endif
-
-EncryptString((char*)&fin6, (char*)&fin6, Min8(sizeof(fin6)), &iaUser->ctx);
-
-users->Unauthorize(iaUser->login, this);
-
-int res = Send(sip, iaSettings.GetUserPort(), (char*)&fin6, Min8(sizeof(fin6)));
-
-ip2user.erase(it);
-
-return res;
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Send_FIN_7(IA_USER * iaUser, uint32_t sip, std::map<uint32_t, IA_USER>::iterator it)
-{
-return Send_FIN_6(iaUser, sip, it);
-}
-//-----------------------------------------------------------------------------
-int AUTH_IA::Send_FIN_8(IA_USER * iaUser, uint32_t sip, std::map<uint32_t, IA_USER>::iterator it)
-{
-strcpy((char*)fin8.hdr.magic, IA_ID);
-fin8.hdr.protoVer[0] = 0;
-fin8.hdr.protoVer[1] = 8;
-
-fin8.len = Min8(sizeof(FIN_8));
-strcpy((char*)fin8.type, "FIN");
-strcpy((char*)fin8.ok, "OK");
-
-#ifdef ARCH_BE
-SwapBytes(fin8.len);
-#endif
-
-EncryptString((char*)&fin8, (char*)&fin8, Min8(sizeof(fin8)), &iaUser->ctx);
-
-users->Unauthorize(iaUser->login, this);
-
-int res = Send(sip, iaUser->port, (char*)&fin8, Min8(sizeof(fin8)));
-
-ip2user.erase(it);
-
-return res;
-}
diff --git a/stargazer/plugins/authorization/inetaccess/inetaccess.h b/stargazer/plugins/authorization/inetaccess/inetaccess.h
deleted file mode 100644 (file)
index 83e4d7a..0000000
+++ /dev/null
@@ -1,376 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- */
-#pragma once
-
-#include "stg/auth.h"
-#include "stg/store.h"
-#include "stg/module_settings.h"
-#include "stg/notifer.h"
-#include "stg/user_ips.h"
-#include "stg/user.h"
-#include "stg/users.h"
-#include "stg/user_property.h"
-#include "stg/ia_packets.h"
-#include "stg/blowfish.h"
-#include "stg/logger.h"
-#include "stg/utime.h"
-#include "stg/logger.h"
-
-#include <cstring>
-#include <ctime>
-#include <cstdint>
-#include <string>
-#include <map>
-#include <list>
-#include <functional>
-#include <utility>
-
-#include <sys/time.h>
-#include <pthread.h>
-
-//#define IA_DEBUG (1)
-//#define IA_PHASE_DEBUG (1)
-
-class AUTH_IA;
-//-----------------------------------------------------------------------------
-enum FREEMB {
-    freeMb0 = 0,
-    freeMb1,
-    freeMb2,
-    freeMb3,
-    freeMb4,
-    freeMb5,
-    freeMb6,
-    freeMb7,
-    freeMb8,
-    freeMb9,
-    freeMb10,
-    freeMb11,
-    freeMb12,
-    freeMb13,
-    freeMb14,
-    freeMb15,
-    freeMb16,
-    freeMb17,
-    freeMb18,
-    freeMb19,
-    freeMbCash = 100,
-    freeMbNone = 101
-};
-//-----------------------------------------------------------------------------
-class IA_PHASE {
-public:
-    IA_PHASE();
-    ~IA_PHASE();
-
-    void    SetPhase1();
-    void    SetPhase2();
-    void    SetPhase3();
-    void    SetPhase4();
-    int     GetPhase() const;
-
-    void    UpdateTime();
-    const UTIME & GetTime() const;
-
-    #ifdef IA_PHASE_DEBUG
-    void    SetUserLogin(const std::string & login);
-    void    SetLogFileName(const std::string & logFileName);
-    #endif
-
-private:
-    int             phase;
-    UTIME           phaseTime;
-
-    #ifdef IA_PHASE_DEBUG
-    void WritePhaseChange(int newPhase);
-    std::string log;
-    std::string login;
-    FILE * flog;
-    #endif
-};
-//-----------------------------------------------------------------------------
-struct IA_USER {
-    using ConstUserPtr = const STG::User*;
-    IA_USER()
-        : user(NULL),
-          lastSendAlive(0),
-          rnd(static_cast<uint32_t>(random())),
-          port(0),
-          protoVer(0),
-          password("NO PASSWORD")
-    {
-    unsigned char keyL[PASSWD_LEN];
-    memset(keyL, 0, PASSWD_LEN);
-    strncpy((char *)keyL, password.c_str(), PASSWD_LEN);
-    Blowfish_Init(&ctx, keyL, PASSWD_LEN);
-
-    #ifdef IA_DEBUG
-    aliveSent = false;
-    #endif
-    }
-
-    IA_USER(const IA_USER & u)
-        : login(u.login),
-          user(u.user),
-          phase(u.phase),
-          lastSendAlive(u.lastSendAlive),
-          rnd(u.rnd),
-          port(u.port),
-          ctx(),
-          messagesToSend(u.messagesToSend),
-          protoVer(u.protoVer),
-          password(u.password)
-    {
-    #ifdef IA_DEBUG
-    aliveSent  = u.aliveSent;
-    #endif
-    memcpy(&ctx, &u.ctx, sizeof(BLOWFISH_CTX));
-    }
-
-    IA_USER(const std::string & l,
-            ConstUserPtr u,
-            uint16_t p,
-            int ver)
-        : login(l),
-          user(u),
-          lastSendAlive(0),
-          rnd(static_cast<uint32_t>(random())),
-          port(p),
-          messagesToSend(),
-          protoVer(ver),
-          password(user->GetProperties().password.Get())
-    {
-    unsigned char keyL[PASSWD_LEN];
-    memset(keyL, 0, PASSWD_LEN);
-    strncpy((char *)keyL, password.c_str(), PASSWD_LEN);
-    Blowfish_Init(&ctx, keyL, PASSWD_LEN);
-
-    #ifdef IA_DEBUG
-    aliveSent = false;
-    #endif
-    }
-
-    std::string     login;
-    ConstUserPtr  user;
-    IA_PHASE        phase;
-    UTIME           lastSendAlive;
-    uint32_t        rnd;
-    uint16_t        port;
-    BLOWFISH_CTX    ctx;
-    std::vector<STG::Message> messagesToSend;
-    int             protoVer;
-    std::string     password;
-    #ifdef IA_DEBUG
-    bool            aliveSent;
-    #endif
-
-private:
-    IA_USER & operator=(const IA_USER & rvalue);
-};
-//-----------------------------------------------------------------------------
-class AUTH_IA_SETTINGS {
-public:
-                    AUTH_IA_SETTINGS();
-    virtual         ~AUTH_IA_SETTINGS() {}
-    const std::string & GetStrError() const { return errorStr; }
-    int             ParseSettings(const STG::ModuleSettings & s);
-    UTIME           GetUserDelay() const { return UTIME(userDelay); }
-    UTIME           GetUserTimeout() const { return UTIME(userTimeout); }
-    uint16_t        GetUserPort() const { return port; }
-    FREEMB          GetFreeMbShowType() const { return freeMbShowType; }
-    bool            LogProtocolErrors() const { return logProtocolErrors; }
-
-private:
-    int             userDelay;
-    int             userTimeout;
-    uint16_t        port;
-    std::string     errorStr;
-    FREEMB          freeMbShowType;
-    bool            logProtocolErrors;
-};
-//-----------------------------------------------------------------------------
-class AUTH_IA;
-using UserPtr = STG::User*;
-//-----------------------------------------------------------------------------
-class DEL_USER_NOTIFIER: public STG::NotifierBase<UserPtr> {
-public:
-    explicit DEL_USER_NOTIFIER(AUTH_IA & a) : auth(a) {}
-    virtual ~DEL_USER_NOTIFIER() {}
-
-    void Notify(const UserPtr & user);
-private:
-    DEL_USER_NOTIFIER(const DEL_USER_NOTIFIER & rvalue);
-    DEL_USER_NOTIFIER & operator=(const DEL_USER_NOTIFIER & rvalue);
-
-    AUTH_IA & auth;
-};
-//-----------------------------------------------------------------------------
-class AUTH_IA : public STG::Auth {
-friend class DEL_USER_NOTIFIER;
-public:
-                        AUTH_IA();
-                        ~AUTH_IA() override;
-
-    void                SetUsers(STG::Users * u) override { users = u; }
-    void                SetStgSettings(const STG::Settings * s) override { stgSettings = s; }
-    void                SetSettings(const STG::ModuleSettings & s) override { settings = s; }
-    int                 ParseSettings() override;
-
-    int                 Start() override;
-    int                 Stop() override;
-    int                 Reload(const STG::ModuleSettings & ms) override;
-    bool                IsRunning() override { return isRunningRunTimeouter || isRunningRun; }
-
-    const std::string & GetStrError() const override { return errorStr; }
-    std::string         GetVersion() const override { return "InetAccess authorization plugin v.1.4"; }
-    uint16_t            GetStartPosition() const override { return 30; }
-    uint16_t            GetStopPosition() const override { return 30; }
-
-    int                 SendMessage(const STG::Message & msg, uint32_t ip) const override;
-
-private:
-    AUTH_IA(const AUTH_IA & rvalue);
-    AUTH_IA & operator=(const AUTH_IA & rvalue);
-
-    static void *       Run(void *);
-    static void *       RunTimeouter(void * d);
-    int                 PrepareNet();
-    int                 FinalizeNet();
-    void                DelUser(UserPtr u);
-    int                 RecvData(char * buffer, int bufferSize);
-    int                 CheckHeader(const char * buffer, uint32_t sip, int * protoVer);
-    int                 PacketProcessor(void * buff, size_t dataLen, uint32_t sip, uint16_t sport, int protoVer, UserPtr user);
-
-    int                 Process_CONN_SYN_6(CONN_SYN_6 * connSyn, IA_USER * iaUser, uint32_t sip);
-    int                 Process_CONN_SYN_7(CONN_SYN_7 * connSyn, IA_USER * iaUser, uint32_t sip);
-    int                 Process_CONN_SYN_8(CONN_SYN_8 * connSyn, IA_USER * iaUser, uint32_t sip);
-
-    int                 Process_CONN_ACK_6(CONN_ACK_6 * connAck, IA_USER * iaUser, uint32_t sip);
-    int                 Process_CONN_ACK_7(CONN_ACK_7 * connAck, IA_USER * iaUser, uint32_t sip);
-    int                 Process_CONN_ACK_8(CONN_ACK_8 * connAck, IA_USER * iaUser, uint32_t sip);
-
-    int                 Process_ALIVE_ACK_6(ALIVE_ACK_6 * aliveAck, IA_USER * iaUser, uint32_t sip);
-    int                 Process_ALIVE_ACK_7(ALIVE_ACK_7 * aliveAck, IA_USER * iaUser, uint32_t sip);
-    int                 Process_ALIVE_ACK_8(ALIVE_ACK_8 * aliveAck, IA_USER * iaUser, uint32_t sip);
-
-    int                 Process_DISCONN_SYN_6(DISCONN_SYN_6 * disconnSyn, IA_USER * iaUser, uint32_t sip);
-    int                 Process_DISCONN_SYN_7(DISCONN_SYN_7 * disconnSyn, IA_USER * iaUser, uint32_t sip);
-    int                 Process_DISCONN_SYN_8(DISCONN_SYN_8 * disconnSyn, IA_USER * iaUser, uint32_t sip);
-
-    int                 Process_DISCONN_ACK_6(DISCONN_ACK_6 * disconnSyn,
-                                              IA_USER * iaUser,
-                                              uint32_t sip,
-                                              std::map<uint32_t, IA_USER>::iterator it);
-    int                 Process_DISCONN_ACK_7(DISCONN_ACK_7 * disconnSyn,
-                                              IA_USER * iaUser,
-                                              uint32_t sip,
-                                              std::map<uint32_t, IA_USER>::iterator it);
-    int                 Process_DISCONN_ACK_8(DISCONN_ACK_8 * disconnSyn,
-                                              IA_USER * iaUser,
-                                              uint32_t sip,
-                                              std::map<uint32_t, IA_USER>::iterator it);
-
-    int                 Send_CONN_SYN_ACK_6(IA_USER * iaUser, uint32_t sip);
-    int                 Send_CONN_SYN_ACK_7(IA_USER * iaUser, uint32_t sip);
-    int                 Send_CONN_SYN_ACK_8(IA_USER * iaUser, uint32_t sip);
-
-    int                 Send_ALIVE_SYN_6(IA_USER * iaUser, uint32_t sip);
-    int                 Send_ALIVE_SYN_7(IA_USER * iaUser, uint32_t sip);
-    int                 Send_ALIVE_SYN_8(IA_USER * iaUser, uint32_t sip);
-
-    int                 Send_DISCONN_SYN_ACK_6(IA_USER * iaUser, uint32_t sip);
-    int                 Send_DISCONN_SYN_ACK_7(IA_USER * iaUser, uint32_t sip);
-    int                 Send_DISCONN_SYN_ACK_8(IA_USER * iaUser, uint32_t sip);
-
-    int                 Send_FIN_6(IA_USER * iaUser, uint32_t sip, std::map<uint32_t, IA_USER>::iterator it);
-    int                 Send_FIN_7(IA_USER * iaUser, uint32_t sip, std::map<uint32_t, IA_USER>::iterator it);
-    int                 Send_FIN_8(IA_USER * iaUser, uint32_t sip, std::map<uint32_t, IA_USER>::iterator it);
-
-    int                 Timeouter();
-
-    int                 SendError(uint32_t ip, uint16_t port, int protoVer, const std::string & text);
-    int                 Send(uint32_t ip, uint16_t port, const char * buffer, size_t len);
-    int                 RealSendMessage6(const STG::Message & msg, uint32_t ip, IA_USER & user);
-    int                 RealSendMessage7(const STG::Message & msg, uint32_t ip, IA_USER & user);
-    int                 RealSendMessage8(const STG::Message & msg, uint32_t ip, IA_USER & user);
-
-    BLOWFISH_CTX        ctxS;        //for loginS
-
-    mutable std::string errorStr;
-    AUTH_IA_SETTINGS    iaSettings;
-    STG::ModuleSettings settings;
-
-    bool                nonstop;
-
-    bool                isRunningRun;
-    bool                isRunningRunTimeouter;
-
-    STG::Users *             users;
-    const STG::Settings *    stgSettings;
-
-    mutable std::map<uint32_t, IA_USER> ip2user;
-
-    pthread_t           recvThread;
-    pthread_t           timeouterThread;
-    mutable pthread_mutex_t mutex;
-
-    int                 listenSocket;
-
-    CONN_SYN_ACK_6      connSynAck6;
-    CONN_SYN_ACK_8      connSynAck8;
-
-    DISCONN_SYN_ACK_6   disconnSynAck6;
-    DISCONN_SYN_ACK_8   disconnSynAck8;
-
-    ALIVE_SYN_6         aliveSyn6;
-    ALIVE_SYN_8         aliveSyn8;
-    FIN_6               fin6;
-    FIN_8               fin8;
-
-    std::map<std::string, int> packetTypes;
-
-    uint32_t            enabledDirs;
-
-    DEL_USER_NOTIFIER   onDelUserNotifier;
-
-    STG::PluginLogger   logger;
-
-    friend class UnauthorizeUser;
-};
-//-----------------------------------------------------------------------------
-class UnauthorizeUser : std::unary_function<const std::pair<uint32_t, IA_USER> &, void> {
-    public:
-        explicit UnauthorizeUser(AUTH_IA * a) : auth(a) {}
-        UnauthorizeUser(const UnauthorizeUser & rvalue) : auth(rvalue.auth) {}
-        void operator()(const std::pair<uint32_t, IA_USER> & p)
-        {
-            auth->users->Unauthorize(p.second.user->GetLogin(), auth);
-        }
-    private:
-        UnauthorizeUser & operator=(const UnauthorizeUser & rvalue);
-
-        AUTH_IA * auth;
-};
-//-----------------------------------------------------------------------------
-inline
-void DEL_USER_NOTIFIER::Notify(const UserPtr & user)
-{
-    auth.DelUser(user);
-}
diff --git a/stargazer/plugins/capture/cap_nf/cap_nf.cpp b/stargazer/plugins/capture/cap_nf/cap_nf.cpp
deleted file mode 100644 (file)
index 817ed71..0000000
+++ /dev/null
@@ -1,441 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
-Date: 16.05.2008
-*/
-
-/*
-* Author : Maxim Mamontov <faust@stg.dp.ua>
-*/
-
-/*
-$Revision: 1.11 $
-$Date: 2010/09/10 06:41:06 $
-$Author: faust $
-*/
-
-#include "cap_nf.h"
-
-#include "stg/common.h"
-#include "stg/raw_ip_packet.h"
-#include "stg/traffcounter.h"
-
-#include <vector>
-
-#include <csignal>
-#include <cerrno>
-#include <cstring>
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-namespace
-{
-
-struct NF_HEADER {
-    uint16_t version;   // Protocol version
-    uint16_t count;     // Flows count
-    uint32_t uptime;    // System uptime
-    uint32_t timestamp; // UNIX timestamp
-    uint32_t nsecs;     // Residual nanoseconds
-    uint32_t flowSeq;   // Sequence counter
-    uint8_t  eType;     // Engine type
-    uint8_t  eID;       // Engine ID
-    uint16_t sInterval; // Sampling mode and interval
-};
-
-struct NF_DATA {
-    uint32_t srcAddr;   // Flow source address
-    uint32_t dstAddr;   // Flow destination address
-    uint32_t nextHop;   // IP addres on next hop router
-    uint16_t inSNMP;    // SNMP index of input iface
-    uint16_t outSNMP;   // SNMP index of output iface
-    uint32_t packets;   // Packets in flow
-    uint32_t octets;    // Total number of bytes in flow
-    uint32_t timeStart; // Uptime on first packet in flow
-    uint32_t timeFinish;// Uptime on last packet in flow
-    uint16_t srcPort;   // Flow source port
-    uint16_t dstPort;   // Flow destination port
-    uint8_t  pad1;      // 1-byte padding
-    uint8_t  TCPFlags;  // Cumulative OR of TCP flags
-    uint8_t  proto;     // IP protocol type (tcp, udp, etc.)
-    uint8_t  tos;       // IP Type of Service (ToS)
-    uint16_t srcAS;     // Source BGP autonomous system number
-    uint16_t dstAS;     // Destination BGP autonomus system number
-    uint8_t  srcMask;   // Source address mask in "slash" notation
-    uint8_t  dstMask;   // Destination address mask in "slash" notation
-    uint16_t pad2;      // 2-byte padding
-};
-
-#define BUF_SIZE (sizeof(NF_HEADER) + 30 * sizeof(NF_DATA))
-
-}
-
-extern "C" STG::Plugin* GetPlugin()
-{
-    static NF_CAP plugin;
-    return &plugin;
-}
-
-NF_CAP::NF_CAP()
-    : traffCnt(NULL),
-      runningTCP(false),
-      runningUDP(false),
-      stoppedTCP(true),
-      stoppedUDP(true),
-      portT(0),
-      portU(0),
-      sockTCP(-1),
-      sockUDP(-1),
-      logger(STG::PluginLogger::get("cap_nf"))
-{
-}
-
-int NF_CAP::ParseSettings()
-{
-std::vector<STG::ParamValue>::iterator it;
-for (it = settings.moduleParams.begin(); it != settings.moduleParams.end(); ++it)
-    {
-    if (it->param == "TCPPort" && !it->value.empty())
-        {
-        if (str2x(it->value[0], portT))
-            {
-            errorStr = "Invalid TCPPort value";
-            printfd(__FILE__, "Error: Invalid TCPPort value\n");
-            return -1;
-            }
-        continue;
-        }
-    if (it->param == "UDPPort" && !it->value.empty())
-        {
-        if (str2x(it->value[0], portU))
-            {
-            errorStr = "Invalid UDPPort value";
-            printfd(__FILE__, "Error: Invalid UDPPort value\n");
-            return -1;
-            }
-        continue;
-        }
-    printfd(__FILE__, "'%s' is not a valid module param\n", it->param.c_str());
-    }
-return 0;
-}
-
-int NF_CAP::Start()
-{
-if (portU > 0)
-    {
-    if (OpenUDP())
-        {
-        return -1;
-        }
-    runningUDP = true;
-    if (pthread_create(&tidUDP, NULL, RunUDP, this))
-        {
-        runningUDP = false;
-        CloseUDP();
-        errorStr = "Cannot create UDP thread";
-        logger("Cannot create UDP thread.");
-        printfd(__FILE__, "Error: Cannot create UDP thread\n");
-        return -1;
-        }
-    }
-if (portT > 0)
-    {
-    if (OpenTCP())
-        {
-        return -1;
-        }
-    runningTCP = true;
-    if (pthread_create(&tidTCP, NULL, RunTCP, this))
-        {
-        runningTCP = false;
-        CloseTCP();
-        logger("Cannot create TCP thread.");
-        errorStr = "Cannot create TCP thread";
-        printfd(__FILE__, "Error: Cannot create TCP thread\n");
-        return -1;
-        }
-    }
-return 0;
-}
-
-int NF_CAP::Stop()
-{
-runningTCP = runningUDP = false;
-if (portU && !stoppedUDP)
-    {
-    CloseUDP();
-    for (int i = 0; i < 25 && !stoppedUDP; ++i)
-        {
-        struct timespec ts = {0, 200000000};
-        nanosleep(&ts, NULL);
-        }
-    if (stoppedUDP)
-        {
-        pthread_join(tidUDP, NULL);
-        }
-    else
-        {
-        if (pthread_kill(tidUDP, SIGUSR1))
-            {
-            errorStr = "Error sending signal to UDP thread";
-            logger("Error sending sugnal to UDP thread.");
-            printfd(__FILE__, "Error: Error sending signal to UDP thread\n");
-            return -1;
-            }
-        printfd(__FILE__, "UDP thread NOT stopped\n");
-        logger("Cannot stop UDP thread.");
-        }
-    }
-if (portT && !stoppedTCP)
-    {
-    CloseTCP();
-    for (int i = 0; i < 25 && !stoppedTCP; ++i)
-        {
-        struct timespec ts = {0, 200000000};
-        nanosleep(&ts, NULL);
-        }
-    if (stoppedTCP)
-        {
-        pthread_join(tidTCP, NULL);
-        }
-    else
-        {
-        if (pthread_kill(tidTCP, SIGUSR1))
-            {
-            errorStr = "Error sending signal to TCP thread";
-            logger("Error sending signal to TCP thread.");
-            printfd(__FILE__, "Error: Error sending signal to TCP thread\n");
-            return -1;
-            }
-        printfd(__FILE__, "TCP thread NOT stopped\n");
-        logger("Cannot stop TCP thread.");
-        }
-    }
-return 0;
-}
-
-bool NF_CAP::OpenUDP()
-{
-struct sockaddr_in sin;
-sockUDP = socket(PF_INET, SOCK_DGRAM, 0);
-if (sockUDP <= 0)
-    {
-    errorStr = "Error opening UDP socket";
-    logger("Cannot create UDP socket: %s", strerror(errno));
-    printfd(__FILE__, "Error: Error opening UDP socket\n");
-    return true;
-    }
-sin.sin_family = AF_INET;
-sin.sin_port = htons(portU);
-sin.sin_addr.s_addr = inet_addr("0.0.0.0");
-if (bind(sockUDP, (struct sockaddr *)&sin, sizeof(sin)))
-    {
-    errorStr = "Error binding UDP socket";
-    logger("Cannot bind UDP socket: %s", strerror(errno));
-    printfd(__FILE__, "Error: Error binding UDP socket\n");
-    return true;
-    }
-return false;
-}
-
-bool NF_CAP::OpenTCP()
-{
-struct sockaddr_in sin;
-sockTCP = socket(PF_INET, SOCK_STREAM, 0);
-if (sockTCP <= 0)
-    {
-    errorStr = "Error opening TCP socket";
-    logger("Cannot create TCP socket: %s", strerror(errno));
-    printfd(__FILE__, "Error: Error opening TCP socket\n");
-    return true;
-    }
-sin.sin_family = AF_INET;
-sin.sin_port = htons(portT);
-sin.sin_addr.s_addr = inet_addr("0.0.0.0");
-if (bind(sockTCP, (struct sockaddr *)&sin, sizeof(sin)))
-    {
-    errorStr = "Error binding TCP socket";
-    logger("Cannot bind TCP socket: %s", strerror(errno));
-    printfd(__FILE__, "Error: Error binding TCP socket\n");
-    return true;
-    }
-if (listen(sockTCP, 1))
-    {
-    errorStr = "Error listening on TCP socket";
-    logger("Cannot listen on TCP socket: %s", strerror(errno));
-    printfd(__FILE__, "Error: Error listening TCP socket\n");
-    return true;
-    }
-return false;
-}
-
-void * NF_CAP::RunUDP(void * c)
-{
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-NF_CAP * cap = static_cast<NF_CAP *>(c);
-cap->stoppedUDP = false;
-while (cap->runningUDP)
-    {
-    if (!WaitPackets(cap->sockUDP))
-        {
-        continue;
-        }
-
-    // Data
-    struct sockaddr_in sin;
-    socklen_t slen = sizeof(sin);
-    uint8_t buf[BUF_SIZE];
-    ssize_t res = recvfrom(cap->sockUDP, buf, BUF_SIZE, 0, reinterpret_cast<struct sockaddr *>(&sin), &slen);
-    if (!cap->runningUDP)
-        break;
-
-    if (res < 0)
-        {
-        cap->logger("recvfrom error: %s", strerror(errno));
-        continue;
-        }
-
-    if (res == 0) // EOF
-        {
-        continue;
-        }
-
-    if (res < 24)
-        {
-        if (errno != EINTR)
-            {
-            cap->errorStr = "Invalid data received";
-            printfd(__FILE__, "Error: Invalid data received through UDP\n");
-            }
-        continue;
-        }
-
-    cap->ParseBuffer(buf, res);
-    }
-cap->stoppedUDP = true;
-return NULL;
-}
-
-void * NF_CAP::RunTCP(void * c)
-{
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-NF_CAP * cap = static_cast<NF_CAP *>(c);
-cap->stoppedTCP = false;
-while (cap->runningTCP)
-    {
-    if (!WaitPackets(cap->sockTCP))
-        {
-        continue;
-        }
-
-    // Data
-    struct sockaddr_in sin;
-    socklen_t slen = sizeof(sin);
-    int sd = accept(cap->sockTCP, reinterpret_cast<struct sockaddr *>(&sin), &slen);
-    if (!cap->runningTCP)
-        break;
-
-    if (sd <= 0)
-        {
-        if (sd < 0)
-            cap->logger("accept error: %s", strerror(errno));
-        continue;
-        }
-
-    if (!WaitPackets(sd))
-        {
-        close(sd);
-        continue;
-        }
-
-    uint8_t buf[BUF_SIZE];
-    ssize_t res = recv(sd, buf, BUF_SIZE, MSG_WAITALL);
-
-    if (res < 0)
-        cap->logger("recv error: %s", strerror(errno));
-
-    close(sd);
-
-    if (!cap->runningTCP)
-        break;
-
-    if (res == 0) // EOF
-        {
-        continue;
-        }
-
-    // Wrong logic!
-    // Need to check actual data length and wait all data to receive
-    if (res < 24)
-        {
-        continue;
-        }
-
-    cap->ParseBuffer(buf, res);
-    }
-cap->stoppedTCP = true;
-return NULL;
-}
-
-void NF_CAP::ParseBuffer(uint8_t * buf, ssize_t size)
-{
-STG::RawPacket ip;
-NF_HEADER * hdr = reinterpret_cast<NF_HEADER *>(buf);
-if (htons(hdr->version) != 5)
-    {
-    return;
-    }
-
-int packets = htons(hdr->count);
-
-if (packets < 0 || packets > 30)
-    {
-    return;
-    }
-
-if (24 + 48 * packets != size)
-    {
-    // See 'wrong logic' upper
-    return;
-    }
-
-for (int i = 0; i < packets; ++i)
-    {
-    NF_DATA * data = reinterpret_cast<NF_DATA *>(buf + 24 + i * 48);
-
-    ip.rawPacket.header.ipHeader.ip_v = 4;
-    ip.rawPacket.header.ipHeader.ip_hl = 5;
-    ip.rawPacket.header.ipHeader.ip_p = data->proto;
-    ip.dataLen = ntohl(data->octets);
-    ip.rawPacket.header.ipHeader.ip_src.s_addr = data->srcAddr;
-    ip.rawPacket.header.ipHeader.ip_dst.s_addr = data->dstAddr;
-    ip.rawPacket.header.sPort = data->srcPort;
-    ip.rawPacket.header.dPort = data->dstPort;
-
-    traffCnt->process(ip);
-    }
-}
diff --git a/stargazer/plugins/capture/cap_nf/cap_nf.h b/stargazer/plugins/capture/cap_nf/cap_nf.h
deleted file mode 100644 (file)
index b9f45c5..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
-Date: 16.05.2008
-*/
-
-/*
-* Author : Maxim Mamontov <faust@stg.dp.ua>
-*/
-
-/*
-$Revision: 1.5 $
-$Date: 2009/12/13 12:56:07 $
-$Author: faust $
-*/
-#pragma once
-
-#include "stg/plugin.h"
-#include "stg/module_settings.h"
-#include "stg/logger.h"
-
-#include <string>
-#include <cstdint>
-
-#include <pthread.h>
-#include <unistd.h> // close
-
-#define VERSION "cap_nf v. 0.4"
-#define START_POS 40
-#define STOP_POS 40
-
-namespace STG
-{
-
-struct Users;
-struct Tariffs;
-struct Admins;
-struct TraffCounter;
-struct Store;
-struct Settings;
-
-}
-
-class NF_CAP : public STG::Plugin {
-public:
-    NF_CAP();
-
-    void            SetTraffcounter(STG::TraffCounter * tc) override { traffCnt = tc; }
-    void            SetSettings(const STG::ModuleSettings & s) override { settings = s; }
-    int             ParseSettings() override;
-
-    int             Start() override;
-    int             Stop() override;
-    int             Reload(const STG::ModuleSettings & /*ms*/) override { return 0; }
-
-    bool            IsRunning() override { return runningTCP || runningUDP; }
-    const std::string & GetStrError() const override { return errorStr; }
-    std::string     GetVersion() const override { return VERSION; }
-    uint16_t        GetStartPosition() const override { return START_POS; }
-    uint16_t        GetStopPosition() const override { return STOP_POS; }
-
-private:
-    NF_CAP(const NF_CAP & rvalue);
-    NF_CAP & operator=(const NF_CAP & rvalue);
-
-    STG::TraffCounter * traffCnt;
-    STG::ModuleSettings settings;
-    pthread_t tidTCP;
-    pthread_t tidUDP;
-    bool runningTCP;
-    bool runningUDP;
-    bool stoppedTCP;
-    bool stoppedUDP;
-    uint16_t portT;
-    uint16_t portU;
-    int sockTCP;
-    int sockUDP;
-    mutable std::string errorStr;
-    STG::PluginLogger logger;
-
-    static void * RunUDP(void *);
-    static void * RunTCP(void *);
-    void ParseBuffer(uint8_t * buf, ssize_t size);
-
-    bool OpenTCP();
-    bool OpenUDP();
-    void CloseTCP() { close(sockTCP); }
-    void CloseUDP() { close(sockUDP); }
-};
diff --git a/stargazer/plugins/capture/divert_freebsd/divert_cap.cpp b/stargazer/plugins/capture/divert_freebsd/divert_cap.cpp
deleted file mode 100644 (file)
index 2898468..0000000
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
-* Author : Boris Mikhailenko <stg34@stg.dp.ua>
-*/
-
-/*
-$Revision: 1.13 $
-$Date: 2010/09/10 06:43:03 $
-*/
-
-#include "divert_cap.h"
-
-#include "stg/traffcounter.h"
-#include "stg/raw_ip_packet.h"
-#include "stg/common.h"
-
-#include <algorithm>
-#include <vector>
-
-#include <cstdio>
-#include <cstring>
-#include <cerrno>
-#include <cstdlib>
-#include <csignal>
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-
-#include <sys/uio.h>
-#include <sys/time.h>
-#include <sys/ioctl.h>
-#include <sys/poll.h>
-
-#include <fcntl.h>
-#include <unistd.h>
-
-#define BUFF_LEN (16384) /* max mtu -> lo=16436  TODO why?*/
-
-//-----------------------------------------------------------------------------
-struct DIVERT_DATA {
-int sock;
-short int port;
-char iface[10];
-};
-//-----------------------------------------------------------------------------
-pollfd pollddiv;
-DIVERT_DATA cddiv;  //capture data
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-
-extern "C" STG::Plugin* GetPlugin()
-{
-    static DIVERT_CAP plugin;
-    return &plugin;
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-std::string DIVERT_CAP::GetVersion() const
-{
-return "cap_divert v.1.0";
-}
-//-----------------------------------------------------------------------------
-DIVERT_CAP::DIVERT_CAP()
-    : port(0),
-      disableForwarding(false),
-      nonstop(false),
-      isRunning(false),
-      traffCnt(NULL),
-      logger(STG::PluginLogger::get("cap_divert"))
-{
-}
-//-----------------------------------------------------------------------------
-int DIVERT_CAP::Start()
-{
-if (isRunning)
-    return 0;
-
-if (DivertCapOpen() < 0)
-    {
-    errorStr = "Cannot open socket!";
-    printfd(__FILE__, "Cannot open socket\n");
-    return -1;
-    }
-
-nonstop = true;
-
-if (pthread_create(&thread, NULL, Run, this))
-    {
-    errorStr = "Cannot create thread.";
-    logger("Cannot create thread.");
-    printfd(__FILE__, "Cannot create thread\n");
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int DIVERT_CAP::Stop()
-{
-if (!isRunning)
-    return 0;
-
-DivertCapClose();
-
-nonstop = false;
-
-//5 seconds to thread stops itself
-int i;
-for (i = 0; i < 25; i++)
-    {
-    if (!isRunning)
-        break;
-
-    struct timespec ts = {0, 200000000};
-    nanosleep(&ts, NULL);
-    }
-
-//after 5 seconds waiting thread still running. now killing it
-if (isRunning)
-    {
-    if (pthread_kill(thread, SIGINT))
-        {
-        errorStr = "Cannot kill thread.";
-        logger("Cannot send signal to thread.");
-        printfd(__FILE__, "Cannot kill thread\n");
-        return -1;
-        }
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-void * DIVERT_CAP::Run(void * d)
-{
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-DIVERT_CAP * dc = static_cast<DIVERT_CAP *>(d);
-dc->isRunning = true;
-
-char buffer[STG::packetSize + 14];
-while (dc->nonstop)
-    {
-    STG::RawPacket rp;
-    dc->DivertCapRead(buffer, sizeof(buffer), NULL);
-
-    if (buffer[12] != 0x8)
-        continue;
-
-    memcpy(&rp.rawPacket, &buffer[14], STG::packetSize);
-
-    dc->traffCnt->process(rp);
-    }
-
-dc->isRunning = false;
-return NULL;
-}
-//-----------------------------------------------------------------------------
-int DIVERT_CAP::DivertCapOpen()
-{
-memset(&pollddiv, 0, sizeof(pollddiv));
-memset(&cddiv, 0, sizeof(DIVERT_DATA));
-
-strcpy(cddiv.iface, "foo");
-cddiv.port = port;
-
-DivertCapOpen(0);
-pollddiv.events = POLLIN;
-pollddiv.fd = cddiv.sock;
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int DIVERT_CAP::DivertCapOpen(int)
-{
-int ret;
-cddiv.sock = socket(PF_INET, SOCK_RAW, IPPROTO_DIVERT);
-if (cddiv.sock < 0)
-    {
-    errorStr = "Create divert socket error.";
-    logger("Cannot create a socket: %s", strerror(errno));
-    printfd(__FILE__, "Cannot create divert socket\n");
-    return -1;
-    }
-
-struct sockaddr_in divAddr;
-
-memset(&divAddr, 0, sizeof(divAddr));
-
-divAddr.sin_family = AF_INET;
-divAddr.sin_port = htons(cddiv.port);
-divAddr.sin_addr.s_addr = INADDR_ANY;
-
-ret = bind(cddiv.sock, (struct sockaddr *)&divAddr, sizeof(divAddr));
-
-if (ret < 0)
-    {
-    errorStr = "Bind divert socket error.";
-    logger("Cannot bind the scoket: %s", strerror(errno));
-    printfd(__FILE__, "Cannot bind divert socket\n");
-    return -1;
-    }
-
-return cddiv.sock;
-}
-//-----------------------------------------------------------------------------
-int DIVERT_CAP::DivertCapRead(char * b, int blen, char ** iface)
-{
-poll(&pollddiv, 1, -1);
-
-if (pollddiv.revents & POLLIN)
-    {
-    DivertCapRead(b, blen, iface, 0);
-    pollddiv.revents = 0;
-    return 0;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int DIVERT_CAP::DivertCapRead(char * b, int blen, char ** iface, int)
-{
-static char buf[BUFF_LEN];
-static struct sockaddr_in divertaddr;
-static int bytes;
-static socklen_t divertaddrSize = sizeof(divertaddr);
-
-if ((bytes = recvfrom (cddiv.sock, buf, BUFF_LEN,
-                       0, (struct sockaddr*) &divertaddr, &divertaddrSize)) > 50)
-    {
-    memcpy(b + 14, buf, blen - 14);
-    b[12] = 0x8;
-
-    if (iface)
-        *iface = cddiv.iface;
-
-    if (!disableForwarding)
-        {
-        if (sendto(cddiv.sock, buf, bytes, 0, (struct sockaddr*)&divertaddr, divertaddrSize) < 0)
-            logger("sendto error: %s", strerror(errno));
-        }
-    }
-else
-    {
-    if (bytes < 0)
-        logger("recvfrom error: %s", strerror(errno));
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int DIVERT_CAP::DivertCapClose()
-{
-close(cddiv.sock);
-return 0;
-}
-//-----------------------------------------------------------------------------
-int DIVERT_CAP::ParseSettings()
-{
-int p;
-STG::ParamValue pv;
-std::vector<STG::ParamValue>::const_iterator pvi;
-
-pv.param = "Port";
-pvi = std::find(settings.moduleParams.begin(), settings.moduleParams.end(), pv);
-if (pvi == settings.moduleParams.end() || pvi->value.empty())
-    {
-    p = 15701;
-    }
-else if (ParseIntInRange(pvi->value[0], 1, 65535, &p))
-    {
-    errorStr = "Cannot parse parameter \'Port\': " + errorStr;
-    printfd(__FILE__, "Cannot parse parameter 'Port'\n");
-    return -1;
-    }
-
-port = p;
-
-bool d = false;
-pv.param = "DisableForwarding";
-pvi = std::find(settings.moduleParams.begin(), settings.moduleParams.end(), pv);
-if (pvi == settings.moduleParams.end() || pvi->value.empty())
-    {
-    disableForwarding = false;
-    }
-else if (ParseYesNo(pvi->value[0], &d))
-    {
-    errorStr = "Cannot parse parameter \'DisableForwarding\': " + errorStr;
-    printfd(__FILE__, "Cannot parse parameter 'DisableForwarding'\n");
-    return -1;
-    }
-
-disableForwarding = d;
-
-return 0;
-}
-//-----------------------------------------------------------------------------
diff --git a/stargazer/plugins/capture/divert_freebsd/divert_cap.h b/stargazer/plugins/capture/divert_freebsd/divert_cap.h
deleted file mode 100644 (file)
index 290754f..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-
-/*
- Author : Boris Mikhailenko <stg34@stg.dp.ua>
-*/
-
-#pragma once
-
-#include "stg/plugin.h"
-#include "stg/module_settings.h"
-#include "stg/logger.h"
-
-#include <string>
-
-#include <pthread.h>
-
-namespace STG
-{
-struct Users;
-struct Tariffs;
-struct Admins;
-struct TraffCounter;
-struct Settings;
-}
-
-//-----------------------------------------------------------------------------
-class DIVERT_CAP : public STG::Plugin {
-public:
-    DIVERT_CAP();
-
-    void                SetTraffcounter(STG::TraffCounter * tc) override { traffCnt = tc; }
-
-    int                 Start() override;
-    int                 Stop() override;
-    int                 Reload(const STG::ModuleSettings & /*ms*/) override { return 0; }
-    bool                IsRunning() override { return isRunning; }
-
-    void                SetSettings(const STG::ModuleSettings & s) override { settings = s; }
-    int                 ParseSettings() override;
-    const std::string & GetStrError() const override { return errorStr; }
-    std::string         GetVersion() const override;
-    uint16_t            GetStartPosition() const override { return 40; }
-    uint16_t            GetStopPosition() const override { return 40; }
-
-private:
-    DIVERT_CAP(const DIVERT_CAP & rvalue);
-    DIVERT_CAP & operator=(const DIVERT_CAP & rvalue);
-
-    static void *       Run(void *);
-
-    int                 DivertCapOpen();
-    int                 DivertCapOpen(int n);
-    int                 DivertCapRead(char * buffer, int blen, char ** iface);
-    int                 DivertCapRead(char * buffer, int blen, char ** iface, int n);
-    int                 DivertCapClose();
-
-    STG::ModuleSettings     settings;
-
-    int                 port;
-    bool                disableForwarding;
-
-    mutable std::string errorStr;
-
-    pthread_t           thread;
-
-    bool                nonstop;
-    bool                isRunning;
-
-    STG::TraffCounter *      traffCnt;
-
-    STG::PluginLogger       logger;
-};
diff --git a/stargazer/plugins/capture/ether_freebsd/ether_cap.cpp b/stargazer/plugins/capture/ether_freebsd/ether_cap.cpp
deleted file mode 100644 (file)
index f063da9..0000000
+++ /dev/null
@@ -1,359 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
-Date: 18.09.2002
-*/
-
-/*
-* Author : Boris Mikhailenko <stg34@stg.dp.ua>
-*/
-
-/*
-$Revision: 1.19 $
-$Date: 2009/03/24 11:20:15 $
-$Author: faust $
-*/
-
-#include "ether_cap.h"
-
-#include "stg/common.h"
-#include "stg/raw_ip_packet.h"
-#include "stg/traffcounter.h"
-
-#include <cerrno>
-#include <cstdio>
-#include <cstring>
-#include <cstdlib>
-#include <csignal>
-
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <sys/ioctl.h>
-
-#include <net/bpf.h>
-#include <net/if.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-//#define CAP_DEBUG 1
-
-extern "C" STG::Plugin* GetPlugin()
-{
-    static BPF_CAP plugin;
-    return &plugin;
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-int BPF_CAP_SETTINGS::ParseSettings(const STG::ModuleSettings & s)
-{
-iface.erase(iface.begin(), iface.end());
-
-if (s.moduleParams.empty())
-    {
-    errorStr = "Parameter \'iface\' not found.";
-    printfd(__FILE__, "Parameter 'iface' not found\n");
-    return -1;
-    }
-
-for (unsigned i = 0; i < s.moduleParams.size(); i++)
-    {
-    if (s.moduleParams[i].param != "iface")
-        {
-        errorStr = "Parameter \'" + s.moduleParams[i].param + "\' unrecognized.";
-        printfd(__FILE__, "Invalid parameter: '%s'\n", s.moduleParams[i].param.c_str());
-        return -1;
-        }
-    for (unsigned j = 0; j < s.moduleParams[i].value.size(); j++)
-        {
-        iface.push_back(s.moduleParams[i].value[j]);
-        }
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-std::string BPF_CAP_SETTINGS::GetIface(unsigned int num)
-{
-if (num >= iface.size())
-    {
-    return "";
-    }
-return iface[num];
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-std::string BPF_CAP::GetVersion() const
-{
-return "cap_bpf v.1.0";
-}
-//-----------------------------------------------------------------------------
-BPF_CAP::BPF_CAP()
-    : nonstop(false),
-      isRunning(false),
-      capSock(-1),
-      traffCnt(NULL),
-      logger(STG::PluginLogger::get("cap_bpf"))
-{
-}
-//-----------------------------------------------------------------------------
-int BPF_CAP::ParseSettings()
-{
-int ret = capSettings.ParseSettings(settings);
-if (ret)
-    {
-    errorStr = capSettings.GetStrError();
-    return ret;
-    }
-return 0;
-}
-//-----------------------------------------------------------------------------
-int BPF_CAP::Start()
-{
-if (isRunning)
-    return 0;
-
-if (BPFCapOpen() < 0)
-    {
-    //errorStr = "Cannot open bpf device!";
-    return -1;
-    }
-
-nonstop = true;
-
-if (pthread_create(&thread, NULL, Run, this))
-    {
-    errorStr = "Cannot create thread.";
-    logger("Cannot create thread.");
-    printfd(__FILE__, "Cannot create thread\n");
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int BPF_CAP::Stop()
-{
-if (!isRunning)
-    return 0;
-
-BPFCapClose();
-
-nonstop = false;
-
-//5 seconds to thread stops itself
-int i;
-for (i = 0; i < 25; i++)
-    {
-    if (!isRunning)
-        break;
-
-    struct timespec ts = {0, 200000000};
-    nanosleep(&ts, NULL);
-    }
-
-//after 5 seconds waiting thread still running. now killing it
-if (isRunning)
-    {
-    //TODO pthread_cancel()
-    if (pthread_kill(thread, SIGINT))
-        {
-        errorStr = "Cannot kill thread.";
-        logger("Cannot send signal to thread.");
-        printfd(__FILE__, "Cannot kill thread\n");
-        return -1;
-        }
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-void * BPF_CAP::Run(void * d)
-{
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-BPF_CAP * dc = static_cast<BPF_CAP *>(d);
-dc->isRunning = true;
-
-uint8_t hdr[96]; //68 + 14 + 4(size) + 9(SYS_IFACE) + 1(align to 4) = 96
-
-STG::RawPacket *  rpp = (STG::RawPacket *)&hdr[14];
-memset(hdr, 0, sizeof(hdr));
-
-rpp->dataLen = -1;
-char * iface;
-
-while (dc->nonstop)
-    {
-    if (dc->BPFCapRead((char*)&hdr, 68 + 14, &iface))
-        continue;
-
-    if (!(hdr[12] == 0x8 && hdr[13] == 0x0))
-        continue;
-
-    dc->traffCnt->process(*rpp);
-    }
-
-dc->isRunning = false;
-return NULL;
-}
-//-----------------------------------------------------------------------------
-int BPF_CAP::BPFCapOpen()
-{
-int i = 0;
-BPF_DATA bd;
-pollfd pd;
-
-while ((bd.iface = capSettings.GetIface(i)) != "")
-    {
-    bpfData.push_back(bd);
-    if (BPFCapOpen(&bpfData[i]) < 0)
-        {
-        return -1;
-        }
-
-    pd.events = POLLIN;
-    pd.fd = bpfData[i].fd;
-    polld.push_back(pd);
-    i++;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int BPF_CAP::BPFCapOpen(BPF_DATA * bd)
-{
-char devbpf[20];
-int i = 0;
-int l = BUFF_LEN;
-int im = 1;
-struct ifreq ifr;
-
-do
-    {
-    sprintf(devbpf, "/dev/bpf%d", i);
-    i++;
-    bd->fd = open(devbpf, O_RDONLY);
-    } while(bd->fd < 0 && errno == EBUSY);
-
-if (bd->fd < 0)
-    {
-    errorStr = "Can't capture packets. Open bpf device for " + bd->iface + " error.";
-    logger("Cannot open device for interface '%s': %s", bd->iface.c_str(), strerror(errno));
-    printfd(__FILE__, "Cannot open BPF device\n");
-    return -1;
-    }
-
-strncpy(ifr.ifr_name, bd->iface.c_str(), sizeof(ifr.ifr_name));
-
-if (ioctl(bd->fd, BIOCSBLEN, (caddr_t)&l) < 0)
-    {
-    errorStr = bd->iface + " BIOCSBLEN " + std::string(strerror(errno));
-    logger("ioctl (BIOCSBLEN) error for interface '%s': %s", bd->iface.c_str(), strerror(errno));
-    printfd(__FILE__, "ioctl failed: '%s'\n", errorStr.c_str());
-    return -1;
-    }
-
-if (ioctl(bd->fd, BIOCSETIF, (caddr_t)&ifr) < 0)
-    {
-    errorStr = bd->iface + " BIOCSETIF " + std::string(strerror(errno));
-    logger("ioctl (BIOCSETIF) error for interface '%s': %s", bd->iface.c_str(), strerror(errno));
-    printfd(__FILE__, "ioctl failed: '%s'\n", errorStr.c_str());
-    return -1;
-    }
-
-if (ioctl(bd->fd, BIOCIMMEDIATE, &im) < 0)
-    {
-    errorStr = bd->iface + " BIOCIMMEDIATE " + std::string(strerror(errno));
-    logger("ioctl (BIOCIMMEDIATE) error for interface '%s': %s", bd->iface.c_str(), strerror(errno));
-    printfd(__FILE__, "ioctl failed: '%s'\n", errorStr.c_str());
-    return -1;
-    }
-
-return bd->fd;
-}
-//-----------------------------------------------------------------------------
-int BPF_CAP::BPFCapClose()
-{
-for (unsigned int i = 0; i < bpfData.size(); i++)
-    close(bpfData[i].fd);
-return 0;
-}
-//-----------------------------------------------------------------------------
-int BPF_CAP::BPFCapRead(char * buffer, int blen, char ** capIface)
-{
-poll(&polld[0], polld.size(), -1);
-
-for (unsigned int i = 0; i < polld.size(); i++)
-    {
-    if (polld[i].revents & POLLIN)
-        {
-        if (BPFCapRead(buffer, blen, capIface, &bpfData[i]))
-            {
-            polld[i].revents = 0;
-            continue;
-            }
-        polld[i].revents = 0;
-        return 0;
-        }
-    }
-return -1;
-}
-//-----------------------------------------------------------------------------
-int BPF_CAP::BPFCapRead(char * buffer, int blen, char **, BPF_DATA * bd)
-{
-if (bd->canRead)
-    {
-    bd->r = read(bd->fd, bd->buffer, BUFF_LEN);
-    if (bd->r < 0)
-        {
-        logger("read error: %s", strerror(errno));
-        struct timespec ts = {0, 20000000};
-        nanosleep(&ts, NULL);
-        return -1;
-        }
-
-    bd->p = bd->buffer;
-    bd->bh = (struct bpf_hdr*)bd->p;
-    bd->canRead = 0;
-    }
-
-if(bd->r > bd->sum)
-    {
-    memcpy(buffer, (char*)(bd->p) + bd->bh->bh_hdrlen, blen);
-
-    bd->sum += BPF_WORDALIGN(bd->bh->bh_hdrlen + bd->bh->bh_caplen);
-    bd->p = bd->p + BPF_WORDALIGN(bd->bh->bh_hdrlen + bd->bh->bh_caplen);
-    bd->bh = (struct bpf_hdr*)bd->p;
-    }
-
-if(bd->r <= bd->sum)
-    {
-    bd->canRead = 1;
-    bd->sum = 0;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
diff --git a/stargazer/plugins/capture/ether_freebsd/ether_cap.h b/stargazer/plugins/capture/ether_freebsd/ether_cap.h
deleted file mode 100644 (file)
index 07380bd..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
- /*
- $Revision: 1.11 $
- $Date: 2009/06/23 11:32:27 $
- $Author: faust $
- */
-
-/*
-* Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
-*/
-
-#pragma once
-
-#include "stg/plugin.h"
-#include "stg/module_settings.h"
-#include "stg/logger.h"
-
-#include <string>
-#include <vector>
-#include <cstdint>
-
-#include <pthread.h>
-#include <sys/poll.h>
-
-#define BUFF_LEN (128)
-
-namespace STG
-{
-struct TraffCounter;
-}
-
-//-----------------------------------------------------------------------------
-struct BPF_DATA {
-    BPF_DATA()
-        {
-        fd = 0;
-        p = NULL;
-        r = 0;
-        sum = 0;
-        memset(buffer, 0, BUFF_LEN);
-        bh = NULL;
-        canRead = 1;
-        iface = "";
-        };
-
-    BPF_DATA(const BPF_DATA & bd)
-        {
-        fd = bd.fd;
-        p = bd.p;
-        r = bd.r;
-        sum = bd.sum;
-        memcpy(buffer, bd.buffer, BUFF_LEN);
-        bh = bd.bh;
-        canRead = bd.canRead;
-        iface = bd.iface;
-        };
-
-int              fd;
-uint8_t *        p;
-int              r;
-int              sum;
-uint8_t          buffer[BUFF_LEN];
-struct bpf_hdr * bh;
-int              canRead;
-std::string      iface;
-};
-//-----------------------------------------------------------------------------
-class BPF_CAP_SETTINGS {
-public:
-    const std::string & GetStrError() const { return errorStr; }
-    int             ParseSettings(const STG::ModuleSettings & s);
-    std::string     GetIface(unsigned int num);
-
-private:
-    std::vector<std::string> iface;
-    mutable std::string errorStr;
-};
-//-----------------------------------------------------------------------------
-class BPF_CAP : public STG::Plugin {
-public:
-                        BPF_CAP();
-
-    void                SetTraffcounter(STG::TraffCounter * tc) override { traffCnt = tc; }
-
-    int                 Start() override;
-    int                 Stop() override;
-    int                 Reload(const STG::ModuleSettings & /*ms*/) override { return 0; }
-    bool                IsRunning() override { return isRunning; }
-
-    void                SetSettings(const STG::ModuleSettings & s) override { settings = s; }
-    int                 ParseSettings() override;
-
-    const std::string & GetStrError() const override { return errorStr; }
-    std::string         GetVersion() const override;
-    uint16_t            GetStartPosition() const override { return 40; }
-    uint16_t            GetStopPosition() const override { return 40; }
-
-private:
-    BPF_CAP(const BPF_CAP & rvalue);
-    BPF_CAP & operator=(const BPF_CAP & rvalue);
-
-    static void *       Run(void *);
-    int                 BPFCapOpen();
-    int                 BPFCapOpen(BPF_DATA * bd);
-    int                 BPFCapClose();
-    int                 BPFCapRead(char * buffer, int blen, char ** iface);
-    int                 BPFCapRead(char * buffer, int blen, char ** iface, BPF_DATA * bd);
-
-    BPF_CAP_SETTINGS      capSettings;
-
-    mutable std::string   errorStr;
-
-    std::vector<BPF_DATA> bpfData;
-    std::vector<pollfd>   polld;
-
-    pthread_t             thread;
-    bool                  nonstop;
-    bool                  isRunning;
-    int                   capSock;
-    STG::ModuleSettings       settings;
-
-    STG::TraffCounter *        traffCnt;
-
-    STG::PluginLogger         logger;
-};
diff --git a/stargazer/plugins/capture/ether_linux/ether_cap.cpp b/stargazer/plugins/capture/ether_linux/ether_cap.cpp
deleted file mode 100644 (file)
index 7ca6c01..0000000
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
-Date: 18.09.2002
-*/
-
-/*
-* Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
-*/
-
-/*
-$Revision: 1.23 $
-$Date: 2009/12/13 13:45:13 $
-*/
-
-#include "ether_cap.h"
-
-#include "stg/common.h"
-#include "stg/raw_ip_packet.h"
-#include "stg/traffcounter.h"
-
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-#include <cerrno>
-#include <csignal>
-
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#include <netinet/in.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <linux/if_ether.h>
-#include <linux/if_packet.h>
-#include <sys/ioctl.h>
-#include <net/if.h>
-
-//#define CAP_DEBUG 1
-
-extern "C" STG::Plugin* GetPlugin()
-{
-    static ETHER_CAP plugin;
-    return &plugin;
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-std::string ETHER_CAP::GetVersion() const
-{
-return "cap_ether v.1.2";
-}
-//-----------------------------------------------------------------------------
-ETHER_CAP::ETHER_CAP()
-    : nonstop(false),
-      isRunning(false),
-      capSock(-1),
-      traffCnt(NULL),
-      logger(STG::PluginLogger::get("cap_ether"))
-{
-}
-//-----------------------------------------------------------------------------
-int ETHER_CAP::Start()
-{
-if (isRunning)
-    return 0;
-
-if (EthCapOpen() < 0)
-    {
-    errorStr = "Cannot open socket!";
-    printfd(__FILE__, "Cannot open socket\n");
-    return -1;
-    }
-
-nonstop = true;
-
-if (pthread_create(&thread, NULL, Run, this))
-    {
-    errorStr = "Cannot create thread.";
-    logger("Cannot create thread.");
-    printfd(__FILE__, "Cannot create thread\n");
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int ETHER_CAP::Stop()
-{
-if (!isRunning)
-    return 0;
-
-nonstop = false;
-
-//5 seconds to thread stops itself
-for (int i = 0; i < 25 && isRunning; i++)
-    {
-    struct timespec ts = {0, 200000000};
-    nanosleep(&ts, NULL);
-    }
-//after 5 seconds waiting thread still running. now killing it
-if (isRunning)
-    {
-    if (pthread_kill(thread, SIGUSR1))
-        {
-        errorStr = "Cannot kill thread.";
-        logger("Cannot send signal to thread.");
-        return -1;
-        }
-    for (int i = 0; i < 25 && isRunning; ++i)
-        {
-        struct timespec ts = {0, 200000000};
-        nanosleep(&ts, NULL);
-        }
-    if (isRunning)
-        {
-        errorStr = "ETHER_CAP not stopped.";
-        logger("Cannot stop thread.");
-        printfd(__FILE__, "Cannot stop thread\n");
-        return -1;
-        }
-    else
-        {
-        pthread_join(thread, NULL);
-        }
-    }
-
-EthCapClose();
-return 0;
-}
-//-----------------------------------------------------------------------------
-void * ETHER_CAP::Run(void * d)
-{
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-ETHER_CAP * dc = static_cast<ETHER_CAP *>(d);
-dc->isRunning = true;
-
-struct ETH_IP
-{
-uint16_t    ethHdr[8];
-STG::RawPacket  rp;
-char        padding[4];
-char        padding1[8];
-};
-
-char ethip[sizeof(ETH_IP)];
-
-memset(&ethip, 0, sizeof(ETH_IP));
-
-ETH_IP * ethIP = static_cast<ETH_IP *>(static_cast<void *>(&ethip));
-ethIP->rp.dataLen = -1;
-
-char * iface = NULL;
-
-while (dc->nonstop)
-    {
-    if (dc->EthCapRead(&ethip, 68 + 14, &iface))
-        {
-        continue;
-        }
-
-    if (ethIP->ethHdr[7] != 0x8)
-        continue;
-
-    dc->traffCnt->process(ethIP->rp);
-    }
-
-dc->isRunning = false;
-return NULL;
-}
-//-----------------------------------------------------------------------------
-int ETHER_CAP::EthCapOpen()
-{
-capSock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
-if (capSock < 0)
-    logger("Cannot create socket: %s", strerror(errno));
-return capSock;
-}
-//-----------------------------------------------------------------------------
-int ETHER_CAP::EthCapClose()
-{
-close(capSock);
-return 0;
-}
-//-----------------------------------------------------------------------------
-int ETHER_CAP::EthCapRead(void * buffer, int blen, char **)
-{
-struct sockaddr_ll  addr;
-int addrLen;
-
-if (!WaitPackets(capSock))
-    {
-    return ENODATA;
-    }
-
-addrLen = sizeof(addr);
-
-if (recvfrom(capSock, ((char*)buffer) + 2, blen, 0, (struct sockaddr *)&addr, (socklen_t*)&addrLen) < 0)
-    {
-    logger("recvfrom error: %s", strerror(errno));
-    return ENODATA;
-    }
-
-return 0;
-}
diff --git a/stargazer/plugins/capture/ether_linux/ether_cap.h b/stargazer/plugins/capture/ether_linux/ether_cap.h
deleted file mode 100644 (file)
index cf776a4..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
- /*
- $Revision: 1.12 $
- $Date: 2009/12/13 13:45:13 $
- */
-
-/*
-* Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
-*/
-
-#pragma once
-
-#include <pthread.h>
-
-#include <string>
-
-#include "stg/plugin.h"
-#include "stg/module_settings.h"
-#include "stg/logger.h"
-
-namespace STG
-{
-
-struct Users;
-struct Tariffs;
-struct Admins;
-struct TraffCounter;
-struct Settings;
-
-}
-
-//-----------------------------------------------------------------------------
-class ETHER_CAP : public STG::Plugin {
-public:
-    ETHER_CAP();
-
-    void                SetTraffcounter(STG::TraffCounter * tc) { traffCnt = tc; }
-
-    int                 Start();
-    int                 Stop();
-    int                 Reload(const STG::ModuleSettings & /*ms*/) { return 0; }
-    bool                IsRunning() { return isRunning; }
-
-    int                 ParseSettings() { return 0; }
-    const std::string & GetStrError() const { return errorStr; }
-    std::string         GetVersion() const;
-    uint16_t            GetStartPosition() const { return 40; }
-    uint16_t            GetStopPosition() const { return 40; }
-
-private:
-    ETHER_CAP(const ETHER_CAP & rvalue);
-    ETHER_CAP & operator=(const ETHER_CAP & rvalue);
-
-    static void *       Run(void *);
-    int                 EthCapOpen();
-    int                 EthCapClose();
-    int                 EthCapRead(void * buffer, int blen, char ** iface);
-
-    mutable std::string errorStr;
-
-    pthread_t           thread;
-    bool                nonstop;
-    bool                isRunning;
-    int                 capSock;
-
-    STG::TraffCounter *      traffCnt;
-
-    STG::PluginLogger       logger;
-};
diff --git a/stargazer/plugins/capture/nfqueue/nfqueue.cpp b/stargazer/plugins/capture/nfqueue/nfqueue.cpp
deleted file mode 100644 (file)
index 3c79c1b..0000000
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
-* Author : Maxim Mamontov <faust@stargazer.dp.ua>
-*/
-
-#include "nfqueue.h"
-
-#include "stg/traffcounter.h"
-#include "stg/common.h"
-#include "stg/raw_ip_packet.h"
-
-extern "C" {
-
-#include <linux/netfilter.h>  /* Defines verdicts (NF_ACCEPT, etc) */
-#include <libnetfilter_queue/libnetfilter_queue.h>
-
-}
-
-#include <cerrno>
-#include <csignal>
-
-#include <arpa/inet.h> // ntohl
-
-#include <unistd.h> // read
-
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-namespace
-{
-
-int Callback(struct nfq_q_handle * queueHandle, struct nfgenmsg * /*msg*/,
-             struct nfq_data * nfqData, void *data)
-{
-int id = 0;
-
-struct nfqnl_msg_packet_hdr * packetHeader = nfq_get_msg_packet_hdr(nfqData);
-if (packetHeader == NULL)
-    return 0;
-
-id = ntohl(packetHeader->packet_id);
-
-unsigned char * payload = NULL;
-
-if (nfq_get_payload(nfqData, &payload) < 0 || payload == NULL)
-    return id;
-
-STG::RawPacket packet;
-
-memcpy(&packet.rawPacket, payload, sizeof(packet.rawPacket));
-
-NFQ_CAP * cap = static_cast<NFQ_CAP *>(data);
-
-cap->Process(packet);
-
-return nfq_set_verdict(queueHandle, id, NF_ACCEPT, 0, NULL);
-}
-
-}
-
-extern "C" STG::Plugin* GetPlugin()
-{
-    static NFQ_CAP plugin;
-    return &plugin;
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-std::string NFQ_CAP::GetVersion() const
-{
-return "cap_nfqueue v.1.0";
-}
-//-----------------------------------------------------------------------------
-NFQ_CAP::NFQ_CAP()
-    : nonstop(false),
-      isRunning(false),
-      queueNumber(0),
-      nfqHandle(NULL),
-      queueHandle(NULL),
-      traffCnt(NULL),
-      logger(STG::PluginLogger::get("cap_nfqueue"))
-{
-}
-//-----------------------------------------------------------------------------
-int NFQ_CAP::ParseSettings()
-{
-for (size_t i = 0; i < settings.moduleParams.size(); i++)
-    if (settings.moduleParams[i].param == "queueNumber" && !settings.moduleParams[i].value.empty())
-        if (str2x(settings.moduleParams[i].value[0], queueNumber) < 0)
-            {
-            errorStr = "Queue number should be a number. Got: '" + settings.moduleParams[i].param + "'";
-            logger(errorStr);
-            return -1;
-            }
-return 0;
-}
-//-----------------------------------------------------------------------------
-int NFQ_CAP::Start()
-{
-if (isRunning)
-    return 0;
-
-nfqHandle = nfq_open();
-if (nfqHandle == NULL)
-    {
-    errorStr = "Failed to initialize netfilter queue.";
-    logger(errorStr);
-    return -1;
-    }
-
-if (nfq_unbind_pf(nfqHandle, AF_INET) < 0)
-    {
-    errorStr = "Failed to unbind netfilter queue from IP handling.";
-    logger(errorStr);
-    return -1;
-    }
-
-if (nfq_bind_pf(nfqHandle, AF_INET) < 0)
-    {
-    errorStr = "Failed to bind netfilter queue to IP handling.";
-    logger(errorStr);
-    return -1;
-    }
-
-queueHandle = nfq_create_queue(nfqHandle, queueNumber, &Callback, this);
-if (queueHandle == NULL)
-    {
-    errorStr = "Failed to create queue " + std::to_string(queueNumber) + ".";
-    logger(errorStr);
-    return -1;
-    }
-
-if (nfq_set_mode(queueHandle, NFQNL_COPY_PACKET, 0xffFF) < 0)
-    {
-    errorStr = "Failed to set queue " + std::to_string(queueNumber) + " mode.";
-    logger(errorStr);
-    return -1;
-    }
-
-nonstop = true;
-
-if (pthread_create(&thread, NULL, Run, this))
-    {
-    errorStr = "Cannot create thread.";
-    logger("Cannot create thread.");
-    printfd(__FILE__, "Cannot create thread\n");
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int NFQ_CAP::Stop()
-{
-if (!isRunning)
-    return 0;
-
-nonstop = false;
-
-//5 seconds to thread stops itself
-for (int i = 0; i < 25 && isRunning; i++)
-    {
-    struct timespec ts = {0, 200000000};
-    nanosleep(&ts, NULL);
-    }
-//after 5 seconds waiting thread still running. now killing it
-if (isRunning)
-    {
-    if (pthread_kill(thread, SIGUSR1))
-        {
-        errorStr = "Cannot kill thread.";
-        logger("Cannot send signal to thread.");
-        return -1;
-        }
-    for (int i = 0; i < 25 && isRunning; ++i)
-        {
-        struct timespec ts = {0, 200000000};
-        nanosleep(&ts, NULL);
-        }
-    if (isRunning)
-        {
-        errorStr = "NFQ_CAP not stopped.";
-        logger("Cannot stop thread.");
-        printfd(__FILE__, "Cannot stop thread\n");
-        return -1;
-        }
-    }
-
-pthread_join(thread, NULL);
-
-nfq_destroy_queue(queueHandle);
-nfq_close(nfqHandle);
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-void * NFQ_CAP::Run(void * d)
-{
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-NFQ_CAP * dc = static_cast<NFQ_CAP *>(d);
-dc->isRunning = true;
-
-int fd = nfq_fd(dc->nfqHandle);
-char buf[4096];
-
-while (dc->nonstop)
-    {
-        if (!WaitPackets(fd))
-            continue;
-
-        int rv = read(fd, buf, sizeof(buf));
-        if (rv < 0)
-            {
-            dc->errorStr = std::string("Read error: ") + strerror(errno);
-            dc->logger(dc->errorStr);
-            break;
-            }
-        nfq_handle_packet(dc->nfqHandle, buf, rv);
-    }
-
-dc->isRunning = false;
-return NULL;
-}
-//-----------------------------------------------------------------------------
-void NFQ_CAP::Process(const STG::RawPacket & packet)
-{
-traffCnt->process(packet);
-}
diff --git a/stargazer/plugins/capture/nfqueue/nfqueue.h b/stargazer/plugins/capture/nfqueue/nfqueue.h
deleted file mode 100644 (file)
index 7d71bcd..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
-* Author : Maxim Mamontov <faust@stargazer.dp.ua>
-*/
-
-#pragma once
-
-#include "stg/plugin.h"
-#include "stg/module_settings.h"
-#include "stg/logger.h"
-
-#include <string>
-#include <vector>
-
-#include <pthread.h>
-
-namespace STG
-{
-
-struct Users;
-struct Tariffs;
-struct Admins;
-struct TraffCounter;
-struct Settings;
-struct RawPacket;
-
-}
-
-struct nfq_handle;
-struct nfq_q_handle;
-
-class NFQ_CAP : public STG::Plugin {
-public:
-    NFQ_CAP();
-
-    void                SetTraffcounter(STG::TraffCounter * tc) override { traffCnt = tc; }
-
-    int                 Start() override;
-    int                 Stop() override;
-    int                 Reload(const STG::ModuleSettings & /*ms*/) override { return 0; }
-    bool                IsRunning() override { return isRunning; }
-
-    void                SetSettings(const STG::ModuleSettings & s) override { settings = s; }
-    int                 ParseSettings() override;
-
-    const std::string & GetStrError() const override { return errorStr; }
-    std::string         GetVersion() const override;
-    uint16_t            GetStartPosition() const override { return 40; }
-    uint16_t            GetStopPosition() const override { return 40; }
-
-    void                Process(const STG::RawPacket & packet);
-
-private:
-    NFQ_CAP(const NFQ_CAP & rvalue);
-    NFQ_CAP & operator=(const NFQ_CAP & rvalue);
-
-    static void *       Run(void *);
-
-    mutable std::string errorStr;
-
-    pthread_t           thread;
-    bool                nonstop;
-    bool                isRunning;
-    STG::ModuleSettings     settings;
-
-    size_t              queueNumber;
-
-    struct nfq_handle * nfqHandle;
-    struct nfq_q_handle * queueHandle;
-
-    STG::TraffCounter *      traffCnt;
-
-    STG::PluginLogger       logger;
-};
diff --git a/stargazer/plugins/capture/pcap/pcap_cap.cpp b/stargazer/plugins/capture/pcap/pcap_cap.cpp
deleted file mode 100644 (file)
index 394487f..0000000
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
-* Author : Maxim Mamontov <faust@stargazer.dp.ua>
-*/
-
-#include "pcap_cap.h"
-
-#include "stg/traffcounter.h"
-#include "stg/common.h"
-#include "stg/raw_ip_packet.h"
-
-#include <signal.h>
-
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-namespace
-{
-
-const size_t SNAP_LEN = 1518;
-const size_t ETHER_ADDR_LEN = 6;
-
-struct ETH
-{
-u_char     ether_dhost[ETHER_ADDR_LEN];    /* destination host address */
-u_char     ether_shost[ETHER_ADDR_LEN];    /* source host address */
-u_short    ether_type;                     /* IP? ARP? RARP? etc */
-};
-
-}
-
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-extern "C" STG::Plugin* GetPlugin()
-{
-    static PCAP_CAP plugin;
-    return &plugin;
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-std::string PCAP_CAP::GetVersion() const
-{
-return "pcap_cap v.1.0";
-}
-//-----------------------------------------------------------------------------
-PCAP_CAP::PCAP_CAP()
-    : nonstop(false),
-      isRunning(false),
-      traffCnt(NULL),
-      logger(STG::PluginLogger::get("pcap_cap"))
-{
-}
-//-----------------------------------------------------------------------------
-int PCAP_CAP::ParseSettings()
-{
-devices.erase(devices.begin(), devices.end());
-
-if (settings.moduleParams.empty())
-    {
-    devices.push_back(DEV());
-    logger("Defaulting to pseudo-device 'any'.");
-    return 0;
-    }
-
-for (size_t i = 0; i < settings.moduleParams.size(); i++)
-    if (settings.moduleParams[i].param == "interfaces")
-        for (size_t j = 0; j < settings.moduleParams[i].value.size(); j++)
-            devices.push_back(DEV(settings.moduleParams[i].value[j]));
-
-for (size_t i = 0; i < settings.moduleParams.size(); i++)
-    if (settings.moduleParams[i].param == "filters")
-        for (size_t j = 0; j < settings.moduleParams[i].value.size(); j++)
-            if (j < devices.size())
-                devices[j].filterExpression = settings.moduleParams[i].value[j];
-
-if (devices.empty())
-    {
-    devices.push_back(DEV());
-    logger("Defaulting to pseudo-device 'all'.");
-    return 0;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int PCAP_CAP::Start()
-{
-if (isRunning)
-    return 0;
-
-DEV_MAP::iterator it(devices.begin());
-while (it != devices.end())
-    {
-    bpf_u_int32 mask;
-    bpf_u_int32 net;
-    char errbuf[PCAP_ERRBUF_SIZE];
-
-    /* get network number and mask associated with capture device */
-    if (pcap_lookupnet(it->device.c_str(), &net, &mask, errbuf) == -1)
-        {
-        errorStr = "Couldn't get netmask for device " + it->device + ": " + errbuf;
-        logger(errorStr);
-        printfd(__FILE__, "%s\n", errorStr.c_str());
-        return -1;
-        }
-
-    /* open capture device */
-    it->handle = pcap_open_live(it->device.c_str(), SNAP_LEN, 1, 1000, errbuf);
-    if (it->handle == NULL)
-        {
-        errorStr = "Couldn't open device " + it->device + ": " + errbuf;
-        logger(errorStr);
-        printfd(__FILE__, "%s\n", errorStr.c_str());
-        return -1;
-        }
-
-    if (pcap_setnonblock(it->handle, true, errbuf) == -1)
-        {
-        errorStr = "Couldn't put device " + it->device + " into non-blocking mode: " + errbuf;
-        logger(errorStr);
-        printfd(__FILE__, "%s\n", errorStr.c_str());
-        return -1;
-        }
-
-    /* make sure we're capturing on an Ethernet device [2] */
-    if (pcap_datalink(it->handle) != DLT_EN10MB)
-        {
-        errorStr = it->device + " is not an Ethernet";
-        logger(errorStr);
-        printfd(__FILE__, "%s\n", errorStr.c_str());
-        return -1;
-        }
-
-    /* compile the filter expression */
-    if (pcap_compile(it->handle, &it->filter, it->filterExpression.c_str(), 0, net) == -1)
-        {
-        errorStr = "Couldn't parse filter " + it->filterExpression + ": " + pcap_geterr(it->handle);
-        logger(errorStr);
-        printfd(__FILE__, "%s\n", errorStr.c_str());
-        return -1;
-        }
-
-    /* apply the compiled filter */
-    if (pcap_setfilter(it->handle, &it->filter) == -1)
-        {
-        errorStr = "Couldn't install filter " + it->filterExpression + ": " + pcap_geterr(it->handle);
-        logger(errorStr);
-        printfd(__FILE__, "%s\n", errorStr.c_str());
-        return -1;
-        }
-
-    it->fd = pcap_get_selectable_fd(it->handle);
-    if (it->fd == -1)
-        {
-        errorStr = "Couldn't get a file descriptor for " + it->device + ": " + pcap_geterr(it->handle);
-        logger(errorStr);
-        printfd(__FILE__, "%s\n", errorStr.c_str());
-        return -1;
-        }
-
-    ++it;
-    }
-
-nonstop = true;
-
-if (pthread_create(&thread, NULL, Run, this))
-    {
-    errorStr = "Cannot create thread.";
-    logger("Cannot create thread.");
-    printfd(__FILE__, "Cannot create thread\n");
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int PCAP_CAP::Stop()
-{
-if (!isRunning)
-    return 0;
-
-nonstop = false;
-
-//5 seconds to thread stops itself
-for (int i = 0; i < 25 && isRunning; i++)
-    {
-    struct timespec ts = {0, 200000000};
-    nanosleep(&ts, NULL);
-    }
-//after 5 seconds waiting thread still running. now killing it
-if (isRunning)
-    {
-    if (pthread_kill(thread, SIGUSR1))
-        {
-        errorStr = "Cannot kill thread.";
-        logger("Cannot send signal to thread.");
-        return -1;
-        }
-    for (int i = 0; i < 25 && isRunning; ++i)
-        {
-        struct timespec ts = {0, 200000000};
-        nanosleep(&ts, NULL);
-        }
-    if (isRunning)
-        {
-        errorStr = "PCAP_CAP not stopped.";
-        logger("Cannot stop thread.");
-        printfd(__FILE__, "Cannot stop thread\n");
-        return -1;
-        }
-    }
-
-pthread_join(thread, NULL);
-
-for (DEV_MAP::iterator it(devices.begin()); it != devices.end(); ++it)
-    {
-    pcap_freecode(&it->filter);
-    pcap_close(it->handle);
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-void * PCAP_CAP::Run(void * d)
-{
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-PCAP_CAP * dc = static_cast<PCAP_CAP *>(d);
-dc->isRunning = true;
-
-fd_set fds;
-FD_ZERO(&fds);
-int maxFd = 0;
-for (DEV_MAP::const_iterator it(dc->devices.begin()); it != dc->devices.end(); ++it)
-    {
-    FD_SET(it->fd, &fds);
-    maxFd = std::max(maxFd, it->fd);
-    }
-
-while (dc->nonstop)
-    {
-    fd_set rfds = fds;
-    struct timeval tv = {0, 500000};
-
-    if (select(maxFd + 1, &rfds, NULL, NULL, &tv) > 0)
-        dc->TryRead(rfds);
-    }
-
-dc->isRunning = false;
-return NULL;
-}
-
-void PCAP_CAP::TryRead(const fd_set & set)
-{
-for (DEV_MAP::const_iterator it(devices.begin()); it != devices.end(); ++it)
-    if (FD_ISSET(it->fd, &set))
-        TryReadDev(*it);
-}
-
-void PCAP_CAP::TryReadDev(const DEV & dev)
-{
-struct pcap_pkthdr * header;
-const u_char * packet;
-if (pcap_next_ex(dev.handle, &header, &packet) == -1)
-    {
-    printfd(__FILE__, "Failed to read data from '%s': %s\n", dev.device.c_str(), pcap_geterr(dev.handle));
-    return;
-    }
-
-const ETH * eth = reinterpret_cast<const ETH *>(packet);
-if (eth->ether_type != 0x8)
-    return;
-
-STG::RawPacket ip;
-memcpy(&ip.rawPacket, packet + 14, sizeof(ip.rawPacket));
-traffCnt->process(ip);
-}
diff --git a/stargazer/plugins/capture/pcap/pcap_cap.h b/stargazer/plugins/capture/pcap/pcap_cap.h
deleted file mode 100644 (file)
index f47c6b8..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
-* Author : Maxim Mamontov <faust@stargazer.dp.ua>
-*/
-
-#pragma once
-
-#include "stg/plugin.h"
-#include "stg/module_settings.h"
-#include "stg/logger.h"
-
-#include <string>
-#include <vector>
-
-#include <pcap.h>
-#include <pthread.h>
-#include <sys/select.h>
-
-namespace STG
-{
-
-struct Users;
-struct Tariffs;
-struct Admins;
-struct TraffCounter;
-struct Settings;
-
-}
-
-struct DEV
-{
-    DEV() : device("any"), filterExpression("ip"), handle(NULL), fd(-1) {}
-    DEV(const std::string & d) : device(d), filterExpression("ip"), handle(NULL), fd(-1) {}
-    DEV(const std::string & d, const std::string & f)
-        : device(d), filterExpression(f), handle(NULL), fd(-1) {}
-
-    std::string device;
-    std::string filterExpression;
-    pcap_t * handle;
-    struct bpf_program filter;
-    int fd;
-};
-
-typedef std::vector<DEV> DEV_MAP;
-
-class PCAP_CAP : public STG::Plugin {
-public:
-    PCAP_CAP();
-
-    void                SetTraffcounter(STG::TraffCounter * tc) override { traffCnt = tc; }
-
-    int                 Start() override;
-    int                 Stop() override;
-    int                 Reload(const STG::ModuleSettings & /*ms*/) override { return 0; }
-    bool                IsRunning() override { return isRunning; }
-
-    void                SetSettings(const STG::ModuleSettings & s) override { settings = s; }
-    int                 ParseSettings() override;
-
-    const std::string & GetStrError() const override { return errorStr; }
-    std::string         GetVersion() const override;
-    uint16_t            GetStartPosition() const override { return 40; }
-    uint16_t            GetStopPosition() const override { return 40; }
-
-private:
-    PCAP_CAP(const PCAP_CAP & rvalue);
-    PCAP_CAP & operator=(const PCAP_CAP & rvalue);
-
-    void TryRead(const fd_set & set);
-    void TryReadDev(const DEV & dev);
-
-    static void *       Run(void *);
-
-    mutable std::string errorStr;
-
-    pthread_t           thread;
-    bool                nonstop;
-    bool                isRunning;
-    STG::ModuleSettings     settings;
-    DEV_MAP             devices;
-
-    STG::TraffCounter *      traffCnt;
-
-    STG::PluginLogger       logger;
-};
diff --git a/stargazer/plugins/configuration/rpcconfig/admins_methods.cpp b/stargazer/plugins/configuration/rpcconfig/admins_methods.cpp
deleted file mode 100644 (file)
index d8fb012..0000000
+++ /dev/null
@@ -1,257 +0,0 @@
-#include "admins_methods.h"
-#include "rpcconfig.h"
-
-#include "stg/common.h"
-
-#include "stg/admins.h"
-#include "stg/admin.h"
-#include "stg/admin_conf.h"
-
-#include <ostream> // xmlrpc-c devs have missed something :)
-
-//------------------------------------------------------------------------------
-
-void METHOD_ADMIN_GET::execute(xmlrpc_c::paramList const & paramList,
-                               xmlrpc_c::value *   const   retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-std::string login = paramList.getString(1);
-paramList.verifyEnd(2);
-
-std::map<std::string, xmlrpc_c::value> structVal;
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
-    {
-    structVal["result"] = xmlrpc_c::value_boolean(false);
-    *retvalPtr = xmlrpc_c::value_struct(structVal);
-    return;
-    }
-
-STG::Admin * admin;
-
-if (admins->find(login, &admin))
-    {
-    structVal["result"] = xmlrpc_c::value_boolean(false);
-    *retvalPtr = xmlrpc_c::value_struct(structVal);
-    return;
-    }
-
-structVal["result"] = xmlrpc_c::value_boolean(true);
-structVal["login"] = xmlrpc_c::value_string(admin->login());
-structVal["password"] = xmlrpc_c::value_string(admin->password());
-
-const auto priv = admin->priv();
-
-structVal["user_stat"] = xmlrpc_c::value_boolean(priv.userStat);
-structVal["user_conf"] = xmlrpc_c::value_boolean(priv.userConf);
-structVal["user_cash"] = xmlrpc_c::value_boolean(priv.userCash);
-structVal["user_passwd"] = xmlrpc_c::value_boolean(priv.userPasswd);
-structVal["user_add_del"] = xmlrpc_c::value_boolean(priv.userAddDel);
-structVal["admin_chg"] = xmlrpc_c::value_boolean(priv.adminChg);
-structVal["tariff_chg"] = xmlrpc_c::value_boolean(priv.tariffChg);
-
-*retvalPtr = xmlrpc_c::value_struct(structVal);
-}
-
-//------------------------------------------------------------------------------
-
-void METHOD_ADMIN_ADD::execute(xmlrpc_c::paramList const & paramList,
-                               xmlrpc_c::value *   const   retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-std::string login = paramList.getString(1);
-paramList.verifyEnd(2);
-
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
-    {
-    printfd(__FILE__, "METHOD_ADMIN_ADD::execute(): 'Not logged or cookie timeout'\n");
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-
-STG::Admin * admin;
-
-if (admins->find(adminInfo.admin, &admin))
-    {
-    printfd(__FILE__, "METHOD_ADMIN_ADD::execute(): 'Invalid admin (logged)'\n");
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-
-if (admins->add(login, *admin))
-    {
-    printfd(__FILE__, "METHOD_ADMIN_ADD::execute(): 'Failed to add admin'\n");
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-
-*retvalPtr = xmlrpc_c::value_boolean(true);
-}
-
-//------------------------------------------------------------------------------
-
-void METHOD_ADMIN_DEL::execute(xmlrpc_c::paramList const & paramList,
-                               xmlrpc_c::value *   const   retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-std::string login = paramList.getString(1);
-paramList.verifyEnd(2);
-
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-
-STG::Admin * admin;
-
-if (admins->find(adminInfo.admin, &admin))
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-
-if (admins->del(login, *admin))
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-
-*retvalPtr = xmlrpc_c::value_boolean(true);
-}
-
-//------------------------------------------------------------------------------
-
-void METHOD_ADMIN_CHG::execute(xmlrpc_c::paramList const & paramList,
-                               xmlrpc_c::value *   const   retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-std::string login = paramList.getString(1);
-xmlrpc_c::value_struct info(paramList.getStruct(2));
-paramList.verifyEnd(3);
-
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-
-STG::Admin * loggedAdmin;
-
-if (admins->find(adminInfo.admin, &loggedAdmin))
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-
-STG::Admin * admin;
-
-if (admins->find(login, &admin))
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-
-STG::AdminConf conf;
-
-conf.priv = admin->priv();
-conf.password = admin->password();
-conf.login = login;
-
-std::map<std::string, xmlrpc_c::value> structVal = info;
-
-std::map<std::string, xmlrpc_c::value>::iterator it;
-
-if ((it = structVal.find("password")) != structVal.end())
-    {
-    conf.password = xmlrpc_c::value_string(it->second);
-    }
-
-if ((it = structVal.find("user_stat")) != structVal.end())
-    {
-    conf.priv.userStat = xmlrpc_c::value_boolean(it->second);
-    }
-
-if ((it = structVal.find("user_conf")) != structVal.end())
-    {
-    conf.priv.userConf = xmlrpc_c::value_boolean(it->second);
-    }
-
-if ((it = structVal.find("user_cash")) != structVal.end())
-    {
-    conf.priv.userCash = xmlrpc_c::value_boolean(it->second);
-    }
-
-if ((it = structVal.find("user_passwd")) != structVal.end())
-    {
-    conf.priv.userPasswd = xmlrpc_c::value_boolean(it->second);
-    }
-
-if ((it = structVal.find("user_add_del")) != structVal.end())
-    {
-    conf.priv.userAddDel = xmlrpc_c::value_boolean(it->second);
-    }
-
-if ((it = structVal.find("admin_chg")) != structVal.end())
-    {
-    conf.priv.adminChg = xmlrpc_c::value_boolean(it->second);
-    }
-
-if ((it = structVal.find("tariff_chg")) != structVal.end())
-    {
-    conf.priv.tariffChg = xmlrpc_c::value_boolean(it->second);
-    }
-
-if (admins->change(conf, *loggedAdmin))
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    }
-
-*retvalPtr = xmlrpc_c::value_boolean(true);
-}
-
-//------------------------------------------------------------------------------
-
-void METHOD_ADMINS_GET::execute(xmlrpc_c::paramList const & paramList,
-                                xmlrpc_c::value *   const   retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-paramList.verifyEnd(1);
-
-std::map<std::string, xmlrpc_c::value> mainStructVal;
-std::vector<xmlrpc_c::value> retval;
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
-    {
-    mainStructVal["result"] = xmlrpc_c::value_boolean(false);
-    *retvalPtr = xmlrpc_c::value_struct(mainStructVal);
-    return;
-    }
-
-admins->fmap([&retval](const auto& admin)
-    {
-        const std::map<std::string, xmlrpc_c::value> structVal{
-            {"result", xmlrpc_c::value_boolean(true)},
-            {"login", xmlrpc_c::value_string(admin.login())},
-            {"password", xmlrpc_c::value_string(admin.password())},
-            {"user_stat", xmlrpc_c::value_boolean(admin.priv().userStat)},
-            {"user_conf", xmlrpc_c::value_boolean(admin.priv().userConf)},
-            {"user_cash", xmlrpc_c::value_boolean(admin.priv().userCash)},
-            {"user_passwd", xmlrpc_c::value_boolean(admin.priv().userPasswd)},
-            {"user_add_del", xmlrpc_c::value_boolean(admin.priv().userAddDel)},
-            {"admin_chg", xmlrpc_c::value_boolean(admin.priv().adminChg)},
-            {"tariff_chg", xmlrpc_c::value_boolean(admin.priv().tariffChg)}
-        };
-        retval.push_back(xmlrpc_c::value_struct(structVal));
-    });
-
-*retvalPtr = xmlrpc_c::value_array(retval);
-}
diff --git a/stargazer/plugins/configuration/rpcconfig/admins_methods.h b/stargazer/plugins/configuration/rpcconfig/admins_methods.h
deleted file mode 100644 (file)
index 43c8073..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-#pragma once
-
-#include <xmlrpc-c/base.hpp>
-#include <xmlrpc-c/registry.hpp>
-
-namespace STG
-{
-
-struct Admins;
-
-}
-
-class RPC_CONFIG;
-
-class METHOD_ADMIN_GET : public xmlrpc_c::method {
-public:
-    METHOD_ADMIN_GET(RPC_CONFIG * c,
-                     STG::Admins * a)
-        : config(c),
-          admins(a)
-    {
-    }
-
-    void execute(xmlrpc_c::paramList const & paramList,
-                 xmlrpc_c::value * const retvalPtr);
-
-private:
-    METHOD_ADMIN_GET(const METHOD_ADMIN_GET & rvalue);
-    METHOD_ADMIN_GET & operator=(const METHOD_ADMIN_GET & rvalue);
-
-    RPC_CONFIG * config;
-    STG::Admins * admins;
-};
-
-class METHOD_ADMIN_ADD : public xmlrpc_c::method {
-public:
-    METHOD_ADMIN_ADD(RPC_CONFIG * c,
-                     STG::Admins * a)
-        : config(c),
-          admins(a)
-    {
-    }
-
-    void execute(xmlrpc_c::paramList const & paramList,
-                 xmlrpc_c::value * const retvalPtr);
-
-private:
-    METHOD_ADMIN_ADD(const METHOD_ADMIN_ADD & rvalue);
-    METHOD_ADMIN_ADD & operator=(const METHOD_ADMIN_ADD & rvalue);
-
-    RPC_CONFIG * config;
-    STG::Admins * admins;
-};
-
-class METHOD_ADMIN_DEL : public xmlrpc_c::method {
-public:
-    METHOD_ADMIN_DEL(RPC_CONFIG * c,
-                     STG::Admins * a)
-        : config(c),
-          admins(a)
-    {
-    }
-
-    void execute(xmlrpc_c::paramList const & paramList,
-                 xmlrpc_c::value * const retvalPtr);
-
-private:
-    METHOD_ADMIN_DEL(const METHOD_ADMIN_DEL & rvalue);
-    METHOD_ADMIN_DEL & operator=(const METHOD_ADMIN_DEL & rvalue);
-
-    RPC_CONFIG * config;
-    STG::Admins * admins;
-};
-
-class METHOD_ADMIN_CHG : public xmlrpc_c::method {
-public:
-    METHOD_ADMIN_CHG(RPC_CONFIG * c,
-                     STG::Admins * a)
-        : config(c),
-          admins(a)
-    {
-    }
-
-    void execute(xmlrpc_c::paramList const & paramList,
-                 xmlrpc_c::value * const retvalPtr);
-
-private:
-    METHOD_ADMIN_CHG(const METHOD_ADMIN_CHG & rvalue);
-    METHOD_ADMIN_CHG & operator=(const METHOD_ADMIN_CHG & rvalue);
-
-    RPC_CONFIG * config;
-    STG::Admins * admins;
-};
-
-class METHOD_ADMINS_GET : public xmlrpc_c::method {
-public:
-    METHOD_ADMINS_GET(RPC_CONFIG * c,
-                      STG::Admins * a)
-        : config(c),
-          admins(a)
-    {
-    }
-
-    void execute(xmlrpc_c::paramList const & paramList,
-                 xmlrpc_c::value * const retvalPtr);
-
-private:
-    METHOD_ADMINS_GET(const METHOD_ADMINS_GET & rvalue);
-    METHOD_ADMINS_GET & operator=(const METHOD_ADMINS_GET & rvalue);
-
-    RPC_CONFIG * config;
-    STG::Admins * admins;
-};
diff --git a/stargazer/plugins/configuration/rpcconfig/info_methods.cpp b/stargazer/plugins/configuration/rpcconfig/info_methods.cpp
deleted file mode 100644 (file)
index e0c371c..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-#include "info_methods.h"
-#include "rpcconfig.h"
-
-#include "stg/users.h"
-#include "stg/tariffs.h"
-#include "stg/version.h"
-#include "stg/common.h"
-#include "stg/const.h"
-
-#include <ostream> // xmlrpc-c devs have missed something :)
-
-#include <sys/utsname.h>
-
-void METHOD_INFO::execute(xmlrpc_c::paramList const & paramList,
-                          xmlrpc_c::value *   const   retvalPtr)
-{
-paramList.verifyEnd(0);
-std::map<std::string, xmlrpc_c::value> structVal;
-
-std::string un;
-struct utsname utsn;
-
-uname(&utsn);
-un[0] = 0;
-
-un += utsn.sysname;
-un += " ";
-un += utsn.release;
-un += " ";
-un += utsn.machine;
-un += " ";
-un += utsn.nodename;
-
-structVal["version"] = xmlrpc_c::value_string(SERVER_VERSION);
-structVal["tariff_num"] = xmlrpc_c::value_int(static_cast<int>(tariffs->Count()));
-structVal["tariff"] = xmlrpc_c::value_int(2);
-structVal["users_num"] = xmlrpc_c::value_int(static_cast<int>(users->Count()));
-structVal["uname"] = xmlrpc_c::value_string(un);
-structVal["dir_num"] = xmlrpc_c::value_int(DIR_NUM);
-structVal["day_fee"] = xmlrpc_c::value_int(static_cast<int>(dayFee));
-
-std::vector<xmlrpc_c::value> dirnameVal;
-
-for (int i = 0; i< DIR_NUM; i++)
-    {
-    dirnameVal.push_back(xmlrpc_c::value_string(IconvString(dirNames[i], "KOI8-RU", "UTF-8")));
-    }
-
-structVal["dir_names"] = xmlrpc_c::value_array(dirnameVal);
-
-*retvalPtr = xmlrpc_c::value_struct(structVal);
-}
-
-void METHOD_LOGIN::execute(xmlrpc_c::paramList const & paramList,
-                           xmlrpc_c::value *   const   retvalPtr)
-{
-std::string login = paramList.getString(0);
-std::string password = paramList.getString(1);
-paramList.verifyEnd(2);
-
-std::map<std::string, xmlrpc_c::value> structVal;
-
-std::string cookie;
-if (config->CheckAdmin(login, password, &cookie))
-    {
-    structVal["result"] = xmlrpc_c::value_boolean(false);
-    structVal["cookie"] = xmlrpc_c::value_string("");
-    }
-else
-    {
-    structVal["result"] = xmlrpc_c::value_boolean(true);
-    structVal["cookie"] = xmlrpc_c::value_string(cookie);
-    }
-
-*retvalPtr = xmlrpc_c::value_struct(structVal);
-}
-
-void METHOD_LOGOUT::execute(xmlrpc_c::paramList const & paramList,
-                            xmlrpc_c::value *   const   retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-paramList.verifyEnd(1);
-
-if (config->LogoutAdmin(cookie))
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    }
-else
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(true);
-    }
-}
diff --git a/stargazer/plugins/configuration/rpcconfig/info_methods.h b/stargazer/plugins/configuration/rpcconfig/info_methods.h
deleted file mode 100644 (file)
index 709a066..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-#pragma once
-
-#include <xmlrpc-c/base.hpp>
-#include <xmlrpc-c/registry.hpp>
-
-#include <string>
-#include <vector>
-
-namespace STG
-{
-
-struct Settings;
-struct Users;
-struct Tariffs;
-
-}
-
-// Forward declaration
-class RPC_CONFIG;
-
-class METHOD_INFO : public xmlrpc_c::method
-{
-public:
-    METHOD_INFO(STG::Tariffs * t,
-                STG::Users * u,
-                size_t df,
-                const std::vector<std::string> & dn)
-        : tariffs(t),
-          users(u),
-          dayFee(df),
-          dirNames(dn)
-    {
-    }
-
-    void execute(xmlrpc_c::paramList const & paramList,
-                 xmlrpc_c::value *   const   retvalP);
-
-private:
-    METHOD_INFO(const METHOD_INFO & rvalue);
-    METHOD_INFO & operator=(const METHOD_INFO & rvalue);
-
-    STG::Tariffs * tariffs;
-    STG::Users * users;
-    size_t dayFee;
-    const std::vector<std::string> & dirNames;
-};
-
-class METHOD_LOGIN : public xmlrpc_c::method
-{
-public:
-    explicit METHOD_LOGIN(RPC_CONFIG * c)
-        : config(c)
-    {
-    }
-
-    void execute(xmlrpc_c::paramList const & paramList,
-                 xmlrpc_c::value *   const   retvalP);
-
-private:
-    METHOD_LOGIN(const METHOD_LOGIN & rvalue);
-    METHOD_LOGIN & operator=(const METHOD_LOGIN & rvalue);
-
-    RPC_CONFIG * config;
-};
-
-class METHOD_LOGOUT : public xmlrpc_c::method
-{
-public:
-    explicit METHOD_LOGOUT(RPC_CONFIG * c)
-        : config(c)
-    {
-    }
-
-    void execute(xmlrpc_c::paramList const & paramList,
-                 xmlrpc_c::value *   const   retvalP);
-
-private:
-    METHOD_LOGOUT(const METHOD_LOGOUT & rvalue);
-    METHOD_LOGOUT & operator=(const METHOD_LOGOUT & rvalue);
-
-    RPC_CONFIG * config;
-};
diff --git a/stargazer/plugins/configuration/rpcconfig/messages_methods.cpp b/stargazer/plugins/configuration/rpcconfig/messages_methods.cpp
deleted file mode 100644 (file)
index 854b276..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-#include "messages_methods.h"
-#include "rpcconfig.h"
-
-#include "stg/users.h"
-#include "stg/user.h"
-#include "stg/message.h"
-#include "stg/common.h"
-
-#include <ostream> // xmlrpc-c devs have missed something :)
-
-extern volatile time_t stgTime;
-
-//------------------------------------------------------------------------------
-
-void METHOD_MESSAGE_SEND::execute(xmlrpc_c::paramList const & paramList,
-                                  xmlrpc_c::value *   const   retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-std::vector<xmlrpc_c::value> logins(paramList.getArray(1));
-std::map<std::string, xmlrpc_c::value> msgInfo(paramList.getStruct(2));
-paramList.verifyEnd(3);
-
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-
-STG::Message message;
-
-std::map<std::string, xmlrpc_c::value>::iterator it;
-
-if ((it = msgInfo.find("version")) == msgInfo.end())
-    {
-    message.header.ver = 1; // Default value
-    }
-else
-    {
-    message.header.ver = xmlrpc_c::value_int(it->second);
-    }
-
-if ((it = msgInfo.find("type")) == msgInfo.end())
-    {
-    message.header.type = 1; // default value
-    }
-else
-    {
-    message.header.type = xmlrpc_c::value_int(it->second);
-    }
-
-if ((it = msgInfo.find("repeat")) == msgInfo.end())
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-message.header.repeat = xmlrpc_c::value_int(it->second);
-
-if ((it = msgInfo.find("repeat_period")) == msgInfo.end())
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-message.header.repeatPeriod = xmlrpc_c::value_int(it->second);
-
-if ((it = msgInfo.find("show_time")) == msgInfo.end())
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-message.header.showTime = xmlrpc_c::value_int(it->second);
-
-if ((it = msgInfo.find("text")) == msgInfo.end())
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-message.text = IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "CP1251");
-
-message.header.creationTime = static_cast<int>(stgTime);
-message.header.lastSendTime = 0;
-
-std::vector<xmlrpc_c::value>::iterator lit;
-for (lit = logins.begin(); lit != logins.end(); ++lit)
-    {
-    using UserPtr = STG::User*;
-    UserPtr ui;
-    if (users->FindByName(xmlrpc_c::value_string(*lit), &ui))
-        {
-        printfd(__FILE__, "METHOD_MESSAGE_SEND::execute(): 'User '%s' not found'\n", std::string(xmlrpc_c::value_string(*lit)).c_str());
-        }
-    else
-        {
-        ui->AddMessage(&message);
-        }
-    }
-
-*retvalPtr = xmlrpc_c::value_boolean(true);
-}
diff --git a/stargazer/plugins/configuration/rpcconfig/messages_methods.h b/stargazer/plugins/configuration/rpcconfig/messages_methods.h
deleted file mode 100644 (file)
index 210ef69..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-#pragma once
-
-#include <xmlrpc-c/base.hpp>
-#include <xmlrpc-c/registry.hpp>
-
-namespace STG
-{
-
-struct Users;
-
-}
-
-class RPC_CONFIG;
-
-class METHOD_MESSAGE_SEND : public xmlrpc_c::method {
-public:
-    METHOD_MESSAGE_SEND(RPC_CONFIG * c,
-                     STG::Users * u)
-        : config(c),
-          users(u)
-    {
-    }
-
-    void execute(xmlrpc_c::paramList const & paramList,
-                 xmlrpc_c::value * const retvalPtr);
-
-private:
-    METHOD_MESSAGE_SEND(const METHOD_MESSAGE_SEND & rvalue);
-    METHOD_MESSAGE_SEND & operator=(const METHOD_MESSAGE_SEND & rvalue);
-
-    RPC_CONFIG * config;
-    STG::Users * users;
-};
diff --git a/stargazer/plugins/configuration/rpcconfig/rpcconfig.cpp b/stargazer/plugins/configuration/rpcconfig/rpcconfig.cpp
deleted file mode 100644 (file)
index 2d45f10..0000000
+++ /dev/null
@@ -1,471 +0,0 @@
-#include "rpcconfig.h"
-
-#include "info_methods.h"
-#include "users_methods.h"
-#include "tariffs_methods.h"
-#include "admins_methods.h"
-#include "messages_methods.h"
-
-#include "stg/admins.h"
-#include "stg/admin.h"
-#include "stg/module_settings.h"
-#include "stg/settings.h"
-#include "stg/common.h"
-#include "stg/const.h"
-
-#include <algorithm>
-#include <vector>
-#include <ostream> // xmlrpc-c devs have missed something :)
-#include <cstdlib>
-#include <csignal>
-#include <cerrno>
-#include <cstring>
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <unistd.h>
-
-RPC_CONFIG_SETTINGS::RPC_CONFIG_SETTINGS()
-    : port(0),
-      cookieTimeout(0)
-{
-}
-
-int RPC_CONFIG_SETTINGS::ParseSettings(const STG::ModuleSettings & s)
-{
-STG::ParamValue pv;
-pv.param = "Port";
-std::vector<STG::ParamValue>::const_iterator pvi;
-pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-if (pvi == s.moduleParams.end() || pvi->value.empty())
-    {
-    errorStr = "Parameter \'Port\' not found.";
-    printfd(__FILE__, "Parameter 'Port' not found\n");
-    return -1;
-    }
-int p;
-if (ParseIntInRange(pvi->value[0], 2, 65535, &p))
-    {
-    errorStr = "Cannot parse parameter \'Port\': " + errorStr;
-    printfd(__FILE__, "Cannot parse parameter 'Port'\n");
-    return -1;
-    }
-port = static_cast<uint16_t>(p);
-
-pv.param = "CookieTimeout";
-pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-if (pvi == s.moduleParams.end() || pvi->value.empty())
-    {
-    cookieTimeout = 1800; // 30 * 60
-    }
-else
-    {
-    if (str2x(pvi->value[0], cookieTimeout))
-        {
-        errorStr = "Incorrect value of CookieTimeout: \'" + pvi->value[0] + "\'";
-        printfd(__FILE__, "Incorrect value of 'CookieTimeout'\n");
-        return -1;
-        }
-    }
-
-return 0;
-}
-
-extern "C" STG::Plugin* GetPlugin()
-{
-    static RPC_CONFIG plugin;
-    return &plugin;
-}
-
-RPC_CONFIG::RPC_CONFIG()
-    : users(NULL),
-      admins(NULL),
-      tariffs(NULL),
-      store(NULL),
-      fd(-1),
-      rpcServer(NULL),
-      running(false),
-      stopped(true),
-      dayFee(0),
-      logger(STG::PluginLogger::get("conf_rpc"))
-{
-}
-
-RPC_CONFIG::~RPC_CONFIG()
-{
-// delete server
-delete rpcServer;
-}
-
-int RPC_CONFIG::ParseSettings()
-{
-int ret = rpcConfigSettings.ParseSettings(settings);
-
-if (ret)
-    errorStr = rpcConfigSettings.GetStrError();
-
-return ret;
-}
-
-void RPC_CONFIG::SetStgSettings(const STG::Settings * s)
-{
-    dayFee = s->GetDayFee();
-    dirNames.erase(dirNames.begin(), dirNames.end());
-    for (size_t i = 0; i < DIR_NUM; ++i) {
-        dirNames.push_back(s->GetDirName(i));
-    }
-}
-
-int RPC_CONFIG::Start()
-{
-InitiateRegistry();
-running = true;
-
-fd = socket(AF_INET, SOCK_STREAM, 0);
-if (fd < 0)
-    {
-    errorStr = "Failed to create socket";
-    logger("Cannot create a socket: %s", strerror(errno));
-    printfd(__FILE__, "Failed to create listening socket: %s\n", strerror(errno));
-    return -1;
-    }
-
-int flag = 1;
-
-if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)))
-    {
-    errorStr = "Setsockopt failed.";
-    logger("setsockopt error: %s", strerror(errno));
-    printfd(__FILE__, "Setsockopt failed: %s\n", strerror(errno));
-    return -1;
-    }
-
-struct sockaddr_in addr;
-addr.sin_family = AF_INET;
-addr.sin_port = htons(rpcConfigSettings.GetPort());
-addr.sin_addr.s_addr = inet_addr("0.0.0.0");
-
-if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)))
-    {
-    logger("Cannot bind the socket: %s", strerror(errno));
-    errorStr = "Failed to bind socket";
-    printfd(__FILE__, "Failed to bind listening socket: %s\n", strerror(errno));
-    return -1;
-    }
-
-if (listen(fd, 10))
-    {
-    logger("Cannot listen the socket: %s", strerror(errno));
-    errorStr = "Failed to listen socket";
-    printfd(__FILE__, "Failed to listen listening socket: %s\n", strerror(errno));
-    return -1;
-    }
-
-rpcServer = new xmlrpc_c::serverAbyss(
-        xmlrpc_c::serverAbyss::constrOpt()
-        .registryP(&rpcRegistry)
-        .logFileName("/var/log/stargazer_rpc.log")
-        .socketFd(fd)
-        );
-
-if (pthread_create(&tid, NULL, Run, this))
-    {
-    errorStr = "Failed to create RPC thread";
-    logger("Cannot create RPC thread.");
-    printfd(__FILE__, "Failed to crate RPC thread\n");
-    return -1;
-    }
-
-return 0;
-}
-
-int RPC_CONFIG::Stop()
-{
-running = false;
-for (int i = 0; i < 5 && !stopped; ++i)
-    {
-    struct timespec ts = {0, 200000000};
-    nanosleep(&ts, NULL);
-    }
-
-if (!stopped)
-    {
-    running = true;
-    logger("Cannot stop RPC thread.");
-    printfd(__FILE__, "Failed to stop RPC thread\n");
-    errorStr = "Failed to stop RPC thread";
-    return -1;
-    }
-else
-    {
-    pthread_join(tid, NULL);
-    }
-
-close(fd);
-
-return 0;
-}
-
-void * RPC_CONFIG::Run(void * rc)
-{
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-RPC_CONFIG * config = static_cast<RPC_CONFIG *>(rc);
-
-config->stopped = false;
-while (config->running)
-    {
-    if (WaitPackets(config->fd))
-        config->rpcServer->runOnce();
-    }
-config->stopped = true;
-
-return NULL;
-}
-
-bool RPC_CONFIG::GetAdminInfo(const std::string & cookie,
-                              ADMIN_INFO * info)
-{
-std::map<std::string,
-         ADMIN_INFO>::iterator it;
-
-it = cookies.find(cookie);
-
-if (it == cookies.end())
-    {
-    return true;
-    }
-
-if (difftime(it->second.accessTime, time(NULL)) >
-    rpcConfigSettings.GetCookieTimeout())
-    {
-    cookies.erase(it);
-    return true;
-    }
-
-// Update access time
-time(&it->second.accessTime);
-*info = it->second;
-return false;
-}
-
-bool RPC_CONFIG::CheckAdmin(const std::string & login,
-                            const std::string & password,
-                            std::string * cookie)
-{
-STG::Admin * admin = NULL;
-
-if (!admins->correct(login, password, &admin))
-    {
-    logger("Attempt to connect with invalid credentials. Login: %s", login.c_str());
-    return true;
-    }
-
-ADMIN_INFO info;
-time(&info.accessTime);
-info.admin = login;
-info.priviledges = admin->priv();
-*cookie = GetCookie();
-cookies[*cookie] = info;
-
-return false;
-}
-
-bool RPC_CONFIG::LogoutAdmin(const std::string & cookie)
-{
-std::map<std::string,
-         ADMIN_INFO>::iterator it;
-
-it = cookies.find(cookie);
-
-if (it == cookies.end())
-    {
-    return true;
-    }
-
-cookies.erase(it);
-
-return false;
-}
-
-std::string RPC_CONFIG::GetCookie() const
-{
-std::string charset("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890");
-std::string cookie;
-
-for (int i = 0; i < 64; ++i)
-    {
-    cookie += charset[rand() % charset.length()];
-    };
-
-return cookie;
-}
-
-void RPC_CONFIG::InitiateRegistry()
-{
-// manage registry
-xmlrpc_c::methodPtr const methodInfoPtr(new METHOD_INFO(
-            tariffs,
-            users,
-            dayFee,
-            dirNames
-            ));
-rpcRegistry.addMethod("stargazer.info", methodInfoPtr);
-
-xmlrpc_c::methodPtr const methodLoginPtr(new METHOD_LOGIN(
-            this
-            ));
-rpcRegistry.addMethod("stargazer.login", methodLoginPtr);
-
-xmlrpc_c::methodPtr const methodLogoutPtr(new METHOD_LOGOUT(
-            this
-            ));
-rpcRegistry.addMethod("stargazer.logout", methodLogoutPtr);
-
-xmlrpc_c::methodPtr const methodGetUserPtr(new METHOD_USER_GET(
-            this,
-            users
-            ));
-rpcRegistry.addMethod("stargazer.get_user", methodGetUserPtr);
-
-xmlrpc_c::methodPtr const methodAddUserPtr(new METHOD_USER_ADD(
-            this,
-            admins,
-            users
-            ));
-rpcRegistry.addMethod("stargazer.add_user", methodAddUserPtr);
-
-xmlrpc_c::methodPtr const methodDelUserPtr(new METHOD_USER_DEL(
-            this,
-            admins,
-            users
-            ));
-rpcRegistry.addMethod("stargazer.del_user", methodDelUserPtr);
-
-xmlrpc_c::methodPtr const methodGetUsersPtr(new METHOD_USERS_GET(
-            this,
-            users
-            ));
-rpcRegistry.addMethod("stargazer.get_users", methodGetUsersPtr);
-
-xmlrpc_c::methodPtr const methodChgUserPtr(new METHOD_USER_CHG(
-            this,
-            admins,
-            tariffs,
-            store,
-            users
-            ));
-rpcRegistry.addMethod("stargazer.chg_user", methodChgUserPtr);
-
-xmlrpc_c::methodPtr const methodAddCashPtr(new METHOD_USER_CASH_ADD(
-            this,
-            admins,
-            store,
-            users
-            ));
-rpcRegistry.addMethod("stargazer.add_user_cash", methodAddCashPtr);
-
-xmlrpc_c::methodPtr const methodSetCashPtr(new METHOD_USER_CASH_SET(
-            this,
-            admins,
-            store,
-            users
-            ));
-rpcRegistry.addMethod("stargazer.set_user_cash", methodSetCashPtr);
-
-xmlrpc_c::methodPtr const methodTariffChangePtr(new METHOD_USER_TARIFF_CHANGE(
-            this,
-            admins,
-            tariffs,
-            store,
-            users
-            ));
-rpcRegistry.addMethod("stargazer.chg_user_tariff", methodTariffChangePtr);
-
-xmlrpc_c::methodPtr const methodGetTariffPtr(new METHOD_TARIFF_GET(
-            this,
-            tariffs
-            ));
-rpcRegistry.addMethod("stargazer.get_tariff", methodGetTariffPtr);
-
-xmlrpc_c::methodPtr const methodChgTariffPtr(new METHOD_TARIFF_CHG(
-            this,
-            admins,
-            tariffs
-            ));
-rpcRegistry.addMethod("stargazer.chg_tariff", methodChgTariffPtr);
-
-xmlrpc_c::methodPtr const methodGetTariffsPtr(new METHOD_TARIFFS_GET(
-            this,
-            tariffs
-            ));
-rpcRegistry.addMethod("stargazer.get_tariffs", methodGetTariffsPtr);
-
-xmlrpc_c::methodPtr const methodAddTariffPtr(new METHOD_TARIFF_ADD(
-            this,
-            admins,
-            tariffs
-            ));
-rpcRegistry.addMethod("stargazer.add_tariff", methodAddTariffPtr);
-
-xmlrpc_c::methodPtr const methodDelTariffPtr(new METHOD_TARIFF_DEL(
-            this,
-            admins,
-            tariffs,
-            users
-            ));
-rpcRegistry.addMethod("stargazer.del_tariff", methodDelTariffPtr);
-
-xmlrpc_c::methodPtr const methodGetAdminPtr(new METHOD_ADMIN_GET(
-            this,
-            admins
-            ));
-rpcRegistry.addMethod("stargazer.get_admin", methodGetAdminPtr);
-
-xmlrpc_c::methodPtr const methodAddAdminPtr(new METHOD_ADMIN_ADD(
-            this,
-            admins
-            ));
-rpcRegistry.addMethod("stargazer.add_admin", methodAddAdminPtr);
-
-xmlrpc_c::methodPtr const methodDelAdminPtr(new METHOD_ADMIN_DEL(
-            this,
-            admins
-            ));
-rpcRegistry.addMethod("stargazer.del_admin", methodDelAdminPtr);
-
-xmlrpc_c::methodPtr const methodChgAdminPtr(new METHOD_ADMIN_CHG(
-            this,
-            admins
-            ));
-rpcRegistry.addMethod("stargazer.chg_admin", methodChgAdminPtr);
-
-xmlrpc_c::methodPtr const methodGetAdminsPtr(new METHOD_ADMINS_GET(
-            this,
-            admins
-            ));
-rpcRegistry.addMethod("stargazer.get_admins", methodGetAdminsPtr);
-
-xmlrpc_c::methodPtr const methodSendMessagePtr(new METHOD_MESSAGE_SEND(
-            this,
-            users
-            ));
-rpcRegistry.addMethod("stargazer.send_user_message", methodSendMessagePtr);
-
-xmlrpc_c::methodPtr const methodGetOnlinIPsPtr(new METHOD_GET_ONLINE_IPS(
-            this,
-            users
-            ));
-rpcRegistry.addMethod("stargazer.get_online_ips", methodGetOnlinIPsPtr);
-
-xmlrpc_c::methodPtr const methodGetUserAuthByPtr(new METHOD_GET_USER_AUTH_BY(
-            this,
-            users
-            ));
-rpcRegistry.addMethod("stargazer.get_user_auth_by", methodGetUserAuthByPtr);
-}
-
diff --git a/stargazer/plugins/configuration/rpcconfig/rpcconfig.h b/stargazer/plugins/configuration/rpcconfig/rpcconfig.h
deleted file mode 100644 (file)
index e7c800d..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-#pragma once
-
-#include "stg/plugin.h"
-#include "stg/admin_conf.h"
-#include "stg/module_settings.h"
-#include "stg/logger.h"
-
-#include <xmlrpc-c/base.hpp>
-#include <xmlrpc-c/registry.hpp>
-#include <xmlrpc-c/server_abyss.hpp>
-
-#include <ctime>
-#include <cstdint>
-#include <string>
-#include <map>
-#include <vector>
-
-#include <pthread.h>
-
-#define RPC_CONFIG_VERSION "Stargazer RPC v. 0.2"
-
-namespace STG
-{
-
-struct Admins;
-struct Tariffs;
-struct Users;
-struct Store;
-
-}
-
-class RPC_CONFIG_SETTINGS
-{
-public:
-                         RPC_CONFIG_SETTINGS();
-    virtual              ~RPC_CONFIG_SETTINGS() {}
-    const std::string &  GetStrError() const { return errorStr; }
-    int                  ParseSettings(const STG::ModuleSettings & s);
-    uint16_t             GetPort() const { return port; }
-    double               GetCookieTimeout() const { return cookieTimeout; }
-
-private:
-    std::string  errorStr;
-    uint16_t     port;
-    double       cookieTimeout;
-};
-
-struct ADMIN_INFO
-{
-    ADMIN_INFO()
-        : admin(),
-          accessTime(0),
-          priviledges()
-    {}
-
-    std::string admin;
-    time_t      accessTime;
-    STG::Priv        priviledges;
-};
-
-class RPC_CONFIG : public STG::Plugin
-{
-public:
-    RPC_CONFIG();
-    ~RPC_CONFIG() override;
-
-    void                SetUsers(STG::Users * u) override { users = u; }
-    void                SetTariffs(STG::Tariffs * t) override { tariffs = t; }
-    void                SetAdmins(STG::Admins * a) override { admins = a; }
-    void                SetStore(STG::Store * s) override { store = s; }
-    void                SetStgSettings(const STG::Settings * s) override;
-    void                SetSettings(const STG::ModuleSettings & s) override { settings = s; }
-    int                 ParseSettings() override;
-
-    int                 Start() override;
-    int                 Stop() override;
-    int                 Reload(const STG::ModuleSettings & /*ms*/) override { return 0; }
-    bool                IsRunning() override { return running && !stopped; }
-
-    const std::string & GetStrError() const override { return errorStr; }
-    std::string         GetVersion() const override { return RPC_CONFIG_VERSION; }
-    uint16_t            GetStartPosition() const override { return 20; }
-    uint16_t            GetStopPosition() const override { return 20; }
-
-    bool                GetAdminInfo(const std::string & cookie,
-                                     ADMIN_INFO * info);
-    bool                CheckAdmin(const std::string & login,
-                                   const std::string & password,
-                                   std::string * cookie);
-    bool                LogoutAdmin(const std::string & cookie);
-
-private:
-    RPC_CONFIG(const RPC_CONFIG & rvalue);
-    RPC_CONFIG & operator=(const RPC_CONFIG & rvalue);
-
-    static void *           Run(void *);
-    std::string             GetCookie() const;
-    void                    InitiateRegistry();
-
-    mutable std::string     errorStr;
-    RPC_CONFIG_SETTINGS     rpcConfigSettings;
-    STG::Users *                 users;
-    STG::Admins *                admins;
-    STG::Tariffs *               tariffs;
-    STG::Store *                 store;
-    STG::ModuleSettings         settings;
-    int                     fd;
-    xmlrpc_c::registry      rpcRegistry;
-    xmlrpc_c::serverAbyss * rpcServer;
-    bool                    running;
-    bool                    stopped;
-    pthread_t               tid;
-    std::map<std::string,
-             ADMIN_INFO>    cookies;
-    size_t                  dayFee;
-    std::vector<std::string> dirNames;
-    STG::PluginLogger           logger;
-};
diff --git a/stargazer/plugins/configuration/rpcconfig/tariff_helper.cpp b/stargazer/plugins/configuration/rpcconfig/tariff_helper.cpp
deleted file mode 100644 (file)
index a6ec1fe..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-#include "tariff_helper.h"
-
-#include "stg/tariff_conf.h"
-#include "stg/common.h"
-#include "stg/const.h"
-
-#include <ostream> // xmlrpc-c devs have missed something :)
-
-void TARIFF_HELPER::GetTariffInfo(xmlrpc_c::value * info) const
-{
-std::map<std::string, xmlrpc_c::value> structVal;
-
-structVal["result"] = xmlrpc_c::value_boolean(true);
-structVal["name"] = xmlrpc_c::value_string(data.tariffConf.name);
-structVal["fee"] = xmlrpc_c::value_double(data.tariffConf.fee);
-structVal["freemb"] = xmlrpc_c::value_double(data.tariffConf.free);
-structVal["passivecost"] = xmlrpc_c::value_double(data.tariffConf.passiveCost);
-structVal["traffType"] = xmlrpc_c::value_int(data.tariffConf.traffType);
-structVal["period"] = xmlrpc_c::value_string(STG::Tariff::toString(data.tariffConf.period));
-structVal["changePolicy"] = xmlrpc_c::value_string(STG::Tariff::toString(data.tariffConf.changePolicy));
-structVal["changePolicyTimeout"] = xmlrpc_c::value_string(formatTime(data.tariffConf.changePolicyTimeout));
-
-std::vector<xmlrpc_c::value> prices(DIR_NUM);
-
-for (unsigned i = 0; i < DIR_NUM; ++i)
-    {
-    std::map<std::string, xmlrpc_c::value> dirPrice;
-    dirPrice["hday"] = xmlrpc_c::value_int(data.dirPrice[i].hDay);
-    dirPrice["mday"] = xmlrpc_c::value_int(data.dirPrice[i].mDay);
-    dirPrice["hnight"] = xmlrpc_c::value_int(data.dirPrice[i].hNight);
-    dirPrice["mnight"] = xmlrpc_c::value_int(data.dirPrice[i].mNight);
-    dirPrice["pricedaya"] = xmlrpc_c::value_double(data.dirPrice[i].priceDayA * 1024 * 1024);
-    dirPrice["pricedayb"] = xmlrpc_c::value_double(data.dirPrice[i].priceDayB * 1024 * 1024);
-    dirPrice["pricenighta"] = xmlrpc_c::value_double(data.dirPrice[i].priceNightA * 1024 * 1024);
-    dirPrice["pricenightb"] = xmlrpc_c::value_double(data.dirPrice[i].priceNightB * 1024 * 1024);
-    dirPrice["threshold"] = xmlrpc_c::value_int(data.dirPrice[i].threshold);
-    dirPrice["singleprice"] = xmlrpc_c::value_boolean(data.dirPrice[i].singlePrice);
-    dirPrice["nodiscount"] = xmlrpc_c::value_boolean(data.dirPrice[i].noDiscount);
-    prices[i] = xmlrpc_c::value_struct(dirPrice);
-    }
-
-structVal["dirprices"] = xmlrpc_c::value_array(prices);
-
-*info = xmlrpc_c::value_struct(structVal);
-}
-
-bool TARIFF_HELPER::SetTariffInfo(const xmlrpc_c::value & info)
-{
-std::map<std::string, xmlrpc_c::value> structVal(
-    static_cast<std::map<std::string, xmlrpc_c::value> >(xmlrpc_c::value_struct(info))
-    );
-
-std::map<std::string, xmlrpc_c::value>::iterator it;
-
-if ((it = structVal.find("fee")) != structVal.end())
-    {
-    data.tariffConf.fee = xmlrpc_c::value_double(it->second);
-    }
-
-if ((it = structVal.find("freemb")) != structVal.end())
-    {
-    data.tariffConf.free = xmlrpc_c::value_double(it->second);
-    }
-
-if ((it = structVal.find("passivecost")) != structVal.end())
-    {
-    data.tariffConf.passiveCost = xmlrpc_c::value_double(it->second);
-    }
-
-if ((it = structVal.find("traffType")) != structVal.end())
-    {
-    data.tariffConf.traffType = static_cast<STG::Tariff::TraffType>(xmlrpc_c::value_int(it->second).cvalue());
-    }
-
-if ((it = structVal.find("period")) != structVal.end())
-    {
-    data.tariffConf.period = STG::Tariff::parsePeriod(xmlrpc_c::value_string(it->second));
-    }
-
-if ((it = structVal.find("changePolicy")) != structVal.end())
-    {
-    data.tariffConf.changePolicy = STG::Tariff::parseChangePolicy(xmlrpc_c::value_string(it->second));
-    }
-
-if ((it = structVal.find("changePolicyTimeout")) != structVal.end())
-    {
-    data.tariffConf.changePolicyTimeout = readTime(xmlrpc_c::value_string(it->second));
-    }
-
-if ((it = structVal.find("dirprices")) != structVal.end())
-    {
-    std::vector<xmlrpc_c::value> prices(
-            xmlrpc_c::value_array(it->second).vectorValueValue()
-            );
-
-    for (unsigned i = 0; i < DIR_NUM; ++i)
-        {
-        std::map<std::string, xmlrpc_c::value> dirPrice(
-            static_cast<std::map<std::string, xmlrpc_c::value> >(xmlrpc_c::value_struct(prices[i]))
-            );
-        data.dirPrice[i].mDay = xmlrpc_c::value_int(dirPrice["mday"]);
-        data.dirPrice[i].hDay = xmlrpc_c::value_int(dirPrice["hday"]);
-        data.dirPrice[i].mNight = xmlrpc_c::value_int(dirPrice["mnight"]);
-        data.dirPrice[i].hNight = xmlrpc_c::value_int(dirPrice["hnight"]);
-        data.dirPrice[i].priceDayA = xmlrpc_c::value_double(dirPrice["pricedaya"]) / 1024 / 1024;
-        data.dirPrice[i].priceDayB = xmlrpc_c::value_double(dirPrice["pricedayb"]) / 1024 / 1024;
-        data.dirPrice[i].priceNightA = xmlrpc_c::value_double(dirPrice["pricenighta"]) / 1024 / 1024;
-        data.dirPrice[i].priceNightB = xmlrpc_c::value_double(dirPrice["pricenightb"]) / 1024 / 1024;
-        data.dirPrice[i].threshold = xmlrpc_c::value_int(dirPrice["threshold"]);
-        data.dirPrice[i].singlePrice = xmlrpc_c::value_boolean(dirPrice["singleprice"]);
-        data.dirPrice[i].noDiscount = xmlrpc_c::value_boolean(dirPrice["nodiscount"]);
-        }
-    }
-
-return false;
-}
diff --git a/stargazer/plugins/configuration/rpcconfig/tariff_helper.h b/stargazer/plugins/configuration/rpcconfig/tariff_helper.h
deleted file mode 100644 (file)
index 9f68a74..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#pragma once
-
-#include <xmlrpc-c/base.hpp>
-
-namespace STG
-{
-
-struct TariffData;
-
-}
-
-class TARIFF_HELPER
-{
-public:
-    explicit TARIFF_HELPER(STG::TariffData & td)
-        : data(td)
-    {}
-
-    void GetTariffInfo(xmlrpc_c::value * info) const;
-    bool SetTariffInfo(const xmlrpc_c::value & info);
-private:
-    STG::TariffData & data;
-};
diff --git a/stargazer/plugins/configuration/rpcconfig/tariffs_methods.cpp b/stargazer/plugins/configuration/rpcconfig/tariffs_methods.cpp
deleted file mode 100644 (file)
index 2047202..0000000
+++ /dev/null
@@ -1,196 +0,0 @@
-#include <ostream> // xmlrpc-c devs have missed something :)
-
-#include "tariffs_methods.h"
-#include "rpcconfig.h"
-#include "tariff_helper.h"
-
-#include "stg/tariffs.h"
-#include "stg/tariff.h"
-#include "stg/tariff_conf.h"
-#include "stg/users.h"
-#include "stg/admins.h"
-#include "stg/admin.h"
-
-void METHOD_TARIFF_GET::execute(xmlrpc_c::paramList const & paramList,
-                                xmlrpc_c::value *   const   retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-std::string name = paramList.getString(1);
-paramList.verifyEnd(2);
-
-std::map<std::string, xmlrpc_c::value> structVal;
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
-    {
-    structVal["result"] = xmlrpc_c::value_boolean(false);
-    *retvalPtr = xmlrpc_c::value_struct(structVal);
-    return;
-    }
-
-const auto tariff = tariffs->FindByName(name);
-
-if (!tariff)
-    {
-    structVal["result"] = xmlrpc_c::value_boolean(false);
-    *retvalPtr = xmlrpc_c::value_struct(structVal);
-    return;
-    }
-
-auto td = tariff->GetTariffData();
-
-TARIFF_HELPER helper(td);
-
-helper.GetTariffInfo(retvalPtr);
-}
-
-void METHOD_TARIFF_CHG::execute(xmlrpc_c::paramList const & paramList,
-                                xmlrpc_c::value *   const   retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-std::string name = paramList.getString(1);
-xmlrpc_c::value_struct info(paramList.getStruct(2));
-paramList.verifyEnd(3);
-
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-
-STG::Admin * admin;
-
-if (admins->find(adminInfo.admin, &admin))
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-
-const auto tariff = tariffs->FindByName(name);
-
-if (!tariff)
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-
-auto td = tariff->GetTariffData();
-
-TARIFF_HELPER helper(td);
-
-helper.SetTariffInfo(info);
-
-if (tariffs->Chg(td, admin))
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-
-*retvalPtr = xmlrpc_c::value_boolean(true);
-}
-
-void METHOD_TARIFFS_GET::execute(xmlrpc_c::paramList const & paramList,
-                                 xmlrpc_c::value *   const   retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-paramList.verifyEnd(1);
-
-std::map<std::string, xmlrpc_c::value> structVal;
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
-    {
-    structVal["result"] = xmlrpc_c::value_boolean(false);
-    *retvalPtr = xmlrpc_c::value_struct(structVal);
-    return;
-    }
-
-std::vector<xmlrpc_c::value> tariffsInfo;
-
-
-std::vector<STG::TariffData> dataList;
-tariffs->GetTariffsData(&dataList);
-auto it = dataList.begin();
-for (; it != dataList.end(); ++it)
-    {
-    xmlrpc_c::value info;
-    auto td = *it; // 'cause TARIFF_HELPER work in both ways and take not const referense
-    TARIFF_HELPER helper(td);
-    helper.GetTariffInfo(&info);
-    tariffsInfo.push_back(info);
-    }
-
-*retvalPtr = xmlrpc_c::value_array(tariffsInfo);
-}
-
-void METHOD_TARIFF_ADD::execute(xmlrpc_c::paramList const & paramList,
-                                xmlrpc_c::value *   const   retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-std::string tariff = paramList.getString(1);
-paramList.verifyEnd(2);
-
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-
-STG::Admin * admin;
-
-if (admins->find(adminInfo.admin, &admin))
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-
-if (tariffs->Add(tariff, admin))
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-
-*retvalPtr = xmlrpc_c::value_boolean(true);
-}
-
-void METHOD_TARIFF_DEL::execute(xmlrpc_c::paramList const & paramList,
-                                xmlrpc_c::value *   const   retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-std::string tariff = paramList.getString(1);
-paramList.verifyEnd(2);
-
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-
-STG::Admin * admin;
-
-if (admins->find(adminInfo.admin, &admin))
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-
-if (users->TariffInUse(tariff))
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-
-if (tariffs->Del(tariff, admin))
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-
-*retvalPtr = xmlrpc_c::value_boolean(true);
-}
diff --git a/stargazer/plugins/configuration/rpcconfig/tariffs_methods.h b/stargazer/plugins/configuration/rpcconfig/tariffs_methods.h
deleted file mode 100644 (file)
index 4f4d668..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-#pragma once
-
-#include <xmlrpc-c/base.hpp>
-#include <xmlrpc-c/registry.hpp>
-
-namespace STG
-{
-
-struct Tariffs;
-struct Users;
-struct Admins;
-
-}
-
-class RPC_CONFIG;
-
-class METHOD_TARIFF_GET : public xmlrpc_c::method {
-public:
-    METHOD_TARIFF_GET(RPC_CONFIG * c,
-                      STG::Tariffs * t)
-        : config(c),
-          tariffs(t)
-    {
-    }
-
-    void execute(xmlrpc_c::paramList const & paramList,
-                 xmlrpc_c::value *   const   retvalPtr);
-
-private:
-    METHOD_TARIFF_GET(const METHOD_TARIFF_GET & rvalue);
-    METHOD_TARIFF_GET & operator=(const METHOD_TARIFF_GET & rvalue);
-
-    RPC_CONFIG * config;
-    STG::Tariffs * tariffs;
-};
-
-class METHOD_TARIFF_CHG : public xmlrpc_c::method {
-public:
-    METHOD_TARIFF_CHG(RPC_CONFIG * c,
-                      STG::Admins * a,
-                      STG::Tariffs * t)
-        : config(c),
-          admins(a),
-          tariffs(t)
-    {
-    }
-
-    void execute(xmlrpc_c::paramList const & paramList,
-                 xmlrpc_c::value *   const   retvalPtr);
-
-private:
-    METHOD_TARIFF_CHG(const METHOD_TARIFF_CHG & rvalue);
-    METHOD_TARIFF_CHG & operator=(const METHOD_TARIFF_CHG & rvalue);
-
-    RPC_CONFIG * config;
-    STG::Admins * admins;
-    STG::Tariffs * tariffs;
-};
-
-class METHOD_TARIFFS_GET : public xmlrpc_c::method {
-public:
-    METHOD_TARIFFS_GET(RPC_CONFIG * c,
-                      STG::Tariffs * t)
-        : config(c),
-          tariffs(t)
-    {
-    }
-
-    void execute(xmlrpc_c::paramList const & paramList,
-                 xmlrpc_c::value *   const   retvalPtr);
-
-private:
-    METHOD_TARIFFS_GET(const METHOD_TARIFFS_GET & rvalue);
-    METHOD_TARIFFS_GET & operator=(const METHOD_TARIFFS_GET & rvalue);
-
-    RPC_CONFIG * config;
-    STG::Tariffs * tariffs;
-};
-
-class METHOD_TARIFF_ADD : public xmlrpc_c::method {
-public:
-    METHOD_TARIFF_ADD(RPC_CONFIG * c,
-                      STG::Admins * a,
-                      STG::Tariffs * t)
-        : config(c),
-          admins(a),
-          tariffs(t)
-    {
-    }
-
-    void execute(xmlrpc_c::paramList const & paramList,
-                 xmlrpc_c::value *   const   retvalP);
-
-private:
-    METHOD_TARIFF_ADD(const METHOD_TARIFF_ADD & rvalue);
-    METHOD_TARIFF_ADD & operator=(const METHOD_TARIFF_ADD & rvalue);
-
-    RPC_CONFIG * config;
-    STG::Admins * admins;
-    STG::Tariffs * tariffs;
-};
-
-class METHOD_TARIFF_DEL : public xmlrpc_c::method {
-public:
-    METHOD_TARIFF_DEL(RPC_CONFIG * c,
-                      STG::Admins * a,
-                      STG::Tariffs * t,
-                      STG::Users * u)
-        : config(c),
-          admins(a),
-          tariffs(t),
-          users(u)
-    {
-    }
-
-    void execute(xmlrpc_c::paramList const & paramList,
-                 xmlrpc_c::value *   const   retvalP);
-
-private:
-    METHOD_TARIFF_DEL(const METHOD_TARIFF_DEL & rvalue);
-    METHOD_TARIFF_DEL & operator=(const METHOD_TARIFF_DEL & rvalue);
-
-    RPC_CONFIG * config;
-    STG::Admins * admins;
-    STG::Tariffs * tariffs;
-    STG::Users * users;
-};
diff --git a/stargazer/plugins/configuration/rpcconfig/user_helper.cpp b/stargazer/plugins/configuration/rpcconfig/user_helper.cpp
deleted file mode 100644 (file)
index 7a7a9b9..0000000
+++ /dev/null
@@ -1,401 +0,0 @@
-#include "user_helper.h"
-
-#include "stg/tariffs.h"
-#include "stg/tariff.h"
-#include "stg/admin.h"
-#include "stg/store.h"
-#include "stg/users.h"
-#include "stg/user.h"
-#include "stg/user_ips.h"
-#include "stg/user_property.h"
-#include "stg/common.h"
-#include "stg/const.h"
-
-#include <cmath>
-
-//------------------------------------------------------------------------------
-
-void USER_HELPER::GetUserInfo(xmlrpc_c::value * info,
-                              bool hidePassword)
-{
-std::map<std::string, xmlrpc_c::value> structVal;
-
-structVal["result"] = xmlrpc_c::value_boolean(true);
-structVal["login"] = xmlrpc_c::value_string(ptr->GetLogin());
-
-if (!hidePassword)
-    {
-    structVal["password"] = xmlrpc_c::value_string(ptr->GetProperties().password.Get());
-    }
-else
-    {
-    structVal["password"] = xmlrpc_c::value_string("++++++++");
-    }
-
-structVal["cash"] = xmlrpc_c::value_double(ptr->GetProperties().cash.Get());
-structVal["freemb"] = xmlrpc_c::value_double(ptr->GetProperties().freeMb.Get());
-structVal["credit"] = xmlrpc_c::value_double(ptr->GetProperties().credit.Get());
-
-if (ptr->GetProperties().nextTariff.Get() != "")
-    {
-    structVal["tariff"] = xmlrpc_c::value_string(
-            ptr->GetProperties().tariffName.Get() +
-            "/" +
-            ptr->GetProperties().nextTariff.Get()
-            );
-    }
-else
-    {
-    structVal["tariff"] = xmlrpc_c::value_string(ptr->GetProperties().tariffName.Get());
-    }
-
-structVal["note"] = xmlrpc_c::value_string(IconvString(ptr->GetProperties().note, "KOI8-RU", "UTF-8"));
-
-structVal["phone"] = xmlrpc_c::value_string(IconvString(ptr->GetProperties().phone, "KOI8-RU", "UTF-8"));
-
-structVal["address"] = xmlrpc_c::value_string(IconvString(ptr->GetProperties().address, "KOI8-RU", "UTF-8"));
-
-structVal["email"] = xmlrpc_c::value_string(IconvString(ptr->GetProperties().email, "KOI8-RU", "UTF-8"));
-
-std::vector<xmlrpc_c::value> userdata;
-
-userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperties().userdata0.Get(), "KOI8-RU", "UTF-8")));
-userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperties().userdata1.Get(), "KOI8-RU", "UTF-8")));
-userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperties().userdata2.Get(), "KOI8-RU", "UTF-8")));
-userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperties().userdata3.Get(), "KOI8-RU", "UTF-8")));
-userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperties().userdata4.Get(), "KOI8-RU", "UTF-8")));
-userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperties().userdata5.Get(), "KOI8-RU", "UTF-8")));
-userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperties().userdata6.Get(), "KOI8-RU", "UTF-8")));
-userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperties().userdata7.Get(), "KOI8-RU", "UTF-8")));
-userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperties().userdata8.Get(), "KOI8-RU", "UTF-8")));
-userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperties().userdata9.Get(), "KOI8-RU", "UTF-8")));
-
-structVal["userdata"] = xmlrpc_c::value_array(userdata);
-
-structVal["name"] = xmlrpc_c::value_string(IconvString(ptr->GetProperties().realName, "KOI8-RU", "UTF-8"));
-
-structVal["group"] = xmlrpc_c::value_string(IconvString(ptr->GetProperties().group, "KOI8-RU", "UTF-8"));
-
-structVal["status"] = xmlrpc_c::value_boolean(ptr->GetConnected());
-structVal["aonline"] = xmlrpc_c::value_boolean(ptr->GetProperties().alwaysOnline.Get());
-structVal["currip"] = xmlrpc_c::value_string(inet_ntostring(ptr->GetCurrIP()));
-structVal["pingtime"] = xmlrpc_c::value_int(static_cast<int>(ptr->GetPingTime()));
-structVal["ips"] = xmlrpc_c::value_string(ptr->GetProperties().ips.Get().toString());
-
-std::map<std::string, xmlrpc_c::value> traffInfo;
-std::vector<xmlrpc_c::value> mu(DIR_NUM);
-std::vector<xmlrpc_c::value> md(DIR_NUM);
-std::vector<xmlrpc_c::value> su(DIR_NUM);
-std::vector<xmlrpc_c::value> sd(DIR_NUM);
-
-auto upload = ptr->GetProperties().up.Get();
-auto download = ptr->GetProperties().down.Get();
-auto supload = ptr->GetSessionUpload();
-auto sdownload = ptr->GetSessionDownload();
-
-for (int j = 0; j < DIR_NUM; j++)
-    {
-    mu[j] = xmlrpc_c::value_string(std::to_string(upload[j]));
-    md[j] = xmlrpc_c::value_string(std::to_string(download[j]));
-    su[j] = xmlrpc_c::value_string(std::to_string(supload[j]));
-    sd[j] = xmlrpc_c::value_string(std::to_string(sdownload[j]));
-    }
-
-traffInfo["mu"] = xmlrpc_c::value_array(mu);
-traffInfo["md"] = xmlrpc_c::value_array(md);
-traffInfo["su"] = xmlrpc_c::value_array(su);
-traffInfo["sd"] = xmlrpc_c::value_array(sd);
-
-structVal["traff"] = xmlrpc_c::value_struct(traffInfo);
-
-structVal["down"] = xmlrpc_c::value_boolean(ptr->GetProperties().disabled.Get());
-structVal["disableddetailstat"] = xmlrpc_c::value_boolean(ptr->GetProperties().disabledDetailStat.Get());
-structVal["passive"] = xmlrpc_c::value_boolean(ptr->GetProperties().passive.Get());
-structVal["lastcash"] = xmlrpc_c::value_double(ptr->GetProperties().lastCashAdd.Get());
-structVal["lasttimecash"] = xmlrpc_c::value_int(static_cast<int>(ptr->GetProperties().lastCashAddTime.Get()));
-structVal["lastactivitytime"] = xmlrpc_c::value_int(static_cast<int>(ptr->GetProperties().lastActivityTime.Get()));
-structVal["creditexpire"] = xmlrpc_c::value_int(static_cast<int>(ptr->GetProperties().creditExpire.Get()));
-
-*info = xmlrpc_c::value_struct(structVal);
-}
-
-//------------------------------------------------------------------------------
-
-bool USER_HELPER::SetUserInfo(const xmlrpc_c::value & info,
-                              const STG::Admin& admin,
-                              const std::string & login,
-                              const STG::Store & store,
-                              STG::Tariffs * tariffs)
-{
-std::map<std::string, xmlrpc_c::value> structVal(
-    static_cast<std::map<std::string, xmlrpc_c::value> >(xmlrpc_c::value_struct(info))
-    );
-
-std::map<std::string, xmlrpc_c::value>::iterator it;
-
-bool check = false;
-bool alwaysOnline = ptr->GetProperties().alwaysOnline;
-if ((it = structVal.find("aonline")) != structVal.end())
-    {
-    check = true;
-    alwaysOnline = xmlrpc_c::value_boolean(it->second);
-    }
-bool onlyOneIP = ptr->GetProperties().ips.ConstData().onlyOneIP();
-if ((it = structVal.find("ips")) != structVal.end())
-    {
-    check = true;
-    onlyOneIP = STG::UserIPs::parse(xmlrpc_c::value_string(it->second)).onlyOneIP();
-    }
-
-if (check && alwaysOnline && !onlyOneIP)
-    {
-    printfd(__FILE__, "Requested change leads to a forbidden state: AlwaysOnline with multiple IP's\n");
-    return true;
-    }
-
-if ((it = structVal.find("ips")) != structVal.end())
-    {
-    auto ips = STG::UserIPs::parse(xmlrpc_c::value_string(it->second));
-
-    for (size_t i = 0; i < ips.count(); ++i)
-        {
-        using ConstUserPtr = const STG::User*;
-        ConstUserPtr user;
-        uint32_t ip = ips[i].ip;
-        if (users.IsIPInUse(ip, login, &user))
-            {
-            printfd(__FILE__, "Trying to assign an IP %s to '%s' that is already in use by '%s'\n", inet_ntostring(ip).c_str(), login.c_str(), user->GetLogin().c_str());
-            return true;
-            }
-        }
-
-    if (!ptr->GetProperties().ips.Set(ips, admin, login, store))
-        return true;
-    }
-
-if ((it = structVal.find("aonline")) != structVal.end())
-    {
-    bool value(xmlrpc_c::value_boolean(it->second));
-    if (ptr->GetProperties().alwaysOnline.Get() != value)
-        if (!ptr->GetProperties().alwaysOnline.Set(value, admin, login, store))
-            return true;
-    }
-
-if ((it = structVal.find("password")) != structVal.end())
-    {
-    std::string value(xmlrpc_c::value_string(it->second));
-    if (ptr->GetProperties().password.Get() != value)
-        if (!ptr->GetProperties().password.Set(value, admin, login, store))
-            return true;
-    }
-
-if ((it = structVal.find("address")) != structVal.end())
-    {
-    std::string value(IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "KOI8-RU"));
-    if (ptr->GetProperties().address.Get() != value)
-        if (!ptr->GetProperties().address.Set(value, admin, login, store))
-            return true;
-    }
-
-if ((it = structVal.find("phone")) != structVal.end())
-    {
-    std::string value(IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "KOI8-RU"));
-    if (ptr->GetProperties().phone.Get() != value)
-        if (!ptr->GetProperties().phone.Set(value, admin, login, store))
-            return true;
-    }
-
-if ((it = structVal.find("email")) != structVal.end())
-    {
-    std::string value(IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "KOI8-RU"));
-    if (ptr->GetProperties().email.Get() != value)
-        if (!ptr->GetProperties().email.Set(value, admin, login, store))
-            return true;
-    }
-
-if ((it = structVal.find("cash")) != structVal.end())
-    {
-    double value(xmlrpc_c::value_double(it->second));
-    if (std::fabs(ptr->GetProperties().cash.Get() - value) > 1.0e-3)
-        if (!ptr->GetProperties().cash.Set(value, admin, login, store))
-            return true;
-    }
-
-if ((it = structVal.find("creditexpire")) != structVal.end())
-    {
-    time_t value(xmlrpc_c::value_int(it->second));
-    if (ptr->GetProperties().creditExpire.Get() != value)
-        if (!ptr->GetProperties().creditExpire.Set(value, admin, login, store))
-            return true;
-    }
-
-if ((it = structVal.find("credit")) != structVal.end())
-    {
-    double value(xmlrpc_c::value_double(it->second));
-    if (std::fabs(ptr->GetProperties().credit.Get() - value) > 1.0e-3)
-        if (!ptr->GetProperties().credit.Set(value, admin, login, store))
-            return true;
-    }
-
-if ((it = structVal.find("freemb")) != structVal.end())
-    {
-    double value(xmlrpc_c::value_double(it->second));
-    if (std::fabs(ptr->GetProperties().freeMb.Get() - value) > 1.0e-3)
-        if (!ptr->GetProperties().freeMb.Set(value, admin, login, store))
-            return true;
-    }
-
-if ((it = structVal.find("down")) != structVal.end())
-    {
-    bool value(xmlrpc_c::value_boolean(it->second));
-    if (ptr->GetProperties().disabled.Get() != value)
-        if (!ptr->GetProperties().disabled.Set(value, admin, login, store))
-            return true;
-    }
-
-if ((it = structVal.find("passive")) != structVal.end())
-    {
-    bool value(xmlrpc_c::value_boolean(it->second));
-    if (ptr->GetProperties().passive.Get() != value)
-        if (!ptr->GetProperties().passive.Set(value, admin, login, store))
-            return true;
-    }
-
-if ((it = structVal.find("disableddetailstat")) != structVal.end())
-    {
-    bool value(xmlrpc_c::value_boolean(it->second));
-    if (ptr->GetProperties().disabledDetailStat.Get() != value)
-        if (!ptr->GetProperties().disabledDetailStat.Set(value, admin, login, store))
-            return true;
-    }
-
-if ((it = structVal.find("name")) != structVal.end())
-    {
-    std::string value(IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "KOI8-RU"));
-    if (ptr->GetProperties().realName.Get() != value)
-        if (!ptr->GetProperties().realName.Set(value, admin, login, store))
-            return true;
-    }
-
-if ((it = structVal.find("group")) != structVal.end())
-    {
-    std::string value(IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "KOI8-RU"));
-    if (ptr->GetProperties().group.Get() != value)
-        if (!ptr->GetProperties().group.Set(value, admin, login, store))
-            return true;
-    }
-
-if ((it = structVal.find("note")) != structVal.end())
-    {
-    std::string value(IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "KOI8-RU"));
-    if (ptr->GetProperties().note.Get() != value)
-        if (!ptr->GetProperties().note.Set(value, admin, login, store))
-            return true;
-    }
-
-if ((it = structVal.find("userdata")) != structVal.end())
-    {
-    std::vector<STG::UserPropertyLogged<std::string> *> userdata;
-    userdata.push_back(ptr->GetProperties().userdata0.GetPointer());
-    userdata.push_back(ptr->GetProperties().userdata1.GetPointer());
-    userdata.push_back(ptr->GetProperties().userdata2.GetPointer());
-    userdata.push_back(ptr->GetProperties().userdata3.GetPointer());
-    userdata.push_back(ptr->GetProperties().userdata4.GetPointer());
-    userdata.push_back(ptr->GetProperties().userdata5.GetPointer());
-    userdata.push_back(ptr->GetProperties().userdata6.GetPointer());
-    userdata.push_back(ptr->GetProperties().userdata7.GetPointer());
-    userdata.push_back(ptr->GetProperties().userdata8.GetPointer());
-    userdata.push_back(ptr->GetProperties().userdata9.GetPointer());
-
-    std::vector<xmlrpc_c::value> udata(
-        xmlrpc_c::value_array(it->second).vectorValueValue()
-        );
-
-    for (unsigned i = 0; i < userdata.size(); ++i)
-        {
-        std::string value(IconvString(xmlrpc_c::value_string(udata[i]), "UTF-8", "KOI8-RU"));
-        if (userdata[i]->Get() != value)
-            if (!userdata[i]->Set(value, admin, login, store))
-                return true;
-        }
-    }
-
-if ((it = structVal.find("traff")) != structVal.end())
-    {
-    std::map<std::string, xmlrpc_c::value> traff(
-        static_cast<std::map<std::string, xmlrpc_c::value> >(xmlrpc_c::value_struct(it->second))
-        );
-
-    auto dtData = ptr->GetProperties().up.Get();
-    if ((it = traff.find("mu")) != traff.end())
-        {
-        std::vector<xmlrpc_c::value> data(xmlrpc_c::value_array(it->second).vectorValueValue());
-
-        for (int i = 0; i < std::min(DIR_NUM, static_cast<int>(data.size())); ++i)
-            {
-            int64_t value;
-            if (str2x(xmlrpc_c::value_string(data[i]), value))
-                printfd(__FILE__, "USER_HELPER::SetUserInfo(): 'Invalid month upload value'\n");
-            else
-                dtData[i] = value;
-            }
-        if (!ptr->GetProperties().up.Set(dtData, admin, login, store))
-            return true;
-        }
-    dtData = ptr->GetProperties().down.Get();
-    if ((it = traff.find("md")) != traff.end())
-        {
-        std::vector<xmlrpc_c::value> data(xmlrpc_c::value_array(it->second).vectorValueValue());
-
-        for (int i = 0; i < std::min(DIR_NUM, static_cast<int>(data.size())); ++i)
-            {
-            int64_t value;
-            if (str2x(xmlrpc_c::value_string(data[i]), value))
-                printfd(__FILE__, "USER_HELPER::SetUserInfo(): 'Invalid month download value'\n");
-            else
-                dtData[i] = value;
-            }
-        if (!ptr->GetProperties().down.Set(dtData, admin, login, store))
-            return true;
-        }
-    }
-
-if ((it = structVal.find("tariff")) != structVal.end())
-    {
-    std::string tariff(xmlrpc_c::value_string(it->second));
-    size_t pos = tariff.find('/');
-    std::string nextTariff;
-    if (pos != std::string::npos)
-        {
-        nextTariff = tariff.substr(pos + 1);
-        tariff = tariff.substr(0, pos);
-        }
-
-    const auto newTariff = tariffs->FindByName(tariff);
-    if (newTariff)
-        {
-        const auto currentTariff = ptr->GetTariff();
-        std::string message = currentTariff->TariffChangeIsAllowed(*newTariff, stgTime);
-        if (message.empty())
-            {
-            if (ptr->GetProperties().tariffName.Get() != tariff)
-                {
-                if (!ptr->GetProperties().tariffName.Set(tariff, admin, login, store))
-                    return true;
-                }
-            }
-        else
-            {
-                STG::PluginLogger::get("conf_rpc")("Tariff change is prohibited for user %s. %s", ptr->GetLogin().c_str(), message.c_str());
-            }
-        }
-
-    if (nextTariff != "" &&
-        tariffs->FindByName(nextTariff))
-        if (ptr->GetProperties().nextTariff.Get() != nextTariff)
-            if (!ptr->GetProperties().nextTariff.Set(tariff, admin, login, store))
-                return true;
-    }
-
-return false;
-}
diff --git a/stargazer/plugins/configuration/rpcconfig/user_helper.h b/stargazer/plugins/configuration/rpcconfig/user_helper.h
deleted file mode 100644 (file)
index 5457c95..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-#pragma once
-
-#include <string>
-
-#include <xmlrpc-c/base.hpp>
-
-namespace STG
-{
-
-struct Admin;
-struct Store;
-struct Tariffs;
-struct User;
-struct Users;
-
-}
-
-class USER_HELPER
-{
-public:
-    using UserPtr = STG::User*;
-    USER_HELPER(UserPtr & p, STG::Users & us)
-        : ptr(p),
-          users(us)
-    {
-    }
-
-    void GetUserInfo(xmlrpc_c::value * info,
-                     bool hidePassword = false);
-    bool SetUserInfo(const xmlrpc_c::value & info,
-                     const STG::Admin& admin,
-                     const std::string & login,
-                     const STG::Store & store,
-                     STG::Tariffs * tariffs);
-private:
-    UserPtr & ptr;
-    STG::Users & users;
-};
diff --git a/stargazer/plugins/configuration/rpcconfig/users_methods.cpp b/stargazer/plugins/configuration/rpcconfig/users_methods.cpp
deleted file mode 100644 (file)
index 650f7b3..0000000
+++ /dev/null
@@ -1,552 +0,0 @@
-#include "users_methods.h"
-#include "rpcconfig.h"
-#include "user_helper.h"
-
-#include "stg/users.h"
-#include "stg/admins.h"
-#include "stg/tariffs.h"
-#include "stg/tariff.h"
-#include "stg/user.h"
-#include "stg/user_property.h"
-#include "stg/common.h"
-
-#include <cerrno>
-
-using UserPtr = STG::User*;
-
-//------------------------------------------------------------------------------
-
-void METHOD_USER_GET::execute(xmlrpc_c::paramList const & paramList,
-                              xmlrpc_c::value *   const   retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-std::string login = paramList.getString(1);
-paramList.verifyEnd(2);
-
-std::map<std::string, xmlrpc_c::value> structVal;
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
-    {
-    structVal["result"] = xmlrpc_c::value_boolean(false);
-    *retvalPtr = xmlrpc_c::value_struct(structVal);
-    return;
-    }
-
-UserPtr u;
-
-if (users->FindByName(login, &u))
-    {
-    structVal["result"] = xmlrpc_c::value_boolean(false);
-    *retvalPtr = xmlrpc_c::value_struct(structVal);
-    return;
-    }
-
-USER_HELPER uhelper(u, *users);
-
-if (!adminInfo.priviledges.userConf || !adminInfo.priviledges.userPasswd)
-    {
-    uhelper.GetUserInfo(retvalPtr, true);
-    return;
-    }
-
-uhelper.GetUserInfo(retvalPtr);
-}
-
-//------------------------------------------------------------------------------
-
-void METHOD_USER_ADD::execute(xmlrpc_c::paramList const & paramList,
-                              xmlrpc_c::value *   const   retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-std::string login = paramList.getString(1);
-paramList.verifyEnd(2);
-
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-
-STG::Admin * admin = NULL;
-
-if (admins->find(adminInfo.admin, &admin))
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-
-UserPtr u;
-
-if (users->FindByName(login, &u))
-    {
-    if (users->Add(login, admin))
-        {
-        *retvalPtr = xmlrpc_c::value_boolean(false);
-        return;
-        }
-
-    *retvalPtr = xmlrpc_c::value_boolean(true);
-    return;
-    }
-
-*retvalPtr = xmlrpc_c::value_boolean(false);
-return;
-}
-
-//------------------------------------------------------------------------------
-
-void METHOD_USER_DEL::execute(xmlrpc_c::paramList const & paramList,
-                              xmlrpc_c::value *   const   retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-std::string login = paramList.getString(1);
-paramList.verifyEnd(2);
-
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-
-STG::Admin * admin;
-
-if (admins->find(adminInfo.admin, &admin))
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-
-UserPtr u;
-
-if (!users->FindByName(login, &u))
-    {
-    users->Del(login, admin);
-    *retvalPtr = xmlrpc_c::value_boolean(true);
-    return;
-    }
-
-*retvalPtr = xmlrpc_c::value_boolean(false);
-return;
-}
-
-//------------------------------------------------------------------------------
-
-void METHOD_USERS_GET::execute(xmlrpc_c::paramList const & paramList,
-                               xmlrpc_c::value *   const   retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-paramList.verifyEnd(1);
-
-std::map<std::string, xmlrpc_c::value> structVal;
-std::vector<xmlrpc_c::value> retval;
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
-    {
-    structVal["result"] = xmlrpc_c::value_boolean(false);
-    *retvalPtr = xmlrpc_c::value_struct(structVal);
-    return;
-    }
-
-bool hidePassword = !adminInfo.priviledges.userConf ||
-                    !adminInfo.priviledges.userPasswd;
-
-UserPtr u;
-
-int h = users->OpenSearch();
-if (!h)
-    {
-    printfd(__FILE__, "users->OpenSearch() error\n");
-    users->CloseSearch(h);
-    return;
-    }
-
-while (1)
-    {
-    if (users->SearchNext(h, &u))
-        {
-        break;
-        }
-
-    xmlrpc_c::value info;
-
-    USER_HELPER uhelper(u, *users);
-
-    uhelper.GetUserInfo(&info, hidePassword);
-
-    retval.push_back(info);
-    }
-
-*retvalPtr = xmlrpc_c::value_array(retval);
-}
-
-//------------------------------------------------------------------------------
-
-void METHOD_USER_CHG::execute(xmlrpc_c::paramList const & paramList,
-                              xmlrpc_c::value *   const   retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-std::string login = paramList.getString(1);
-xmlrpc_c::value_struct info(paramList.getStruct(2));
-paramList.verifyEnd(3);
-
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-
-STG::Admin * admin;
-
-if (admins->find(adminInfo.admin, &admin))
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-
-UserPtr u;
-
-if (users->FindByName(login, &u))
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-
-USER_HELPER uhelper(u, *users);
-
-if (!adminInfo.priviledges.userConf || !adminInfo.priviledges.userPasswd)
-    {
-    uhelper.SetUserInfo(info, *admin, login, *store, tariffs);
-    }
-else
-    {
-    uhelper.SetUserInfo(info, *admin, login, *store, tariffs);
-    }
-
-u->WriteConf();
-u->WriteStat();
-
-*retvalPtr = xmlrpc_c::value_boolean(true);
-}
-
-//------------------------------------------------------------------------------
-
-void METHOD_USER_CASH_ADD::execute(xmlrpc_c::paramList const & paramList,
-                                   xmlrpc_c::value *   const   retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-std::string login = paramList.getString(1);
-double amount = paramList.getDouble(2);
-std::string comment = IconvString(paramList.getString(3), "UTF-8", "KOI8-R");
-paramList.verifyEnd(4);
-
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-
-STG::Admin * admin;
-
-if (admins->find(adminInfo.admin, &admin))
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-
-UserPtr u;
-
-if (users->FindByName(login, &u))
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-
-double cash = u->GetProperties().cash.Get();
-cash += amount;
-
-if (!u->GetProperties().cash.Set(cash, *admin, login, *store, comment))
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-
-u->WriteStat();
-
-*retvalPtr = xmlrpc_c::value_boolean(true);
-}
-
-//------------------------------------------------------------------------------
-
-void METHOD_USER_CASH_SET::execute(xmlrpc_c::paramList const & paramList,
-                                   xmlrpc_c::value *   const   retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-std::string login = paramList.getString(1);
-double cash = paramList.getDouble(2);
-std::string comment = IconvString(paramList.getString(3), "UTF-8", "KOI8-R");
-paramList.verifyEnd(4);
-
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-
-STG::Admin * admin;
-
-if (admins->find(adminInfo.admin, &admin))
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-
-UserPtr u;
-
-if (users->FindByName(login, &u))
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-
-if (!u->GetProperties().cash.Set(cash, *admin, login, *store, comment))
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-
-u->WriteStat();
-
-*retvalPtr = xmlrpc_c::value_boolean(true);
-}
-
-//------------------------------------------------------------------------------
-
-void METHOD_USER_TARIFF_CHANGE::execute(xmlrpc_c::paramList const & paramList,
-                                        xmlrpc_c::value *   const   retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-std::string login = paramList.getString(1);
-std::string tariff = paramList.getString(2);
-bool delayed = paramList.getBoolean(3);
-std::string comment = IconvString(paramList.getString(4), "UTF-8", "KOI8-R");
-paramList.verifyEnd(5);
-
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-
-STG::Admin * admin;
-
-if (admins->find(adminInfo.admin, &admin))
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-
-UserPtr u;
-
-if (users->FindByName(login, &u))
-    {
-    *retvalPtr = xmlrpc_c::value_boolean(false);
-    return;
-    }
-
-if (tariffs->FindByName(tariff))
-    {
-    if (delayed)
-        {
-        if (u->GetProperties().nextTariff.Set(tariff, *admin, login, *store, comment))
-            {
-            u->WriteConf();
-            *retvalPtr = xmlrpc_c::value_boolean(true);
-            return;
-            }
-        }
-    else
-        {
-        const auto newTariff = tariffs->FindByName(tariff);
-        if (newTariff)
-            {
-            const auto currentTariff = u->GetTariff();
-            std::string message = currentTariff->TariffChangeIsAllowed(*newTariff, stgTime);
-            if (message.empty())
-                {
-                if (u->GetProperties().tariffName.Set(tariff, *admin, login, *store, comment))
-                    {
-                    u->ResetNextTariff();
-                    u->WriteConf();
-                    *retvalPtr = xmlrpc_c::value_boolean(true);
-                    return;
-                    }
-                }
-            else
-                {
-                    STG::PluginLogger::get("conf_rpc")("Tariff change is prohibited for user %s. %s", u->GetLogin().c_str(), message.c_str());
-                }
-            }
-        }
-    }
-
-*retvalPtr = xmlrpc_c::value_boolean(false);
-}
-
-//------------------------------------------------------------------------------
-
-void METHOD_GET_ONLINE_IPS::execute(xmlrpc_c::paramList const & paramList,
-                                    xmlrpc_c::value *   const   retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-typedef std::vector<xmlrpc_c::value> ValueVector;
-ValueVector subnetsStr = paramList.getArray(1);
-paramList.verifyEnd(2);
-
-std::vector<STG::IPMask> subnets;
-
-for (ValueVector::const_iterator it(subnetsStr.begin()); it != subnetsStr.end(); ++it)
-    {
-    STG::IPMask ipm;
-    if (ParseNet(xmlrpc_c::value_string(*it), ipm))
-        {
-        printfd(__FILE__, "METHOD_GET_ONLINE_IPS::execute(): Failed to parse subnet ('%s')\n", std::string(xmlrpc_c::value_string(*it)).c_str());
-        }
-    else
-        {
-        subnets.push_back(ipm);
-        }
-    }
-
-std::map<std::string, xmlrpc_c::value> structVal;
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
-    {
-    structVal["result"] = xmlrpc_c::value_boolean(false);
-    *retvalPtr = xmlrpc_c::value_struct(structVal);
-    return;
-    }
-
-ValueVector ips;
-
-UserPtr u;
-
-int handle = users->OpenSearch();
-if (!handle)
-    {
-    printfd(__FILE__, "users->OpenSearch() error\n");
-    users->CloseSearch(handle);
-    return;
-    }
-
-while (1)
-    {
-    if (users->SearchNext(handle, &u))
-        {
-        break;
-        }
-
-    if (u->GetAuthorized())
-        {
-        uint32_t ip = u->GetCurrIP();
-
-        for (std::vector<STG::IPMask>::const_iterator it(subnets.begin()); it != subnets.end(); ++it)
-            {
-            if ((it->ip & it->mask) == (ip & it->mask))
-                {
-                ips.push_back(xmlrpc_c::value_string(inet_ntostring(u->GetCurrIP())));
-                break;
-                }
-            }
-        }
-    }
-
-structVal["ips"] = xmlrpc_c::value_array(ips);
-
-*retvalPtr = xmlrpc_c::value_struct(structVal);
-}
-
-bool METHOD_GET_ONLINE_IPS::ParseNet(const std::string & net, STG::IPMask & ipm) const
-{
-size_t pos = net.find_first_of('/');
-
-if (pos == std::string::npos)
-    {
-    printfd(__FILE__, "METHOD_GET_ONLINE_IPS::ParseNet(): Network address is not in CIDR-notation\n");
-    return true;
-    }
-
-int res = inet_pton(AF_INET, net.substr(0, pos).c_str(), &ipm.ip);
-
-if (res < 0)
-    {
-    printfd(__FILE__, "METHOD_GET_ONLINE_IPS::ParseNet(): '%s'\n", strerror(errno));
-    return true;
-    }
-else if (res == 0)
-    {
-    printfd(__FILE__, "METHOD_GET_ONLINE_IPS::ParseNet(): Invalid network address\n", strerror(errno));
-    return true;
-    }
-
-if (str2x(net.substr(pos + 1, net.length() - pos - 1), ipm.mask))
-    {
-    printfd(__FILE__, "METHOD_GET_ONLINE_IPS::ParseNet(): Invalid network mask\n");
-    return true;
-    }
-if (ipm.mask > 32)
-    {
-    printfd(__FILE__, "METHOD_GET_ONLINE_IPS::ParseNet(): Network mask is out of range\n");
-    return true;
-    }
-ipm.mask = htonl(0xffFFffFF << (32 - ipm.mask));
-
-return false;
-}
-
-void METHOD_GET_USER_AUTH_BY::execute(xmlrpc_c::paramList const & paramList,
-                                      xmlrpc_c::value *   const   retvalPtr)
-{
-std::string cookie = paramList.getString(0);
-std::string login = paramList.getString(1);
-paramList.verifyEnd(2);
-
-std::map<std::string, xmlrpc_c::value> structVal;
-ADMIN_INFO adminInfo;
-
-if (config->GetAdminInfo(cookie, &adminInfo))
-    {
-    structVal["result"] = xmlrpc_c::value_boolean(false);
-    *retvalPtr = xmlrpc_c::value_struct(structVal);
-    return;
-    }
-
-UserPtr u;
-
-if (users->FindByName(login, &u))
-    {
-    structVal["result"] = xmlrpc_c::value_boolean(false);
-    *retvalPtr = xmlrpc_c::value_struct(structVal);
-    return;
-    }
-
-std::vector<std::string> list(u->GetAuthorizers());
-std::vector<xmlrpc_c::value> authList;
-for (std::vector<std::string>::const_iterator it = list.begin(); it != list.end(); ++it)
-    authList.push_back(xmlrpc_c::value_string(*it));
-*retvalPtr = xmlrpc_c::value_array(authList);
-}
diff --git a/stargazer/plugins/configuration/rpcconfig/users_methods.h b/stargazer/plugins/configuration/rpcconfig/users_methods.h
deleted file mode 100644 (file)
index f03e988..0000000
+++ /dev/null
@@ -1,255 +0,0 @@
-#pragma once
-
-#include <xmlrpc-c/base.hpp>
-#include <xmlrpc-c/registry.hpp>
-
-namespace STG
-{
-
-struct Admins;
-struct Tariffs;
-struct Users;
-struct Store;
-struct IPMask;
-
-}
-
-class RPC_CONFIG;
-
-class METHOD_USER_GET : public xmlrpc_c::method {
-public:
-    METHOD_USER_GET(RPC_CONFIG * c,
-                    STG::Users * u)
-        : config(c),
-          users(u)
-    {
-    }
-
-    void execute(xmlrpc_c::paramList const & paramList,
-                 xmlrpc_c::value *   const   retvalP);
-
-private:
-    METHOD_USER_GET(const METHOD_USER_GET & rvalue);
-    METHOD_USER_GET & operator=(const METHOD_USER_GET & rvalue);
-
-    RPC_CONFIG * config;
-    STG::Users * users;
-};
-
-class METHOD_USER_ADD : public xmlrpc_c::method {
-public:
-    METHOD_USER_ADD(RPC_CONFIG * c,
-                    STG::Admins * a,
-                    STG::Users * u)
-        : config(c),
-          admins(a),
-          users(u)
-    {
-    }
-
-    void execute(xmlrpc_c::paramList const & paramList,
-                 xmlrpc_c::value *   const   retvalP);
-
-private:
-    METHOD_USER_ADD(const METHOD_USER_ADD & rvalue);
-    METHOD_USER_ADD & operator=(const METHOD_USER_ADD & rvalue);
-
-    RPC_CONFIG * config;
-    STG::Admins * admins;
-    STG::Users * users;
-};
-
-class METHOD_USER_DEL : public xmlrpc_c::method {
-public:
-    METHOD_USER_DEL(RPC_CONFIG * c,
-                    STG::Admins * a,
-                    STG::Users * u)
-        : config(c),
-          admins(a),
-          users(u)
-    {
-    }
-
-    void execute(xmlrpc_c::paramList const & paramList,
-                 xmlrpc_c::value *   const   retvalP);
-
-private:
-    METHOD_USER_DEL(const METHOD_USER_DEL & rvalue);
-    METHOD_USER_DEL & operator=(const METHOD_USER_DEL & rvalue);
-
-    RPC_CONFIG * config;
-    STG::Admins * admins;
-    STG::Users * users;
-};
-
-class METHOD_USERS_GET : public xmlrpc_c::method {
-public:
-    METHOD_USERS_GET(RPC_CONFIG * c,
-                     STG::Users * u)
-        : config(c),
-          users(u)
-    {
-    }
-
-    void execute(xmlrpc_c::paramList const & paramList,
-                 xmlrpc_c::value *   const   retvalP);
-
-private:
-    METHOD_USERS_GET(const METHOD_USERS_GET & rvalue);
-    METHOD_USERS_GET & operator=(const METHOD_USERS_GET & rvalue);
-
-    RPC_CONFIG * config;
-    STG::Users * users;
-};
-
-class METHOD_USER_CHG : public xmlrpc_c::method {
-public:
-    METHOD_USER_CHG(RPC_CONFIG * c,
-                    STG::Admins * a,
-                    STG::Tariffs * t,
-                    STG::Store * s,
-                    STG::Users * u)
-        : config(c),
-          admins(a),
-          tariffs(t),
-          store(s),
-          users(u)
-    {
-    }
-
-    void execute(xmlrpc_c::paramList const & paramList,
-                 xmlrpc_c::value *   const   retvalP);
-
-private:
-    METHOD_USER_CHG(const METHOD_USER_CHG & rvalue);
-    METHOD_USER_CHG & operator=(const METHOD_USER_CHG & rvalue);
-
-    RPC_CONFIG * config;
-    STG::Admins * admins;
-    STG::Tariffs * tariffs;
-    STG::Store * store;
-    STG::Users * users;
-};
-
-class METHOD_USER_CASH_ADD : public xmlrpc_c::method {
-public:
-    METHOD_USER_CASH_ADD(RPC_CONFIG * c,
-                         STG::Admins * a,
-                         STG::Store * s,
-                         STG::Users * u)
-        : config(c),
-          admins(a),
-          store(s),
-          users(u)
-    {
-    }
-
-    void execute(xmlrpc_c::paramList const & paramList,
-                 xmlrpc_c::value *   const   retvalP);
-
-private:
-    METHOD_USER_CASH_ADD(const METHOD_USER_CASH_ADD & rvalue);
-    METHOD_USER_CASH_ADD & operator=(const METHOD_USER_CASH_ADD & rvalue);
-
-    RPC_CONFIG * config;
-    STG::Admins * admins;
-    STG::Store * store;
-    STG::Users * users;
-};
-
-class METHOD_USER_CASH_SET : public xmlrpc_c::method {
-public:
-    METHOD_USER_CASH_SET(RPC_CONFIG * c,
-                         STG::Admins * a,
-                         STG::Store * s,
-                         STG::Users * u)
-        : config(c),
-          admins(a),
-          store(s),
-          users(u)
-    {
-    }
-
-    void execute(xmlrpc_c::paramList const & paramList,
-                 xmlrpc_c::value *   const   retvalP);
-
-private:
-    METHOD_USER_CASH_SET(const METHOD_USER_CASH_SET & rvalue);
-    METHOD_USER_CASH_SET & operator=(const METHOD_USER_CASH_SET & rvalue);
-
-    RPC_CONFIG * config;
-    STG::Admins * admins;
-    STG::Store * store;
-    STG::Users * users;
-};
-
-class METHOD_USER_TARIFF_CHANGE : public xmlrpc_c::method {
-public:
-    METHOD_USER_TARIFF_CHANGE(RPC_CONFIG * c,
-                              STG::Admins * a,
-                              STG::Tariffs * t,
-                              STG::Store * s,
-                              STG::Users * u)
-        : config(c),
-          admins(a),
-          tariffs(t),
-          store(s),
-          users(u)
-    {
-    }
-
-    void execute(xmlrpc_c::paramList const & paramList,
-                 xmlrpc_c::value *   const   retvalP);
-
-private:
-    METHOD_USER_TARIFF_CHANGE(const METHOD_USER_TARIFF_CHANGE & rvalue);
-    METHOD_USER_TARIFF_CHANGE & operator=(const METHOD_USER_TARIFF_CHANGE & rvalue);
-
-    RPC_CONFIG * config;
-    STG::Admins * admins;
-    STG::Tariffs * tariffs;
-    STG::Store * store;
-    STG::Users * users;
-};
-
-class METHOD_GET_ONLINE_IPS : public xmlrpc_c::method {
-public:
-    METHOD_GET_ONLINE_IPS(RPC_CONFIG * c,
-                          STG::Users * u)
-        : config(c),
-          users(u)
-    {
-    }
-
-    void execute(xmlrpc_c::paramList const & paramList,
-                 xmlrpc_c::value *   const   retvalP);
-
-private:
-    METHOD_GET_ONLINE_IPS(const METHOD_GET_ONLINE_IPS & rvalue);
-    METHOD_GET_ONLINE_IPS & operator=(const METHOD_GET_ONLINE_IPS & rvalue);
-
-    RPC_CONFIG * config;
-    STG::Users * users;
-
-    bool ParseNet(const std::string & net, STG::IPMask & ipm) const;
-};
-
-class METHOD_GET_USER_AUTH_BY : public xmlrpc_c::method {
-public:
-    METHOD_GET_USER_AUTH_BY(RPC_CONFIG * c,
-                            STG::Users * u)
-        : config(c),
-          users(u)
-    {
-    }
-
-    void execute(xmlrpc_c::paramList const & paramList,
-                 xmlrpc_c::value *   const   retvalP);
-
-private:
-    METHOD_GET_USER_AUTH_BY(const METHOD_GET_ONLINE_IPS & rvalue);
-    METHOD_GET_USER_AUTH_BY & operator=(const METHOD_GET_ONLINE_IPS & rvalue);
-
-    RPC_CONFIG * config;
-    STG::Users * users;
-};
diff --git a/stargazer/plugins/configuration/sgconfig/configproto.cpp b/stargazer/plugins/configuration/sgconfig/configproto.cpp
deleted file mode 100644 (file)
index 0119790..0000000
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#include "configproto.h"
-
-#include "conn.h"
-
-#include "parser_server_info.h"
-#include "parser_admins.h"
-#include "parser_tariffs.h"
-#include "parser_users.h"
-#include "parser_services.h"
-#include "parser_message.h"
-#include "parser_user_info.h"
-#include "parser_auth_by.h"
-
-#include "stg/common.h"
-#include "stg/logger.h"
-
-#include <algorithm>
-#include <functional>
-#include <vector>
-#include <csignal>
-#include <cstring>
-#include <cerrno>
-#include <cassert>
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-
-namespace SP = STG::PARSER;
-
-CONFIGPROTO::CONFIGPROTO(STG::PluginLogger & l)
-    : m_settings(NULL),
-      m_admins(NULL),
-      m_tariffs(NULL),
-      m_users(NULL),
-      m_services(NULL),
-      m_corporations(NULL),
-      m_store(NULL),
-      m_port(0),
-      m_bindAddress("0.0.0.0"),
-      m_running(false),
-      m_stopped(true),
-      m_logger(l),
-      m_listenSocket(-1)
-{
-}
-
-CONFIGPROTO::~CONFIGPROTO()
-{
-    {
-    std::deque<STG::Conn *>::iterator it;
-    for (it = m_conns.begin(); it != m_conns.end(); ++it)
-        delete *it;
-    }
-    {
-    BASE_PARSER::REGISTRY::iterator it;
-    for (it = m_registry.begin(); it != m_registry.end(); ++it)
-        delete it->second;
-    }
-}
-
-int CONFIGPROTO::Prepare()
-{
-    sigset_t sigmask, oldmask;
-    sigemptyset(&sigmask);
-    sigaddset(&sigmask, SIGINT);
-    sigaddset(&sigmask, SIGTERM);
-    sigaddset(&sigmask, SIGUSR1);
-    sigaddset(&sigmask, SIGHUP);
-    pthread_sigmask(SIG_BLOCK, &sigmask, &oldmask);
-    m_listenSocket = socket(PF_INET, SOCK_STREAM, 0);
-
-    if (m_listenSocket < 0)
-    {
-        m_errorStr = std::string("Cannot create listen socket: '") + strerror(errno) + "'.";
-        m_logger(m_errorStr);
-        return -1;
-    }
-
-    int dummy = 1;
-
-    if (setsockopt(m_listenSocket, SOL_SOCKET, SO_REUSEADDR, &dummy, 4) != 0)
-    {
-        m_errorStr = std::string("Failed to set SO_REUSEADDR to the listen socket: '") + strerror(errno) + "'.";
-        m_logger(m_errorStr);
-        return -1;
-    }
-
-    if (!Bind())
-        return -1;
-
-    if (listen(m_listenSocket, 64) == -1) // TODO: backlog length
-    {
-        m_errorStr = std::string("Failed to start listening for connections: '") + strerror(errno) + "'.";
-        m_logger(m_errorStr);
-        return -1;
-    }
-
-    RegisterParsers();
-
-    m_running = true;
-    m_stopped = false;
-    return 0;
-}
-
-int CONFIGPROTO::Stop()
-{
-    m_running = false;
-    for (int i = 0; i < 5 && !m_stopped; ++i)
-    {
-        struct timespec ts = {0, 200000000};
-        nanosleep(&ts, NULL);
-    }
-
-    if (!m_stopped)
-    {
-        m_errorStr = "Cannot stop listenign thread.";
-        m_logger(m_errorStr);
-        return -1;
-    }
-
-    shutdown(m_listenSocket, SHUT_RDWR);
-    close(m_listenSocket);
-    return 0;
-}
-
-void CONFIGPROTO::Run()
-{
-    while (m_running)
-    {
-        fd_set fds;
-
-        BuildFDSet(fds);
-
-        struct timeval tv;
-        tv.tv_sec = 0;
-        tv.tv_usec = 500000;
-
-        int res = select(MaxFD() + 1, &fds, NULL, NULL, &tv);
-        if (res < 0)
-        {
-            m_errorStr = std::string("'select' is failed: '") + strerror(errno) + "'.";
-            printfd(__FILE__, "%s\n", m_errorStr.c_str());
-            m_logger(m_errorStr);
-            break;
-        }
-        if (!m_running)
-            break;
-        if (res > 0)
-            HandleEvents(fds);
-
-        CleanupConns();
-    }
-    m_stopped = true;
-}
-
-bool CONFIGPROTO::Bind()
-{
-    const hostent * he = gethostbyname(m_bindAddress.c_str());
-    if (he == NULL)
-    {
-        m_errorStr = "Failed to resolve name '" + m_bindAddress + "': '" + hstrerror(h_errno) + "'.";
-        printfd(__FILE__, "%s\n", m_errorStr.c_str());
-        m_logger(m_errorStr);
-        return false;
-    }
-
-    char ** ptr = he->h_addr_list;
-    while (*ptr != NULL)
-    {
-        struct sockaddr_in listenAddr;
-        listenAddr.sin_family = PF_INET;
-        listenAddr.sin_port = htons(m_port);
-        listenAddr.sin_addr.s_addr = *reinterpret_cast<in_addr_t *>(*ptr);
-
-        printfd(__FILE__, "Trying to bind to %s:%d\n", inet_ntostring(listenAddr.sin_addr.s_addr).c_str(), m_port);
-
-        if (bind(m_listenSocket, reinterpret_cast<sockaddr *>(&listenAddr), sizeof(listenAddr)) == 0)
-            return true;
-
-        m_errorStr = std::string("Cannot bind listen socket: '") + strerror(errno) + "'.";
-        printfd(__FILE__, "%s\n", m_errorStr.c_str());
-        m_logger(m_errorStr);
-
-        ++ptr;
-    }
-
-    return false;
-}
-
-void CONFIGPROTO::RegisterParsers()
-{
-    assert(m_settings != NULL);
-    assert(m_store != NULL);
-    assert(m_admins != NULL);
-    assert(m_users != NULL);
-    assert(m_tariffs != NULL);
-    assert(m_services != NULL);
-    assert(m_corporations != NULL);
-
-    SP::GET_SERVER_INFO::FACTORY::Register(m_registry, *m_settings, *m_users, *m_tariffs);
-
-    SP::GET_ADMINS::FACTORY::Register(m_registry, *m_admins);
-    SP::ADD_ADMIN::FACTORY::Register(m_registry, *m_admins);
-    SP::DEL_ADMIN::FACTORY::Register(m_registry, *m_admins);
-    SP::CHG_ADMIN::FACTORY::Register(m_registry, *m_admins);
-
-    SP::GET_TARIFFS::FACTORY::Register(m_registry, *m_tariffs);
-    SP::ADD_TARIFF::FACTORY::Register(m_registry, *m_tariffs);
-    SP::DEL_TARIFF::FACTORY::Register(m_registry, *m_tariffs, *m_users);
-    SP::CHG_TARIFF::FACTORY::Register(m_registry, *m_tariffs);
-
-    SP::GET_USERS::FACTORY::Register(m_registry, *m_users);
-    SP::GET_USER::FACTORY::Register(m_registry, *m_users);
-    SP::ADD_USER::FACTORY::Register(m_registry, *m_users);
-    SP::DEL_USER::FACTORY::Register(m_registry, *m_users);
-    SP::CHG_USER::FACTORY::Register(m_registry, *m_users, *m_store, *m_tariffs);
-    SP::CHECK_USER::FACTORY::Register(m_registry, *m_users);
-
-    SP::GET_SERVICES::FACTORY::Register(m_registry, *m_services);
-    SP::GET_SERVICE::FACTORY::Register(m_registry, *m_services);
-    SP::ADD_SERVICE::FACTORY::Register(m_registry, *m_services);
-    SP::DEL_SERVICE::FACTORY::Register(m_registry, *m_services);
-    SP::CHG_SERVICE::FACTORY::Register(m_registry, *m_services);
-
-    SP::SEND_MESSAGE::FACTORY::Register(m_registry, *m_users);
-
-    SP::AUTH_BY::FACTORY::Register(m_registry, *m_users);
-
-    SP::USER_INFO::FACTORY::Register(m_registry, *m_users);
-}
-
-int CONFIGPROTO::MaxFD() const
-{
-    int maxFD = m_listenSocket;
-    std::deque<STG::Conn *>::const_iterator it;
-    for (it = m_conns.begin(); it != m_conns.end(); ++it)
-        if (maxFD < (*it)->Sock())
-            maxFD = (*it)->Sock();
-    return maxFD;
-}
-
-void CONFIGPROTO::BuildFDSet(fd_set & fds) const
-{
-    FD_ZERO(&fds);
-    FD_SET(m_listenSocket, &fds);
-    std::deque<STG::Conn *>::const_iterator it;
-    for (it = m_conns.begin(); it != m_conns.end(); ++it)
-        FD_SET((*it)->Sock(), &fds);
-}
-
-void CONFIGPROTO::CleanupConns()
-{
-    std::deque<STG::Conn *>::iterator pos;
-    for (pos = m_conns.begin(); pos != m_conns.end(); ++pos)
-        if (((*pos)->IsDone() && !(*pos)->IsKeepAlive()) || !(*pos)->IsOk())
-        {
-            delete *pos;
-            *pos = NULL;
-        }
-
-    pos = std::remove(m_conns.begin(), m_conns.end(), static_cast<STG::Conn *>(NULL));
-    m_conns.erase(pos, m_conns.end());
-}
-
-void CONFIGPROTO::HandleEvents(const fd_set & fds)
-{
-    if (FD_ISSET(m_listenSocket, &fds))
-        AcceptConnection();
-    else
-    {
-        std::deque<STG::Conn *>::iterator it;
-        for (it = m_conns.begin(); it != m_conns.end(); ++it)
-            if (FD_ISSET((*it)->Sock(), &fds))
-                (*it)->Read();
-    }
-}
-
-void CONFIGPROTO::AcceptConnection()
-{
-    struct sockaddr_in outerAddr;
-    socklen_t outerAddrLen(sizeof(outerAddr));
-    int sock = accept(m_listenSocket, reinterpret_cast<sockaddr *>(&outerAddr), &outerAddrLen);
-
-    if (sock < 0)
-    {
-        m_errorStr = std::string("Failed to accept connection: '") + strerror(errno) + "'.";
-        printfd(__FILE__, "%s\n", m_errorStr.c_str());
-        m_logger(m_errorStr);
-        return;
-    }
-
-    assert(m_admins != NULL);
-
-    try
-    {
-        m_conns.push_back(new STG::Conn(m_registry, *m_admins, sock, outerAddr, m_logger));
-        printfd(__FILE__, "New connection from %s:%d. Total connections: %d\n", inet_ntostring(m_conns.back()->IP()).c_str(), m_conns.back()->Port(), m_conns.size());
-    }
-    catch (const STG::Conn::Error & error)
-    {
-        // Unlikely.
-        m_logger(std::string("Failed to create new client connection: '") + error.what() + "'.");
-    }
-}
diff --git a/stargazer/plugins/configuration/sgconfig/configproto.h b/stargazer/plugins/configuration/sgconfig/configproto.h
deleted file mode 100644 (file)
index 7721938..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#pragma once
-
-#include "parser.h"
-
-#include "stg/module_settings.h"
-
-#include <string>
-#include <deque>
-#include <cstdint>
-
-#include <sys/select.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-namespace STG
-{
-
-struct Settings;
-struct Admins;
-struct Tariffs;
-struct Users;
-struct Services;
-struct Corporations;
-struct Store;
-class PluginLogger;
-
-class Conn;
-
-}
-
-class CONFIGPROTO {
-public:
-    explicit CONFIGPROTO(STG::PluginLogger & l);
-    ~CONFIGPROTO();
-
-    void SetPort(uint16_t port) { m_port = port; }
-    void SetBindAddress(const std::string & address) { m_bindAddress = address; }
-    void SetSettings(const STG::Settings * settings) { m_settings = settings; }
-    void SetAdmins(STG::Admins * admins) { m_admins = admins; }
-    void SetTariffs(STG::Tariffs * tariffs) { m_tariffs = tariffs; }
-    void SetUsers(STG::Users * users) { m_users = users; }
-    void SetStore(STG::Store * store) { m_store = store; }
-    void SetServices(STG::Services * services) { m_services = services; }
-    void SetCorporations(STG::Corporations * corporations) { m_corporations = corporations; }
-
-    int Prepare();
-    int Stop();
-    const std::string & GetStrError() const { return m_errorStr; }
-    void Run();
-
-private:
-    CONFIGPROTO(const CONFIGPROTO & rvalue);
-    CONFIGPROTO & operator=(const CONFIGPROTO & rvalue);
-
-    const STG::Settings * m_settings;
-    STG::Admins *         m_admins;
-    STG::Tariffs *        m_tariffs;
-    STG::Users *          m_users;
-    STG::Services *       m_services;
-    STG::Corporations *   m_corporations;
-    STG::Store *          m_store;
-
-    uint16_t         m_port;
-    std::string      m_bindAddress;
-    bool             m_running;
-    bool             m_stopped;
-    STG::PluginLogger &   m_logger;
-    int              m_listenSocket;
-
-    std::string      m_errorStr;
-
-    BASE_PARSER::REGISTRY m_registry;
-    std::deque<STG::Conn *> m_conns;
-
-    bool Bind();
-
-    void RegisterParsers();
-
-    int MaxFD() const;
-    void BuildFDSet(fd_set & fds) const;
-    void CleanupConns();
-    void HandleEvents(const fd_set & fds);
-    void AcceptConnection();
-};
diff --git a/stargazer/plugins/configuration/sgconfig/conn.cpp b/stargazer/plugins/configuration/sgconfig/conn.cpp
deleted file mode 100644 (file)
index 92d7479..0000000
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#include "conn.h"
-
-#include "stg/admins.h"
-#include "stg/admin.h"
-#include "stg/logger.h"
-#include "stg/blowfish.h"
-#include "stg/bfstream.h"
-#include "stg/common.h"
-
-#include <cassert>
-#include <cstring>
-#include <cerrno>
-
-#include <unistd.h>
-#include <sys/socket.h>
-
-using STG::Conn;
-
-const char Conn::STG_HEADER[] = "SG04";
-const char Conn::OK_HEADER[] = "OKHD";
-const char Conn::ERR_HEADER[] = "ERHD";
-const char Conn::OK_LOGIN[] = "OKLG";
-const char Conn::ERR_LOGIN[] = "ERLG";
-const char Conn::OK_LOGINS[] = "OKLS";
-const char Conn::ERR_LOGINS[] = "ERLS";
-
-Conn::Conn(const BASE_PARSER::REGISTRY & registry,
-           Admins & admins, int sock, const sockaddr_in& addr,
-           PluginLogger & logger)
-    : m_registry(registry),
-      m_admins(admins),
-      m_admin(NULL),
-      m_sock(sock),
-      m_addr(addr),
-      m_keepAlive(false),
-      m_parser(NULL),
-      m_xmlParser(XML_ParserCreate(NULL)),
-      m_state(HEADER),
-      m_buffer(m_header),
-      m_bufferSize(sizeof(m_header)),
-      m_stream(NULL),
-      m_logger(logger),
-#ifdef DUMPCRYPTO
-      m_dataState(false, *this),
-      m_dumper(endpoint())
-#else
-      m_dataState(false, *this)
-#endif
-{
-    if (m_xmlParser == NULL)
-        throw Error("Failed to create XML parser.");
-
-    XML_ParserReset(m_xmlParser, NULL);
-    XML_SetElementHandler(m_xmlParser, ParseXMLStart, ParseXMLEnd);
-    XML_SetUserData(m_xmlParser, this);
-}
-
-Conn::~Conn()
-{
-    shutdown(m_sock, SHUT_RDWR);
-    close(m_sock);
-
-    XML_ParserFree(m_xmlParser);
-
-    delete m_stream;
-    delete m_parser;
-}
-
-bool Conn::Read()
-{
-    ssize_t res = read(m_sock, m_buffer, m_bufferSize);
-    if (res < 0)
-    {
-        m_state = ERROR;
-        Log(__FILE__, "Failed to read data from " + endpoint() + ". Reason: '" + strerror(errno) + "'");
-        return false;
-    }
-    if (res == 0 && m_state != DATA) // EOF is ok for data.
-    {
-        m_state = ERROR;
-        Log(__FILE__, "Failed to read data from " + endpoint() + ". Unexpected EOF.");
-        return false;
-    }
-#ifdef DUMPCRYPTO
-    m_dumper.write(m_buffer, res);
-#endif
-    m_bufferSize -= res;
-    m_buffer = static_cast<char*>(m_buffer) + res;
-    return HandleBuffer(res);
-}
-
-bool Conn::WriteAnswer(const void* buffer, size_t size)
-{
-    ssize_t res = write(m_sock, buffer, size);
-    if (res < 0)
-    {
-        m_state = ERROR;
-        Log(__FILE__, "Failed to write data to " + endpoint() + ". Reason: '" + strerror(errno) + "'.");
-        return false;
-    }
-    return true;
-}
-
-BASE_PARSER * Conn::GetParser(const std::string & tag) const
-{
-    BASE_PARSER::REGISTRY::const_iterator it = m_registry.find(ToLower(tag));
-    if (it == m_registry.end())
-        return NULL;
-    return it->second->create(*m_admin);
-}
-
-bool Conn::HandleBuffer(size_t size)
-{
-    if (m_state == DATA)
-        return HandleData(size);
-
-    if (m_bufferSize > 0)
-        return true;
-
-    switch (m_state)
-    {
-        case HEADER: return HandleHeader();
-        case LOGIN: return HandleLogin();
-        case CRYPTO_LOGIN: return HandleCryptoLogin();
-        default: return true;
-    }
-
-    return true;
-}
-
-bool Conn::HandleHeader()
-{
-    if (strncmp(m_header, STG_HEADER, sizeof(m_header)) != 0)
-    {
-        Log(__FILE__, "Received invalid header from " + endpoint() + ".");
-        WriteAnswer(ERR_HEADER, sizeof(ERR_HEADER) - 1); // Without \0
-        m_state = ERROR;
-        return false;
-    }
-    m_state = LOGIN;
-    m_buffer = m_login;
-    m_bufferSize = sizeof(m_login);
-    return WriteAnswer(OK_HEADER, sizeof(OK_HEADER) - 1); // Without \0
-}
-
-bool Conn::HandleLogin()
-{
-    if (m_admins.find(m_login, &m_admin)) // ADMINS::Find returns true on error.
-    {
-        std::string login(m_login, strnlen(m_login, sizeof(m_login)));
-        Log(__FILE__, "Received invalid login '" + ToPrintable(login) + "' from " + endpoint() + ".");
-        WriteAnswer(ERR_LOGIN, sizeof(ERR_LOGIN) - 1); // Without \0
-        m_state = ERROR;
-        return false;
-    }
-    m_admin->setIP(IP());
-    m_state = CRYPTO_LOGIN;
-    m_buffer = m_cryptoLogin;
-    m_bufferSize = sizeof(m_cryptoLogin);
-    return WriteAnswer(OK_LOGIN, sizeof(OK_LOGIN) - 1); // Without \0
-}
-
-bool Conn::HandleCryptoLogin()
-{
-    char login[ADM_LOGIN_LEN + 1];
-    BLOWFISH_CTX ctx;
-    InitContext(m_admin->password().c_str(), ADM_PASSWD_LEN, &ctx);
-    DecryptString(login, m_cryptoLogin, ADM_LOGIN_LEN, &ctx);
-
-    if (strncmp(m_login, login, sizeof(login)) != 0)
-    {
-        Log(__FILE__, "Attempt to connect with wrong password from " + m_admin->login() + "@" + endpoint() + ".");
-        WriteAnswer(ERR_LOGINS, sizeof(ERR_LOGINS) - 1); // Without \0
-        m_state = ERROR;
-        return false;
-    }
-
-    m_state = DATA;
-    m_buffer = m_data;
-    m_bufferSize = sizeof(m_data);
-    m_stream = new STG::DECRYPT_STREAM(m_admin->password(), DataCallback, &m_dataState);
-    return WriteAnswer(OK_LOGINS, sizeof(OK_LOGINS) - 1); // Without \0
-}
-
-bool Conn::HandleData(size_t size)
-{
-    m_stream->Put(m_data, size, size == 0 || memchr(m_data, 0, size) != NULL);
-    m_buffer = m_data;
-    return m_stream->IsOk();
-}
-
-bool Conn::DataCallback(const void * block, size_t size, void * data)
-{
-    assert(data != NULL);
-    DataState& state = *static_cast<DataState *>(data);
-
-    const char * xml = static_cast<const char *>(block);
-    size_t length = strnlen(xml, size);
-
-    state.final = state.final || length < size || size == 0;
-
-    if (XML_Parse(state.conn.m_xmlParser, xml, length, state.final) == XML_STATUS_ERROR)
-    {
-        state.conn.Log(__FILE__, "Received invalid XML from " + state.conn.m_admin->login() + "@" + state.conn.endpoint() + ".");
-        printfd(__FILE__, "XML parse error at line %d, %d: %s. Is final: %d\n",
-                  static_cast<int>(XML_GetCurrentLineNumber(state.conn.m_xmlParser)),
-                  static_cast<int>(XML_GetCurrentColumnNumber(state.conn.m_xmlParser)),
-                  XML_ErrorString(XML_GetErrorCode(state.conn.m_xmlParser)), (int)state.final);
-        printfd(__FILE__, "Data block: '%s' of size %d\n", xml, length);
-        state.conn.m_state = ERROR;
-        return false;
-    }
-
-    if (state.final)
-    {
-        if (!state.conn.WriteResponse())
-        {
-            state.conn.Log(__FILE__, "Failed to write response to " + state.conn.m_admin->login() + "@" + state.conn.endpoint() + ".");
-            state.conn.m_state = ERROR;
-            return false;
-        }
-        state.conn.m_state = DONE;
-    }
-
-    return true;
-}
-
-void Conn::ParseXMLStart(void * data, const char * el, const char ** attr)
-{
-    assert(data != NULL);
-    Conn & conn = *static_cast<Conn *>(data);
-
-    if (conn.m_parser == NULL)
-        conn.m_parser = conn.GetParser(el);
-
-    if (conn.m_parser == NULL)
-    {
-        conn.Log(__FILE__, "Received unknown command '" + std::string(el) + "' from " + conn.m_admin->login() + "@" + conn.endpoint() + ".");
-        conn.m_state = ERROR;
-        return;
-    }
-
-    conn.m_parser->Start(data, el, attr);
-}
-
-void Conn::ParseXMLEnd(void * data, const char * el)
-{
-    assert(data != NULL);
-    Conn & conn = *static_cast<Conn *>(data);
-
-    if (conn.m_parser == NULL)
-    {
-        // No need to log it.
-        conn.m_state = ERROR;
-        return;
-    }
-
-    conn.m_parser->End(data, el);
-}
-
-bool Conn::WriteResponse()
-{
-    STG::ENCRYPT_STREAM stream(m_admin->password(), WriteCallback, this);
-    std::string answer;
-    if (m_parser != NULL)
-        answer = m_parser->GetAnswer();
-    else
-        answer = "<Error result=\"Unknown command.\"/>";
-    delete m_parser;
-    m_parser = NULL;
-    printfd(__FILE__, "Writing %d bytes of answer.\n", answer.length());
-    stream.Put(answer.c_str(), answer.length() + 1 /* including \0 */, true /* final */);
-    return stream.IsOk();
-}
-
-bool Conn::WriteCallback(const void * block, size_t size, void * data)
-{
-    assert(data != NULL);
-    Conn & conn = *static_cast<Conn *>(data);
-    return WriteAll(conn.m_sock, block, size);;
-}
-
-void Conn::Log(const char * file, const std::string & message)
-{
-    printfd(file, "%s\n", message.c_str());
-    m_logger(message);
-}
diff --git a/stargazer/plugins/configuration/sgconfig/conn.h b/stargazer/plugins/configuration/sgconfig/conn.h
deleted file mode 100644 (file)
index c96be90..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#pragma once
-
-#include "parser.h"
-
-#include "dumphelpers.h"
-
-#include "stg/const.h"
-
-#include <stdexcept>
-#include <string>
-#include <cstdint>
-
-#include <expat.h>
-
-#include <netinet/in.h>
-
-namespace STG
-{
-
-struct Settings;
-struct Admins;
-struct Users;
-struct Tariffs;
-struct Admin;
-class PluginLogger;
-
-class DECRYPT_STREAM;
-
-class Conn
-{
-    public:
-        struct Error : public std::runtime_error
-        {
-            explicit Error(const std::string& message) : runtime_error(message.c_str()) {}
-        };
-
-        Conn(const BASE_PARSER::REGISTRY & registry,
-             Admins & admins, int sock, const sockaddr_in& addr,
-             PluginLogger & logger);
-        ~Conn();
-
-        int Sock() const { return m_sock; }
-        uint32_t IP() const { return *(uint32_t *)(&m_addr.sin_addr); }
-        uint16_t Port() const { return ntohs(m_addr.sin_port); }
-
-        std::string endpoint() const { return inet_ntostring(IP()) + ":" + std::to_string(Port()); }
-
-        bool Read();
-
-        bool IsOk() const { return m_state != ERROR; }
-        bool IsDone() const { return m_state == DONE; }
-        bool IsKeepAlive() const { return m_keepAlive; }
-
-        void SetKeepAlive() { m_keepAlive = true; }
-
-    private:
-
-        static const char STG_HEADER[5];
-        static const char OK_HEADER[5];
-        static const char ERR_HEADER[5];
-        static const char OK_LOGIN[5];
-        static const char ERR_LOGIN[5];
-        static const char OK_LOGINS[5];
-        static const char ERR_LOGINS[5];
-
-        const BASE_PARSER::REGISTRY & m_registry;
-
-        Admins & m_admins;
-
-        Admin * m_admin;
-
-        int m_sock;
-        sockaddr_in m_addr;
-        bool m_keepAlive;
-
-        BASE_PARSER * m_parser;
-
-        XML_Parser m_xmlParser;
-
-        enum { HEADER, LOGIN, CRYPTO_LOGIN, DATA, DONE, ERROR } m_state;
-
-        void * m_buffer;
-        size_t m_bufferSize;
-        char m_header[sizeof(STG_HEADER) - 1]; // Without \0
-        char m_login[ADM_LOGIN_LEN]; // Without \0
-        char m_cryptoLogin[ADM_LOGIN_LEN]; // Without \0
-        char m_data[1024];
-        STG::DECRYPT_STREAM * m_stream;
-        PluginLogger &  m_logger;
-
-        BASE_PARSER * GetParser(const std::string & tag) const;
-
-        bool HandleBuffer(size_t size);
-
-        bool HandleHeader();
-        bool HandleLogin();
-        bool HandleCryptoLogin();
-        bool HandleData(size_t size);
-
-        bool WriteAnswer(const void* buffer, size_t size);
-        bool WriteResponse();
-
-        void Log(const char * file, const std::string & message);
-
-        struct DataState
-        {
-            DataState(bool f, Conn & c) : final(f), conn(c) {}
-            bool final;
-            Conn & conn;
-        } m_dataState;
-
-#ifdef DUMPCRYPTO
-        Dumper m_dumper;
-#endif
-
-        static bool DataCallback(const void * block, size_t size, void * data);
-        static void ParseXMLStart(void * data, const char * el, const char ** attr);
-        static void ParseXMLEnd(void * data, const char * el);
-        static bool WriteCallback(const void * block, size_t size, void * data);
-};
-
-}
diff --git a/stargazer/plugins/configuration/sgconfig/dumphelpers.h b/stargazer/plugins/configuration/sgconfig/dumphelpers.h
deleted file mode 100644 (file)
index 86bf197..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-#ifndef __STG_DUMP_HELPERS_H__
-#define __STG_DUMP_HELPERS_H__
-
-#include "stg/common.h"
-
-#include <string>
-#include <fstream>
-#include <sstream>
-#include <iomanip>
-
-#include <cstddef>
-#include <ctime>
-
-namespace STG
-{
-
-class Dumper
-{
-    public:
-        explicit Dumper(const std::string& tag)
-            : m_stream(getName(tag).c_str())
-        {
-        }
-        ~Dumper() {}
-
-        void write(const void* data, size_t size)
-        {
-            writePrefix();
-            m_stream << " ";
-            writeHEX(data, size);
-        }
-
-    private:
-        std::ofstream m_stream;
-
-        tm getTime() const
-        {
-            time_t now = time(NULL);
-            tm localTime;
-            localtime_r(&now, &localTime);
-            return localTime;
-        }
-
-        std::string getName(const std::string& tag) const
-        {
-            tm localTime = getTime();
-
-            std::ostringstream res;
-            res << tag
-                << "-" << (localTime.tm_year + 1900) << twoDigit(localTime.tm_mon + 1) << twoDigit(localTime.tm_mday)
-                << "-" << twoDigit(localTime.tm_hour) << twoDigit(localTime.tm_min) << twoDigit(localTime.tm_sec)
-                << ".data";
-
-            return res.str();
-        }
-
-        void writePrefix()
-        {
-            tm localTime = getTime();
-            m_stream << "[" << (localTime.tm_year + 1900) << "-" << twoDigit(localTime.tm_mon + 1) << "-" << twoDigit(localTime.tm_mday)
-                     << " " << twoDigit(localTime.tm_hour) << ":" << twoDigit(localTime.tm_min) << ":" << twoDigit(localTime.tm_sec)
-                     << "]";
-        }
-
-        void writeHEX(const void* data, size_t size)
-        {
-            m_stream << "(" << std::setw(4) << std::setfill(' ') << size << ") ";
-            const unsigned char* pos = static_cast<const unsigned char*>(data);
-            for (size_t i = 0; i < size; ++i)
-                m_stream << std::hex << std::setw(2) << std::setfill('0') << static_cast<unsigned int>(*pos++);
-            m_stream << std::dec << "\n";
-        }
-
-        std::string twoDigit(int value) const
-        {
-            std::string res = std::to_string(value);
-            if (res.length() < 2)
-                res = "0" + res;
-            return res;
-        }
-};
-
-} // namespace STG
-
-#endif
diff --git a/stargazer/plugins/configuration/sgconfig/parser.cpp b/stargazer/plugins/configuration/sgconfig/parser.cpp
deleted file mode 100644 (file)
index 0371798..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- */
-
-#include "parser.h"
-
-#include <cstring>
-
-//-----------------------------------------------------------------------------
-//  BASE PARSER
-//-----------------------------------------------------------------------------
-int BASE_PARSER::Start(void *, const char * el, const char **)
-{
-    if (strcasecmp(el, m_tag.c_str()) == 0)
-        return 0;
-
-    return -1;
-}
-//-----------------------------------------------------------------------------
-int BASE_PARSER::End(void *, const char * el)
-{
-    if (m_depth < 2)
-    {
-        if (strcasecmp(el, m_tag.c_str()) != 0)
-            return -1;
-        CreateAnswer();
-    }
-
-    --m_depth;
-    return 0;
-}
diff --git a/stargazer/plugins/configuration/sgconfig/parser.h b/stargazer/plugins/configuration/sgconfig/parser.h
deleted file mode 100644 (file)
index 5dd339b..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- */
-
-#pragma once
-
-#include <string>
-#include <map>
-
-namespace STG
-{
-struct Admin;
-}
-
-class BASE_PARSER
-{
-    public:
-        struct FACTORY
-        {
-            virtual ~FACTORY() {}
-            virtual BASE_PARSER * create(const STG::Admin & admin) = 0;
-        };
-        typedef std::map<std::string, FACTORY *> REGISTRY;
-
-        BASE_PARSER(const STG::Admin & admin, const std::string & t)
-            : m_currAdmin(admin),
-              m_depth(0),
-              m_tag(t)
-        {}
-        virtual ~BASE_PARSER() {}
-        virtual int Start(void * data, const char * el, const char ** attr);
-        virtual int End(void * data, const char * el);
-
-        const std::string & GetAnswer() const { return m_answer; }
-        const std::string & GetTag() const { return m_tag; }
-        std::string GetOpenTag() const { return "<" + m_tag + ">"; }
-        std::string GetCloseTag() const { return "</" + m_tag + ">"; }
-
-    protected:
-        BASE_PARSER(const BASE_PARSER & rvalue);
-        BASE_PARSER & operator=(const BASE_PARSER & rvalue);
-
-        const STG::Admin & m_currAdmin;
-        size_t        m_depth;
-        std::string   m_answer;
-        std::string   m_tag;
-
-    private:
-        virtual void CreateAnswer() = 0;
-};
diff --git a/stargazer/plugins/configuration/sgconfig/parser_admins.cpp b/stargazer/plugins/configuration/sgconfig/parser_admins.cpp
deleted file mode 100644 (file)
index bc47b7f..0000000
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#include "parser_admins.h"
-
-#include "stg/admins.h"
-#include "stg/admin.h"
-#include "stg/admin_conf.h"
-
-#include <strings.h> // strcasecmp
-
-using STG::PARSER::GET_ADMINS;
-using STG::PARSER::ADD_ADMIN;
-using STG::PARSER::DEL_ADMIN;
-using STG::PARSER::CHG_ADMIN;
-
-const char * GET_ADMINS::tag = "GetAdmins";
-const char * ADD_ADMIN::tag  = "AddAdmin";
-const char * DEL_ADMIN::tag  = "DelAdmin";
-const char * CHG_ADMIN::tag  = "ChgAdmin";
-
-void GET_ADMINS::CreateAnswer()
-{
-    const auto& priv = m_currAdmin.priv();
-    if (!priv.adminChg)
-    {
-        m_answer = "<Error Result=\"Error. Access denied.\"/>";
-        return;
-    }
-
-    m_answer = "<Admins>";
-    m_admins.fmap([this](const Admin& admin)
-                  {
-                      const unsigned int p = (admin.priv().userStat << 0) +
-                                             (admin.priv().userConf << 2) +
-                                             (admin.priv().userCash << 4) +
-                                             (admin.priv().userPasswd << 6) +
-                                             (admin.priv().userAddDel << 8) +
-                                             (admin.priv().adminChg << 10) +
-                                             (admin.priv().tariffChg << 12);
-                      m_answer += "<admin login=\"" + admin.login() + "\" priv=\"" + std::to_string(p) + "\"/>";
-                  });
-    m_answer += "</Admins>";
-}
-
-int DEL_ADMIN::Start(void *, const char * el, const char ** attr)
-{
-    if (strcasecmp(el, m_tag.c_str()) == 0)
-    {
-        m_admin = attr[1];
-        return 0;
-    }
-    return -1;
-}
-
-void DEL_ADMIN::CreateAnswer()
-{
-    if (m_admins.del(m_admin, m_currAdmin) == 0)
-        m_answer = "<" + m_tag + " Result=\"Ok\"/>";
-    else
-        m_answer = "<" + m_tag + " Result=\"Error. " + m_admins.strError() + "\"/>";
-}
-
-int ADD_ADMIN::Start(void *, const char *el, const char **attr)
-{
-    if (strcasecmp(el, m_tag.c_str()) == 0)
-    {
-        m_admin = attr[1];
-        return 0;
-    }
-    return -1;
-}
-
-void ADD_ADMIN::CreateAnswer()
-{
-    if (m_admins.add(m_admin, m_currAdmin) == 0)
-        m_answer = "<" + m_tag + " Result=\"Ok\"/>";
-    else
-        m_answer = "<" + m_tag + " Result=\"Error. " + m_admins.strError() + "\"/>";
-}
-
-int CHG_ADMIN::Start(void *, const char * el, const char ** attr)
-{
-    if (strcasecmp(el, m_tag.c_str()) == 0)
-    {
-        for (size_t i = 0; i < 6; i += 2)
-        {
-            printfd(__FILE__, "PARSER_CHG_ADMIN::attr[%d] = %s\n", i, attr[i]);
-            if (attr[i] == NULL)
-                break;
-
-            if (strcasecmp(attr[i], "Login") == 0)
-            {
-                login = attr[i + 1];
-                continue;
-            }
-
-            if (strcasecmp(attr[i], "Priv") == 0)
-            {
-                privAsString = attr[i + 1];
-                continue;
-            }
-
-            if (strcasecmp(attr[i], "Password") == 0)
-            {
-                password = attr[i + 1];
-                continue;
-            }
-        }
-
-        return 0;
-    }
-    return -1;
-}
-
-void CHG_ADMIN::CreateAnswer()
-{
-    if (!login.empty())
-    {
-        Admin * origAdmin = NULL;
-
-        if (m_admins.find(login, &origAdmin))
-        {
-            m_answer = "<" + m_tag + " Result = \"Admin '" + login + "' is not found.\"/>";
-            return;
-        }
-
-        AdminConf conf(origAdmin->conf());
-
-        if (!password.empty())
-            conf.password = password.data();
-
-        if (!privAsString.empty())
-        {
-            int p = 0;
-            if (str2x(privAsString.data().c_str(), p) < 0)
-            {
-                m_answer = "<" + m_tag + " Result = \"Incorrect parameter Priv.\"/>";
-                return;
-            }
-
-            conf.priv = Priv(p);
-        }
-
-        if (m_admins.change(conf, m_currAdmin) != 0)
-            m_answer = "<" + m_tag + " Result = \"" + m_admins.strError() + "\"/>";
-        else
-            m_answer = "<" + m_tag + " Result = \"Ok\"/>";
-    }
-    else
-        m_answer = "<" + m_tag + " Result = \"Incorrect parameter login.\"/>";
-}
diff --git a/stargazer/plugins/configuration/sgconfig/parser_admins.h b/stargazer/plugins/configuration/sgconfig/parser_admins.h
deleted file mode 100644 (file)
index 423ac3c..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#pragma once
-
-#include "parser.h"
-
-#include "stg/common.h"
-#include "stg/optional.h"
-
-#include <string>
-
-namespace STG
-{
-
-struct Admins;
-struct Admin;
-
-namespace PARSER
-{
-
-class GET_ADMINS: public BASE_PARSER
-{
-    public:
-        class FACTORY : public BASE_PARSER::FACTORY
-        {
-            public:
-                explicit FACTORY(const Admins & admins) : m_admins(admins) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new GET_ADMINS(admin, m_admins); }
-                static void Register(REGISTRY & registry, const Admins & admins)
-                { registry[ToLower(tag)] = new FACTORY(admins); }
-            private:
-                const Admins & m_admins;
-        };
-
-        static const char * tag;
-
-        GET_ADMINS(const Admin & admin, const Admins & admins)
-            : BASE_PARSER(admin, tag), m_admins(admins) {}
-
-    private:
-        const Admins & m_admins;
-
-        void CreateAnswer();
-};
-
-class ADD_ADMIN: public BASE_PARSER
-{
-    public:
-        class FACTORY : public BASE_PARSER::FACTORY
-        {
-            public:
-                explicit FACTORY(Admins & admins) : m_admins(admins) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new ADD_ADMIN(admin, m_admins); }
-                static void Register(REGISTRY & registry, Admins & admins)
-                { registry[ToLower(tag)] = new FACTORY(admins); }
-            private:
-                Admins & m_admins;
-        };
-
-        static const char * tag;
-
-        ADD_ADMIN(const Admin & admin, Admins & admins)
-            : BASE_PARSER(admin, tag), m_admins(admins) {}
-        int Start(void * data, const char * el, const char ** attr);
-
-    private:
-        std::string m_admin;
-        Admins & m_admins;
-
-        void CreateAnswer();
-};
-
-class DEL_ADMIN: public BASE_PARSER
-{
-    public:
-        class FACTORY : public BASE_PARSER::FACTORY
-        {
-            public:
-                explicit FACTORY(Admins & admins) : m_admins(admins) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new DEL_ADMIN(admin, m_admins); }
-                static void Register(REGISTRY & registry, Admins & admins)
-                { registry[ToLower(tag)] = new FACTORY(admins); }
-            private:
-                Admins & m_admins;
-        };
-
-        static const char * tag;
-
-        DEL_ADMIN(const Admin & admin, Admins & admins)
-            : BASE_PARSER(admin, tag), m_admins(admins) {}
-        int Start(void * data, const char * el, const char ** attr);
-
-    private:
-        std::string m_admin;
-        Admins & m_admins;
-
-        void CreateAnswer();
-};
-
-class CHG_ADMIN: public BASE_PARSER
-{
-    public:
-        class FACTORY : public BASE_PARSER::FACTORY
-        {
-            public:
-                explicit FACTORY(Admins & admins) : m_admins(admins) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new CHG_ADMIN(admin, m_admins); }
-                static void Register(REGISTRY & registry, Admins & admins)
-                { registry[ToLower(tag)] = new FACTORY(admins); }
-            private:
-                Admins & m_admins;
-        };
-
-        static const char * tag;
-
-        CHG_ADMIN(const Admin & admin, Admins & admins)
-            : BASE_PARSER(admin, tag), m_admins(admins) {}
-        int Start(void * data, const char * el, const char ** attr);
-
-    private:
-        std::string login;
-        Optional<std::string> password;
-        Optional<std::string> privAsString;
-        Admins & m_admins;
-
-        void CreateAnswer();
-};
-
-} // namespace PARSER
-} // namespace STG
diff --git a/stargazer/plugins/configuration/sgconfig/parser_auth_by.cpp b/stargazer/plugins/configuration/sgconfig/parser_auth_by.cpp
deleted file mode 100644 (file)
index 7e38a11..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#include "parser_auth_by.h"
-
-#include "stg/users.h"
-#include "stg/user.h"
-
-#include <cstring>
-
-using STG::PARSER::AUTH_BY;
-
-const char * AUTH_BY::tag = "GetUserAuthBy";
-
-int AUTH_BY::Start(void * /*data*/, const char *el, const char **attr)
-{
-    if (strcasecmp(el, m_tag.c_str()) != 0)
-        return -1;
-
-    if (!attr[1])
-        return -1;
-
-    m_login = attr[1];
-    return 0;
-}
-
-void AUTH_BY::CreateAnswer()
-{
-    using ConstUserPtr = const User*;
-    ConstUserPtr u;
-    if (m_users.FindByName(m_login, &u))
-    {
-        m_answer = "<AuthorizedBy result=\"error\" reason=\"User not found.\"/>";
-        return;
-    }
-
-    m_answer = "<AuthorizedBy result=\"ok\">";
-    std::vector<std::string> list(u->GetAuthorizers());
-    for (std::vector<std::string>::const_iterator it = list.begin(); it != list.end(); ++it)
-        m_answer += "<Auth name=\"" + *it + "\"/>";
-    m_answer += "</AuthorizedBy>";
-}
diff --git a/stargazer/plugins/configuration/sgconfig/parser_auth_by.h b/stargazer/plugins/configuration/sgconfig/parser_auth_by.h
deleted file mode 100644 (file)
index 5016474..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#pragma once
-
-#include "parser.h"
-
-#include "stg/common.h"
-
-#include <string>
-
-namespace STG
-{
-
-struct Admin;
-struct Users;
-
-namespace PARSER
-{
-
-class AUTH_BY : public BASE_PARSER
-{
-    public:
-        class FACTORY : public BASE_PARSER::FACTORY
-        {
-            public:
-                explicit FACTORY(const Users & users) : m_users(users) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new AUTH_BY(admin, m_users); }
-                static void Register(REGISTRY & registry, const Users & users)
-                { registry[ToLower(tag)] = new FACTORY(users); }
-            private:
-                const Users & m_users;
-        };
-
-        static const char * tag;
-
-        AUTH_BY(const Admin & admin, const Users & users)
-            : BASE_PARSER(admin, tag), m_users(users) {}
-        int Start(void * data, const char * el, const char ** attr);
-
-    private:
-        const Users & m_users;
-        std::string m_login;
-
-        void CreateAnswer();
-};
-
-} // namespace PARSER
-} // namespace STG
diff --git a/stargazer/plugins/configuration/sgconfig/parser_message.cpp b/stargazer/plugins/configuration/sgconfig/parser_message.cpp
deleted file mode 100644 (file)
index b460799..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#include "parser_message.h"
-
-#include "stg/users.h"
-#include "stg/user.h"
-
-#include <cstring>
-
-extern volatile time_t stgTime; // So sad...
-
-using STG::PARSER::SEND_MESSAGE;
-
-const char * SEND_MESSAGE::tag = "Message";
-
-int SEND_MESSAGE::Start(void *, const char *el, const char **attr)
-{
-    if (strcasecmp(el, m_tag.c_str()) != 0)
-        return -1;
-
-    for (size_t i = 0; i < 14; i++)
-        if (attr[i] == NULL)
-        {
-            m_result = res_params_error;
-            CreateAnswer();
-            printfd(__FILE__, "To few parameters\n");
-            return 0;
-        }
-
-    for (size_t i = 0; i < 14; i += 2)
-    {
-        if (strcasecmp(attr[i], "login") == 0)
-            ParseLogins(attr[i + 1]);
-
-        if (strcasecmp(attr[i], "MsgVer") == 0)
-        {
-            str2x(attr[i + 1], m_msg.header.ver);
-            if (m_msg.header.ver != 1)
-                m_result = res_params_error;
-        }
-
-        if (strcasecmp(attr[i], "MsgType") == 0)
-        {
-            str2x(attr[i + 1], m_msg.header.type);
-            if (m_msg.header.type != 1)
-                m_result = res_params_error;
-        }
-
-        if (strcasecmp(attr[i], "Repeat") == 0)
-        {
-            str2x(attr[i + 1], m_msg.header.repeat);
-            if (m_msg.header.repeat < 0)
-                m_result = res_params_error;
-        }
-
-        if (strcasecmp(attr[i], "RepeatPeriod") == 0)
-            str2x(attr[i + 1], m_msg.header.repeatPeriod);
-
-        if (strcasecmp(attr[i], "ShowTime") == 0)
-            str2x(attr[i + 1], m_msg.header.showTime);
-
-        if (strcasecmp(attr[i], "Text") == 0)
-        {
-            Decode21str(m_msg.text, attr[i + 1]);
-            m_result = res_ok;
-        }
-    }
-    return 0;
-}
-
-int SEND_MESSAGE::End(void *, const char *el)
-{
-    if (strcasecmp(el, m_tag.c_str()) != 0)
-        return -1;
-
-    m_result = res_unknown;
-    for (unsigned i = 0; i < m_logins.size(); i++)
-    {
-        if (m_users.FindByName(m_logins[i], &m_user))
-        {
-            printfd(__FILE__, "User not found. %s\n", m_logins[i].c_str());
-            continue;
-        }
-        m_msg.header.creationTime = static_cast<unsigned int>(stgTime);
-        m_user->AddMessage(&m_msg);
-        m_result = res_ok;
-    }
-    CreateAnswer();
-    return 0;
-}
-
-int SEND_MESSAGE::ParseLogins(const char * login)
-{
-    char * p;
-    char * l = new char[strlen(login) + 1];
-    strcpy(l, login);
-    p = strtok(l, ":");
-    m_logins.clear();
-    while (p)
-    {
-        m_logins.push_back(p);
-        p = strtok(NULL, ":");
-    }
-
-    delete[] l;
-    return 0;
-}
-
-void SEND_MESSAGE::CreateAnswer()
-{
-    switch (m_result)
-    {
-        case res_ok:
-            m_answer = "<SendMessageResult value=\"ok\"/>";
-            break;
-        case res_params_error:
-            m_answer = "<SendMessageResult value=\"Parameters error.\"/>";
-            break;
-        case res_unknown:
-            m_answer = "<SendMessageResult value=\"Unknown user.\"/>";
-            break;
-    }
-}
diff --git a/stargazer/plugins/configuration/sgconfig/parser_message.h b/stargazer/plugins/configuration/sgconfig/parser_message.h
deleted file mode 100644 (file)
index 3f75993..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#pragma once
-
-#include "parser.h"
-
-#include "stg/message.h"
-#include "stg/common.h"
-
-#include <vector>
-#include <string>
-
-namespace STG
-{
-
-struct Users;
-struct User;
-
-namespace PARSER
-{
-
-class SEND_MESSAGE: public BASE_PARSER
-{
-    public:
-        class FACTORY : public BASE_PARSER::FACTORY
-        {
-            public:
-                explicit FACTORY(Users & users) : m_users(users) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new SEND_MESSAGE(admin, m_users); }
-                static void Register(REGISTRY & registry, Users & users)
-                { registry[ToLower(tag)] = new FACTORY(users); }
-            private:
-                Users & m_users;
-        };
-
-        static const char * tag;
-
-        SEND_MESSAGE(const Admin & admin, Users & users)
-            : BASE_PARSER(admin, tag), m_users(users), m_result(res_ok), m_user(NULL) {}
-        int Start(void *data, const char *el, const char **attr);
-        int End(void *data, const char *el);
-
-    private:
-        Users & m_users;
-        std::vector<std::string> m_logins;
-        enum { res_ok, res_params_error, res_unknown } m_result;
-        STG::Message m_msg;
-        User * m_user;
-
-        int ParseLogins(const char * logins);
-        void CreateAnswer();
-};
-
-} // namespace PARSER
-} // namespace STG
diff --git a/stargazer/plugins/configuration/sgconfig/parser_server_info.cpp b/stargazer/plugins/configuration/sgconfig/parser_server_info.cpp
deleted file mode 100644 (file)
index 1b47d57..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#include "parser_server_info.h"
-
-#include "stg/settings.h"
-#include "stg/users.h"
-#include "stg/tariffs.h"
-#include "stg/version.h"
-#include "stg/const.h"
-
-#include <string>
-#include <cstring>
-
-#include <sys/utsname.h>
-
-using STG::PARSER::GET_SERVER_INFO;
-
-const char * GET_SERVER_INFO::tag = "GetServerInfo";
-
-void GET_SERVER_INFO::CreateAnswer()
-{
-    struct utsname utsn;
-    uname(&utsn);
-
-    std::string name = std::string(utsn.sysname) + " " +
-                       utsn.release + " " +
-                       utsn.machine + " " +
-                       utsn.nodename;
-
-    m_answer = std::string("<ServerInfo><version value=\"") + SERVER_VERSION + "\"/>" +
-               "<tariff_num value=\"" + std::to_string(m_tariffs.Count()) + "\"/>" +
-               "<tariff value=\"2\"/>" +
-               "<user_num value=\"" + std::to_string(m_users.Count()) + "\"/>" +
-               "<uname value=\"" + name + "\"/>" +
-               "<dir_num value=\"" + std::to_string(DIR_NUM) + "\"/>" +
-               "<day_fee value=\"" + std::to_string(m_settings.GetDayFee()) + "\"/>";
-
-    for (size_t i = 0; i< DIR_NUM; i++)
-        m_answer += "<dir_name_" + std::to_string(i) + " value=\"" + Encode12str(m_settings.GetDirName(i)) + "\"/>";
-
-    m_answer += "</ServerInfo>";
-}
diff --git a/stargazer/plugins/configuration/sgconfig/parser_server_info.h b/stargazer/plugins/configuration/sgconfig/parser_server_info.h
deleted file mode 100644 (file)
index fad2412..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#pragma once
-
-#include "parser.h"
-
-#include "stg/common.h"
-
-namespace STG
-{
-
-struct Admin;
-struct Settings;
-struct Users;
-struct Tariffs;
-
-namespace PARSER
-{
-
-class GET_SERVER_INFO: public BASE_PARSER {
-    public:
-        class FACTORY : public BASE_PARSER::FACTORY
-        {
-            public:
-                FACTORY(const Settings & settings, const Users & users, const Tariffs & tariffs)
-                    : m_settings(settings), m_users(users), m_tariffs(tariffs) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new GET_SERVER_INFO(admin, m_settings, m_users, m_tariffs); }
-                static void Register(REGISTRY & registry, const Settings & settings, const Users & users, const Tariffs & tariffs)
-                { registry[ToLower(tag)] = new FACTORY(settings, users, tariffs); }
-            private:
-                const Settings & m_settings;
-                const Users & m_users;
-                const Tariffs & m_tariffs;
-        };
-
-        static const char * tag;
-
-        GET_SERVER_INFO(const Admin & admin,
-                        const Settings & settings,
-                        const Users & users,
-                        const Tariffs & tariffs)
-            : BASE_PARSER(admin, tag),
-              m_settings(settings),
-              m_users(users),
-              m_tariffs(tariffs)
-        {}
-
-    private:
-        const Settings & m_settings;
-        const Users & m_users;
-        const Tariffs & m_tariffs;
-
-        void CreateAnswer();
-};
-
-}
-}
diff --git a/stargazer/plugins/configuration/sgconfig/parser_services.cpp b/stargazer/plugins/configuration/sgconfig/parser_services.cpp
deleted file mode 100644 (file)
index 118d819..0000000
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#include "parser_services.h"
-
-#include "stg/services.h"
-
-#include <strings.h> // strcasecmp
-
-using STG::PARSER::GET_SERVICES;
-using STG::PARSER::GET_SERVICE;
-using STG::PARSER::ADD_SERVICE;
-using STG::PARSER::DEL_SERVICE;
-using STG::PARSER::CHG_SERVICE;
-
-const char * GET_SERVICES::tag = "GetServices";
-const char * GET_SERVICE::tag  = "AddService";
-const char * ADD_SERVICE::tag  = "AddService";
-const char * DEL_SERVICE::tag  = "DelService";
-const char * CHG_SERVICE::tag  = "SetService";
-
-void GET_SERVICES::CreateAnswer()
-{
-    // TODO: no priviledges implemented yet
-    /*const PRIV * priv = m_currAdmin.GetPriv();
-    if (!priv->serviceChg)
-    {
-        m_answer = "<Error Result=\"Error. Access denied.\"/>";
-        return;
-    }*/
-
-    m_answer = "<Services>";
-    ServiceConf conf;
-    int h = m_services.OpenSearch();
-    while (m_services.SearchNext(h, &conf) == 0)
-    {
-        m_answer += "<Service name=\"" + conf.name +
-                    "\" comment=\"" + Encode12str(conf.comment) +
-                    "\" cost=\"" + std::to_string(conf.cost) +
-                    "\" payDay=\"" + std::to_string(conf.payDay) + "\"/>";
-    }
-    m_services.CloseSearch(h);
-    m_answer += "</Services>";
-}
-
-int GET_SERVICE::Start(void *, const char * el, const char ** attr)
-{
-    if (strcasecmp(el, m_tag.c_str()) == 0)
-    {
-        m_name = attr[1];
-        return 0;
-    }
-    return -1;
-}
-
-void GET_SERVICE::CreateAnswer()
-{
-    // TODO: no priviledges implemented yet
-    /*const PRIV * priv = m_currAdmin.GetPriv();
-    if (!priv->serviceChg)
-    {
-        m_answer = "<Error Result=\"Error. Access denied.\"/>";
-        return;
-    }*/
-
-    ServiceConf conf;
-    if (!m_services.Find(m_name, &conf))
-        m_answer = "<Error result=\"Service '" + m_name + "' does not exist.\"/>";
-    else
-        m_answer += "<" + m_tag + " name=\"" + conf.name +
-                    "\" comment=\"" + Encode12str(conf.comment) +
-                    "\" cost=\"" + std::to_string(conf.cost) +
-                    "\" payDay=\"" + std::to_string(conf.payDay) + "\"/>";
-}
-
-int ADD_SERVICE::Start(void *, const char * el, const char ** attr)
-{
-    if (strcasecmp(el, m_tag.c_str()) == 0)
-    {
-        m_name = attr[1];
-        return 0;
-    }
-    return -1;
-}
-
-void ADD_SERVICE::CreateAnswer()
-{
-    ServiceConf conf(m_name);
-    if (m_services.Add(conf, &m_currAdmin) == 0)
-        m_answer = "<" + m_tag + " result=\"Ok\"/>";
-    else
-        m_answer = "<" + m_tag + " result=\"" + m_services.GetStrError() + "\"/>";
-}
-
-int DEL_SERVICE::Start(void *, const char * el, const char ** attr)
-{
-    if (strcasecmp(el, m_tag.c_str()) == 0)
-    {
-        m_name = attr[1];
-        return 0;
-    }
-    return -1;
-}
-
-void DEL_SERVICE::CreateAnswer()
-{
-    if (m_services.Del(m_name, &m_currAdmin) == 0)
-        m_answer = "<" + m_tag + " result=\"Ok\"/>";
-    else
-        m_answer = "<" + m_tag + " result=\"" + m_services.GetStrError() + "\"/>";
-}
-
-int CHG_SERVICE::Start(void *, const char * el, const char ** attr)
-{
-    if (strcasecmp(el, m_tag.c_str()) == 0)
-    {
-        for (size_t i = 0; i < 8; i += 2)
-        {
-            if (attr[i] == NULL)
-                break;
-
-            if (strcasecmp(attr[i], "name") == 0)
-            {
-                m_service.name = attr[i + 1];
-                continue;
-            }
-
-            if (strcasecmp(attr[i], "comment") == 0)
-            {
-                m_service.comment = Decode21str(attr[i + 1]);
-                continue;
-            }
-
-            if (strcasecmp(attr[i], "cost") == 0)
-            {
-                double cost = 0;
-                if (str2x(attr[i + 1], cost) == 0)
-                    m_service.cost = cost;
-                else
-                    printfd(__FILE__, "Bad cast from '%s' to double\n", attr[i + 1]);
-                // TODO: log it
-                continue;
-            }
-
-            if (strcasecmp(attr[i], "payDay") == 0)
-            {
-                unsigned payDay;
-                if (str2x(attr[i + 1], payDay) == 0)
-                    m_service.payDay = payDay;
-                else
-                    printfd(__FILE__, "Bad cast from '%s' to unsigned\n", attr[i + 1]);
-                // TODO: log it
-                continue;
-            }
-        }
-
-        return 0;
-    }
-    return -1;
-}
-
-void CHG_SERVICE::CreateAnswer()
-{
-    if (m_service.name.empty())
-    {
-        m_answer = "<" + m_tag + " result=\"Empty service name.\"/>";
-        return;
-    }
-
-    if (!m_services.Exists(m_service.name.const_data()))
-    {
-        m_answer = "<" + m_tag + " result = \"Service '" + m_service.name.const_data() + "' does not exist.\"/>";
-        return;
-    }
-
-    ServiceConf orig;
-    m_services.Find(m_service.name.const_data(), &orig);
-
-    ServiceConfOpt conf(orig);
-    conf.splice(m_service);
-
-    if (m_services.Change(conf.get({}), &m_currAdmin) != 0)
-        m_answer = "<" + m_tag + " result = \"" + m_services.GetStrError() + "\"/>";
-    else
-        m_answer = "<" + m_tag + " result = \"Ok\"/>";
-}
diff --git a/stargazer/plugins/configuration/sgconfig/parser_services.h b/stargazer/plugins/configuration/sgconfig/parser_services.h
deleted file mode 100644 (file)
index 6eb67e0..0000000
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#pragma once
-
-#include "parser.h"
-
-#include "stg/service_conf.h"
-
-#include "stg/common.h"
-
-#include <string>
-
-namespace STG
-{
-
-struct Services;
-
-namespace PARSER
-{
-
-class GET_SERVICES: public BASE_PARSER
-{
-    public:
-        class FACTORY : public BASE_PARSER::FACTORY
-        {
-            public:
-                FACTORY(const Services & services) : m_services(services) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new GET_SERVICES(admin, m_services); }
-                static void Register(REGISTRY & registry, const Services & services)
-                { registry[ToLower(tag)] = new FACTORY(services); }
-            private:
-                const Services & m_services;
-        };
-
-        static const char * tag;
-
-        GET_SERVICES(const Admin & admin, const Services & services)
-            : BASE_PARSER(admin, tag), m_services(services) {}
-
-    private:
-        const Services & m_services;
-
-        void CreateAnswer();
-};
-
-class GET_SERVICE: public BASE_PARSER
-{
-    public:
-        class FACTORY : public BASE_PARSER::FACTORY
-        {
-            public:
-                FACTORY(const Services & services) : m_services(services) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new GET_SERVICE(admin, m_services); }
-                static void Register(REGISTRY & registry, Services & services)
-                { registry[ToLower(tag)] = new FACTORY(services); }
-            private:
-                const Services & m_services;
-        };
-
-        static const char * tag;
-
-        GET_SERVICE(const Admin & admin, const Services & services)
-            : BASE_PARSER(admin, tag), m_services(services) {}
-        int Start(void * data, const char * el, const char ** attr);
-
-    private:
-        std::string m_name;
-        const Services & m_services;
-
-        void CreateAnswer();
-};
-
-class ADD_SERVICE: public BASE_PARSER
-{
-    public:
-        class FACTORY : public BASE_PARSER::FACTORY
-        {
-            public:
-                FACTORY(Services & services) : m_services(services) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new ADD_SERVICE(admin, m_services); }
-                static void Register(REGISTRY & registry, Services & services)
-                { registry[ToLower(tag)] = new FACTORY(services); }
-            private:
-                Services & m_services;
-        };
-
-        static const char * tag;
-
-        ADD_SERVICE(const Admin & admin, Services & services)
-            : BASE_PARSER(admin, tag), m_services(services) {}
-        int Start(void * data, const char * el, const char ** attr);
-
-    private:
-        std::string m_name;
-        Services & m_services;
-
-        void CreateAnswer();
-};
-
-class DEL_SERVICE: public BASE_PARSER
-{
-    public:
-        class FACTORY : public BASE_PARSER::FACTORY
-        {
-            public:
-                FACTORY(Services & services) : m_services(services) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new DEL_SERVICE(admin, m_services); }
-                static void Register(REGISTRY & registry, Services & services)
-                { registry[ToLower(tag)] = new FACTORY(services); }
-            private:
-                Services & m_services;
-        };
-
-        static const char * tag;
-
-        DEL_SERVICE(const Admin & admin, Services & services)
-            : BASE_PARSER(admin, tag), m_services(services) {}
-        int Start(void * data, const char * el, const char ** attr);
-
-    private:
-        std::string m_name;
-        Services & m_services;
-
-        void CreateAnswer();
-};
-
-class CHG_SERVICE: public BASE_PARSER
-{
-    public:
-        class FACTORY : public BASE_PARSER::FACTORY
-        {
-            public:
-                FACTORY(Services & services) : m_services(services) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new CHG_SERVICE(admin, m_services); }
-                static void Register(REGISTRY & registry, Services & services)
-                { registry[ToLower(tag)] = new FACTORY(services); }
-            private:
-                Services & m_services;
-        };
-
-        static const char * tag;
-
-        CHG_SERVICE(const Admin & admin, Services & services)
-            : BASE_PARSER(admin, tag), m_services(services) {}
-        int Start(void * data, const char * el, const char ** attr);
-
-    private:
-        ServiceConfOpt m_service;
-        Services & m_services;
-
-        void CreateAnswer();
-};
-
-} // namespace PARSER
-} // namespace STG
diff --git a/stargazer/plugins/configuration/sgconfig/parser_tariffs.cpp b/stargazer/plugins/configuration/sgconfig/parser_tariffs.cpp
deleted file mode 100644 (file)
index 8f8e8db..0000000
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#include "parser_tariffs.h"
-
-#include "stg/tariffs.h"
-#include "stg/users.h"
-#include "stg/optional.h"
-
-#include <cstdio> // snprintf
-#include <cstring>
-
-using STG::PARSER::GET_TARIFFS;
-using STG::PARSER::ADD_TARIFF;
-using STG::PARSER::DEL_TARIFF;
-using STG::PARSER::CHG_TARIFF;
-
-const char * GET_TARIFFS::tag = "GetTariffs";
-const char * ADD_TARIFF::tag  = "AddTariff";
-const char * DEL_TARIFF::tag  = "DelTariff";
-const char * CHG_TARIFF::tag  = "SetTariff";
-
-namespace
-{
-
-const double pt_mega = 1024 * 1024;
-
-template <typename A, typename C, typename F>
-std::string AOS2String(const A & array, size_t size, const F C::* field, F multiplier)
-{
-    std::string res;
-    for (size_t i = 0; i < size; ++i)
-    {
-        if (!res.empty())
-            res += "/";
-        res += std::to_string((array[i].*field) * multiplier);
-    }
-    return res;
-}
-
-template <typename T>
-bool str2res(const std::string& source, STG::Optional<T>& dest, T divisor)
-{
-    T value = 0;
-    if (str2x(source, value))
-        return false;
-    dest = value / divisor;
-    return true;
-}
-
-template <typename A, typename C, typename F>
-bool String2AOS(const std::string & source, A & array, size_t size, STG::Optional<F> C::* field, F divisor)
-{
-    size_t index = 0;
-    std::string::size_type from = 0;
-    std::string::size_type pos = 0;
-    while (index < size && (pos = source.find('/', from)) != std::string::npos)
-    {
-        if (!str2res(source.substr(from, pos - from), array[index].*field, divisor))
-            return false;
-        from = pos + 1;
-        ++index;
-    }
-    if (str2res(source.substr(from), array[index].*field, divisor))
-        return false;
-    return true;
-}
-
-}
-
-void GET_TARIFFS::CreateAnswer()
-{
-    m_answer = "<Tariffs>";
-
-    std::vector<TariffData> dataList;
-    m_tariffs.GetTariffsData(&dataList);
-    auto it = dataList.begin();
-    for (; it != dataList.end(); ++it)
-        {
-        m_answer += "<tariff name=\"" + it->tariffConf.name + "\">";
-
-        for (size_t i = 0; i < DIR_NUM; i++)
-            m_answer += "<Time" + std::to_string(i) + " value=\"" +
-                std::to_string(it->dirPrice[i].hDay)   + ":" + std::to_string(it->dirPrice[i].mDay)   + "-" +
-                std::to_string(it->dirPrice[i].hNight) + ":" + std::to_string(it->dirPrice[i].mNight) + "\"/>";
-
-        m_answer += "<PriceDayA value=\"" + AOS2String(it->dirPrice, DIR_NUM, &DirPriceData::priceDayA, pt_mega) + "\"/>" +
-                  "<PriceDayB value=\"" + AOS2String(it->dirPrice, DIR_NUM, &DirPriceData::priceDayB, pt_mega) + "\"/>" +
-                  "<PriceNightA value=\"" + AOS2String(it->dirPrice, DIR_NUM, &DirPriceData::priceNightA, pt_mega) + "\"/>" +
-                  "<PriceNightB value=\"" + AOS2String(it->dirPrice, DIR_NUM, &DirPriceData::priceNightB, pt_mega) + "\"/>" +
-                  "<Threshold value=\"" + AOS2String(it->dirPrice, DIR_NUM, &DirPriceData::threshold, 1) + "\"/>" +
-                  "<SinglePrice value=\"" + AOS2String(it->dirPrice, DIR_NUM, &DirPriceData::singlePrice, 1) + "\"/>" +
-                  "<NoDiscount value=\"" + AOS2String(it->dirPrice, DIR_NUM, &DirPriceData::noDiscount, 1) + "\"/>" +
-                  "<Fee value=\"" + std::to_string(it->tariffConf.fee) + "\"/>" +
-                  "<PassiveCost value=\"" + std::to_string(it->tariffConf.passiveCost) + "\"/>" +
-                  "<Free value=\"" + std::to_string(it->tariffConf.free) + "\"/>" +
-                  "<TraffType value=\"" + Tariff::toString(it->tariffConf.traffType) + "\"/>" +
-                  "<Period value=\"" + Tariff::toString(it->tariffConf.period) + "\"/>" +
-                  "<ChangePolicy value=\"" + Tariff::toString(it->tariffConf.changePolicy) + "\"/>" +
-                  "<ChangePolicyTimeout value=\"" + std::to_string(it->tariffConf.changePolicyTimeout) + "\"/>" +
-                  "</tariff>";
-        }
-
-    m_answer += "</Tariffs>";
-}
-
-int ADD_TARIFF::Start(void *, const char * el, const char ** attr)
-{
-    if (strcasecmp(el, m_tag.c_str()) != 0)
-        return -1;
-
-    if (attr[1] == NULL)
-        return -1;
-
-    tariff = attr[1];
-    return 0;
-}
-
-void ADD_TARIFF::CreateAnswer()
-{
-    if (m_tariffs.Add(tariff, &m_currAdmin) == 0)
-        m_answer = "<" + m_tag + " Result=\"Ok\"/>";
-    else
-        m_answer = "<" + m_tag + " Result=\"Error. " + m_tariffs.GetStrError() + "\"/>";
-}
-
-int DEL_TARIFF::Start(void *, const char * el, const char ** attr)
-{
-    if (strcasecmp(el, m_tag.c_str()) != 0)
-        return -1;
-
-    if (attr[1] == NULL)
-        return -1;
-
-    tariff = attr[1];
-    return 0;
-}
-
-void DEL_TARIFF::CreateAnswer()
-{
-    if (m_users.TariffInUse(tariff))
-        m_answer = "<" + m_tag + " Result=\"Error. Tariff \'" + tariff + "\' cannot be deleted, it is in use.\"/>";
-    else if (m_tariffs.Del(tariff, &m_currAdmin) == 0)
-        m_answer = "<" + m_tag + " Result=\"Ok\"/>";
-    else
-        m_answer = "<" + m_tag + " Result=\"Error. " + m_tariffs.GetStrError() + "\"/>";
-}
-
-int CHG_TARIFF::Start(void *, const char * el, const char ** attr)
-{
-    m_depth++;
-
-    if (m_depth == 1)
-    {
-        if (strcasecmp(el, m_tag.c_str()) == 0)
-        {
-            const auto tariff = m_tariffs.FindByName(attr[1]);
-            if (tariff != NULL)
-                td = tariff->GetTariffData();
-            else
-                return -1;
-            return 0;
-        }
-    }
-    else
-    {
-        if (strcasecmp(el, "PriceDayA") == 0)
-        {
-            if (!String2AOS(attr[1], td.dirPrice, DIR_NUM, &DirPriceDataOpt::priceDayA, pt_mega))
-                return -1; // TODO: log it
-            else
-                return 0;
-        }
-
-        if (strcasecmp(el, "PriceDayB") == 0)
-        {
-            if (!String2AOS(attr[1], td.dirPrice, DIR_NUM, &DirPriceDataOpt::priceDayB, pt_mega))
-                return -1; // TODO: log it
-            else
-                return 0;
-        }
-
-        if (strcasecmp(el, "PriceNightA") == 0)
-        {
-            if (!String2AOS(attr[1], td.dirPrice, DIR_NUM, &DirPriceDataOpt::priceNightA, pt_mega))
-                return -1; // TODO: log it
-            else
-                return 0;
-        }
-
-        if (strcasecmp(el, "PriceNightB") == 0)
-        {
-            if (!String2AOS(attr[1], td.dirPrice, DIR_NUM, &DirPriceDataOpt::priceNightB, pt_mega))
-                return -1; // TODO: log it
-            else
-                return 0;
-        }
-
-        if (strcasecmp(el, "Threshold") == 0)
-        {
-            if (!String2AOS(attr[1], td.dirPrice, DIR_NUM, &DirPriceDataOpt::threshold, 1))
-                return -1; // TODO: log it
-            else
-                return 0;
-        }
-
-        if (strcasecmp(el, "SinglePrice") == 0)
-        {
-            if (!String2AOS(attr[1], td.dirPrice, DIR_NUM, &DirPriceDataOpt::singlePrice, 1))
-                return -1; // TODO: log it
-            else
-                return 0;
-        }
-
-        if (strcasecmp(el, "NoDiscount") == 0)
-        {
-            if (!String2AOS(attr[1], td.dirPrice, DIR_NUM, &DirPriceDataOpt::noDiscount, 1))
-                return -1; // TODO: log it
-            else
-                return 0;
-        }
-
-        for (int j = 0; j < DIR_NUM; j++)
-        {
-            char st[50];
-            snprintf(st, 50, "Time%d", j);
-            if (strcasecmp(el, st) == 0)
-            {
-                int h1 = 0;
-                int m1 = 0;
-                int h2 = 0;
-                int m2 = 0;
-                if (ParseTariffTimeStr(attr[1], h1, m1, h2, m2) == 0)
-                    {
-                    td.dirPrice[j].hDay = h1;
-                    td.dirPrice[j].mDay = m1;
-                    td.dirPrice[j].hNight = h2;
-                    td.dirPrice[j].mNight = m2;
-                    }
-                return 0;
-            }
-        }
-
-        if (strcasecmp(el, "Fee") == 0)
-        {
-            double fee;
-            if (strtodouble2(attr[1], fee) == 0)
-                td.tariffConf.fee = fee;
-            return 0;
-        }
-
-        if (strcasecmp(el, "PassiveCost") == 0)
-        {
-            double pc;
-            if (strtodouble2(attr[1], pc) == 0)
-                td.tariffConf.passiveCost = pc;
-            return 0;
-        }
-
-        if (strcasecmp(el, "Free") == 0)
-        {
-            double free;
-            if (strtodouble2(attr[1], free) == 0)
-                td.tariffConf.free = free;
-            return 0;
-        }
-
-        if (strcasecmp(el, "TraffType") == 0)
-        {
-            td.tariffConf.traffType = Tariff::parseTraffType(attr[1]);
-            return 0;
-        }
-
-        if (strcasecmp(el, "Period") == 0)
-        {
-            td.tariffConf.period = Tariff::parsePeriod(attr[1]);
-            return 0;
-        }
-
-        if (strcasecmp(el, "ChangePolicy") == 0)
-        {
-            td.tariffConf.changePolicy = Tariff::parseChangePolicy(attr[1]);
-            return 0;
-        }
-
-        if (strcasecmp(el, "ChangePolicyTimeout") == 0)
-        {
-            int64_t policyTime = 0;
-            if (str2x(attr[1], policyTime) == 0)
-                td.tariffConf.changePolicyTimeout = (time_t)policyTime;
-            return 0;
-        }
-    }
-    return -1;
-}
-
-void CHG_TARIFF::CreateAnswer()
-{
-    if (!td.tariffConf.name.data().empty())
-    {
-        auto tariffData = td.get({});
-        if (m_tariffs.Chg(tariffData, &m_currAdmin) == 0)
-            m_answer = "<" + m_tag + " Result=\"ok\"/>";
-        else
-            m_answer = "<" + m_tag + " Result=\"Change tariff error! " + m_tariffs.GetStrError() + "\"/>";
-    }
-    else
-        m_answer = "<" + m_tag + " Result=\"Change tariff error!\"/>";
-}
diff --git a/stargazer/plugins/configuration/sgconfig/parser_tariffs.h b/stargazer/plugins/configuration/sgconfig/parser_tariffs.h
deleted file mode 100644 (file)
index 9f9c503..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#pragma once
-
-#include "parser.h"
-
-#include "stg/tariff_conf.h"
-#include "stg/common.h"
-
-#include <string>
-
-namespace STG
-{
-
-struct Tariffs;
-struct Users;
-struct Admin;
-
-namespace PARSER
-{
-
-class GET_TARIFFS: public BASE_PARSER
-{
-    public:
-        class FACTORY : public BASE_PARSER::FACTORY
-        {
-            public:
-                explicit FACTORY(const Tariffs & tariffs) : m_tariffs(tariffs) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new GET_TARIFFS(admin, m_tariffs); }
-                static void Register(REGISTRY & registry, const Tariffs & tariffs)
-                { registry[ToLower(tag)] = new FACTORY(tariffs); }
-            private:
-                const Tariffs & m_tariffs;
-        };
-
-        static const char * tag;
-
-        GET_TARIFFS(const Admin & admin, const Tariffs & tariffs)
-            : BASE_PARSER(admin, tag), m_tariffs(tariffs) {}
-
-    private:
-        const Tariffs & m_tariffs;
-
-        void CreateAnswer();
-};
-
-class ADD_TARIFF: public BASE_PARSER
-{
-    public:
-        class FACTORY : public BASE_PARSER::FACTORY
-        {
-            public:
-                explicit FACTORY(Tariffs & tariffs) : m_tariffs(tariffs) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new ADD_TARIFF(admin, m_tariffs); }
-                static void Register(REGISTRY & registry, Tariffs & tariffs)
-                { registry[ToLower(tag)] = new FACTORY(tariffs); }
-            private:
-                Tariffs & m_tariffs;
-        };
-
-        static const char * tag;
-
-        ADD_TARIFF(const Admin & admin, Tariffs & tariffs)
-            : BASE_PARSER(admin, tag), m_tariffs(tariffs) {}
-        int Start(void * data, const char * el, const char ** attr);
-
-    private:
-        std::string tariff;
-        Tariffs & m_tariffs;
-
-        void CreateAnswer();
-};
-
-class DEL_TARIFF: public BASE_PARSER
-{
-    public:
-        class FACTORY : public BASE_PARSER::FACTORY
-        {
-            public:
-                FACTORY(Tariffs & tariffs, const Users & users) : m_tariffs(tariffs), m_users(users) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new DEL_TARIFF(admin, m_users, m_tariffs); }
-                static void Register(REGISTRY & registry, Tariffs & tariffs, const Users & users)
-                { registry[ToLower(tag)] = new FACTORY(tariffs, users); }
-            private:
-                Tariffs & m_tariffs;
-                const Users & m_users;
-        };
-
-        static const char * tag;
-
-        DEL_TARIFF(const Admin & admin, const Users & users, Tariffs & tariffs)
-            : BASE_PARSER(admin, tag), m_users(users), m_tariffs(tariffs) {}
-        int Start(void * data, const char * el, const char ** attr);
-
-    private:
-        std::string tariff;
-        const Users & m_users;
-        Tariffs & m_tariffs;
-
-        void CreateAnswer();
-};
-
-class CHG_TARIFF: public BASE_PARSER
-{
-    public:
-        class FACTORY : public BASE_PARSER::FACTORY
-        {
-            public:
-                explicit FACTORY(Tariffs & tariffs) : m_tariffs(tariffs) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new CHG_TARIFF(admin, m_tariffs); }
-                static void Register(REGISTRY & registry, Tariffs & tariffs)
-                { registry[ToLower(tag)] = new FACTORY(tariffs); }
-            private:
-                Tariffs & m_tariffs;
-        };
-
-        static const char * tag;
-
-        CHG_TARIFF(const Admin & admin, Tariffs & tariffs)
-            : BASE_PARSER(admin, tag), m_tariffs(tariffs) {}
-        int Start(void * data, const char * el, const char ** attr);
-
-    private:
-        TariffDataOpt td;
-        Tariffs & m_tariffs;
-
-        int CheckTariffData();
-        void CreateAnswer();
-};
-
-} // namespace PARSER
-} // namespace STG
diff --git a/stargazer/plugins/configuration/sgconfig/parser_user_info.cpp b/stargazer/plugins/configuration/sgconfig/parser_user_info.cpp
deleted file mode 100644 (file)
index ccc86d8..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#include "parser_user_info.h"
-
-#include "stg/users.h"
-#include "stg/user.h"
-
-#include <strings.h> // strcasecmp
-
-using STG::PARSER::USER_INFO;
-
-const char * USER_INFO::tag = "GetUserInfo";
-
-int USER_INFO::Start(void * /*data*/, const char *el, const char **attr)
-{
-    if (strcasecmp(el, m_tag.c_str()) != 0)
-        return -1;
-
-    if (!attr[1])
-        return -1;
-
-    m_login = attr[1];
-    return 0;
-}
-
-void USER_INFO::CreateAnswer()
-{
-    using ConstUserPtr = const User*;
-    ConstUserPtr u;
-    if (m_users.FindByName(m_login, &u))
-    {
-        m_answer = "<UserInfo result=\"error\"/>";
-        return;
-    }
-
-    m_answer = "<UserInfo lastAuthTime=\"" + std::to_string(u->GetAuthorizedModificationTime()) + "\"" +
-             " lastDisconnectTime=\"" + std::to_string(u->GetConnectedModificationTime()) + "\"" +
-             " connected=\"" + (u->GetConnected() ? "true" : "false") + "\"" +
-             " lastDisconnectReason=\"" + u->GetLastDisconnectReason() + "\">";
-    std::vector<std::string> list(u->GetAuthorizers());
-    for (std::vector<std::string>::const_iterator it = list.begin(); it != list.end(); ++it)
-        m_answer += "<Auth name=\"" + *it + "\"/>";
-    m_answer += "</UserInfo>";
-}
diff --git a/stargazer/plugins/configuration/sgconfig/parser_user_info.h b/stargazer/plugins/configuration/sgconfig/parser_user_info.h
deleted file mode 100644 (file)
index 50f3101..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#pragma once
-
-#include "parser.h"
-
-#include "stg/common.h"
-
-#include <string>
-
-namespace STG
-{
-
-struct Users;
-
-namespace PARSER
-{
-
-class USER_INFO : public BASE_PARSER
-{
-    public:
-        class FACTORY : public BASE_PARSER::FACTORY
-        {
-            public:
-                FACTORY(const Users & users) : m_users(users) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new USER_INFO(admin, m_users); }
-                static void Register(REGISTRY & registry, const Users & users)
-                { registry[ToLower(tag)] = new FACTORY(users); }
-            private:
-                const Users & m_users;
-        };
-
-        static const char * tag;
-
-        USER_INFO(const Admin & admin, const Users & users)
-            : BASE_PARSER(admin, tag), m_users(users) {}
-        int Start(void * data, const char * el, const char ** attr);
-
-    private:
-        const Users & m_users;
-        std::string m_login;
-
-        void CreateAnswer();
-};
-
-} // namespace PARSER
-} // namespace STG
diff --git a/stargazer/plugins/configuration/sgconfig/parser_users.cpp b/stargazer/plugins/configuration/sgconfig/parser_users.cpp
deleted file mode 100644 (file)
index bd7dd4e..0000000
+++ /dev/null
@@ -1,761 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#include "parser_users.h"
-
-#include "stg/users.h"
-#include "stg/user.h"
-#include "stg/user_conf.h"
-#include "stg/user_stat.h"
-#include "stg/tariffs.h"
-#include "stg/tariff.h"
-#include "stg/user_property.h"
-
-#include <cstdio>
-#include <cassert>
-
-using STG::PARSER::GET_USERS;
-using STG::PARSER::GET_USER;
-using STG::PARSER::ADD_USER;
-using STG::PARSER::DEL_USER;
-using STG::PARSER::CHG_USER;
-using STG::PARSER::CHECK_USER;
-
-const char * GET_USERS::tag  = "GetUsers";
-const char * GET_USER::tag   = "GetUser";
-const char * ADD_USER::tag   = "AddUser";
-const char * CHG_USER::tag   = "SetUser";
-const char * DEL_USER::tag   = "DelUser";
-const char * CHECK_USER::tag = "CheckUser";
-
-using UserPtr = STG::User*;
-using ConstUserPtr = const STG::User*;
-
-namespace
-{
-
-std::string UserToXML(const STG::User & user, bool loginInStart, bool showPass, time_t lastTime = 0)
-{
-    std::string answer;
-
-    if (loginInStart)
-        answer += "<User login=\"" + user.GetLogin() + "\" result=\"ok\">";
-    else
-        answer += "<User result=\"ok\">";
-
-    answer += "<Login value=\"" + user.GetLogin() + "\"/>";
-
-    if (user.GetProperties().password.ModificationTime() > lastTime)
-    {
-        if (showPass)
-            answer += "<Password value=\"" + user.GetProperties().password.Get() + "\" />";
-        else
-            answer += "<Password value=\"++++++\"/>";
-    }
-
-    if (user.GetProperties().cash.ModificationTime() > lastTime)
-        answer += "<Cash value=\"" + std::to_string(user.GetProperties().cash.Get()) + "\"/>";
-    if (user.GetProperties().freeMb.ModificationTime() > lastTime)
-        answer += "<FreeMb value=\"" + std::to_string(user.GetProperties().freeMb.Get()) + "\"/>";
-    if (user.GetProperties().credit.ModificationTime() > lastTime)
-        answer += "<Credit value=\"" + std::to_string(user.GetProperties().credit.Get()) + "\"/>";
-
-    if (user.GetProperties().nextTariff.Get() != "")
-    {
-        if (user.GetProperties().tariffName.ModificationTime() > lastTime ||
-            user.GetProperties().nextTariff.ModificationTime() > lastTime)
-            answer += "<Tariff value=\"" + user.GetProperties().tariffName.Get() + "/" + user.GetProperties().nextTariff.Get() + "\"/>";
-    }
-    else
-    {
-        if (user.GetProperties().tariffName.ModificationTime() > lastTime)
-            answer += "<Tariff value=\"" + user.GetProperties().tariffName.Get() + "\"/>";
-    }
-
-    if (user.GetProperties().note.ModificationTime() > lastTime)
-        answer += "<Note value=\"" + Encode12str(user.GetProperties().note) + "\"/>";
-    if (user.GetProperties().phone.ModificationTime() > lastTime)
-        answer += "<Phone value=\"" + Encode12str(user.GetProperties().phone) + "\"/>";
-    if (user.GetProperties().address.ModificationTime() > lastTime)
-        answer += "<Address value=\"" + Encode12str(user.GetProperties().address) + "\"/>";
-    if (user.GetProperties().email.ModificationTime() > lastTime)
-        answer += "<Email value=\"" + Encode12str(user.GetProperties().email) + "\"/>";
-
-    std::vector<const STG::UserPropertyLogged<std::string> *> userdata;
-    userdata.push_back(user.GetProperties().userdata0.GetPointer());
-    userdata.push_back(user.GetProperties().userdata1.GetPointer());
-    userdata.push_back(user.GetProperties().userdata2.GetPointer());
-    userdata.push_back(user.GetProperties().userdata3.GetPointer());
-    userdata.push_back(user.GetProperties().userdata4.GetPointer());
-    userdata.push_back(user.GetProperties().userdata5.GetPointer());
-    userdata.push_back(user.GetProperties().userdata6.GetPointer());
-    userdata.push_back(user.GetProperties().userdata7.GetPointer());
-    userdata.push_back(user.GetProperties().userdata8.GetPointer());
-    userdata.push_back(user.GetProperties().userdata9.GetPointer());
-
-    for (size_t i = 0; i < userdata.size(); i++)
-        if (userdata[i]->ModificationTime() > lastTime)
-            answer += "<UserData" + std::to_string(i) + " value=\"" + Encode12str(userdata[i]->Get()) + "\" />";
-
-    if (user.GetProperties().realName.ModificationTime() > lastTime)
-        answer += "<Name value=\"" + Encode12str(user.GetProperties().realName) + "\"/>";
-    if (user.GetProperties().group.ModificationTime() > lastTime)
-        answer += "<Group value=\"" + Encode12str(user.GetProperties().group) + "\"/>";
-    if (user.GetConnectedModificationTime() > lastTime)
-        answer += std::string("<Status value=\"") + (user.GetConnected() ? "1" : "0") + "\"/>";
-    if (user.GetProperties().alwaysOnline.ModificationTime() > lastTime)
-        answer += std::string("<AOnline value=\"") + (user.GetProperties().alwaysOnline.Get() ? "1" : "0") + "\"/>";
-    if (user.GetCurrIPModificationTime() > lastTime)
-        answer += "<CurrIP value=\"" + inet_ntostring(user.GetCurrIP()) + "\"/>";
-    if (user.GetPingTime() > lastTime)
-        answer += "<PingTime value=\"" + std::to_string(user.GetPingTime()) + "\"/>";
-    if (user.GetProperties().ips.ModificationTime() > lastTime)
-        answer += "<IP value=\"" + user.GetProperties().ips.Get().toString() + "\"/>";
-
-    answer += "<Traff";
-    const auto & upload(user.GetProperties().up.Get());
-    const auto & download(user.GetProperties().down.Get());
-    if (user.GetProperties().up.ModificationTime() > lastTime)
-        for (size_t j = 0; j < DIR_NUM; j++)
-            answer += " MU" + std::to_string(j) + "=\"" + std::to_string(upload[j]) + "\"";
-    if (user.GetProperties().down.ModificationTime() > lastTime)
-        for (size_t j = 0; j < DIR_NUM; j++)
-            answer += " MD" + std::to_string(j) + "=\"" + std::to_string(download[j]) + "\"";
-    if (user.GetSessionUploadModificationTime() > lastTime)
-        for (size_t j = 0; j < DIR_NUM; j++)
-            answer += " SU" + std::to_string(j) + "=\"" + std::to_string(user.GetSessionUpload()[j]) + "\"";
-    if (user.GetSessionDownloadModificationTime() > lastTime)
-        for (size_t j = 0; j < DIR_NUM; j++)
-            answer += " SD" + std::to_string(j) + "=\"" + std::to_string(user.GetSessionDownload()[j]) + "\"";
-    answer += "/>";
-
-    if (user.GetProperties().disabled.ModificationTime() > lastTime)
-        answer += std::string("<Down value=\"") + (user.GetProperties().disabled.Get() ? "1" : "0") + "\"/>";
-    if (user.GetProperties().disabledDetailStat.ModificationTime() > lastTime)
-        answer += std::string("<DisableDetailStat value=\"") + (user.GetProperties().disabledDetailStat.Get() ? "1" : "0") + "\"/>";
-    if (user.GetProperties().passive.ModificationTime() > lastTime)
-        answer += std::string("<Passive value=\"") + (user.GetProperties().passive.Get() ? "1" : "0") + "\"/>";
-    if (user.GetProperties().lastCashAdd.ModificationTime() > lastTime)
-        answer += "<LastCash value=\"" + std::to_string(user.GetProperties().lastCashAdd.Get()) + "\"/>";
-    if (user.GetProperties().lastCashAddTime.ModificationTime() > lastTime)
-        answer += "<LastTimeCash value=\"" + std::to_string(user.GetProperties().lastCashAddTime.Get()) + "\"/>";
-    if (user.GetProperties().lastActivityTime.ModificationTime() > lastTime)
-        answer += "<LastActivityTime value=\"" + std::to_string(user.GetProperties().lastActivityTime.Get()) + "\"/>";
-    if (user.GetProperties().creditExpire.ModificationTime() > lastTime)
-        answer += "<CreditExpire value=\"" + std::to_string(user.GetProperties().creditExpire.Get()) + "\"/>";
-
-    if (lastTime == 0)
-    {
-        answer += "<AuthorizedBy>";
-        std::vector<std::string> list(user.GetAuthorizers());
-        for (std::vector<std::string>::const_iterator it = list.begin(); it != list.end(); ++it)
-            answer += "<Auth name=\"" + *it + "\"/>";
-        answer += "</AuthorizedBy>";
-    }
-
-    answer += "</User>";
-
-    return answer;
-}
-
-} // namespace anonymous
-
-int GET_USERS::Start(void *, const char * el, const char ** attr)
-{
-    if (strcasecmp(el, m_tag.c_str()) != 0)
-    {
-        printfd(__FILE__, "Got wrong tag: '%s' instead of '%s'\n", el, m_tag.c_str());
-        return -1;
-    }
-
-    while (attr && *attr && *(attr + 1))
-    {
-        if (strcasecmp(*attr, "LastUpdate") == 0)
-            str2x(*(attr + 1), m_lastUserUpdateTime);
-        ++attr;
-    }
-
-    return 0;
-}
-
-void GET_USERS::CreateAnswer()
-{
-    int h = m_users.OpenSearch();
-    assert(h);
-
-    if (m_lastUserUpdateTime > 0)
-        m_answer = "<Users LastUpdate=\"" + std::to_string(time(NULL)) + "\">";
-    else
-        m_answer = "<Users>";
-
-    UserPtr u;
-
-    while (m_users.SearchNext(h, &u) == 0)
-        m_answer += UserToXML(*u, true, m_currAdmin.priv().userConf || m_currAdmin.priv().userPasswd, m_lastUserUpdateTime);
-
-    m_users.CloseSearch(h);
-
-    m_answer += "</Users>";
-}
-
-int GET_USER::Start(void *, const char * el, const char ** attr)
-{
-    if (strcasecmp(el, m_tag.c_str()) != 0)
-        return -1;
-
-    if (attr[1] == NULL)
-        return -1;
-
-    m_login = attr[1];
-    return 0;
-}
-
-void GET_USER::CreateAnswer()
-{
-    ConstUserPtr u;
-
-    if (m_users.FindByName(m_login, &u))
-        m_answer = "<User result=\"error\" reason=\"User not found.\"/>";
-    else
-        m_answer = UserToXML(*u, false, m_currAdmin.priv().userConf || m_currAdmin.priv().userPasswd);
-}
-
-int ADD_USER::Start(void *, const char * el, const char ** attr)
-{
-    m_depth++;
-
-    if (m_depth == 1)
-    {
-        if (strcasecmp(el, m_tag.c_str()) == 0)
-            return 0;
-    }
-    else
-    {
-        if (strcasecmp(el, "login") == 0)
-        {
-            m_login = attr[1];
-            return 0;
-        }
-    }
-    return -1;
-}
-
-void ADD_USER::CreateAnswer()
-{
-    if (m_users.Exists(m_login))
-        m_answer = "<" + m_tag + " result=\"error\" reason=\"User '" + m_login + "' exists.\"/>";
-    else if (m_users.Add(m_login, &m_currAdmin) == 0)
-        m_answer = "<" + m_tag + " result=\"ok\"/>";
-    else
-        m_answer = "<" + m_tag + " result=\"error\" reason=\"Access denied\"/>";
-}
-
-int CHG_USER::Start(void *, const char * el, const char ** attr)
-{
-    m_depth++;
-
-    if (m_depth == 1)
-    {
-        if (strcasecmp(el, m_tag.c_str()) == 0)
-            return 0;
-    }
-    else
-    {
-        if (strcasecmp(el, "login") == 0)
-        {
-            m_login = attr[1];
-            return 0;
-        }
-
-        if (strcasecmp(el, "ip") == 0)
-        {
-            m_ucr.ips = UserIPs::parse(attr[1]);
-            return 0;
-        }
-
-        if (strcasecmp(el, "password") == 0)
-        {
-            m_ucr.password = attr[1];
-            return 0;
-        }
-
-        if (strcasecmp(el, "address") == 0)
-        {
-            m_ucr.address = Decode21str(attr[1]);
-            return 0;
-        }
-
-        if (strcasecmp(el, "aonline") == 0)
-        {
-            m_ucr.alwaysOnline = (*(attr[1]) != '0');
-            return 0;
-        }
-
-        if (strcasecmp(el, "cash") == 0)
-        {
-            if (attr[2] && (strcasecmp(attr[2], "msg") == 0))
-                m_cashMsg = Decode21str(attr[3]);
-
-            double cash = 0;
-            if (strtodouble2(attr[1], cash) == 0)
-                m_usr.cash = cash;
-
-            m_cashMustBeAdded = (strcasecmp(attr[0], "add") == 0);
-
-            return 0;
-        }
-
-        if (strcasecmp(el, "CreditExpire") == 0)
-        {
-            long int creditExpire = 0;
-            if (str2x(attr[1], creditExpire) == 0)
-                m_ucr.creditExpire = (time_t)creditExpire;
-
-            return 0;
-        }
-
-        if (strcasecmp(el, "credit") == 0)
-        {
-            double credit = 0;
-            if (strtodouble2(attr[1], credit) == 0)
-                m_ucr.credit = credit;
-            return 0;
-        }
-
-        if (strcasecmp(el, "freemb") == 0)
-        {
-            double freeMb = 0;
-            if (strtodouble2(attr[1], freeMb) == 0)
-                m_usr.freeMb = freeMb;
-            return 0;
-        }
-
-        if (strcasecmp(el, "down") == 0)
-        {
-            int down = 0;
-            if (str2x(attr[1], down) == 0)
-                m_ucr.disabled = down;
-            return 0;
-        }
-
-        if (strcasecmp(el, "DisableDetailStat") == 0)
-        {
-            int disabledDetailStat = 0;
-            if (str2x(attr[1], disabledDetailStat) == 0)
-                m_ucr.disabledDetailStat = disabledDetailStat;
-            return 0;
-        }
-
-        if (strcasecmp(el, "email") == 0)
-        {
-            m_ucr.email = Decode21str(attr[1]);
-            return 0;
-        }
-
-        for (int i = 0; i < USERDATA_NUM; i++)
-        {
-            char name[15];
-            sprintf(name, "userdata%d", i);
-            if (strcasecmp(el, name) == 0)
-            {
-                m_ucr.userdata[i] = Decode21str(attr[1]);
-                return 0;
-            }
-        }
-
-        if (strcasecmp(el, "group") == 0)
-        {
-            m_ucr.group = Decode21str(attr[1]);
-            return 0;
-        }
-
-        if (strcasecmp(el, "note") == 0)
-        {
-            m_ucr.note = Decode21str(attr[1]);
-            return 0;
-        }
-
-        if (strcasecmp(el, "passive") == 0)
-        {
-            int passive = 0;
-            if (str2x(attr[1], passive) == 0)
-                m_ucr.passive = passive;
-            return 0;
-        }
-
-        if (strcasecmp(el, "phone") == 0)
-        {
-            m_ucr.phone = Decode21str(attr[1]);
-            return 0;
-        }
-
-        if (strcasecmp(el, "Name") == 0)
-        {
-            m_ucr.realName = Decode21str(attr[1]);
-            return 0;
-        }
-
-        if (strcasecmp(el, "traff") == 0)
-        {
-            int j = 0;
-            while (attr[j])
-            {
-                int dir = attr[j][2] - '0';
-
-                if (strncasecmp(attr[j], "md", 2) == 0)
-                {
-                    uint64_t t = 0;
-                    str2x(attr[j + 1], t);
-                    m_downr[dir] = t;
-                }
-                if (strncasecmp(attr[j], "mu", 2) == 0)
-                {
-                    uint64_t t = 0;
-                    str2x(attr[j + 1], t);
-                    m_upr[dir] = t;
-                }
-                j += 2;
-            }
-            return 0;
-        }
-
-        if (strcasecmp(el, "tariff") == 0)
-        {
-            if (strcasecmp(attr[0], "now") == 0)
-                m_ucr.tariffName = attr[1];
-
-            if (strcasecmp(attr[0], "delayed") == 0)
-                m_ucr.nextTariff = attr[1];
-
-            return 0;
-        }
-    }
-    return -1;
-}
-
-void CHG_USER::CreateAnswer()
-{
-    if (ApplyChanges() == 0)
-        m_answer = "<" + m_tag + " result=\"ok\"/>";
-    else
-        m_answer = "<" + m_tag + " result=\"error\"/>";
-}
-
-int CHG_USER::ApplyChanges()
-{
-    printfd(__FILE__, "PARSER_CHG_USER::ApplyChanges()\n");
-    UserPtr u;
-
-    if (m_users.FindByName(m_login, &u))
-        return -1;
-
-    bool check = false;
-    bool alwaysOnline = u->GetProperties().alwaysOnline;
-    if (!m_ucr.alwaysOnline.empty())
-    {
-        check = true;
-        alwaysOnline = m_ucr.alwaysOnline.const_data();
-    }
-    bool onlyOneIP = u->GetProperties().ips.ConstData().onlyOneIP();
-    if (!m_ucr.ips.empty())
-    {
-        check = true;
-        onlyOneIP = m_ucr.ips.const_data().onlyOneIP();
-    }
-
-    if (check && alwaysOnline && !onlyOneIP)
-    {
-        printfd(__FILE__, "Requested change leads to a forbidden state: AlwaysOnline with multiple IP's\n");
-        PluginLogger::get("conf_sg")("%s Requested change leads to a forbidden state: AlwaysOnline with multiple IP's", m_currAdmin.logStr().c_str());
-        return -1;
-    }
-
-    for (size_t i = 0; i < m_ucr.ips.const_data().count(); ++i)
-    {
-        ConstUserPtr user;
-        uint32_t ip = m_ucr.ips.const_data().operator[](i).ip;
-        if (m_users.IsIPInUse(ip, m_login, &user))
-        {
-            printfd(__FILE__, "Trying to assign an IP %s to '%s' that is already in use by '%s'\n", inet_ntostring(ip).c_str(), m_login.c_str(), user->GetLogin().c_str());
-            PluginLogger::get("conf_sg")("%s trying to assign an IP %s to '%s' that is currently in use by '%s'", m_currAdmin.logStr().c_str(), inet_ntostring(ip).c_str(), m_login.c_str(), user->GetLogin().c_str());
-            return -1;
-        }
-    }
-
-    if (!m_ucr.ips.empty())
-        if (!u->GetProperties().ips.Set(m_ucr.ips.const_data(), m_currAdmin, m_login, m_store))
-            return -1;
-
-    if (!m_ucr.alwaysOnline.empty())
-        if (!u->GetProperties().alwaysOnline.Set(m_ucr.alwaysOnline.const_data(),
-                                                 m_currAdmin, m_login, m_store))
-            return -1;
-
-    if (!m_ucr.address.empty())
-        if (!u->GetProperties().address.Set(m_ucr.address.const_data(), m_currAdmin, m_login, m_store))
-            return -1;
-
-    if (!m_ucr.creditExpire.empty())
-        if (!u->GetProperties().creditExpire.Set(m_ucr.creditExpire.const_data(),
-                                                 m_currAdmin, m_login, m_store))
-            return -1;
-
-    if (!m_ucr.credit.empty())
-        if (!u->GetProperties().credit.Set(m_ucr.credit.const_data(), m_currAdmin, m_login, m_store))
-            return -1;
-
-    if (!m_usr.freeMb.empty())
-        if (!u->GetProperties().freeMb.Set(m_usr.freeMb.const_data(), m_currAdmin, m_login, m_store))
-            return -1;
-
-    if (!m_ucr.disabled.empty())
-        if (!u->GetProperties().disabled.Set(m_ucr.disabled.const_data(), m_currAdmin, m_login, m_store))
-            return -1;
-
-    if (!m_ucr.disabledDetailStat.empty())
-        if (!u->GetProperties().disabledDetailStat.Set(m_ucr.disabledDetailStat.const_data(), m_currAdmin, m_login, m_store))
-            return -1;
-
-    if (!m_ucr.email.empty())
-        if (!u->GetProperties().email.Set(m_ucr.email.const_data(), m_currAdmin, m_login, m_store))
-            return -1;
-
-    if (!m_ucr.group.empty())
-        if (!u->GetProperties().group.Set(m_ucr.group.const_data(), m_currAdmin, m_login, m_store))
-            return -1;
-
-    if (!m_ucr.note.empty())
-        if (!u->GetProperties().note.Set(m_ucr.note.const_data(), m_currAdmin, m_login, m_store))
-            return -1;
-
-    std::vector<STG::UserPropertyLogged<std::string> *> userdata;
-    userdata.push_back(u->GetProperties().userdata0.GetPointer());
-    userdata.push_back(u->GetProperties().userdata1.GetPointer());
-    userdata.push_back(u->GetProperties().userdata2.GetPointer());
-    userdata.push_back(u->GetProperties().userdata3.GetPointer());
-    userdata.push_back(u->GetProperties().userdata4.GetPointer());
-    userdata.push_back(u->GetProperties().userdata5.GetPointer());
-    userdata.push_back(u->GetProperties().userdata6.GetPointer());
-    userdata.push_back(u->GetProperties().userdata7.GetPointer());
-    userdata.push_back(u->GetProperties().userdata8.GetPointer());
-    userdata.push_back(u->GetProperties().userdata9.GetPointer());
-
-    for (int i = 0; i < (int)userdata.size(); i++)
-        if (!m_ucr.userdata[i].empty())
-            if(!userdata[i]->Set(m_ucr.userdata[i].const_data(), m_currAdmin, m_login, m_store))
-                return -1;
-
-    if (!m_ucr.passive.empty())
-        if (!u->GetProperties().passive.Set(m_ucr.passive.const_data(), m_currAdmin, m_login, m_store))
-            return -1;
-
-    if (!m_ucr.password.empty())
-        if (!u->GetProperties().password.Set(m_ucr.password.const_data(), m_currAdmin, m_login, m_store))
-            return -1;
-
-    if (!m_ucr.phone.empty())
-        if (!u->GetProperties().phone.Set(m_ucr.phone.const_data(), m_currAdmin, m_login, m_store))
-            return -1;
-
-    if (!m_ucr.realName.empty())
-        if (!u->GetProperties().realName.Set(m_ucr.realName.const_data(), m_currAdmin, m_login, m_store))
-            return -1;
-
-    if (!m_usr.cash.empty())
-    {
-        if (m_cashMustBeAdded)
-        {
-            if (!u->GetProperties().cash.Set(m_usr.cash.const_data() + u->GetProperties().cash,
-                                             m_currAdmin,
-                                             m_login,
-                                             m_store,
-                                             m_cashMsg))
-                return -1;
-        }
-        else
-        {
-            if (!u->GetProperties().cash.Set(m_usr.cash.const_data(), m_currAdmin, m_login, m_store, m_cashMsg))
-                return -1;
-        }
-    }
-
-    if (!m_ucr.tariffName.empty())
-    {
-        const auto newTariff = m_tariffs.FindByName(m_ucr.tariffName.const_data());
-        if (newTariff)
-        {
-            const auto tariff = u->GetTariff();
-            std::string message = tariff->TariffChangeIsAllowed(*newTariff, stgTime);
-            if (message.empty())
-            {
-                if (!u->GetProperties().tariffName.Set(m_ucr.tariffName.const_data(), m_currAdmin, m_login, m_store))
-                    return -1;
-                u->ResetNextTariff();
-            }
-            else
-            {
-                PluginLogger::get("conf_sg")("Tariff change is prohibited for user %s. %s", u->GetLogin().c_str(), message.c_str());
-            }
-        }
-        else
-        {
-            //WriteServLog("SetUser: Tariff %s not found", ud.conf.tariffName.c_str());
-            return -1;
-        }
-    }
-
-    if (!m_ucr.nextTariff.empty())
-    {
-        if (m_tariffs.FindByName(m_ucr.nextTariff.const_data()))
-        {
-            if (!u->GetProperties().nextTariff.Set(m_ucr.nextTariff.const_data(), m_currAdmin, m_login, m_store))
-                return -1;
-        }
-        else
-        {
-            //WriteServLog("SetUser: Tariff %s not found", ud.conf.tariffName.c_str());
-            return -1;
-        }
-    }
-
-    auto up = u->GetProperties().up.get();
-    auto down = u->GetProperties().down.get();
-    int upCount = 0;
-    int downCount = 0;
-    for (int i = 0; i < DIR_NUM; i++)
-    {
-        if (!m_upr[i].empty())
-        {
-            up[i] = m_upr[i].data();
-            upCount++;
-        }
-        if (!m_downr[i].empty())
-        {
-            down[i] = m_downr[i].data();
-            downCount++;
-        }
-    }
-
-    if (upCount)
-        if (!u->GetProperties().up.Set(up, m_currAdmin, m_login, m_store))
-            return -1;
-
-    if (downCount)
-        if (!u->GetProperties().down.Set(down, m_currAdmin, m_login, m_store))
-            return -1;
-
-    u->WriteConf();
-    u->WriteStat();
-
-    return 0;
-}
-
-int DEL_USER::Start(void *, const char *el, const char **attr)
-{
-    res = 0;
-    if (strcasecmp(el, m_tag.c_str()) == 0)
-    {
-        if (attr[0] == NULL || attr[1] == NULL)
-        {
-            //CreateAnswer("Parameters error!");
-            CreateAnswer();
-            return 0;
-        }
-
-        if (m_users.FindByName(attr[1], &u))
-        {
-            res = 1;
-            CreateAnswer();
-            return 0;
-        }
-        CreateAnswer();
-        return 0;
-    }
-    return -1;
-}
-
-int DEL_USER::End(void *, const char *el)
-{
-    if (strcasecmp(el, m_tag.c_str()) == 0)
-    {
-        if (!res)
-            m_users.Del(u->GetLogin(), &m_currAdmin);
-
-        return 0;
-    }
-    return -1;
-}
-
-void DEL_USER::CreateAnswer()
-{
-    if (res)
-        m_answer = "<" + m_tag + " value=\"error\" reason=\"User not found\"/>";
-    else
-        m_answer = "<" + m_tag + " value=\"ok\"/>";
-}
-
-int CHECK_USER::Start(void *, const char *el, const char **attr)
-{
-    if (strcasecmp(el, m_tag.c_str()) == 0)
-    {
-        if (attr[0] == NULL || attr[1] == NULL ||
-            attr[2] == NULL || attr[3] == NULL)
-        {
-            CreateAnswer("Invalid parameters.");
-            printfd(__FILE__, "PARSER_CHECK_USER - attr err\n");
-            return 0;
-        }
-
-        ConstUserPtr user;
-        if (m_users.FindByName(attr[1], &user))
-        {
-            CreateAnswer("User not found.");
-            printfd(__FILE__, "PARSER_CHECK_USER - login err\n");
-            return 0;
-        }
-
-        if (strcmp(user->GetProperties().password.Get().c_str(), attr[3]))
-        {
-            CreateAnswer("Wrong password.");
-            printfd(__FILE__, "PARSER_CHECK_USER - passwd err\n");
-            return 0;
-        }
-
-        CreateAnswer(NULL);
-        return 0;
-    }
-    return -1;
-}
-
-int CHECK_USER::End(void *, const char *el)
-{
-    if (strcasecmp(el, m_tag.c_str()) == 0)
-        return 0;
-    return -1;
-}
-
-void CHECK_USER::CreateAnswer(const char * error)
-{
-    if (error)
-        m_answer = "<" + m_tag + " value=\"Err\" reason=\"" + error + "\"/>";
-    else
-        m_answer = "<" + m_tag + " value=\"Ok\"/>";
-}
diff --git a/stargazer/plugins/configuration/sgconfig/parser_users.h b/stargazer/plugins/configuration/sgconfig/parser_users.h
deleted file mode 100644 (file)
index cdef451..0000000
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#pragma once
-
-#include "parser.h"
-
-#include "stg/user_conf.h"
-#include "stg/user_stat.h"
-#include "stg/common.h"
-#include "stg/optional.h"
-
-#include <string>
-
-namespace STG
-{
-
-struct Users;
-struct User;
-struct Tariffs;
-struct Admin;
-struct Store;
-
-namespace PARSER
-{
-
-class GET_USERS: public BASE_PARSER
-{
-    public:
-        class FACTORY : public BASE_PARSER::FACTORY
-        {
-            public:
-                explicit FACTORY(Users & users) : m_users(users) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new GET_USERS(admin, m_users); }
-                static void Register(REGISTRY & registry, Users & users)
-                { registry[ToLower(tag)] = new FACTORY(users); }
-            private:
-                Users & m_users;
-        };
-
-        static const char * tag;
-
-        GET_USERS(const Admin & admin, Users & users)
-            : BASE_PARSER(admin, tag), m_users(users),
-              m_lastUserUpdateTime(0) {}
-        int Start(void * data, const char * el, const char ** attr);
-
-    private:
-        Users & m_users;
-        time_t m_lastUserUpdateTime;
-
-        void CreateAnswer();
-};
-
-class GET_USER: public BASE_PARSER
-{
-    public:
-        class FACTORY : public BASE_PARSER::FACTORY
-        {
-            public:
-                explicit FACTORY(const Users & users) : m_users(users) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new GET_USER(admin, m_users); }
-                static void Register(REGISTRY & registry, const Users & users)
-                { registry[ToLower(tag)] = new FACTORY(users); }
-            private:
-                const Users & m_users;
-        };
-
-        static const char * tag;
-
-        GET_USER(const Admin & admin, const Users & users)
-            : BASE_PARSER(admin, tag), m_users(users) {}
-        int Start(void * data, const char * el, const char ** attr);
-
-    private:
-        const Users & m_users;
-        std::string m_login;
-
-        void CreateAnswer();
-};
-
-class ADD_USER: public BASE_PARSER
-{
-    public:
-        class FACTORY : public BASE_PARSER::FACTORY
-        {
-            public:
-                explicit FACTORY(Users & users) : m_users(users) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new ADD_USER(admin, m_users); }
-                static void Register(REGISTRY & registry, Users & users)
-                { registry[ToLower(tag)] = new FACTORY(users); }
-            private:
-                Users & m_users;
-        };
-
-        static const char * tag;
-
-        ADD_USER(const Admin & admin, Users & users)
-            : BASE_PARSER(admin, tag), m_users(users) {}
-        int Start(void * data, const char * el, const char ** attr);
-
-    private:
-        Users & m_users;
-        std::string m_login;
-
-        void CreateAnswer();
-};
-
-class CHG_USER: public BASE_PARSER
-{
-    public:
-        class FACTORY : public BASE_PARSER::FACTORY
-        {
-            public:
-                FACTORY(Users & users, Store & store, const Tariffs & tariffs)
-                    : m_users(users), m_store(store), m_tariffs(tariffs)
-                {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new CHG_USER(admin, m_users, m_store, m_tariffs); }
-                static void Register(REGISTRY & registry, Users & users, Store & store, const Tariffs & tariffs)
-                { registry[ToLower(tag)] = new FACTORY(users, store, tariffs); }
-            private:
-                Users & m_users;
-                Store & m_store;
-                const Tariffs & m_tariffs;
-        };
-
-        static const char * tag;
-
-        CHG_USER(const Admin & admin, Users & users,
-                 Store & store, const Tariffs & tariffs)
-            : BASE_PARSER(admin, tag),
-              m_users(users),
-              m_store(store),
-              m_tariffs(tariffs),
-              m_cashMustBeAdded(false) {}
-
-        int Start(void * data, const char * el, const char ** attr);
-
-    private:
-        Users & m_users;
-        Store & m_store;
-        const Tariffs & m_tariffs;
-        UserStatOpt m_usr;
-        UserConfOpt m_ucr;
-        Optional<uint64_t> m_upr[DIR_NUM];
-        Optional<uint64_t> m_downr[DIR_NUM];
-        std::string m_cashMsg;
-        std::string m_login;
-        bool m_cashMustBeAdded;
-
-        int ApplyChanges();
-        void CreateAnswer();
-};
-
-class DEL_USER: public BASE_PARSER
-{
-    public:
-        class FACTORY : public BASE_PARSER::FACTORY
-        {
-            public:
-                explicit FACTORY(Users & users) : m_users(users) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new DEL_USER(admin, m_users); }
-                static void Register(REGISTRY & registry, Users & users)
-                { registry[ToLower(tag)] = new FACTORY(users); }
-            private:
-                Users & m_users;
-        };
-
-        static const char * tag;
-
-        DEL_USER(const Admin & admin, Users & users)
-            : BASE_PARSER(admin, tag), m_users(users), res(0), u(NULL) {}
-        int Start(void * data, const char * el, const char ** attr);
-        int End(void * data, const char * el);
-
-    private:
-        Users & m_users;
-        int res;
-        User * u;
-
-        void CreateAnswer();
-};
-
-class CHECK_USER: public BASE_PARSER
-{
-    public:
-        class FACTORY : public BASE_PARSER::FACTORY
-        {
-            public:
-                explicit FACTORY(const Users & users) : m_users(users) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new CHECK_USER(admin, m_users); }
-                static void Register(REGISTRY & registry, const Users & users)
-                { registry[ToLower(tag)] = new FACTORY(users); }
-            private:
-                const Users & m_users;
-        };
-
-        static const char * tag;
-
-        CHECK_USER(const Admin & admin, const Users & users)
-            : BASE_PARSER(admin, tag), m_users(users) {}
-        int Start(void * data, const char * el, const char ** attr);
-        int End(void * data, const char * el);
-
-    private:
-        const Users & m_users;
-
-        void CreateAnswer(const char * error);
-        void CreateAnswer() {} // dummy
-};
-
-} // namespace PARSER
-} // namespace STG
diff --git a/stargazer/plugins/configuration/sgconfig/stgconfig.cpp b/stargazer/plugins/configuration/sgconfig/stgconfig.cpp
deleted file mode 100644 (file)
index 3f47f24..0000000
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- */
-
-#include "stgconfig.h"
-
-#include "stg/common.h"
-
-#include <algorithm>
-#include <csignal>
-#include <cstring>
-#include <cerrno>
-
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-bool STG_CONFIG_SETTINGS::ParseSettings(const STG::ModuleSettings & s)
-{
-    STG::ParamValue pv;
-    std::vector<STG::ParamValue>::const_iterator pvi;
-    ///////////////////////////
-    pv.param = "Port";
-    pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-    if (pvi == s.moduleParams.end() || pvi->value.empty())
-        {
-        errorStr = "Parameter \'Port\' is not found.";
-        printfd(__FILE__, "%s\n", errorStr.c_str());
-        return false;
-        }
-    int p;
-    if (ParseIntInRange(pvi->value[0], 2, 65535, &p))
-        {
-        errorStr = "Parameter \'Port\' should be an integral value in range (2, 65535). Actual value: '" + pvi->value[0] + "'.";
-        printfd(__FILE__, "%s\n", errorStr.c_str());
-        return false;
-        }
-    m_port = static_cast<uint16_t>(p);
-
-    pv.param = "BindAddress";
-    pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-    if (pvi != s.moduleParams.end() && !pvi->value.empty())
-        m_bindAddress = pvi->value[0];
-
-    return true;
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-extern "C" STG::Plugin * GetPlugin()
-{
-    static STG_CONFIG plugin;
-    return &plugin;
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-STG_CONFIG::STG_CONFIG()
-    : nonstop(false),
-      isRunning(false),
-      logger(STG::PluginLogger::get("conf_sg")),
-      config(logger)
-{
-}
-//-----------------------------------------------------------------------------
-int STG_CONFIG::ParseSettings()
-{
-    if (stgConfigSettings.ParseSettings(settings))
-        return 0;
-    errorStr = stgConfigSettings.GetStrError();
-    return -1;
-}
-//-----------------------------------------------------------------------------
-int STG_CONFIG::Start()
-{
-    if (isRunning)
-        return 0;
-
-    nonstop = true;
-
-    config.SetPort(stgConfigSettings.GetPort());
-    config.SetBindAddress(stgConfigSettings.GetBindAddress());
-
-    if (config.Prepare())
-    {
-        errorStr = config.GetStrError();
-        return -1;
-    }
-
-    if (pthread_create(&thread, NULL, Run, this))
-    {
-        errorStr = std::string("Cannot create thread: '") + strerror(errno) + "'.";
-        printfd(__FILE__, "%s\n", errorStr.c_str());
-        logger(errorStr);
-        return -1;
-    }
-
-    return 0;
-}
-//-----------------------------------------------------------------------------
-int STG_CONFIG::Stop()
-{
-    if (!isRunning)
-        return 0;
-
-    config.Stop();
-
-    //5 seconds to thread stops itself
-    for (size_t i = 0; i < 25; ++i)
-    {
-        if (!isRunning)
-            break;
-
-        struct timespec ts = {0, 200000000};
-        nanosleep(&ts, NULL);
-    }
-
-    if (isRunning)
-        return -1;
-
-    return 0;
-}
-//-----------------------------------------------------------------------------
-void * STG_CONFIG::Run(void * d)
-{
-    sigset_t signalSet;
-    sigfillset(&signalSet);
-    pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-    STG_CONFIG & stgConf = *static_cast<STG_CONFIG *>(d);
-    stgConf.isRunning = true;
-
-    stgConf.config.Run();
-
-    stgConf.isRunning = false;
-
-    return NULL;
-}
diff --git a/stargazer/plugins/configuration/sgconfig/stgconfig.h b/stargazer/plugins/configuration/sgconfig/stgconfig.h
deleted file mode 100644 (file)
index b7684e3..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- */
-
-#pragma once
-
-#include "configproto.h"
-
-#include "stg/plugin.h"
-#include "stg/logger.h"
-
-#include <string>
-
-#include <pthread.h>
-
-class STG_CONFIG_SETTINGS
-{
-    public:
-        STG_CONFIG_SETTINGS() : m_port(0), m_bindAddress("0.0.0.0") {}
-        const std::string & GetStrError() const { return errorStr; }
-        bool ParseSettings(const STG::ModuleSettings & s);
-        uint16_t GetPort() const { return m_port; }
-        const std::string & GetBindAddress() const { return m_bindAddress; }
-    private:
-        std::string errorStr;
-        uint16_t m_port;
-        std::string m_bindAddress;
-};
-
-class STG_CONFIG : public STG::Plugin
-{
-    public:
-        STG_CONFIG();
-
-        void                SetUsers(STG::Users * users) override { config.SetUsers(users); }
-        void                SetTariffs(STG::Tariffs * tariffs) override { config.SetTariffs(tariffs); }
-        void                SetAdmins(STG::Admins * admins) override { config.SetAdmins(admins); }
-        void                SetServices(STG::Services * services) override { config.SetServices(services); }
-        void                SetCorporations(STG::Corporations * corporations) override { config.SetCorporations( corporations); }
-        void                SetStore(STG::Store * store) override { config.SetStore(store); }
-        void                SetStgSettings(const STG::Settings * s) override { config.SetSettings(s); }
-        void                SetSettings(const STG::ModuleSettings & s) override { settings = s; }
-        int                 ParseSettings() override;
-
-        int                 Start() override;
-        int                 Stop() override;
-        int                 Reload(const STG::ModuleSettings & /*ms*/) override { return 0; }
-        bool                IsRunning() override { return isRunning; }
-
-        const std::string & GetStrError() const override { return errorStr; }
-        std::string         GetVersion() const override { return "Stg Configurator v. 2.0"; }
-        uint16_t            GetStartPosition() const override { return 20; }
-        uint16_t            GetStopPosition() const override { return 20; }
-
-    private:
-        STG_CONFIG(const STG_CONFIG & rvalue);
-        STG_CONFIG & operator=(const STG_CONFIG & rvalue);
-
-        static void *       Run(void *);
-
-        mutable std::string errorStr;
-        STG_CONFIG_SETTINGS stgConfigSettings;
-        pthread_t           thread;
-        bool                nonstop;
-        bool                isRunning;
-        STG::PluginLogger   logger;
-        CONFIGPROTO         config;
-        STG::ModuleSettings settings;
-};
diff --git a/stargazer/plugins/other/ping/ping.cpp b/stargazer/plugins/other/ping/ping.cpp
deleted file mode 100644 (file)
index 147ef68..0000000
+++ /dev/null
@@ -1,334 +0,0 @@
-#include "ping.h"
-
-#include "stg/user.h"
-#include "stg/locker.h"
-#include "stg/user_property.h"
-
-#include <cstdio>
-#include <cassert>
-#include <csignal>
-#include <ctime>
-#include <algorithm>
-
-namespace
-{
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-template <typename varType>
-class HAS_USER: public std::binary_function<varType, UserPtr, bool>
-{
-public:
-    explicit HAS_USER(const UserPtr & u) : user(u) {}
-    bool operator()(varType notifier) const
-        {
-        return notifier.GetUser() == user;
-        }
-private:
-    const UserPtr & user;
-};
-}
-
-extern "C" STG::Plugin* GetPlugin()
-{
-    static PING plugin;
-    return &plugin;
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-int PING_SETTINGS::ParseSettings(const STG::ModuleSettings & s)
-{
-STG::ParamValue pv;
-std::vector<STG::ParamValue>::const_iterator pvi;
-
-pv.param = "PingDelay";
-pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-if (pvi == s.moduleParams.end() || pvi->value.empty())
-    {
-    errorStr = "Parameter \'PingDelay\' not found.";
-    printfd(__FILE__, "Parameter 'PingDelay' not found\n");
-    return -1;
-    }
-if (ParseIntInRange(pvi->value[0], 5, 3600, &pingDelay))
-    {
-    errorStr = "Cannot parse parameter \'PingDelay\': " + errorStr;
-    printfd(__FILE__, "Canot parse parameter 'PingDelay'\n");
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-PING::PING()
-    : users(NULL),
-      nonstop(false),
-      isRunning(false),
-      onAddUserNotifier(*this),
-      onDelUserNotifier(*this),
-      logger(STG::PluginLogger::get("ping"))
-{
-pthread_mutex_init(&mutex, NULL);
-}
-//-----------------------------------------------------------------------------
-PING::~PING()
-{
-pthread_mutex_destroy(&mutex);
-}
-//-----------------------------------------------------------------------------
-int PING::ParseSettings()
-{
-int ret = pingSettings.ParseSettings(settings);
-if (ret)
-    errorStr = pingSettings.GetStrError();
-return ret;
-}
-//-----------------------------------------------------------------------------
-int PING::Start()
-{
-GetUsers();
-
-users->AddNotifierUserAdd(&onAddUserNotifier);
-users->AddNotifierUserDel(&onDelUserNotifier);
-
-nonstop = true;
-
-pinger.SetDelayTime(pingSettings.GetPingDelay());
-pinger.Start();
-
-if (pthread_create(&thread, NULL, Run, this))
-    {
-    errorStr = "Cannot start thread.";
-    logger("Cannot create thread.");
-    printfd(__FILE__, "Cannot start thread\n");
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int PING::Stop()
-{
-STG_LOCKER lock(&mutex);
-
-if (!isRunning)
-    return 0;
-
-pinger.Stop();
-nonstop = false;
-//5 seconds to thread stops itself
-struct timespec ts = {0, 200000000};
-for (int i = 0; i < 25; i++)
-    {
-    if (!isRunning)
-        break;
-
-    nanosleep(&ts, NULL);
-    }
-
-users->DelNotifierUserAdd(&onAddUserNotifier);
-users->DelNotifierUserDel(&onDelUserNotifier);
-
-std::list<UserPtr>::iterator users_iter;
-users_iter = usersList.begin();
-while (users_iter != usersList.end())
-    {
-    UnSetUserNotifiers(*users_iter);
-    ++users_iter;
-    }
-
-if (isRunning)
-    return -1;
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-bool PING::IsRunning()
-{
-return isRunning;
-}
-//-----------------------------------------------------------------------------
-void * PING::Run(void * d)
-{
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-PING * ping = static_cast<PING *>(d);
-ping->isRunning = true;
-
-long delay = (10000000 * ping->pingSettings.GetPingDelay()) / 3 + 50000000;
-
-while (ping->nonstop)
-    {
-    std::list<UserPtr>::iterator iter = ping->usersList.begin();
-        {
-        STG_LOCKER lock(&ping->mutex);
-        while (iter != ping->usersList.end())
-            {
-            if ((*iter)->GetProperties().ips.ConstData().onlyOneIP())
-                {
-                uint32_t ip = (*iter)->GetProperties().ips.ConstData()[0].ip;
-                time_t t;
-                if (ping->pinger.GetIPTime(ip, &t) == 0)
-                    {
-                    if (t)
-                        (*iter)->UpdatePingTime(t);
-                    }
-                }
-            else
-                {
-                uint32_t ip = (*iter)->GetCurrIP();
-                if (ip)
-                    {
-                    time_t t;
-                    if (ping->pinger.GetIPTime(ip, &t) == 0)
-                        {
-                        if (t)
-                            (*iter)->UpdatePingTime(t);
-                        }
-                    }
-                }
-            ++iter;
-            }
-        }
-    struct timespec ts = {delay / 1000000000, delay % 1000000000};
-    for (int i = 0; i < 100; i++)
-        {
-        if (ping->nonstop)
-            {
-            nanosleep(&ts, NULL);
-            }
-        }
-    }
-
-ping->isRunning = false;
-return NULL;
-}
-//-----------------------------------------------------------------------------
-void PING::SetUserNotifiers(UserPtr u)
-{
-CHG_CURRIP_NOTIFIER_PING ChgCurrIPNotifier(*this, u);
-CHG_IPS_NOTIFIER_PING ChgIPNotifier(*this, u);
-
-ChgCurrIPNotifierList.push_front(ChgCurrIPNotifier);
-ChgIPNotifierList.push_front(ChgIPNotifier);
-
-u->AddCurrIPAfterNotifier(&(*ChgCurrIPNotifierList.begin()));
-u->GetProperties().ips.AddAfterNotifier(&(*ChgIPNotifierList.begin()));
-}
-//-----------------------------------------------------------------------------
-void PING::UnSetUserNotifiers(UserPtr u)
-{
-// ---          CurrIP              ---
-HAS_USER<CHG_CURRIP_NOTIFIER_PING> IsContainsUserCurrIP(u);
-HAS_USER<CHG_IPS_NOTIFIER_PING> IsContainsUserIP(u);
-
-std::list<CHG_CURRIP_NOTIFIER_PING>::iterator currIPter;
-std::list<CHG_IPS_NOTIFIER_PING>::iterator IPIter;
-
-currIPter = find_if(ChgCurrIPNotifierList.begin(),
-                    ChgCurrIPNotifierList.end(),
-                    IsContainsUserCurrIP);
-
-if (currIPter != ChgCurrIPNotifierList.end())
-    {
-    currIPter->GetUser()->DelCurrIPAfterNotifier(&(*currIPter));
-    ChgCurrIPNotifierList.erase(currIPter);
-    }
-// ---         CurrIP end          ---
-
-// ---          IP              ---
-IPIter = find_if(ChgIPNotifierList.begin(),
-                 ChgIPNotifierList.end(),
-                 IsContainsUserIP);
-
-if (IPIter != ChgIPNotifierList.end())
-    {
-    IPIter->GetUser()->GetProperties().ips.DelAfterNotifier(&(*IPIter));
-    ChgIPNotifierList.erase(IPIter);
-    }
-// ---          IP end          ---
-}
-//-----------------------------------------------------------------------------
-void PING::GetUsers()
-{
-STG_LOCKER lock(&mutex);
-
-UserPtr u;
-int h = users->OpenSearch();
-assert(h && "USERS::OpenSearch is always correct");
-
-while (users->SearchNext(h, &u) == 0)
-    {
-    usersList.push_back(u);
-    SetUserNotifiers(u);
-    if (u->GetProperties().ips.ConstData().onlyOneIP())
-        {
-        pinger.AddIP(u->GetProperties().ips.ConstData()[0].ip);
-        }
-    else
-        {
-        uint32_t ip = u->GetCurrIP();
-        if (ip)
-            pinger.AddIP(ip);
-        }
-    }
-
-users->CloseSearch(h);
-}
-//-----------------------------------------------------------------------------
-void PING::AddUser(UserPtr u)
-{
-STG_LOCKER lock(&mutex);
-
-SetUserNotifiers(u);
-usersList.push_back(u);
-}
-//-----------------------------------------------------------------------------
-void PING::DelUser(UserPtr u)
-{
-STG_LOCKER lock(&mutex);
-
-UnSetUserNotifiers(u);
-
-std::list<UserPtr>::iterator users_iter;
-users_iter = usersList.begin();
-
-while (users_iter != usersList.end())
-    {
-    if (u == *users_iter)
-        {
-        usersList.erase(users_iter);
-        break;
-        }
-    ++users_iter;
-    }
-}
-//-----------------------------------------------------------------------------
-void CHG_CURRIP_NOTIFIER_PING::Notify(const uint32_t & oldIP, const uint32_t & newIP)
-{
-ping.pinger.DelIP(oldIP);
-if (newIP)
-    ping.pinger.AddIP(newIP);
-}
-//-----------------------------------------------------------------------------
-void CHG_IPS_NOTIFIER_PING::Notify(const STG::UserIPs & oldIPS, const STG::UserIPs & newIPS)
-{
-if (oldIPS.onlyOneIP())
-    ping.pinger.DelIP(oldIPS[0].ip);
-
-if (newIPS.onlyOneIP())
-    ping.pinger.AddIP(newIPS[0].ip);
-}
-//-----------------------------------------------------------------------------
-void ADD_USER_NONIFIER_PING::Notify(const UserPtr & user)
-{
-ping.AddUser(user);
-}
-//-----------------------------------------------------------------------------
-void DEL_USER_NONIFIER_PING::Notify(const UserPtr & user)
-{
-ping.DelUser(user);
-}
-//-----------------------------------------------------------------------------
diff --git a/stargazer/plugins/other/ping/ping.h b/stargazer/plugins/other/ping/ping.h
deleted file mode 100644 (file)
index 9986be3..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-#pragma once
-
-#include "stg/plugin.h"
-#include "stg/module_settings.h"
-#include "stg/notifer.h"
-#include "stg/user_ips.h"
-#include "stg/pinger.h"
-#include "stg/users.h"
-#include "stg/logger.h"
-
-#include <string>
-#include <list>
-#include <cstdint>
-
-#include <pthread.h>
-
-class PING;
-
-namespace STG
-{
-struct USER;
-struct SETTINGS;
-}
-
-using UserPtr = STG::User*;
-//-----------------------------------------------------------------------------*/
-class CHG_CURRIP_NOTIFIER_PING: public STG::PropertyNotifierBase<uint32_t> {
-public:
-    CHG_CURRIP_NOTIFIER_PING(const PING & p, UserPtr u)
-        : user(u), ping(p) {}
-    void Notify(const uint32_t & oldIP, const uint32_t & newIP);
-    UserPtr GetUser() const { return user; }
-
-private:
-    CHG_CURRIP_NOTIFIER_PING & operator=(const CHG_CURRIP_NOTIFIER_PING &);
-
-    UserPtr user;
-    const PING & ping;
-};
-//-----------------------------------------------------------------------------
-class CHG_IPS_NOTIFIER_PING: public STG::PropertyNotifierBase<STG::UserIPs> {
-public:
-    CHG_IPS_NOTIFIER_PING(const PING & p, UserPtr u)
-        : user(u), ping(p) {}
-    void Notify(const STG::UserIPs & oldIPS, const STG::UserIPs & newIPS);
-    UserPtr GetUser() const { return user; }
-
-private:
-    CHG_IPS_NOTIFIER_PING & operator=(const CHG_IPS_NOTIFIER_PING &);
-
-    UserPtr user;
-    const PING & ping;
-};
-//-----------------------------------------------------------------------------
-class ADD_USER_NONIFIER_PING: public STG::NotifierBase<UserPtr> {
-public:
-    explicit ADD_USER_NONIFIER_PING(PING & p) : ping(p) {}
-    void Notify(const UserPtr & user);
-
-private:
-    ADD_USER_NONIFIER_PING(const ADD_USER_NONIFIER_PING &);
-    ADD_USER_NONIFIER_PING & operator=(const ADD_USER_NONIFIER_PING &);
-
-    PING & ping;
-};
-//-----------------------------------------------------------------------------
-class DEL_USER_NONIFIER_PING: public STG::NotifierBase<UserPtr> {
-public:
-    explicit DEL_USER_NONIFIER_PING(PING & p) : ping(p) {}
-    void Notify(const UserPtr & user);
-
-private:
-    DEL_USER_NONIFIER_PING(const DEL_USER_NONIFIER_PING &);
-    DEL_USER_NONIFIER_PING & operator=(const DEL_USER_NONIFIER_PING &);
-
-    PING & ping;
-};
-//-----------------------------------------------------------------------------
-class PING_SETTINGS {
-public:
-    PING_SETTINGS() : pingDelay(0) {}
-    const std::string & GetStrError() const { return errorStr; }
-    int ParseSettings(const STG::ModuleSettings & s);
-    int GetPingDelay() const { return pingDelay; }
-private:
-    int pingDelay;
-    mutable std::string errorStr;
-};
-//-----------------------------------------------------------------------------
-class PING : public STG::Plugin {
-friend class CHG_CURRIP_NOTIFIER_PING;
-friend class CHG_IPS_NOTIFIER_PING;
-public:
-    PING();
-    ~PING() override;
-
-    void SetUsers(STG::Users * u) override { users = u; }
-    void SetSettings(const STG::ModuleSettings & s) override { settings = s; }
-    int ParseSettings() override;
-
-    int Start() override;
-    int Stop() override;
-    int Reload(const STG::ModuleSettings & /*ms*/) override { return 0; }
-    bool IsRunning() override;
-
-    const std::string & GetStrError() const override { return errorStr; }
-    std::string GetVersion() const override { return "Pinger v.1.01"; }
-    uint16_t GetStartPosition() const override { return 10; }
-    uint16_t GetStopPosition() const override { return 10; }
-
-    void AddUser(UserPtr u);
-    void DelUser(UserPtr u);
-
-private:
-    explicit PING(const PING & rvalue);
-    PING & operator=(const PING & rvalue);
-
-    void GetUsers();
-    void SetUserNotifiers(UserPtr u);
-    void UnSetUserNotifiers(UserPtr u);
-    static void * Run(void * d);
-
-    mutable std::string errorStr;
-    PING_SETTINGS pingSettings;
-    STG::ModuleSettings settings;
-    STG::Users * users;
-    std::list<UserPtr> usersList;
-
-    pthread_t thread;
-    pthread_mutex_t mutex;
-    bool nonstop;
-    bool isRunning;
-    mutable STG_PINGER pinger;
-
-    std::list<CHG_CURRIP_NOTIFIER_PING> ChgCurrIPNotifierList;
-    std::list<CHG_IPS_NOTIFIER_PING> ChgIPNotifierList;
-
-    ADD_USER_NONIFIER_PING onAddUserNotifier;
-    DEL_USER_NONIFIER_PING onDelUserNotifier;
-
-    STG::PluginLogger logger;
-};
diff --git a/stargazer/plugins/other/rscript/nrmap_parser.cpp b/stargazer/plugins/other/rscript/nrmap_parser.cpp
deleted file mode 100644 (file)
index 308d5d0..0000000
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
- /*
- $Revision: 1.8 $
- $Author: faust $
- $Date: 2009/10/22 09:58:53 $
- */
-
-#include <fstream>
-#include <cerrno>
-#include <cstring>
-#include <algorithm>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-
-#include "stg/common.h"
-#include "nrmap_parser.h"
-
-bool NRMapParser::ReadFile(const std::string & fileName)
-{
-std::ifstream source(fileName.c_str());
-
-if (!source)
-    {
-    errorStr = "Error opening file ";
-    errorStr += fileName;
-    printfd(__FILE__, "NRMapParser::ReadFile(): %s\n", errorStr.c_str());
-    return true;
-    }
-
-int lineNumber = 0;
-std::string line;
-std::vector<NET_ROUTER> _nrmap;
-
-while (getline(source, line))
-    {
-    ++lineNumber;
-    NET_ROUTER nr;
-
-    if (Trim(line) == "")
-        {
-        continue;
-        }
-
-    if (ParseLine(line, nr))
-        {
-        printfd(__FILE__, "NRMapParser::ReadFile(): Error parsing line %d: '%s'\n", lineNumber, errorStr.c_str());
-        return true;
-        }
-
-    _nrmap.push_back(nr);
-    }
-
-nrmap = _nrmap;
-
-return false;
-}
-
-bool NRMapParser::ParseLine(const std::string & line, NET_ROUTER & nr) const
-{
-// xxx.xxx.xxx.xxx/yy zzz.zzz.zzz.zzz
-size_t pos = line.find_first_of(" \t");
-
-if (pos == std::string::npos)
-    {
-    errorStr = "No space between subnet and router";
-    return true;
-    }
-
-std::string subnet(line.substr(0, pos)); // xxx.xxx.xxx.xxx/yy
-
-uint32_t ip = 0;
-uint32_t mask = 0;
-
-if (ParseNet(subnet, ip, mask))
-    {
-    return true;
-    }
-
-nr.subnetIP = ip;
-nr.subnetMask = mask;
-
-pos = line.find_first_not_of(" \t", pos);
-
-if (pos == std::string::npos)
-    {
-    errorStr = "No router address found";
-    return true;
-    }
-
-size_t pos2 = line.find_first_of(" \t", pos);
-
-std::string router(line.substr(pos, pos2 == std::string::npos ? line.length() - pos2 - 1 : pos2 - pos)); //zzz.zzz.zzz.zzz
-
-uint32_t routerIP;
-
-if (ParseRouter(router, routerIP))
-    {
-    return true;
-    }
-
-std::vector<uint32_t>::iterator it;
-
-it = std::lower_bound(
-        nr.routers.begin(),
-        nr.routers.end(),
-        routerIP
-        );
-nr.routers.insert(it, routerIP);
-
-//nr.routers.push_back(routerIP);
-
-while (pos2 != std::string::npos)
-    {
-    pos = line.find_first_not_of(" \t", pos2);
-
-    if (pos == std::string::npos)
-        {
-        return false;
-        }
-
-    pos2 = line.find_first_of(" \t", pos);
-
-    if (ParseRouter(line.substr(
-                        pos,
-                        pos2 == std::string::npos ? line.length() - pos2 - 1 : pos2 - pos),
-                    routerIP))
-        {
-        return true;
-        }
-
-    it = std::lower_bound(
-            nr.routers.begin(),
-            nr.routers.end(),
-            routerIP
-            );
-    nr.routers.insert(it, routerIP);
-
-    //nr.routers.push_back(routerIP);
-
-    }
-
-return false;
-}
-
-bool NRMapParser::ParseNet(const std::string & line, uint32_t & ip, uint32_t & mask) const
-{
-// xxx.xxx.xxx.xxx/yy
-
-size_t pos = line.find_first_of('/');
-
-if (pos == std::string::npos)
-    {
-    errorStr = "Subnet is not in CIDR notation";
-    return true;
-    }
-
-int res = inet_pton(AF_INET, line.substr(0, pos).c_str(), &ip); //xxx.xxx.xxx.xxx
-
-if (res < 0)
-    {
-    errorStr = strerror(errno);
-    return true;
-    }
-else if (res == 0)
-    {
-    errorStr = "Invalid subnet address";
-    return true;
-    }
-
-if (str2x(line.substr(pos + 1, line.length() - pos - 1), mask)) //yy
-    {
-    errorStr = "Invalid subnet mask";
-    return true;
-    }
-if (mask > 32)
-    {
-    errorStr = "Subnet mask is out of range [0..32]";
-    return true;
-    }
-mask = htonl(0xffFFffFF << (32 - mask)); //bitmask
-
-return false;
-}
-
-bool NRMapParser::ParseRouter(const std::string & line, uint32_t & ip) const
-{
-int res = inet_pton(AF_INET, line.c_str(), &ip); //zzz.zzz.zzz.zzz
-
-if (res < 0)
-    {
-    errorStr = strerror(errno);
-    return true;
-    }
-else if (res == 0)
-    {
-    printfd(__FILE__, "NRMapParser::ParseRouter(): IP '%s' is invalid\n", line.c_str());
-    errorStr = "Invalid router address";
-    return true;
-    }
-return false;
-}
diff --git a/stargazer/plugins/other/rscript/nrmap_parser.h b/stargazer/plugins/other/rscript/nrmap_parser.h
deleted file mode 100644 (file)
index 82e7edb..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
- /*
- $Revision: 1.2 $
- $Author: faust $
- $Date: 2009/09/23 12:51:42 $
- */
-
-#ifndef __NRMAP_PARSER_H__
-#define __NRMAP_PARSER_H__
-
-#include <string>
-#include <vector>
-#include <cstdint>
-
-struct NET_ROUTER
-{
-    NET_ROUTER() : subnetIP(0), subnetMask(0), routers() {}
-    NET_ROUTER(const NET_ROUTER & rvalue)
-        : subnetIP(rvalue.subnetIP),
-          subnetMask(rvalue.subnetMask),
-          routers(rvalue.routers)
-    {}
-
-    uint32_t              subnetIP;
-    uint32_t              subnetMask;
-    std::vector<uint32_t> routers;
-
-    NET_ROUTER & operator=(const NET_ROUTER & rvalue)
-    {
-    subnetIP = rvalue.subnetIP;
-    subnetMask = rvalue.subnetMask;
-    routers = rvalue.routers;
-    return *this;
-    }
-};
-
-class NRMapParser {
-public:
-    NRMapParser() : nrmap(), errorStr() {}
-    ~NRMapParser() {}
-
-    bool ReadFile(const std::string & fileName);
-    const std::vector<NET_ROUTER> & GetMap() const { return nrmap; }
-    const std::string & GetErrorStr() const { return errorStr; }
-
-private:
-    NRMapParser(const NRMapParser & rvalue);
-    NRMapParser & operator=(const NRMapParser & rvalue);
-
-    std::vector<NET_ROUTER> nrmap;
-    mutable std::string errorStr;
-
-    bool ParseLine(const std::string & line, NET_ROUTER & nr) const;
-    bool ParseNet(const std::string & line, uint32_t & ip, uint32_t & mask) const;
-    bool ParseRouter(const std::string & line, uint32_t & ip) const;
-};
-
-#endif
diff --git a/stargazer/plugins/other/rscript/rscript.cpp b/stargazer/plugins/other/rscript/rscript.cpp
deleted file mode 100644 (file)
index 764e536..0000000
+++ /dev/null
@@ -1,590 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#include "rscript.h"
-
-#include "ur_functor.h"
-#include "send_functor.h"
-
-#include "stg/common.h"
-#include "stg/locker.h"
-#include "stg/users.h"
-#include "stg/user_property.h"
-#include "stg/logger.h"
-
-#include <algorithm>
-
-#include <csignal>
-#include <cassert>
-#include <cstdlib>
-#include <cerrno>
-#include <cstring>
-
-#include <sys/time.h>
-#include <netinet/ip.h>
-
-#define RS_DEBUG (1)
-#define MAX_SHORT_PCKT  (3)
-
-extern volatile time_t stgTime;
-
-using RS::REMOTE_SCRIPT;
-
-namespace {
-
-template<typename T>
-struct USER_IS
-{
-    explicit USER_IS(RS::UserPtr u) : user(u) {}
-    bool operator()(const T & notifier) { return notifier.GetUser() == user; }
-
-    RS::UserPtr user;
-};
-
-} // namespace anonymous
-
-extern "C" STG::Plugin* GetPlugin()
-{
-    static REMOTE_SCRIPT plugin;
-    return &plugin;
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-RS::SETTINGS::SETTINGS()
-    : sendPeriod(0),
-      port(0)
-{
-}
-//-----------------------------------------------------------------------------
-int RS::SETTINGS::ParseSettings(const STG::ModuleSettings & s)
-{
-int p;
-STG::ParamValue pv;
-std::vector<STG::ParamValue>::const_iterator pvi;
-netRouters.clear();
-///////////////////////////
-pv.param = "Port";
-pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-if (pvi == s.moduleParams.end() || pvi->value.empty())
-    {
-    errorStr = "Parameter \'Port\' not found.";
-    printfd(__FILE__, "Parameter 'Port' not found\n");
-    return -1;
-    }
-if (ParseIntInRange(pvi->value[0], 2, 65535, &p))
-    {
-    errorStr = "Cannot parse parameter \'Port\': " + errorStr;
-    printfd(__FILE__, "Cannot parse parameter 'Port'\n");
-    return -1;
-    }
-port = static_cast<uint16_t>(p);
-///////////////////////////
-pv.param = "SendPeriod";
-pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-if (pvi == s.moduleParams.end() || pvi->value.empty())
-    {
-    errorStr = "Parameter \'SendPeriod\' not found.";
-    printfd(__FILE__, "Parameter 'SendPeriod' not found\n");
-    return -1;
-    }
-
-if (ParseIntInRange(pvi->value[0], 5, 600, &sendPeriod))
-    {
-    errorStr = "Cannot parse parameter \'SendPeriod\': " + errorStr;
-    printfd(__FILE__, "Cannot parse parameter 'SendPeriod'\n");
-    return -1;
-    }
-///////////////////////////
-pv.param = "UserParams";
-pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-if (pvi == s.moduleParams.end() || pvi->value.empty())
-    {
-    errorStr = "Parameter \'UserParams\' not found.";
-    printfd(__FILE__, "Parameter 'UserParams' not found\n");
-    return -1;
-    }
-userParams = pvi->value;
-///////////////////////////
-pv.param = "Password";
-pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-if (pvi == s.moduleParams.end() || pvi->value.empty())
-    {
-    errorStr = "Parameter \'Password\' not found.";
-    printfd(__FILE__, "Parameter 'Password' not found\n");
-    return -1;
-    }
-password = pvi->value[0];
-///////////////////////////
-pv.param = "SubnetFile";
-pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-if (pvi == s.moduleParams.end() || pvi->value.empty())
-    {
-    errorStr = "Parameter \'SubnetFile\' not found.";
-    printfd(__FILE__, "Parameter 'SubnetFile' not found\n");
-    return -1;
-    }
-subnetFile = pvi->value[0];
-
-NRMapParser nrMapParser;
-
-if (!nrMapParser.ReadFile(subnetFile))
-    {
-    netRouters = nrMapParser.GetMap();
-    }
-else
-    {
-        STG::PluginLogger::get("rscript")("mod_rscript: error opening subnets file '%s'", subnetFile.c_str());
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-REMOTE_SCRIPT::REMOTE_SCRIPT()
-    : sendPeriod(15),
-      halfPeriod(8),
-      nonstop(false),
-      isRunning(false),
-      users(NULL),
-      sock(0),
-      onAddUserNotifier(*this),
-      onDelUserNotifier(*this),
-      logger(STG::PluginLogger::get("rscript"))
-{
-pthread_mutex_init(&mutex, NULL);
-}
-//-----------------------------------------------------------------------------
-REMOTE_SCRIPT::~REMOTE_SCRIPT()
-{
-pthread_mutex_destroy(&mutex);
-}
-//-----------------------------------------------------------------------------
-void * REMOTE_SCRIPT::Run(void * d)
-{
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-REMOTE_SCRIPT * rs = static_cast<REMOTE_SCRIPT *>(d);
-
-rs->isRunning = true;
-
-while (rs->nonstop)
-    {
-    rs->PeriodicSend();
-    sleep(2);
-    }
-
-rs->isRunning = false;
-return NULL;
-}
-//-----------------------------------------------------------------------------
-int REMOTE_SCRIPT::ParseSettings()
-{
-int ret = rsSettings.ParseSettings(settings);
-if (ret)
-    errorStr = rsSettings.GetStrError();
-
-sendPeriod = rsSettings.GetSendPeriod();
-halfPeriod = sendPeriod / 2;
-
-return ret;
-}
-//-----------------------------------------------------------------------------
-int REMOTE_SCRIPT::Start()
-{
-netRouters = rsSettings.GetSubnetsMap();
-
-InitEncrypt(&ctx, rsSettings.GetPassword());
-
-users->AddNotifierUserAdd(&onAddUserNotifier);
-users->AddNotifierUserDel(&onDelUserNotifier);
-
-nonstop = true;
-
-if (GetUsers())
-    {
-    return -1;
-    }
-
-if (PrepareNet())
-    {
-    return -1;
-    }
-
-if (!isRunning)
-    {
-    if (pthread_create(&thread, NULL, Run, this))
-        {
-        errorStr = "Cannot create thread.";
-        logger("Cannot create thread.");
-        printfd(__FILE__, "Cannot create thread\n");
-        return -1;
-        }
-    }
-
-errorStr = "";
-return 0;
-}
-//-----------------------------------------------------------------------------
-int REMOTE_SCRIPT::Stop()
-{
-if (!IsRunning())
-    return 0;
-
-nonstop = false;
-
-std::for_each(
-        authorizedUsers.begin(),
-        authorizedUsers.end(),
-        DisconnectUser(*this)
-        );
-
-FinalizeNet();
-
-if (isRunning)
-    {
-    //5 seconds to thread stops itself
-    for (int i = 0; i < 25 && isRunning; i++)
-        {
-        struct timespec ts = {0, 200000000};
-        nanosleep(&ts, NULL);
-        }
-    }
-
-users->DelNotifierUserDel(&onDelUserNotifier);
-users->DelNotifierUserAdd(&onAddUserNotifier);
-
-if (isRunning)
-    {
-    logger("Cannot stop thread.");
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int REMOTE_SCRIPT::Reload(const STG::ModuleSettings & /*ms*/)
-{
-NRMapParser nrMapParser;
-
-if (nrMapParser.ReadFile(rsSettings.GetMapFileName()))
-    {
-    errorStr = nrMapParser.GetErrorStr();
-    logger("Map file reading error: %s", errorStr.c_str());
-    return -1;
-    }
-
-    {
-    STG_LOCKER lock(&mutex);
-
-    printfd(__FILE__, "REMOTE_SCRIPT::Reload()\n");
-
-    netRouters = nrMapParser.GetMap();
-    }
-
-std::for_each(authorizedUsers.begin(),
-              authorizedUsers.end(),
-              UpdateRouter(*this));
-
-logger("%s reloaded successfully.", rsSettings.GetMapFileName().c_str());
-printfd(__FILE__, "REMOTE_SCRIPT::Reload() %s reloaded successfully.\n");
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-bool REMOTE_SCRIPT::PrepareNet()
-{
-sock = socket(AF_INET, SOCK_DGRAM, 0);
-
-if (sock < 0)
-    {
-    errorStr = "Cannot create socket.";
-    logger("Canot create a socket: %s", strerror(errno));
-    printfd(__FILE__, "Cannot create socket\n");
-    return true;
-    }
-
-return false;
-}
-//-----------------------------------------------------------------------------
-bool REMOTE_SCRIPT::FinalizeNet()
-{
-close(sock);
-return false;
-}
-//-----------------------------------------------------------------------------
-void REMOTE_SCRIPT::PeriodicSend()
-{
-STG_LOCKER lock(&mutex);
-
-std::map<uint32_t, RS::USER>::iterator it(authorizedUsers.begin());
-while (it != authorizedUsers.end())
-    {
-    if (difftime(stgTime, it->second.lastSentTime) - (rand() % halfPeriod) > sendPeriod)
-        {
-        Send(it->second);
-        }
-    ++it;
-    }
-}
-//-----------------------------------------------------------------------------
-#ifdef NDEBUG
-bool REMOTE_SCRIPT::PreparePacket(char * buf, size_t, RS::USER & rsu, bool forceDisconnect) const
-#else
-bool REMOTE_SCRIPT::PreparePacket(char * buf, size_t bufSize, RS::USER & rsu, bool forceDisconnect) const
-#endif
-{
-RS::PACKET_HEADER packetHead;
-
-memset(packetHead.padding, 0, sizeof(packetHead.padding));
-strcpy((char*)packetHead.magic, RS_ID);
-packetHead.protoVer[0] = '0';
-packetHead.protoVer[1] = '2';
-if (forceDisconnect)
-    {
-    packetHead.packetType = RS_DISCONNECT_PACKET;
-    printfd(__FILE__, "RSCRIPT: force disconnect for '%s'\n", rsu.user->GetLogin().c_str());
-    }
-else
-    {
-    if (rsu.shortPacketsCount % MAX_SHORT_PCKT == 0)
-        {
-        //SendLong
-        packetHead.packetType = rsu.user->IsInetable() ? RS_CONNECT_PACKET : RS_DISCONNECT_PACKET;
-        if (rsu.user->IsInetable())
-            printfd(__FILE__, "RSCRIPT: connect for '%s'\n", rsu.user->GetLogin().c_str());
-        else
-            printfd(__FILE__, "RSCRIPT: disconnect for '%s'\n", rsu.user->GetLogin().c_str());
-        }
-    else
-        {
-        //SendShort
-        packetHead.packetType = rsu.user->IsInetable() ? RS_ALIVE_PACKET : RS_DISCONNECT_PACKET;
-        if (rsu.user->IsInetable())
-            printfd(__FILE__, "RSCRIPT: alive for '%s'\n", rsu.user->GetLogin().c_str());
-        else
-            printfd(__FILE__, "RSCRIPT: disconnect for '%s'\n", rsu.user->GetLogin().c_str());
-        }
-    }
-rsu.shortPacketsCount++;
-rsu.lastSentTime = stgTime;
-
-packetHead.ip = htonl(rsu.ip);
-packetHead.id = htonl(rsu.user->GetID());
-strncpy((char*)packetHead.login, rsu.user->GetLogin().c_str(), RS_LOGIN_LEN);
-packetHead.login[RS_LOGIN_LEN - 1] = 0;
-
-memcpy(buf, &packetHead, sizeof(packetHead));
-
-if (packetHead.packetType == RS_ALIVE_PACKET)
-    {
-    return false;
-    }
-
-RS::PACKET_TAIL packetTail;
-
-memset(packetTail.padding, 0, sizeof(packetTail.padding));
-strcpy((char*)packetTail.magic, RS_ID);
-std::vector<std::string>::const_iterator it;
-std::string params;
-for(it = rsSettings.GetUserParams().begin();
-    it != rsSettings.GetUserParams().end();
-    ++it)
-    {
-    std::string parameter(rsu.user->GetParamValue(it->c_str()));
-    if (params.length() + parameter.length() > RS_PARAMS_LEN - 1)
-    {
-        logger("Script params string length %d exceeds the limit of %d symbols.", params.length() + parameter.length(), RS_PARAMS_LEN);
-        break;
-    }
-    params += parameter + " ";
-    }
-strncpy((char *)packetTail.params, params.c_str(), RS_PARAMS_LEN);
-packetTail.params[RS_PARAMS_LEN - 1] = 0;
-
-assert(sizeof(packetHead) + sizeof(packetTail) <= bufSize && "Insufficient buffer space");
-
-Encrypt(&ctx, buf + sizeof(packetHead), (char *)&packetTail, sizeof(packetTail) / 8);
-
-return false;
-}
-//-----------------------------------------------------------------------------
-bool REMOTE_SCRIPT::Send(RS::USER & rsu, bool forceDisconnect) const
-{
-char buffer[RS_MAX_PACKET_LEN];
-
-memset(buffer, 0, sizeof(buffer));
-
-if (PreparePacket(buffer, sizeof(buffer), rsu, forceDisconnect))
-    {
-    printfd(__FILE__, "REMOTE_SCRIPT::Send() - Invalid packet length!\n");
-    return true;
-    }
-
-std::for_each(
-        rsu.routers.begin(),
-        rsu.routers.end(),
-        PacketSender(sock, buffer, sizeof(buffer), static_cast<uint16_t>(htons(rsSettings.GetPort())))
-        );
-
-return false;
-}
-//-----------------------------------------------------------------------------
-bool REMOTE_SCRIPT::SendDirect(RS::USER & rsu, uint32_t routerIP, bool forceDisconnect) const
-{
-char buffer[RS_MAX_PACKET_LEN];
-
-if (PreparePacket(buffer, sizeof(buffer), rsu, forceDisconnect))
-    {
-    printfd(__FILE__, "REMOTE_SCRIPT::SendDirect() - Invalid packet length!\n");
-    return true;
-    }
-
-struct sockaddr_in sendAddr;
-
-sendAddr.sin_family = AF_INET;
-sendAddr.sin_port = static_cast<uint16_t>(htons(rsSettings.GetPort()));
-sendAddr.sin_addr.s_addr = routerIP;
-
-ssize_t res = sendto(sock, buffer, sizeof(buffer), 0, (struct sockaddr *)&sendAddr, sizeof(sendAddr));
-
-if (res < 0)
-    logger("sendto error: %s", strerror(errno));
-
-return (res != sizeof(buffer));
-}
-//-----------------------------------------------------------------------------
-bool REMOTE_SCRIPT::GetUsers()
-{
-UserPtr u;
-
-int h = users->OpenSearch();
-assert(h && "USERS::OpenSearch is always correct");
-
-while (!users->SearchNext(h, &u))
-    {
-    SetUserNotifiers(u);
-    }
-
-users->CloseSearch(h);
-return false;
-}
-//-----------------------------------------------------------------------------
-std::vector<uint32_t> REMOTE_SCRIPT::IP2Routers(uint32_t ip)
-{
-STG_LOCKER lock(&mutex);
-for (size_t i = 0; i < netRouters.size(); ++i)
-    {
-    if ((ip & netRouters[i].subnetMask) == (netRouters[i].subnetIP & netRouters[i].subnetMask))
-        {
-        return netRouters[i].routers;
-        }
-    }
-return std::vector<uint32_t>();
-}
-//-----------------------------------------------------------------------------
-void REMOTE_SCRIPT::SetUserNotifiers(UserPtr u)
-{
-ipNotifierList.push_front(RS::IP_NOTIFIER(*this, u));
-connNotifierList.push_front(RS::CONNECTED_NOTIFIER(*this, u));
-}
-//-----------------------------------------------------------------------------
-void REMOTE_SCRIPT::UnSetUserNotifiers(UserPtr u)
-{
-ipNotifierList.erase(std::remove_if(ipNotifierList.begin(),
-                                    ipNotifierList.end(),
-                                    USER_IS<IP_NOTIFIER>(u)),
-                     ipNotifierList.end());
-connNotifierList.erase(std::remove_if(connNotifierList.begin(),
-                                      connNotifierList.end(),
-                                      USER_IS<CONNECTED_NOTIFIER>(u)),
-                       connNotifierList.end());
-
-}
-//-----------------------------------------------------------------------------
-void REMOTE_SCRIPT::AddRSU(UserPtr user)
-{
-RS::USER rsu(IP2Routers(user->GetCurrIP()), user);
-Send(rsu);
-
-STG_LOCKER lock(&mutex);
-authorizedUsers.insert(std::make_pair(user->GetCurrIP(), rsu));
-}
-//-----------------------------------------------------------------------------
-void REMOTE_SCRIPT::DelRSU(UserPtr user)
-{
-STG_LOCKER lock(&mutex);
-std::map<uint32_t, RS::USER>::iterator it(authorizedUsers.begin());
-while (it != authorizedUsers.end())
-    {
-    if (it->second.user == user)
-        {
-        Send(it->second, true);
-        authorizedUsers.erase(it);
-        return;
-        }
-    ++it;
-    }
-/*const std::map<uint32_t, RS::USER>::iterator it(
-        authorizedUsers.find(user->GetCurrIP())
-        );
-if (it != authorizedUsers.end())
-    {
-    Send(it->second, true);
-    authorizedUsers.erase(it);
-    }*/
-}
-//-----------------------------------------------------------------------------
-void RS::IP_NOTIFIER::Notify(const uint32_t & /*oldValue*/, const uint32_t & newValue)
-{
-if (newValue)
-    rs.AddRSU(user);
-else
-    rs.DelRSU(user);
-}
-//-----------------------------------------------------------------------------
-void RS::CONNECTED_NOTIFIER::Notify(const bool & /*oldValue*/, const bool & newValue)
-{
-if (newValue)
-    rs.AddRSU(user);
-else
-    rs.DelRSU(user);
-}
-//-----------------------------------------------------------------------------
-void REMOTE_SCRIPT::InitEncrypt(BLOWFISH_CTX * ctx, const std::string & password) const
-{
-unsigned char keyL[PASSWD_LEN];  // Пароль для шифровки
-memset(keyL, 0, PASSWD_LEN);
-strncpy((char *)keyL, password.c_str(), PASSWD_LEN);
-Blowfish_Init(ctx, keyL, PASSWD_LEN);
-}
-//-----------------------------------------------------------------------------
-void REMOTE_SCRIPT::Encrypt(BLOWFISH_CTX * ctx, void * dst, const void * src, size_t len8) const
-{
-if (dst != src)
-    memcpy(dst, src, len8 * 8);
-for (size_t i = 0; i < len8; ++i)
-    Blowfish_Encrypt(ctx, static_cast<uint32_t *>(dst) + i * 2, static_cast<uint32_t *>(dst) + i * 2 + 1);
-}
-//-----------------------------------------------------------------------------
diff --git a/stargazer/plugins/other/rscript/rscript.h b/stargazer/plugins/other/rscript/rscript.h
deleted file mode 100644 (file)
index e734227..0000000
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#pragma once
-
-#include "stg/plugin.h"
-#include "stg/module_settings.h"
-#include "stg/notifer.h"
-#include "stg/user.h"
-#include "stg/blowfish.h"
-#include "stg/rs_packets.h"
-#include "stg/logger.h"
-
-#include "nrmap_parser.h"
-
-#include <string>
-#include <list>
-#include <map>
-#include <functional>
-#include <utility>
-#include <cstdint>
-
-#include <pthread.h>
-
-namespace STG
-{
-struct Settings;
-struct Settings;
-}
-
-namespace RS
-{
-
-class REMOTE_SCRIPT;
-class UpdateRouter;
-class DisconnectUser;
-
-using UserPtr = STG::User*;
-
-//-----------------------------------------------------------------------------
-class ADD_USER_NONIFIER: public STG::NotifierBase<UserPtr> {
-public:
-    explicit ADD_USER_NONIFIER(REMOTE_SCRIPT & r)
-        : rs(r) {}
-    void Notify(const UserPtr & user);
-
-private:
-    ADD_USER_NONIFIER(const ADD_USER_NONIFIER & rhs);
-    ADD_USER_NONIFIER & operator=(const ADD_USER_NONIFIER);
-
-    REMOTE_SCRIPT & rs;
-};
-//-----------------------------------------------------------------------------
-class DEL_USER_NONIFIER: public STG::NotifierBase<UserPtr> {
-public:
-    explicit DEL_USER_NONIFIER(REMOTE_SCRIPT & r)
-        : rs(r) {}
-    void Notify(const UserPtr & user);
-
-private:
-    DEL_USER_NONIFIER(const DEL_USER_NONIFIER & rhs);
-    DEL_USER_NONIFIER & operator=(const DEL_USER_NONIFIER);
-
-    REMOTE_SCRIPT & rs;
-};
-//-----------------------------------------------------------------------------
-class IP_NOTIFIER: public STG::PropertyNotifierBase<uint32_t> {
-public:
-    IP_NOTIFIER(REMOTE_SCRIPT & r, UserPtr u)
-        : user(u), rs(r) { user->AddCurrIPAfterNotifier(this); }
-    IP_NOTIFIER(const IP_NOTIFIER & rhs)
-        : user(rhs.user), rs(rhs.rs) { user->AddCurrIPAfterNotifier(this); }
-    ~IP_NOTIFIER() { user->DelCurrIPAfterNotifier(this); }
-
-    IP_NOTIFIER & operator=(const IP_NOTIFIER & rhs)
-    {
-        user->DelCurrIPAfterNotifier(this);
-        user = rhs.user;
-        user->AddCurrIPAfterNotifier(this);
-        return *this;
-    }
-
-    void Notify(const uint32_t & oldValue, const uint32_t & newValue);
-    UserPtr GetUser() const { return user; }
-
-private:
-
-    UserPtr user;
-    REMOTE_SCRIPT & rs;
-};
-//-----------------------------------------------------------------------------
-class CONNECTED_NOTIFIER: public STG::PropertyNotifierBase<bool> {
-public:
-    CONNECTED_NOTIFIER(REMOTE_SCRIPT & r, UserPtr u)
-        : user(u), rs(r) { user->AddConnectedAfterNotifier(this); }
-    CONNECTED_NOTIFIER(const CONNECTED_NOTIFIER & rhs)
-        : user(rhs.user), rs(rhs.rs) { user->AddConnectedAfterNotifier(this); }
-    ~CONNECTED_NOTIFIER() { user->DelConnectedAfterNotifier(this); }
-
-    CONNECTED_NOTIFIER & operator=(const CONNECTED_NOTIFIER & rhs)
-    {
-        user->DelConnectedAfterNotifier(this);
-        user = rhs.user;
-        user->AddConnectedAfterNotifier(this);
-        return *this;
-    }
-
-    void Notify(const bool & oldValue, const bool & newValue);
-    UserPtr GetUser() const { return user; }
-
-private:
-
-    UserPtr user;
-    REMOTE_SCRIPT & rs;
-};
-//-----------------------------------------------------------------------------
-struct USER {
-    USER(const std::vector<uint32_t> & r, UserPtr it)
-        : lastSentTime(0),
-          user(it),
-          routers(r),
-          shortPacketsCount(0),
-          ip(user->GetCurrIP())
-    {}
-
-    time_t lastSentTime;
-    UserPtr user;
-    std::vector<uint32_t> routers;
-    int shortPacketsCount;
-    uint32_t ip;
-};
-//-----------------------------------------------------------------------------
-class SETTINGS {
-public:
-                        SETTINGS();
-    virtual             ~SETTINGS() {}
-    const std::string & GetStrError() const { return errorStr; }
-    int                 ParseSettings(const STG::ModuleSettings & s);
-    int                 GetSendPeriod() const { return sendPeriod; }
-    uint16_t            GetPort() const { return port; }
-    const std::vector<NET_ROUTER> & GetSubnetsMap() const { return netRouters; }
-    const std::vector<std::string> & GetUserParams() const { return userParams; }
-    const std::string & GetPassword() const { return password; }
-    const std::string & GetMapFileName() const { return subnetFile; }
-
-private:
-    int                 sendPeriod;
-    uint16_t            port;
-    std::string         errorStr;
-    std::vector<NET_ROUTER> netRouters;
-    std::vector<std::string> userParams;
-    std::string         password;
-    std::string         subnetFile;
-};
-//-----------------------------------------------------------------------------
-class REMOTE_SCRIPT : public STG::Plugin {
-public:
-                        REMOTE_SCRIPT();
-                        ~REMOTE_SCRIPT() override;
-
-    void                SetUsers(STG::Users * u) override { users = u; }
-    void                SetSettings(const STG::ModuleSettings & s) override { settings = s; }
-    int                 ParseSettings() override;
-
-    int                 Start() override;
-    int                 Stop() override;
-    int                 Reload(const STG::ModuleSettings & ms) override;
-    bool                IsRunning() override { return isRunning; }
-
-    const std::string & GetStrError() const override { return errorStr; }
-    std::string         GetVersion() const override { return "Remote script v 0.3"; }
-    uint16_t            GetStartPosition() const override { return 10; }
-    uint16_t            GetStopPosition() const override { return 10; }
-
-    void                DelUser(UserPtr u) { UnSetUserNotifiers(u); }
-    void                AddUser(UserPtr u) { SetUserNotifiers(u); }
-
-    void                AddRSU(UserPtr user);
-    void                DelRSU(UserPtr user);
-
-private:
-    REMOTE_SCRIPT(const REMOTE_SCRIPT & rhs);
-    REMOTE_SCRIPT & operator=(const REMOTE_SCRIPT & rhs);
-
-    static void *       Run(void *);
-    bool                PrepareNet();
-    bool                FinalizeNet();
-
-    bool                Send(USER & rsu, bool forceDisconnect = false) const;
-    bool                SendDirect(USER & rsu, uint32_t routerIP, bool forceDisconnect = false) const;
-    bool                PreparePacket(char * buf, size_t bufSize, USER &rsu, bool forceDisconnect = false) const;
-    void                PeriodicSend();
-
-    std::vector<uint32_t> IP2Routers(uint32_t ip);
-    bool                GetUsers();
-
-    void                SetUserNotifiers(UserPtr u);
-    void                UnSetUserNotifiers(UserPtr u);
-
-    void                InitEncrypt(BLOWFISH_CTX * ctx, const std::string & password) const;
-    void                Encrypt(BLOWFISH_CTX * ctx, void * dst, const void * src, size_t len8) const;
-
-    mutable BLOWFISH_CTX ctx;
-
-    std::list<IP_NOTIFIER> ipNotifierList;
-    std::list<CONNECTED_NOTIFIER> connNotifierList;
-    std::map<uint32_t, USER> authorizedUsers;
-
-    mutable std::string errorStr;
-    SETTINGS         rsSettings;
-    STG::ModuleSettings     settings;
-    int                 sendPeriod;
-    int                 halfPeriod;
-
-    bool                nonstop;
-    bool                isRunning;
-
-    STG::Users *             users;
-
-    std::vector<NET_ROUTER> netRouters;
-
-    pthread_t           thread;
-    pthread_mutex_t     mutex;
-
-    int                 sock;
-
-    ADD_USER_NONIFIER onAddUserNotifier;
-    DEL_USER_NONIFIER onDelUserNotifier;
-
-    STG::PluginLogger       logger;
-
-    friend class RS::UpdateRouter;
-    friend class RS::DisconnectUser;
-    friend class RS::CONNECTED_NOTIFIER;
-};
-//-----------------------------------------------------------------------------
-class DisconnectUser : public std::unary_function<std::pair<const uint32_t, USER> &, void> {
-    public:
-        explicit DisconnectUser(REMOTE_SCRIPT & rs) : rscript(rs) {}
-        void operator()(std::pair<const uint32_t, USER> & p)
-        {
-            rscript.Send(p.second, true);
-        }
-    private:
-        REMOTE_SCRIPT & rscript;
-};
-//-----------------------------------------------------------------------------
-inline void ADD_USER_NONIFIER::Notify(const UserPtr & user)
-{
-rs.AddUser(user);
-}
-//-----------------------------------------------------------------------------
-inline void DEL_USER_NONIFIER::Notify(const UserPtr & user)
-{
-rs.DelUser(user);
-}
-//-----------------------------------------------------------------------------
-
-} // namespace RS
diff --git a/stargazer/plugins/other/rscript/send_functor.h b/stargazer/plugins/other/rscript/send_functor.h
deleted file mode 100644 (file)
index fbe6d3b..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-/*
- $Revision: 1.2 $
- $Date: 2010/03/04 12:11:09 $
- $Author: faust $
-*/
-
-#ifndef __SEND_FUNCTOR_H__
-#define __SEND_FUNCTOR_H__
-
-#include <functional>
-#include <cstdint>
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
-
-class PacketSender : public std::unary_function<uint32_t, ssize_t> {
-    public:
-        PacketSender(int s, char * b, size_t l, uint16_t p)
-            : sock(s),
-              buffer(b),
-              length(l),
-              port(p) {}
-        ssize_t operator() (uint32_t ip)
-        {
-        struct sockaddr_in sendAddr;
-
-        sendAddr.sin_family = AF_INET;
-        sendAddr.sin_port = port;
-        sendAddr.sin_addr.s_addr = ip;
-
-        return sendto(sock, buffer, length, 0, (struct sockaddr*)&sendAddr, sizeof(sendAddr));
-        }
-    private:
-        int sock;
-        char * buffer;
-        size_t length;
-        uint16_t port;
-};
-
-#endif
diff --git a/stargazer/plugins/other/rscript/ur_functor.h b/stargazer/plugins/other/rscript/ur_functor.h
deleted file mode 100644 (file)
index 95b03ea..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#ifndef __UR_FUNCTOR_H__
-#define __UR_FUNCTOR_H__
-
-#include "rscript.h"
-
-#include "stg/common.h"
-
-#include <functional>
-#include <algorithm>
-#include <utility>
-#include <cstdint>
-
-namespace RS
-{
-
-class UpdateRouter : public std::unary_function<std::pair<const uint32_t, RS::USER>, void>
-{
-public:
-    explicit UpdateRouter(REMOTE_SCRIPT & t)
-        : obj(t) {}
-
-    void operator() (std::pair<const uint32_t, USER> & val)
-        {
-        std::vector<uint32_t> newRouters = obj.IP2Routers(val.second.ip);
-        std::vector<uint32_t>::const_iterator oldIt(val.second.routers.begin());
-        std::vector<uint32_t>::const_iterator newIt(newRouters.begin());
-        val.second.shortPacketsCount = 0;
-        while (oldIt != val.second.routers.end() ||
-               newIt != newRouters.end())
-            {
-            if (oldIt == val.second.routers.end())
-                {
-                if (newIt != newRouters.end())
-                    {
-                    obj.SendDirect(val.second, *newIt); // Connect on new router
-                    ++newIt;
-                    }
-                }
-            else if (newIt == newRouters.end())
-                {
-                obj.SendDirect(val.second, *oldIt, true); // Disconnect on old router
-                ++oldIt;
-                }
-            else if (*oldIt < *newIt)
-                {
-                obj.SendDirect(val.second, *oldIt, true); // Disconnect on old router
-                ++oldIt;
-                }
-            else if (*oldIt > *newIt)
-                {
-                obj.SendDirect(val.second, *newIt); // Connect on new router
-                ++newIt;
-                }
-            else
-                {
-                ++oldIt;
-                if (newIt != newRouters.end())
-                    ++newIt;
-                }
-            }
-        val.second.routers = newRouters;
-        }
-private:
-    REMOTE_SCRIPT & obj;
-};
-
-} // namespace RS
-
-#endif
diff --git a/stargazer/plugins/other/smux/STG-MIB.mib b/stargazer/plugins/other/smux/STG-MIB.mib
deleted file mode 100644 (file)
index bccf5a2..0000000
+++ /dev/null
@@ -1,231 +0,0 @@
-STG-MIB DEFINITIONS ::= BEGIN
-
-IMPORTS
-    enterprises,
-    MODULE-IDENTITY, OBJECT-TYPE,
-    Integer32                       FROM SNMPv2-SMI
-    DisplayString                   FROM SNMPv2-TC;
-
-stgMIB MODULE-IDENTITY
-    LAST-UPDATED "201101060000Z"
-    ORGANIZATION "STG"
-    CONTACT-INFO    
-        "Primary Contact: Maxim Mamontov
-         email:     faust@stg.dp.ua"
-    DESCRIPTION
-        "This MIB module defines objects for Stargazer data."
-    REVISION     "201101060000Z"
-    DESCRIPTION "Initial revision"
-    ::= { enterprises 38313 }
-
-stg24 OBJECT IDENTIFIER ::= { stgMIB 1 }
-
-users OBJECT IDENTIFIER ::= { stg24 1 }
-tariffs OBJECT IDENTIFIER ::= { stg24 2 }
-admins OBJECT IDENTIFIER ::= { stg24 3 }
-services OBJECT IDENTIFIER ::= { stg24 4 }
-corporations OBJECT IDENTIFIER ::= { stg24 5 }
-traffcounter OBJECT IDENTIFIER ::= { stg24 6 }
-
-totalUsers OBJECT-TYPE
-    SYNTAX      Integer32
-    MAX-ACCESS  read-only
-    STATUS      current
-    DESCRIPTION
-       "Total users registered in the billing"
-    DEFVAL { 0 }
-    ::= { users 1 }
-
-onlineUsers OBJECT-TYPE
-    SYNTAX      Integer32
-    MAX-ACCESS  read-only
-    STATUS      current
-    DESCRIPTION
-       "The number of currently online users"
-    DEFVAL { 0 }
-    ::= { users 2 }
-
-authorizedUsers OBJECT-TYPE
-    SYNTAX      Integer32
-    MAX-ACCESS  read-only
-    STATUS      current
-    DESCRIPTION
-       "The number of currently authorized users"
-    DEFVAL { 0 }
-    ::= { users 3 }
-
-alwaysOnlineUsers OBJECT-TYPE
-    SYNTAX      Integer32
-    MAX-ACCESS  read-only
-    STATUS      current
-    DESCRIPTION
-       "The number of users with 'always online' option"
-    DEFVAL { 0 }
-    ::= { users 4 }
-
-noCashUsers OBJECT-TYPE
-    SYNTAX      Integer32
-    MAX-ACCESS  read-only
-    STATUS      current
-    DESCRIPTION
-       "The number of users with negative cash"
-    DEFVAL { 0 }
-    ::= { users 5 }
-
-disabledDetailStatsUsers OBJECT-TYPE
-    SYNTAX      Integer32
-    MAX-ACCESS  read-only
-    STATUS      current
-    DESCRIPTION
-       "The number of users with disabled detail stats"
-    DEFVAL { 0 }
-    ::= { users 6 }
-
-disabledUsers OBJECT-TYPE
-    SYNTAX      Integer32
-    MAX-ACCESS  read-only
-    STATUS      current
-    DESCRIPTION
-       "The number of disabled users"
-    DEFVAL { 0 }
-    ::= { users 7 }
-
-passiveUsers OBJECT-TYPE
-    SYNTAX      Integer32
-    MAX-ACCESS  read-only
-    STATUS      current
-    DESCRIPTION
-       "The number of passive users"
-    DEFVAL { 0 }
-    ::= { users 8 }
-
-creditUsers OBJECT-TYPE
-    SYNTAX      Integer32
-    MAX-ACCESS  read-only
-    STATUS      current
-    DESCRIPTION
-       "The number of users with positive credit"
-    DEFVAL { 0 }
-    ::= { users 9 }
-
-freeMbUsers OBJECT-TYPE
-    SYNTAX      Integer32
-    MAX-ACCESS  read-only
-    STATUS      current
-    DESCRIPTION
-       "The number of users with positive freeMb"
-    DEFVAL { 0 }
-    ::= { users 10 }
-
-tariffChangeUsers OBJECT-TYPE
-    SYNTAX      Integer32
-    MAX-ACCESS  read-only
-    STATUS      current
-    DESCRIPTION
-       "The number of users changing tariff next month"
-    DEFVAL { 0 }
-    ::= { users 11 }
-
-activeUsers OBJECT-TYPE
-    SYNTAX      Integer32
-    MAX-ACCESS  read-only
-    STATUS      current
-    DESCRIPTION
-        "The number of online users with traffic during session"
-    DEFVAL {0}
-    ::= { users 12 }
-
-totalTariffs OBJECT-TYPE
-    SYNTAX      Integer32
-    MAX-ACCESS  read-only
-    STATUS      current
-    DESCRIPTION
-       "Total tariffs registered in the billing"
-    DEFVAL { 0 }
-    ::= { tariffs 1 }
-
-tariffUsageTable OBJECT-TYPE
-    SYNTAX      SEQUENCE OF TariffUsageTable
-    MAX-ACCESS  not-accessible
-    STATUS      current
-    DESCRIPTION
-       "The number of users by each tariff"
-    DEFVAL { 0 }
-    ::= { tariffs 2 }
-
-tariffUsageTableEntry OBJECT-TYPE
-    SYNTAX      TariffUsageTable
-    MAX-ACCESS  not-accessible
-    STATUS      current
-    DESCRIPTION
-        "A row describing a given tariff"
-    INDEX   { tariffIndex }
-    ::= {tariffUsageTable 1 }
-
-TariffUsageTable ::= SEQUENCE {
-    tariffIndex Integer32,
-    tariffName DisplayString,
-    userCount Integer32
-}
-
-tariffIndex OBJECT-TYPE
-    SYNTAX      Integer32 (0..255)
-    MAX-ACCESS  not-accessible
-    STATUS      current
-    DESCRIPTION
-        "The id of the tariff this table describes."
-    ::= { tariffUsageTableEntry 1 }
-
-tariffName OBJECT-TYPE
-    SYNTAX      DisplayString
-    MAX-ACCESS  read-only
-    STATUS      current
-    DESCRIPTION
-        "The name of the tariff this table describes."
-    ::= { tariffUsageTableEntry 2 }
-
-userCount OBJECT-TYPE
-    SYNTAX      Integer32
-    MAX-ACCESS  read-only
-    STATUS      current
-    DESCRIPTION
-        "The count fo users of the tariff this table describes."
-    ::= { tariffUsageTableEntry 3 }
-
-totalAdmins OBJECT-TYPE
-    SYNTAX      Integer32
-    MAX-ACCESS  read-only
-    STATUS      current
-    DESCRIPTION
-       "Total admins registered in the billing"
-    DEFVAL { 0 }
-    ::= { admins 1 }
-
-totalServices OBJECT-TYPE
-    SYNTAX      Integer32
-    MAX-ACCESS  read-only
-    STATUS      current
-    DESCRIPTION
-       "Total services registered in the billing"
-    DEFVAL { 0 }
-    ::= { services 1 }
-
-totalCorporations OBJECT-TYPE
-    SYNTAX      Integer32
-    MAX-ACCESS  read-only
-    STATUS      current
-    DESCRIPTION
-       "Total corporations registered in the billing"
-    DEFVAL { 0 }
-    ::= { corporations 1 }
-
-totalRules OBJECT-TYPE
-    SYNTAX      Integer32
-    MAX-ACCESS  read-only
-    STATUS      current
-    DESCRIPTION
-        "Total traffic classification rules described by rules file"
-    DEFVAL { 0 }
-    ::= { traffcounter 1 }
-
-END
diff --git a/stargazer/plugins/other/smux/TODO b/stargazer/plugins/other/smux/TODO
deleted file mode 100644 (file)
index 03dc09d..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-Количество пользователей всего в биллинге
-Количество пользователей онлайн
-Количество пользователей с отрицательный балансом
-Количество пользователей с всегда онлайн
-Количество пользователей по отношению к каждому из тарифов
-Количество пользователей по отношению к каждому UserData полю - ?
-Количество пользователей с отключенной детальной статистикой
-Количество отключенных пользователей
-Количество замороженных пользователей
-Количество пользователей, у которых есть кредит
-Количество пользователей, у которых есть предоплаченный трафик
-
-Количество тарифов
-Количество направлений
diff --git a/stargazer/plugins/other/smux/handlers.cpp b/stargazer/plugins/other/smux/handlers.cpp
deleted file mode 100644 (file)
index ac179da..0000000
+++ /dev/null
@@ -1,191 +0,0 @@
-#include <cassert>
-
-#include "stg/GetRequest-PDU.h"
-#include "stg/GetResponse-PDU.h"
-#include "stg/VarBindList.h"
-#include "stg/VarBind.h"
-
-#include "stg/common.h"
-
-#include "utils.h"
-#include "smux.h"
-
-#ifdef SMUX_DEBUG
-bool SMUX::CloseHandler(const SMUX_PDUs_t * pdus)
-{
-printfd(__FILE__, "SMUX::CloseHandler()\n");
-asn_fprint(stderr, &asn_DEF_SMUX_PDUs, pdus);
-return true;
-}
-#else
-bool SMUX::CloseHandler(const SMUX_PDUs_t *)
-{
-return true;
-}
-#endif
-
-#ifdef SMUX_DEBUG
-bool SMUX::RegisterResponseHandler(const SMUX_PDUs_t * pdus)
-{
-printfd(__FILE__, "SMUX::RegisterResponseHandler()\n");
-asn_fprint(stderr, &asn_DEF_SMUX_PDUs, pdus);
-return true;
-}
-#else
-bool SMUX::RegisterResponseHandler(const SMUX_PDUs_t *)
-{
-return true;
-}
-#endif
-
-bool SMUX::PDUsRequestHandler(const SMUX_PDUs_t * pdus)
-{
-#ifdef SMUX_DEBUG
-printfd(__FILE__, "SMUX::PDUsRequestHandler()\n");
-asn_fprint(stderr, &asn_DEF_SMUX_PDUs, pdus);
-#endif
-PDUsHandlers::iterator it(pdusHandlers.find(pdus->choice.pdus.present));
-if (it != pdusHandlers.end())
-    {
-    return (this->*(it->second))(&pdus->choice.pdus);
-    }
-#ifdef SMUX_DEBUG
-else
-    {
-    switch (pdus->present)
-        {
-        case PDUs_PR_NOTHING:
-            printfd(__FILE__, "SMUX::PDUsRequestHandler() - nothing\n");
-            break;
-        case PDUs_PR_get_response:
-            printfd(__FILE__, "SMUX::PDUsRequestHandler() - get response\n");
-            break;
-        case PDUs_PR_trap:
-            printfd(__FILE__, "SMUX::PDUsRequestHandler() - trap\n");
-            break;
-        default:
-            printfd(__FILE__, "SMUX::PDUsRequestHandler() - undefined\n");
-        }
-    }
-#endif
-return true;
-}
-
-#ifdef SMUX_DEBUG
-bool SMUX::CommitOrRollbackHandler(const SMUX_PDUs_t * pdus)
-{
-printfd(__FILE__, "SMUX::CommitOrRollbackHandler()\n");
-asn_fprint(stderr, &asn_DEF_SMUX_PDUs, pdus);
-return true;
-}
-#else
-bool SMUX::CommitOrRollbackHandler(const SMUX_PDUs_t *)
-{
-return true;
-}
-#endif
-
-bool SMUX::GetRequestHandler(const PDUs_t * pdus)
-{
-#ifdef SMUX_DEBUG
-printfd(__FILE__, "SMUX::GetRequestHandler()\n");
-asn_fprint(stderr, &asn_DEF_PDUs, pdus);
-#endif
-const GetRequest_PDU_t * getRequest = &pdus->choice.get_request;
-GetResponse_PDU_t * msg = static_cast<GetResponse_PDU_t *>(calloc(1, sizeof(GetResponse_PDU_t)));
-assert(msg && "Enought mempry to allocate GetResponse_PDU_t");
-VarBindList_t * varBindList = &msg->variable_bindings;
-
-long id = 0;
-asn_INTEGER2long(&getRequest->request_id, &id);
-asn_long2INTEGER(&msg->request_id, id);
-asn_long2INTEGER(&msg->error_status, 0);
-asn_long2INTEGER(&msg->error_index, 0);
-
-const VarBindList_t * vbl = &getRequest->variable_bindings; 
-for (int i = 0; i < vbl->list.count; ++i)
-    {
-    VarBind_t * vb = getRequest->variable_bindings.list.array[i];
-    Sensors::iterator it;
-    it = sensors.find(OID(&vb->name));
-    if (it == sensors.end())
-        {
-        return SendGetResponseErrorPDU(sock, getRequest,
-                                       PDU__error_status_noSuchName, i);
-        }
-
-    VarBind_t * newVb = static_cast<VarBind_t *>(calloc(1, sizeof(VarBind_t)));
-    assert(newVb && "Enought mempry to allocate VarBind_t");
-
-    it->first.ToOID(&newVb->name);
-    it->second->GetValue(&newVb->value);
-
-    ASN_SEQUENCE_ADD(varBindList, newVb);
-    }
-
-bool res = SendGetResponsePDU(sock, msg);
-#ifdef SMUX_DEBUG
-asn_fprint(stderr, &asn_DEF_GetResponse_PDU, msg);
-#endif
-ASN_STRUCT_FREE(asn_DEF_GetResponse_PDU, msg);
-return res;
-}
-
-bool SMUX::GetNextRequestHandler(const PDUs_t * pdus)
-{
-#ifdef SMUX_DEBUG
-printfd(__FILE__, "SMUX::GetNextRequestHandler()\n");
-asn_fprint(stderr, &asn_DEF_PDUs, pdus);
-#endif
-const GetRequest_PDU_t * getRequest = &pdus->choice.get_request;
-GetResponse_PDU_t * msg = static_cast<GetResponse_PDU_t *>(calloc(1, sizeof(GetResponse_PDU_t)));
-assert(msg && "Enought mempry to allocate GetResponse_PDU_t");
-VarBindList_t * varBindList = &msg->variable_bindings;
-
-long id = 0;
-asn_INTEGER2long(&getRequest->request_id, &id);
-asn_long2INTEGER(&msg->request_id, id);
-asn_long2INTEGER(&msg->error_status, 0);
-asn_long2INTEGER(&msg->error_index, 0);
-
-const VarBindList_t * vbl = &getRequest->variable_bindings; 
-for (int i = 0; i < vbl->list.count; ++i)
-    {
-    VarBind_t * vb = getRequest->variable_bindings.list.array[i];
-    Sensors::iterator it;
-    it = sensors.upper_bound(OID(&vb->name));
-    if (it == sensors.end())
-        {
-#ifdef SMUX_DEBUG
-        printfd(__FILE__, "SMUX::GetNextRequestHandler() - '%s' not found\n", OID(&vb->name).ToString().c_str());
-#endif
-        return SendGetResponseErrorPDU(sock, getRequest,
-                                       PDU__error_status_noSuchName, i);
-        }
-
-    VarBind_t * newVb = static_cast<VarBind_t *>(calloc(1, sizeof(VarBind_t)));
-    assert(newVb && "Enought mempry to allocate VarBind_t");
-
-    it->first.ToOID(&newVb->name);
-    it->second->GetValue(&newVb->value);
-
-    ASN_SEQUENCE_ADD(varBindList, newVb);
-    }
-
-bool res = SendGetResponsePDU(sock, msg);
-#ifdef SMUX_DEBUG
-asn_fprint(stderr, &asn_DEF_PDU, msg);
-#endif
-ASN_STRUCT_FREE(asn_DEF_GetResponse_PDU, msg);
-return res;
-}
-
-bool SMUX::SetRequestHandler(const PDUs_t * pdus)
-{
-#ifdef SMUX_DEBUG
-printfd(__FILE__, "SMUX::SetRequestHandler()\n");
-asn_fprint(stderr, &asn_DEF_PDUs, pdus);
-#endif
-return SendGetResponseErrorPDU(sock, &pdus->choice.set_request,
-                               PDU__error_status_readOnly, 0);
-}
diff --git a/stargazer/plugins/other/smux/pen.h b/stargazer/plugins/other/smux/pen.h
deleted file mode 100644 (file)
index 45989bd..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __PEN_H__
-#define __PEN_H__
-
-#define PEN_PREFIX ".1.3.6.1.4.1.38313"
-
-#endif
diff --git a/stargazer/plugins/other/smux/sensors.cpp b/stargazer/plugins/other/smux/sensors.cpp
deleted file mode 100644 (file)
index 9a87cbd..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-#include <cassert>
-
-#include "stg/INTEGER.h"
-
-#include "stg/user.h"
-
-#include "sensors.h"
-
-bool UsersSensor::GetValue(ObjectSyntax_t * objectSyntax) const
-{
-int handle = users.OpenSearch();
-assert(handle && "USERS::OpenSearch is always correct");
-
-STG::User* user;
-size_t count = 0;
-while (!users.SearchNext(handle, &user))
-    {
-    if (UserPredicate(user))
-        ++count;
-    }
-
-users.CloseSearch(handle);
-
-ValueToOS(count, objectSyntax);
-return true;
-}
-
-#ifdef DEBUG
-std::string UsersSensor::ToString() const
-{
-int handle = users.OpenSearch();
-assert(handle && "USERS::OpenSearch is always correct");
-
-STG::User* user;
-size_t count = 0;
-while (!users.SearchNext(handle, &user))
-    {
-    if (UserPredicate(user))
-        ++count;
-    }
-
-users.CloseSearch(handle);
-
-return std::to_string(count);
-}
-#endif
-
-bool ActiveUsersSensor::UserPredicate(STG::User* userPtr) const
-{
-if (!userPtr->GetConnected())
-    return false;
-for (size_t i = 0; i < DIR_NUM; ++i)
-    {
-    if (userPtr->GetSessionUpload()[i] > 0 ||
-        userPtr->GetSessionDownload()[i] > 0)
-        return true;
-    }
-return false;
-}
diff --git a/stargazer/plugins/other/smux/sensors.h b/stargazer/plugins/other/smux/sensors.h
deleted file mode 100644 (file)
index 9215180..0000000
+++ /dev/null
@@ -1,284 +0,0 @@
-#ifndef __SENSORS_H__
-#define __SENSORS_H__
-
-#include <map>
-
-#include "stg/users.h"
-#include "stg/user.h"
-#include "stg/tariffs.h"
-#include "stg/admins.h"
-#include "stg/services.h"
-#include "stg/corporations.h"
-#include "stg/traffcounter.h"
-#include "stg/user_property.h"
-
-#include "stg/ObjectSyntax.h"
-
-#include "value2os.h"
-#include "types.h"
-
-class Sensor {
-    public:
-        virtual ~Sensor() = default;
-        virtual bool GetValue(ObjectSyntax_t * objectSyntax) const = 0;
-#ifdef DEBUG
-        virtual std::string ToString() const = 0;
-#endif
-};
-
-typedef std::map<OID, Sensor *> Sensors;
-
-class TotalUsersSensor : public Sensor {
-    public:
-        explicit TotalUsersSensor(const STG::Users & u) : users(u) {}
-
-        bool GetValue(ObjectSyntax_t * objectSyntax) const override
-        {
-        ValueToOS(users.Count(), objectSyntax);
-        return true;
-        }
-
-#ifdef DEBUG
-        std::string ToString() const override
-        { std::string res; std::to_string(users.Count(), res); return res; }
-#endif
-
-    private:
-        const STG::Users & users;
-};
-
-class UsersSensor : public Sensor {
-    public:
-        explicit UsersSensor(STG::Users & u) : users(u) {}
-
-        bool GetValue(ObjectSyntax_t * objectSyntax) const override;
-#ifdef DEBUG
-        std::string ToString() const override;
-#endif
-
-    private:
-        STG::Users & users;
-
-        virtual bool UserPredicate(STG::User* userPtr) const = 0;
-};
-
-class ConnectedUsersSensor : public UsersSensor {
-    public:
-        explicit ConnectedUsersSensor(STG::Users & u) : UsersSensor(u) {}
-
-    private:
-        bool UserPredicate(STG::User* userPtr) const override
-        { return userPtr->GetConnected(); }
-};
-
-class AuthorizedUsersSensor : public UsersSensor {
-    public:
-        explicit AuthorizedUsersSensor(STG::Users & u) : UsersSensor(u) {}
-
-    private:
-        bool UserPredicate(STG::User* userPtr) const override
-        { return userPtr->GetAuthorized(); }
-};
-
-class AlwaysOnlineUsersSensor : public UsersSensor {
-    public:
-        explicit AlwaysOnlineUsersSensor(STG::Users & u) : UsersSensor(u) {}
-
-    private:
-        bool UserPredicate(STG::User* userPtr) const override
-        { return userPtr->GetProperties().alwaysOnline; }
-};
-
-class NoCashUsersSensor : public UsersSensor {
-    public:
-        explicit NoCashUsersSensor(STG::Users & u) : UsersSensor(u) {}
-
-    private:
-        bool UserPredicate(STG::User* userPtr) const override
-        { return userPtr->GetProperties().cash < 0; }
-};
-
-class DisabledDetailStatsUsersSensor : public UsersSensor {
-    public:
-        explicit DisabledDetailStatsUsersSensor(STG::Users & u) : UsersSensor(u) {}
-
-    private:
-        bool UserPredicate(STG::User* userPtr) const override
-        { return userPtr->GetProperties().disabledDetailStat; }
-};
-
-class DisabledUsersSensor : public UsersSensor {
-    public:
-        explicit DisabledUsersSensor(STG::Users & u) : UsersSensor(u) {}
-
-    private:
-        bool UserPredicate(STG::User* userPtr) const override
-        { return userPtr->GetProperties().disabled; }
-};
-
-class PassiveUsersSensor : public UsersSensor {
-    public:
-        explicit PassiveUsersSensor(STG::Users & u) : UsersSensor(u) {}
-
-    private:
-        bool UserPredicate(STG::User* userPtr) const override
-        { return userPtr->GetProperties().passive; }
-};
-
-class CreditUsersSensor : public UsersSensor {
-    public:
-        explicit CreditUsersSensor(STG::Users & u) : UsersSensor(u) {}
-
-    private:
-        bool UserPredicate(STG::User* userPtr) const override
-        { return userPtr->GetProperties().credit > 0; }
-};
-
-class FreeMbUsersSensor : public UsersSensor {
-    public:
-        explicit FreeMbUsersSensor(STG::Users & u) : UsersSensor(u) {}
-
-    private:
-        bool UserPredicate(STG::User* userPtr) const override
-        { return userPtr->GetProperties().freeMb > 0; }
-};
-
-class TariffChangeUsersSensor : public UsersSensor {
-    public:
-        explicit TariffChangeUsersSensor(STG::Users & u) : UsersSensor(u) {}
-
-    private:
-        bool UserPredicate(STG::User* userPtr) const override
-        { return !userPtr->GetProperties().nextTariff.ConstData().empty(); }
-};
-
-class ActiveUsersSensor : public UsersSensor {
-    public:
-        explicit ActiveUsersSensor(STG::Users & u) : UsersSensor(u) {}
-
-    private:
-        bool UserPredicate(STG::User* userPtr) const override;
-};
-
-class TotalTariffsSensor : public Sensor {
-    public:
-        explicit TotalTariffsSensor(const STG::Tariffs & t) : tariffs(t) {}
-
-        bool GetValue(ObjectSyntax_t * objectSyntax) const override
-        {
-        ValueToOS(tariffs.Count(), objectSyntax);
-        return true;
-        }
-
-#ifdef DEBUG
-        std::string ToString() const override
-        { std::string res; std::to_string(tariffs.Count(), res); return res; }
-#endif
-
-    private:
-        const STG::Tariffs & tariffs;
-};
-
-class TotalAdminsSensor : public Sensor {
-    public:
-        explicit TotalAdminsSensor(const STG::Admins & a) : admins(a) {}
-
-        bool GetValue(ObjectSyntax_t * objectSyntax) const override
-        {
-        ValueToOS(admins.count(), objectSyntax);
-        return true;
-        }
-
-#ifdef DEBUG
-        std::string ToString() const override
-        { std::string res; std::to_string(admins.Count(), res); return res; }
-#endif
-
-    private:
-        const STG::Admins & admins;
-};
-
-class TotalServicesSensor : public Sensor {
-    public:
-        explicit TotalServicesSensor(const STG::Services & s) : services(s) {}
-
-        bool GetValue(ObjectSyntax_t * objectSyntax) const override
-        {
-        ValueToOS(services.Count(), objectSyntax);
-        return true;
-        }
-
-#ifdef DEBUG
-        std::string ToString() const override
-        { std::string res; std::to_string(services.Count(), res); return res; }
-#endif
-
-    private:
-        const STG::Services & services;
-};
-
-class TotalCorporationsSensor : public Sensor {
-    public:
-        explicit TotalCorporationsSensor(const STG::Corporations & c) : corporations(c) {}
-
-        bool GetValue(ObjectSyntax_t * objectSyntax) const override
-        {
-        ValueToOS(corporations.Count(), objectSyntax);
-        return true;
-        }
-
-#ifdef DEBUG
-        std::string ToString() const override
-        { std::string res; std::to_string(corporations.Count(), res); return res; }
-#endif
-
-    private:
-        const STG::Corporations & corporations;
-};
-
-class TotalRulesSensor : public Sensor {
-    public:
-        explicit TotalRulesSensor(const STG::TraffCounter & t) : traffcounter(t) {}
-
-        bool GetValue(ObjectSyntax_t * objectSyntax) const override
-        {
-        ValueToOS(traffcounter.rulesCount(), objectSyntax);
-        return true;
-        }
-
-#ifdef DEBUG
-        std::string ToString() const override
-        { std::string res; std::to_string(traffcounter.rulesCount(), res); return res; }
-#endif
-
-    private:
-        const STG::TraffCounter & traffcounter;
-};
-
-template <typename T>
-class ConstSensor : public Sensor {
-    public:
-        explicit ConstSensor(const T & v) : value(v) {}
-
-        bool GetValue(ObjectSyntax * objectSyntax) const override
-        { return ValueToOS(value, objectSyntax); }
-
-#ifdef DEBUG
-        std::string ToString() const override
-        { std::string res; std::to_string(value, res); return res; }
-#endif
-
-    private:
-        T value;
-};
-
-#ifdef DEBUG
-template <>
-inline
-std::string ConstSensor<std::string>::ToString() const
-{
-return value;
-}
-#endif
-
-#endif
diff --git a/stargazer/plugins/other/smux/smux.cpp b/stargazer/plugins/other/smux/smux.cpp
deleted file mode 100644 (file)
index c74aeae..0000000
+++ /dev/null
@@ -1,512 +0,0 @@
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-
-#include <cstring>
-#include <cerrno>
-#include <ctime>
-#include <csignal>
-#include <cassert>
-
-#include <vector>
-#include <algorithm>
-#include <iterator>
-#include <stdexcept>
-#include <utility>
-
-#include "stg/common.h"
-
-#include "smux.h"
-#include "utils.h"
-
-namespace
-{
-
-bool SPrefixLess(const Sensors::value_type & a,
-                 const Sensors::value_type & b)
-{
-return a.first.PrefixLess(b.first);
-}
-
-}
-
-extern "C" STG::Plugin* GetPlugin()
-{
-    static SMUX plugin;
-    return &plugin;
-}
-
-SMUX_SETTINGS::SMUX_SETTINGS()
-    : errorStr(),
-      ip(0),
-      port(0),
-      password()
-{}
-
-int SMUX_SETTINGS::ParseSettings(const STG::ModuleSettings & s)
-{
-STG::ParamValue pv;
-std::vector<STG::ParamValue>::const_iterator pvi;
-int p;
-
-pv.param = "Port";
-pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-if (pvi == s.moduleParams.end() || pvi->value.empty())
-    {
-    errorStr = "Parameter \'Port\' not found.";
-    printfd(__FILE__, "Parameter 'Port' not found\n");
-    return -1;
-    }
-if (ParseIntInRange(pvi->value[0], 2, 65535, &p))
-    {
-    errorStr = "Cannot parse parameter \'Port\': " + errorStr;
-    printfd(__FILE__, "Cannot parse parameter 'Port'\n");
-    return -1;
-    }
-port = static_cast<uint16_t>(p);
-
-pv.param = "Password";
-pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-if (pvi == s.moduleParams.end() || pvi->value.empty())
-    {
-    errorStr = "Parameter \'Password\' not found.";
-    printfd(__FILE__, "Parameter 'Password' not found\n");
-    password = "";
-    }
-else
-    {
-    password = pvi->value[0];
-    }
-
-pv.param = "Server";
-pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-if (pvi == s.moduleParams.end() || pvi->value.empty())
-    {
-    errorStr = "Parameter \'Server\' not found.";
-    printfd(__FILE__, "Parameter 'Server' not found\n");
-    return -1;
-    }
-ip = inet_strington(pvi->value[0]);
-
-return 0;
-}
-
-SMUX::SMUX()
-    : users(NULL),
-      tariffs(NULL),
-      admins(NULL),
-      services(NULL),
-      corporations(NULL),
-      traffcounter(NULL),
-      running(false),
-      stopped(true),
-      needReconnect(false),
-      lastReconnectTry(0),
-      reconnectTimeout(1),
-      sock(-1),
-      addUserNotifier(*this),
-      delUserNotifier(*this),
-      addDelTariffNotifier(*this),
-      logger(STG::PluginLogger::get("smux"))
-{
-pthread_mutex_init(&mutex, NULL);
-
-smuxHandlers[SMUX_PDUs_PR_close] = &SMUX::CloseHandler;
-smuxHandlers[SMUX_PDUs_PR_registerResponse] = &SMUX::RegisterResponseHandler;
-smuxHandlers[SMUX_PDUs_PR_pdus] = &SMUX::PDUsRequestHandler;
-smuxHandlers[SMUX_PDUs_PR_commitOrRollback] = &SMUX::CommitOrRollbackHandler;
-
-pdusHandlers[PDUs_PR_get_request] = &SMUX::GetRequestHandler;
-pdusHandlers[PDUs_PR_get_next_request] = &SMUX::GetNextRequestHandler;
-pdusHandlers[PDUs_PR_set_request] = &SMUX::SetRequestHandler;
-}
-
-SMUX::~SMUX()
-{
-    {
-    Sensors::iterator it;
-    for (it = sensors.begin(); it != sensors.end(); ++it)
-        delete it->second;
-    }
-    {
-    Tables::iterator it;
-    for (it = tables.begin(); it != tables.end(); ++it)
-        delete it->second;
-    }
-printfd(__FILE__, "SMUX::~SMUX()\n");
-pthread_mutex_destroy(&mutex);
-}
-
-int SMUX::ParseSettings()
-{
-return smuxSettings.ParseSettings(settings);
-}
-
-int SMUX::Start()
-{
-assert(users != NULL && "users must not be NULL");
-assert(tariffs != NULL && "tariffs must not be NULL");
-assert(admins != NULL && "admins must not be NULL");
-assert(services != NULL && "services must not be NULL");
-assert(corporations != NULL && "corporations must not be NULL");
-assert(traffcounter != NULL && "traffcounter must not be NULL");
-
-if (PrepareNet())
-    needReconnect = true;
-
-// Users
-sensors[OID(".1.3.6.1.4.1.38313.1.1.1")] = new TotalUsersSensor(*users);
-sensors[OID(".1.3.6.1.4.1.38313.1.1.2")] = new ConnectedUsersSensor(*users);
-sensors[OID(".1.3.6.1.4.1.38313.1.1.3")] = new AuthorizedUsersSensor(*users);
-sensors[OID(".1.3.6.1.4.1.38313.1.1.4")] = new AlwaysOnlineUsersSensor(*users);
-sensors[OID(".1.3.6.1.4.1.38313.1.1.5")] = new NoCashUsersSensor(*users);
-sensors[OID(".1.3.6.1.4.1.38313.1.1.6")] = new DisabledDetailStatsUsersSensor(*users);
-sensors[OID(".1.3.6.1.4.1.38313.1.1.7")] = new DisabledUsersSensor(*users);
-sensors[OID(".1.3.6.1.4.1.38313.1.1.8")] = new PassiveUsersSensor(*users);
-sensors[OID(".1.3.6.1.4.1.38313.1.1.9")] = new CreditUsersSensor(*users);
-sensors[OID(".1.3.6.1.4.1.38313.1.1.10")] = new FreeMbUsersSensor(*users);
-sensors[OID(".1.3.6.1.4.1.38313.1.1.11")] = new TariffChangeUsersSensor(*users);
-sensors[OID(".1.3.6.1.4.1.38313.1.1.12")] = new ActiveUsersSensor(*users);
-// Tariffs
-sensors[OID(".1.3.6.1.4.1.38313.1.2.1")] = new TotalTariffsSensor(*tariffs);
-// Admins
-sensors[OID(".1.3.6.1.4.1.38313.1.3.1")] = new TotalAdminsSensor(*admins);
-// Services
-sensors[OID(".1.3.6.1.4.1.38313.1.4.1")] = new TotalServicesSensor(*services);
-// Corporations
-sensors[OID(".1.3.6.1.4.1.38313.1.5.1")] = new TotalCorporationsSensor(*corporations);
-// Traffcounter
-sensors[OID(".1.3.6.1.4.1.38313.1.6.1")] = new TotalRulesSensor(*traffcounter);
-
-// Table data
-tables[".1.3.6.1.4.1.38313.1.2.2"] = new TariffUsersTable(".1.3.6.1.4.1.38313.1.2.2", *tariffs, *users);
-
-UpdateTables();
-SetNotifiers();
-
-#ifdef SMUX_DEBUG
-Sensors::const_iterator it(sensors.begin());
-while (it != sensors.end())
-    {
-    printfd(__FILE__, "%s = %s\n",
-            it->first.ToString().c_str(),
-            it->second->ToString().c_str());
-    ++it;
-    }
-#endif
-
-if (!running)
-    {
-    if (pthread_create(&thread, NULL, Runner, this))
-        {
-        errorStr = "Cannot create thread.";
-       logger("Cannot create thread.");
-        printfd(__FILE__, "Cannot create thread\n");
-        return -1;
-        }
-    }
-
-return 0;
-}
-
-int SMUX::Stop()
-{
-printfd(__FILE__, "SMUX::Stop() - Before\n");
-running = false;
-
-if (!stopped)
-    {
-    //5 seconds to thread stops itself
-    for (int i = 0; i < 25 && !stopped; i++)
-        {
-        struct timespec ts = {0, 200000000};
-        nanosleep(&ts, NULL);
-        }
-    }
-
-if (stopped)
-    pthread_join(thread, NULL);
-
-ResetNotifiers();
-
-    {
-    Tables::iterator it;
-    for (it = tables.begin(); it != tables.end(); ++it)
-        delete it->second;
-    }
-    {
-    Sensors::iterator it;
-    for (it = sensors.begin(); it != sensors.end(); ++it)
-        delete it->second;
-    }
-
-tables.erase(tables.begin(), tables.end());
-sensors.erase(sensors.begin(), sensors.end());
-
-close(sock);
-
-if (!stopped)
-    {
-    running = true;
-    return -1;
-    }
-
-printfd(__FILE__, "SMUX::Stop() - After\n");
-return 0;
-}
-
-int SMUX::Reload(const STG::ModuleSettings & /*ms*/)
-{
-if (Stop())
-    return -1;
-if (Start())
-    return -1;
-if (!needReconnect)
-    {
-    printfd(__FILE__, "SMUX reconnected succesfully.\n");
-    logger("Reconnected successfully.");
-    }
-return 0;
-}
-
-void * SMUX::Runner(void * d)
-{
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-SMUX * smux = static_cast<SMUX *>(d);
-
-smux->Run();
-
-return NULL;
-}
-
-void SMUX::Run()
-{
-stopped = true;
-if (!SendOpenPDU(sock))
-    needReconnect = true;
-if (!SendRReqPDU(sock))
-    needReconnect = true;
-running = true;
-stopped = false;
-
-while(running)
-    {
-    if (WaitPackets(sock) && !needReconnect)
-        {
-        SMUX_PDUs_t * pdus = RecvSMUXPDUs(sock);
-        if (pdus)
-            {
-            DispatchPDUs(pdus);
-            ASN_STRUCT_FREE(asn_DEF_SMUX_PDUs, pdus);
-            }
-        else if (running)
-            Reconnect();
-        }
-    else if (running && needReconnect)
-        Reconnect();
-    if (!running)
-        break;
-    }
-SendClosePDU(sock);
-stopped = true;
-}
-
-bool SMUX::PrepareNet()
-{
-sock = socket(AF_INET, SOCK_STREAM, 0);
-
-if (sock < 0)
-    {
-    errorStr = "Cannot create socket.";
-    logger("Cannot create a socket: %s", strerror(errno));
-    printfd(__FILE__, "Cannot create socket\n");
-    return true;
-    }
-
-struct sockaddr_in addr;
-
-addr.sin_family = AF_INET;
-addr.sin_port = htons(smuxSettings.GetPort());
-addr.sin_addr.s_addr = smuxSettings.GetIP();
-
-if (connect(sock, reinterpret_cast<struct sockaddr *>(&addr), sizeof(addr)))
-    {
-    errorStr = "Cannot connect.";
-    logger("Cannot connect the socket: %s", strerror(errno));
-    printfd(__FILE__, "Cannot connect. Message: '%s'\n", strerror(errno));
-    return true;
-    }
-
-return false;
-}
-
-bool SMUX::Reconnect()
-{
-if (needReconnect && difftime(time(NULL), lastReconnectTry) < reconnectTimeout)
-    return true;
-
-time(&lastReconnectTry);
-SendClosePDU(sock);
-close(sock);
-if (!PrepareNet())
-    if (SendOpenPDU(sock))
-        if (SendRReqPDU(sock))
-            {
-            reconnectTimeout = 1;
-            needReconnect = false;
-            logger("Connected successfully");
-            printfd(__FILE__, "Connected successfully\n");
-            return false;
-            }
-
-if (needReconnect)
-    if (reconnectTimeout < 60)
-        reconnectTimeout *= 2;
-
-needReconnect = true;
-return true;
-}
-
-bool SMUX::DispatchPDUs(const SMUX_PDUs_t * pdus)
-{
-SMUXHandlers::iterator it(smuxHandlers.find(pdus->present));
-if (it != smuxHandlers.end())
-    {
-    return (this->*(it->second))(pdus);
-    }
-#ifdef SMUX_DEBUG
-else
-    {
-    switch (pdus->present)
-        {
-        case SMUX_PDUs_PR_NOTHING:
-            printfd(__FILE__, "PDUs: nothing\n");
-            break;
-        case SMUX_PDUs_PR_open:
-            printfd(__FILE__, "PDUs: open\n");
-            break;
-        case SMUX_PDUs_PR_registerRequest:
-            printfd(__FILE__, "PDUs: registerRequest\n");
-            break;
-        default:
-            printfd(__FILE__, "PDUs: undefined\n");
-        }
-    asn_fprint(stderr, &asn_DEF_SMUX_PDUs, pdus);
-    }
-#endif
-return false;
-}
-
-bool SMUX::UpdateTables()
-{
-Sensors newSensors;
-bool done = true;
-Tables::iterator it(tables.begin());
-while (it != tables.end())
-    {
-    try
-        {
-        it->second->UpdateSensors(newSensors);
-        }
-    catch (const std::runtime_error & ex)
-        {
-        printfd(__FILE__,
-                "SMUX::UpdateTables - failed to update table '%s': '%s'\n",
-                it->first.c_str(), ex.what());
-        done = false;
-        break;
-        }
-    ++it;
-    }
-if (!done)
-    {
-    Sensors::iterator it(newSensors.begin());
-    while (it != newSensors.end())
-        {
-        delete it->second;
-        ++it;
-        }
-    return false;
-    }
-
-it = tables.begin();
-while (it != tables.end())
-    {
-    std::pair<Sensors::iterator, Sensors::iterator> res;
-    res = std::equal_range(sensors.begin(),
-                           sensors.end(),
-                           std::pair<OID, Sensor *>(OID(it->first), NULL),
-                           SPrefixLess);
-    Sensors::iterator sit(res.first);
-    while (sit != res.second)
-        {
-        delete sit->second;
-        ++sit;
-        }
-    sensors.erase(res.first, res.second);
-    ++it;
-    }
-
-sensors.insert(newSensors.begin(), newSensors.end());
-
-return true;
-}
-
-void SMUX::SetNotifier(UserPtr userPtr)
-{
-notifiers.push_back(CHG_AFTER_NOTIFIER(*this, userPtr));
-userPtr->GetProperties().tariffName.AddAfterNotifier(&notifiers.back());
-}
-
-void SMUX::UnsetNotifier(UserPtr userPtr)
-{
-std::list<CHG_AFTER_NOTIFIER>::iterator it = notifiers.begin();
-while (it != notifiers.end())
-    {
-    if (it->GetUserPtr() == userPtr)
-        {
-        userPtr->GetProperties().tariffName.DelAfterNotifier(&(*it));
-        notifiers.erase(it);
-        break;
-        }
-    ++it;
-    }
-}
-
-void SMUX::SetNotifiers()
-{
-int h = users->OpenSearch();
-assert(h && "USERS::OpenSearch is always correct");
-
-UserPtr u;
-while (!users->SearchNext(h, &u))
-    SetNotifier(u);
-
-users->CloseSearch(h);
-
-users->AddNotifierUserAdd(&addUserNotifier);
-users->AddNotifierUserDel(&delUserNotifier);
-
-tariffs->AddNotifierAdd(&addDelTariffNotifier);
-tariffs->AddNotifierDel(&addDelTariffNotifier);
-}
-
-void SMUX::ResetNotifiers()
-{
-tariffs->DelNotifierDel(&addDelTariffNotifier);
-tariffs->DelNotifierAdd(&addDelTariffNotifier);
-
-users->DelNotifierUserDel(&delUserNotifier);
-users->DelNotifierUserAdd(&addUserNotifier);
-
-std::list<CHG_AFTER_NOTIFIER>::iterator it(notifiers.begin());
-while (it != notifiers.end())
-    {
-    it->GetUserPtr()->GetProperties().tariffName.DelAfterNotifier(&(*it));
-    ++it;
-    }
-notifiers.clear();
-}
diff --git a/stargazer/plugins/other/smux/smux.h b/stargazer/plugins/other/smux/smux.h
deleted file mode 100644 (file)
index 4954bd0..0000000
+++ /dev/null
@@ -1,223 +0,0 @@
-#ifndef __SMUX_H__
-#define __SMUX_H__
-
-#include <pthread.h>
-
-#include <string>
-#include <map>
-#include <list>
-#include <cstdint>
-
-#include "stg/SMUX-PDUs.h"
-#include "stg/ObjectSyntax.h"
-
-#include "stg/plugin.h"
-#include "stg/module_settings.h"
-#include "stg/notifer.h"
-#include "stg/noncopyable.h"
-#include "stg/logger.h"
-
-#include "sensors.h"
-#include "tables.h"
-#include "types.h"
-
-namespace STG
-{
-struct User;
-struct Settings;
-struct Users;
-struct Tariffs;
-struct Services;
-struct Corporations;
-struct TraffCounter;
-}
-
-class SMUX;
-
-typedef bool (SMUX::*SMUXPacketHandler)(const SMUX_PDUs_t * pdus);
-typedef bool (SMUX::*PDUsHandler)(const PDUs_t * pdus);
-typedef std::map<SMUX_PDUs_PR, SMUXPacketHandler> SMUXHandlers;
-typedef std::map<PDUs_PR, PDUsHandler> PDUsHandlers;
-
-using UserPtr = STG::User*;
-//-----------------------------------------------------------------------------
-class SMUX_SETTINGS {
-public:
-    SMUX_SETTINGS();
-    virtual ~SMUX_SETTINGS() {}
-    const std::string & GetStrError() const { return errorStr; }
-    int ParseSettings(const STG::ModuleSettings & s);
-
-    uint32_t GetIP() const { return ip; }
-    uint16_t GetPort() const { return port; }
-    const std::string GetPassword() const { return password; }
-
-private:
-    mutable std::string errorStr;
-
-    uint32_t ip;
-    uint16_t port;
-    std::string password;
-};
-//-----------------------------------------------------------------------------
-class CHG_AFTER_NOTIFIER : public STG::PropertyNotifierBase<std::string> {
-public:
-             CHG_AFTER_NOTIFIER(SMUX & s, const UserPtr & u)
-                 : STG::PropertyNotifierBase<std::string>(),
-                   smux(s), userPtr(u) {}
-             CHG_AFTER_NOTIFIER(const CHG_AFTER_NOTIFIER & rvalue)
-                 : STG::PropertyNotifierBase<std::string>(),
-                   smux(rvalue.smux), userPtr(rvalue.userPtr) {}
-    void     Notify(const std::string &, const std::string &);
-
-    UserPtr GetUserPtr() const { return userPtr; }
-
-private:
-    CHG_AFTER_NOTIFIER & operator=(const CHG_AFTER_NOTIFIER & rvalue);
-    SMUX & smux;
-    UserPtr userPtr;
-};
-//-----------------------------------------------------------------------------
-class ADD_DEL_TARIFF_NOTIFIER : public STG::NotifierBase<STG::TariffData> {
-public:
-    explicit ADD_DEL_TARIFF_NOTIFIER(SMUX & s)
-             : STG::NotifierBase<STG::TariffData>(), smux(s) {}
-    void Notify(const STG::TariffData &);
-
-private:
-    SMUX & smux;
-};
-//-----------------------------------------------------------------------------
-class ADD_USER_NOTIFIER : public STG::NotifierBase<UserPtr> {
-public:
-    explicit ADD_USER_NOTIFIER(SMUX & s) : STG::NotifierBase<STG::User*>(), smux(s) {}
-    void Notify(const UserPtr &);
-
-private:
-    SMUX & smux;
-};
-//-----------------------------------------------------------------------------
-class DEL_USER_NOTIFIER : public STG::NotifierBase<UserPtr> {
-public:
-    explicit DEL_USER_NOTIFIER(SMUX & s) : STG::NotifierBase<UserPtr>(), smux(s) {}
-    void Notify(const UserPtr &);
-
-private:
-    SMUX & smux;
-};
-//-----------------------------------------------------------------------------
-class SMUX : public STG::Plugin {
-public:
-    SMUX();
-    virtual ~SMUX();
-
-    void SetUsers(STG::Users * u) { users = u; }
-    void SetTariffs(STG::Tariffs * t) { tariffs = t; }
-    void SetAdmins(STG::Admins * a) { admins = a; }
-    void SetServices(STG::Services * s) { services = s; }
-    void SetTraffcounter(STG::TraffCounter * tc) { traffcounter = tc; }
-    void SetCorporations(STG::Corporations * c) { corporations = c; }
-    void SetSettings(const STG::ModuleSettings & s) { settings = s; }
-    int ParseSettings();
-
-    int Start();
-    int Stop();
-    int Reload(const STG::ModuleSettings & ms);
-    bool IsRunning() { return running && !stopped; }
-
-    const std::string & GetStrError() const { return errorStr; }
-    std::string GetVersion() const { return "Stg SMUX Plugin 1.1"; }
-    uint16_t GetStartPosition() const { return 10; }
-    uint16_t GetStopPosition() const { return 10; }
-
-    bool UpdateTables();
-
-    void SetNotifier(UserPtr userPtr);
-    void UnsetNotifier(UserPtr userPtr);
-
-private:
-    SMUX(const SMUX & rvalue);
-    SMUX & operator=(const SMUX & rvalue);
-
-    static void * Runner(void * d);
-    void Run();
-    bool PrepareNet();
-    bool Reconnect();
-
-    bool DispatchPDUs(const SMUX_PDUs_t * pdus);
-
-    bool CloseHandler(const SMUX_PDUs_t * pdus);
-    bool RegisterResponseHandler(const SMUX_PDUs_t * pdus);
-    bool PDUsRequestHandler(const SMUX_PDUs_t * pdus);
-    bool CommitOrRollbackHandler(const SMUX_PDUs_t * pdus);
-
-    bool GetRequestHandler(const PDUs_t * pdus);
-    bool GetNextRequestHandler(const PDUs_t * pdus);
-    bool SetRequestHandler(const PDUs_t * pdus);
-
-    void SetNotifiers();
-    void ResetNotifiers();
-
-    STG::Users * users;
-    STG::Tariffs * tariffs;
-    STG::Admins * admins;
-    STG::Services * services;
-    STG::Corporations * corporations;
-    STG::TraffCounter * traffcounter;
-
-    mutable std::string errorStr;
-    SMUX_SETTINGS smuxSettings;
-    STG::ModuleSettings settings;
-
-    pthread_t thread;
-    pthread_mutex_t mutex;
-    bool running;
-    bool stopped;
-    bool needReconnect;
-
-    time_t lastReconnectTry;
-    unsigned reconnectTimeout;
-
-    int sock;
-
-    SMUXHandlers smuxHandlers;
-    PDUsHandlers pdusHandlers;
-    Sensors sensors;
-    Tables tables;
-
-    std::list<CHG_AFTER_NOTIFIER> notifiers;
-    ADD_USER_NOTIFIER addUserNotifier;
-    DEL_USER_NOTIFIER delUserNotifier;
-    ADD_DEL_TARIFF_NOTIFIER addDelTariffNotifier;
-
-    STG::PluginLogger logger;
-};
-//-----------------------------------------------------------------------------
-
-inline
-void CHG_AFTER_NOTIFIER::Notify(const std::string &, const std::string &)
-{
-smux.UpdateTables();
-}
-
-inline
-void ADD_DEL_TARIFF_NOTIFIER::Notify(const STG::TariffData &)
-{
-smux.UpdateTables();
-}
-
-inline
-void ADD_USER_NOTIFIER::Notify(const UserPtr & userPtr)
-{
-smux.SetNotifier(userPtr);
-smux.UpdateTables();
-}
-
-inline
-void DEL_USER_NOTIFIER::Notify(const UserPtr & userPtr)
-{
-smux.UnsetNotifier(userPtr);
-smux.UpdateTables();
-}
-
-#endif
diff --git a/stargazer/plugins/other/smux/tables.cpp b/stargazer/plugins/other/smux/tables.cpp
deleted file mode 100644 (file)
index 21173b7..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-#include <cassert>
-#include <utility>
-#include <iterator>
-#include <algorithm>
-
-#include "stg/user_property.h"
-#include "stg/tariffs.h"
-#include "stg/tariff_conf.h"
-#include "stg/users.h"
-
-#include "tables.h"
-
-std::pair<std::string, size_t> TD2Info(const STG::TariffData & td);
-
-void TariffUsersTable::UpdateSensors(Sensors & sensors) const
-{
-std::map<std::string, size_t> data;
-
-std::vector<STG::TariffData> tdl;
-tariffs.GetTariffsData(&tdl);
-std::transform(tdl.begin(),
-               tdl.end(),
-               std::inserter(data, data.begin()),
-               TD2Info);
-
-int handle = users.OpenSearch();
-assert(handle && "USERS::OpenSearch is always correct");
-
-STG::User* user;
-while (!users.SearchNext(handle, &user))
-    {
-    if (user->GetDeleted())
-        continue;
-    std::string tariffName(user->GetProperties().tariffName.ConstData());
-    std::map<std::string, size_t>::iterator it(data.lower_bound(tariffName));
-    if (it == data.end() ||
-        it->first != tariffName)
-        {
-        data.insert(it, std::make_pair(tariffName, 1));
-        }
-    else
-        {
-        ++it->second;
-        }
-    }
-
-users.CloseSearch(handle);
-
-size_t idx = 1;
-OID prefixOid(prefix);
-
-std::map<std::string, size_t>::const_iterator it(data.begin());
-while (it != data.end())
-    {
-    sensors[prefixOid.copyWithSuffix(2, static_cast<unsigned int>(idx))] = new ConstSensor<std::string>(it->first);
-    sensors[prefixOid.copyWithSuffix(3, static_cast<unsigned int>(idx))] = new ConstSensor<unsigned long>(it->second);
-    ++idx;
-    ++it;
-    }
-}
-
-std::pair<std::string, size_t> TD2Info(const STG::TariffData & td)
-{
-return std::make_pair(td.tariffConf.name, 0);
-}
diff --git a/stargazer/plugins/other/smux/tables.h b/stargazer/plugins/other/smux/tables.h
deleted file mode 100644 (file)
index edfe437..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-#ifndef __TABLES_H__
-#define __TABLES_H__
-
-#include <string>
-#include <map>
-
-#include "sensors.h"
-
-namespace STG
-{
-struct Tariffs;
-struct Users;
-}
-
-class TableSensor {
-    public:
-        explicit TableSensor(const std::string & p) : prefix(p) {}
-        virtual ~TableSensor() {}
-
-        const std::string & GetPrefix() const { return prefix; }
-        virtual void UpdateSensors(Sensors & sensors) const = 0;
-
-    protected:
-        std::string prefix;
-};
-
-class TariffUsersTable : public TableSensor {
-    public:
-        TariffUsersTable(const std::string & p,
-                         STG::Tariffs & t,
-                         STG::Users & u)
-            : TableSensor(p),
-              tariffs(t),
-              users(u)
-        {}
-        virtual ~TariffUsersTable() {}
-
-        void UpdateSensors(Sensors & sensors) const;
-
-    private:
-        STG::Tariffs & tariffs;
-        STG::Users & users;
-};
-
-typedef std::map<std::string, TableSensor *> Tables;
-
-#endif
diff --git a/stargazer/plugins/other/smux/types.cpp b/stargazer/plugins/other/smux/types.cpp
deleted file mode 100644 (file)
index 4e54749..0000000
+++ /dev/null
@@ -1,252 +0,0 @@
-#include <stdexcept>
-#include <algorithm>
-#include <iterator>
-#include <sstream>
-
-#include "types.h"
-
-namespace
-{
-
-bool ParseArcs(const char * str, ptrdiff_t length, unsigned * a, size_t * pos);
-bool StringToArcs(const char * str, size_t length, std::vector<unsigned> & arcs);
-bool AppendToArcs(const char * str, size_t length, std::vector<unsigned> & arcs);
-
-bool ParseArcs(const char * str, ptrdiff_t length, unsigned * a, size_t * pos)
-{
-if (length == 0)
-    return false;
-const char * left = str;
-if (*left == '.')
-    ++left;
-size_t arcPos = 0;
-while ((left - str) < length)
-    {
-    char * pos = NULL;
-    unsigned arc = static_cast<unsigned int>(strtoul(left, &pos, 10));
-    if (pos == left)
-        return false;
-    a[arcPos++] = arc;
-    if (arcPos >= 1024)
-        return false;
-    left = pos + 1;
-    }
-*pos = arcPos;
-return true;
-}
-
-bool StringToArcs(const char * str, size_t length, std::vector<unsigned> & arcs)
-{
-unsigned a[1024];
-size_t pos = 0;
-
-if (!ParseArcs(str, length, a, &pos))
-    return false;
-
-arcs.assign(a, a + pos);
-return true;
-}
-
-bool AppendToArcs(const char * str, size_t length, std::vector<unsigned> & arcs)
-{
-unsigned a[1024];
-size_t pos = 0;
-
-if (!ParseArcs(str, length, a, &pos))
-    return false;
-
-std::copy(&a[0], &a[pos], std::back_inserter(arcs));
-return true;
-}
-
-}
-
-OID::OID(const std::string & str)
-    : arcs()
-{
-if (!StringToArcs(str.c_str(), str.length(), arcs))
-    throw std::runtime_error("Invalid oid");
-}
-
-OID::OID(const char * str, size_t length)
-    : arcs()
-{
-if (!StringToArcs(str, length, arcs))
-    throw std::runtime_error("Invalid oid");
-}
-
-OID::OID(const std::vector<unsigned> & a)
-    : arcs(a)
-{
-}
-
-OID::OID(const unsigned * a, size_t length)
-    : arcs()
-{
-std::vector<unsigned> newArcs(a, a + length);
-arcs.swap(newArcs);
-}
-
-OID::OID(OBJECT_IDENTIFIER_t * oid)
-    : arcs()
-{
-unsigned a[1024];
-int count = OBJECT_IDENTIFIER_get_arcs(oid, a, sizeof(a[0]), 1024);
-
-if (count > 1024)
-    throw std::runtime_error("OID is too long");
-
-std::vector<unsigned> newArcs(a, a + count);
-arcs.swap(newArcs);
-}
-
-OID::OID(const OID & rvalue)
-    : arcs(rvalue.arcs)
-{
-}
-
-OID::~OID()
-{
-}
-
-bool OID::addSuffix(const char * suffix, size_t length)
-{
-if (!AppendToArcs(suffix, length, arcs))
-    return false;
-return true;
-}
-
-bool OID::addSuffix(const std::string & suffix)
-{
-if (!AppendToArcs(suffix.c_str(), suffix.length(), arcs))
-    return false;
-return true;
-}
-
-bool OID::addSuffix(const unsigned * suffix, size_t length)
-{
-std::copy(suffix, suffix + length, std::back_inserter(arcs));
-return true;
-}
-
-bool OID::addSuffix(const std::vector<unsigned> & suffix)
-{
-std::copy(suffix.begin(), suffix.end(), std::back_inserter(arcs));
-return true;
-}
-
-bool OID::addSuffix(unsigned a, unsigned b)
-{
-arcs.push_back(a);
-arcs.push_back(b);
-return true;
-}
-
-OID OID::copyWithSuffix(const char * suffix, size_t length) const
-{
-OID oid(*this);
-if (!oid.addSuffix(suffix, length))
-    throw std::runtime_error("Invalid suffix");
-return oid;
-}
-
-OID OID::copyWithSuffix(const std::string & suffix) const
-{
-OID oid(*this);
-if (!oid.addSuffix(suffix))
-    throw std::runtime_error("Invalid suffix");
-return oid;
-}
-
-OID OID::copyWithSuffix(const unsigned * suffix, size_t length) const
-{
-OID oid(*this);
-if (!oid.addSuffix(suffix, length))
-    throw std::runtime_error("Invalid suffix");
-return oid;
-}
-
-OID OID::copyWithSuffix(const std::vector<unsigned> & suffix) const
-{
-OID oid(*this);
-if (!oid.addSuffix(suffix))
-    throw std::runtime_error("Invalid suffix");
-return oid;
-}
-
-OID OID::copyWithSuffix(unsigned a, unsigned b) const
-{
-OID oid(*this);
-oid.addSuffix(a, b);
-return oid;
-}
-
-std::string OID::ToString() const
-{
-std::stringstream stream;
-for (size_t i = 0; i < arcs.size(); ++i)
-    stream << "." << arcs[i];
-return stream.str();
-}
-
-void OID::ToOID(OBJECT_IDENTIFIER_t * oid) const
-{
-OBJECT_IDENTIFIER_set_arcs(oid, &arcs.front(), sizeof(unsigned), static_cast<unsigned int>(arcs.size()));
-}
-
-OID & OID::operator=(const OID & rvalue)
-{
-arcs = rvalue.arcs;
-return *this;
-}
-
-bool OID::operator==(const OID & rvalue) const
-{
-if (arcs.size() != rvalue.arcs.size())
-    return false;
-for (size_t i = 0; i < arcs.size(); ++i)
-    if (arcs[i] != rvalue.arcs[i])
-        return false;
-return true;
-}
-
-bool OID::operator<(const OID & rvalue) const
-{
-size_t i = 0;
-size_t min = std::min(arcs.size(), rvalue.arcs.size());
-while (i < min &&
-       arcs[i] == rvalue.arcs[i])
-    ++i;
-if (i == min)
-    {
-    if (rvalue.arcs.size() > arcs.size())
-        return true;
-    return false;
-    }
-
-if (arcs[i] < rvalue.arcs[i])
-    return true;
-
-return false;
-}
-
-bool OID::PrefixLess(const OID & rvalue) const
-{
-size_t i = 0;
-size_t min = std::min(arcs.size(), rvalue.arcs.size());
-while (i < min &&
-       arcs[i] == rvalue.arcs[i])
-    ++i;
-if (i == min)
-    return false;
-if (arcs[i] < rvalue.arcs[i])
-    return true;
-return false;
-}
-
-std::ostream & operator<<(std::ostream & stream, const OID & oid)
-{
-for (size_t i = 0; i < oid.arcs.size(); ++i)
-    stream << "." << oid.arcs[i];
-return stream;
-}
diff --git a/stargazer/plugins/other/smux/types.h b/stargazer/plugins/other/smux/types.h
deleted file mode 100644 (file)
index 2b54f2a..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-#ifndef __TYPES_H__
-#define __TYPES_H__
-
-#include <string>
-#include <vector>
-#include <iostream>
-
-#include "stg/OBJECT_IDENTIFIER.h"
-
-class OID {
-    public:
-        explicit OID(const std::string & str);
-        OID(const char * str, size_t length);
-        explicit OID(const std::vector<unsigned> & arcs);
-        OID(const unsigned * arcs, size_t length);
-        explicit OID(OBJECT_IDENTIFIER_t * oid);
-        OID(const OID & rvalue);
-        ~OID();
-
-        bool addSuffix(const char * suffix, size_t length);
-        bool addSuffix(const std::string & suffix);
-        bool addSuffix(const unsigned * suffix, size_t length);
-        bool addSuffix(const std::vector<unsigned> & suffix);
-        bool addSuffix(unsigned a, unsigned b);
-
-        OID copyWithSuffix(const char * suffix, size_t length) const;
-        OID copyWithSuffix(const std::string & suffix) const;
-        OID copyWithSuffix(const unsigned * suffix, size_t length) const;
-        OID copyWithSuffix(const std::vector<unsigned> & suffix) const;
-        OID copyWithSuffix(unsigned a, unsigned b) const;
-
-        std::string ToString() const;
-        const std::vector<unsigned> & ToVector() const { return arcs; }
-        void ToOID(OBJECT_IDENTIFIER_t * oid) const;
-
-        OID & operator=(const OID & rvalue);
-        bool operator==(const OID & rvalue) const;
-        bool operator!=(const OID & rvalue) const { return !operator==(rvalue); }
-        bool operator<(const OID & rvalue) const;
-        bool operator>(const OID & rvalue) const
-        { return !operator==(rvalue) && !operator<(rvalue); }
-
-        bool PrefixLess(const OID & rvalue) const;
-
-        friend std::ostream & operator<<(std::ostream & stream, const OID & oid);
-
-    private:
-        std::vector<unsigned> arcs;
-};
-
-inline
-bool PrefixLess(const OID & a, const OID & b)
-{
-return a.PrefixLess(b);
-}
-
-#endif
diff --git a/stargazer/plugins/other/smux/utils.cpp b/stargazer/plugins/other/smux/utils.cpp
deleted file mode 100644 (file)
index 0ea39bb..0000000
+++ /dev/null
@@ -1,244 +0,0 @@
-#include <unistd.h> // write
-
-#include <cstring> // memset
-#include <cerrno>
-
-#include "stg/common.h"
-
-#include "stg/OpenPDU.h"
-#include "stg/ClosePDU.h"
-#include "stg/RReqPDU.h"
-#include "stg/ber_decoder.h"
-#include "stg/der_encoder.h"
-
-#include "pen.h"
-#include "utils.h"
-
-bool String2OI(const std::string & str, OBJECT_IDENTIFIER_t * oi)
-{
-size_t left = 0, pos = 0, arcPos = 0;
-int arcs[1024];
-pos = str.find_first_of('.', left);
-if (pos == 0)
-    {
-    left = 1;
-    pos = str.find_first_of('.', left);
-    }
-while (pos != std::string::npos)
-    {
-    int arc = 0;
-    if (str2x(str.substr(left, left - pos), arc))
-        {
-        return false;
-        }
-    arcs[arcPos++] = arc;
-    left = pos + 1;
-    pos = str.find_first_of('.', left);
-    }
-if (left < str.length())
-    {
-    int arc = 0;
-    if (str2x(str.substr(left, left - pos), arc))
-        {
-        return false;
-        }
-    arcs[arcPos++] = arc;
-    }
-OBJECT_IDENTIFIER_set_arcs(oi, arcs, sizeof(arcs[0]), static_cast<unsigned int>(arcPos));
-return true;
-}
-
-bool SendOpenPDU(int fd)
-{
-const char * description = "Stg SMUX Plugin";
-asn_enc_rval_t error;
-OpenPDU_t msg;
-
-memset(&msg, 0, sizeof(msg));
-
-msg.present = OpenPDU_PR_simple;
-asn_long2INTEGER(&msg.choice.simple.version, SimpleOpen__version_version_1);
-if (!String2OI(PEN_PREFIX, &msg.choice.simple.identity))
-    {
-    printfd(__FILE__,
-            "SendOpenPDU() - failed to convert string to OBJECT_IDENTIFIER\n");
-    return false;
-    }
-OCTET_STRING_fromString(&msg.choice.simple.description, description);
-OCTET_STRING_fromString(&msg.choice.simple.password, "");
-
-char buffer[1024];
-error = der_encode_to_buffer(&asn_DEF_OpenPDU, &msg, buffer, sizeof(buffer));
-
-ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_OpenPDU, &msg);
-
-if (error.encoded == -1)
-    {
-    printfd(__FILE__, "Could not encode OpenPDU (at %s)\n",
-            error.failed_type ? error.failed_type->name : "unknown");
-    return false;
-    }
-else
-    {
-    if (write(fd, buffer, error.encoded) < 0)
-        {
-        printfd(__FILE__, "Failed to send OpenPDU: %s\n", strerror(errno));
-        return false;
-        }
-    }
-return true;
-}
-
-bool SendClosePDU(int fd)
-{
-ClosePDU_t msg;
-
-memset(&msg, 0, sizeof(msg));
-
-asn_long2INTEGER(&msg, ClosePDU_goingDown);
-
-char buffer[1024];
-asn_enc_rval_t error;
-error = der_encode_to_buffer(&asn_DEF_ClosePDU, &msg, buffer, sizeof(buffer));
-
-ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_ClosePDU, &msg);
-
-if (error.encoded == -1)
-    {
-    printfd(__FILE__, "Could not encode ClosePDU (at %s)\n",
-            error.failed_type ? error.failed_type->name : "unknown");
-    return false;
-    }
-else
-    {
-    if (write(fd, buffer, error.encoded) < 0)
-        {
-        printfd(__FILE__, "Failed to send ClosePDU: %s\n", strerror(errno));
-        return false;
-        }
-    }
-return true;
-}
-
-bool SendRReqPDU(int fd)
-{
-int oid[] = {1, 3, 6, 1, 4, 1, 38313, 1};
-asn_enc_rval_t error;
-RReqPDU_t msg;
-
-memset(&msg, 0, sizeof(msg));
-
-msg.priority = 0;
-asn_long2INTEGER(&msg.operation, RReqPDU__operation_readOnly);
-OBJECT_IDENTIFIER_set_arcs(&msg.subtree,
-                           oid,
-                           sizeof(oid[0]),
-                           8);
-
-char buffer[1024];
-error = der_encode_to_buffer(&asn_DEF_RReqPDU, &msg, buffer, sizeof(buffer));
-
-ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RReqPDU, &msg);
-
-if (error.encoded == -1)
-    {
-    printfd(__FILE__, "Could not encode RReqPDU (at %s)\n",
-            error.failed_type ? error.failed_type->name : "unknown");
-    return false;
-    }
-else
-    {
-    if (write(fd, buffer, error.encoded) < 0)
-        {
-        printfd(__FILE__, "Failed to send RReqPDU: %s\n", strerror(errno));
-        return false;
-        }
-    }
-return true;
-}
-
-SMUX_PDUs_t * RecvSMUXPDUs(int fd)
-{
-char buffer[1024];
-SMUX_PDUs_t * pdus = NULL;
-
-memset(buffer, 0, sizeof(buffer));
-
-size_t length = read(fd, buffer, sizeof(buffer));
-if (length < 1)
-    return NULL;
-asn_dec_rval_t error;
-error = ber_decode(0, &asn_DEF_SMUX_PDUs, (void **)&pdus, buffer, length);
-
-if(error.code != RC_OK)
-    {
-    printfd(__FILE__, "Failed to decode PDUs at byte %ld\n",
-            (long)error.consumed);
-    return NULL;
-    }
-return pdus;
-}
-
-bool SendGetResponsePDU(int fd, GetResponse_PDU_t * getResponse)
-{
-asn_enc_rval_t error;
-
-char buffer[1024];
-error = der_encode_to_buffer(&asn_DEF_GetResponse_PDU, getResponse, buffer,
-                             sizeof(buffer));
-
-if (error.encoded == -1)
-    {
-    printfd(__FILE__, "Could not encode GetResponsePDU (at %s)\n",
-            error.failed_type ? error.failed_type->name : "unknown");
-    return false;
-    }
-else
-    {
-    if (write(fd, buffer, error.encoded) < 0)
-        {
-        printfd(__FILE__, "Failed to send GetResponsePDU: %s\n", strerror(errno));
-        return false;
-        }
-    }
-return true;
-}
-
-bool SendGetResponseErrorPDU(int fd,
-                             const PDU_t * getRequest,
-                             int errorStatus,
-                             int errorIndex)
-{
-asn_enc_rval_t error;
-GetResponse_PDU_t msg;
-
-memset(&msg, 0, sizeof(msg));
-
-long id = 0;
-asn_INTEGER2long(&getRequest->request_id, &id);
-asn_long2INTEGER(&msg.request_id, id);
-asn_long2INTEGER(&msg.error_status, errorStatus);
-asn_long2INTEGER(&msg.error_index, errorIndex);
-
-char buffer[1024];
-error = der_encode_to_buffer(&asn_DEF_GetResponse_PDU, &msg, buffer,
-                             sizeof(buffer));
-
-ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_GetResponse_PDU, &msg);
-
-if (error.encoded == -1)
-    {
-    printfd(__FILE__, "Could not encode GetResponsePDU for error (at %s)\n",
-            error.failed_type ? error.failed_type->name : "unknown");
-    return false;
-    }
-else
-    {
-    if (write(fd, buffer, error.encoded) < 0)
-        {
-        printfd(__FILE__, "Failed to send GetResponseErrorPDU: %s\n", strerror(errno));
-        return false;
-        }
-    }
-return true;
-}
diff --git a/stargazer/plugins/other/smux/utils.h b/stargazer/plugins/other/smux/utils.h
deleted file mode 100644 (file)
index 52a3988..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef __UTILS_H__
-#define __UTILS_H__
-
-#include <string>
-
-#include "stg/OBJECT_IDENTIFIER.h"
-#include "stg/SMUX-PDUs.h"
-#include "stg/GetResponse-PDU.h"
-
-bool String2OI(const std::string & str, OBJECT_IDENTIFIER_t * oi);
-bool SendOpenPDU(int fd);
-bool SendClosePDU(int fd);
-bool SendRReqPDU(int fd);
-SMUX_PDUs_t * RecvSMUXPDUs(int fd);
-bool SendGetResponsePDU(int fd, GetResponse_PDU_t * getResponse);
-bool SendGetResponseErrorPDU(int fd,
-                             const PDU_t * getRequest,
-                             int errorStatus,
-                             int errorIndex);
-
-#endif
diff --git a/stargazer/plugins/other/smux/value2os.h b/stargazer/plugins/other/smux/value2os.h
deleted file mode 100644 (file)
index c069aff..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-#ifndef __VALUE_2_OS_H__
-#define __VALUE_2_OS_H__
-
-#include "stg/ObjectSyntax.h"
-
-template <typename T>
-bool ValueToOS(const T & value, ObjectSyntax * objectSyntax);
-
-template <>
-inline
-bool ValueToOS<int>(const int & value, ObjectSyntax * objectSyntax)
-{
-objectSyntax->present = ObjectSyntax_PR_simple;
-SimpleSyntax_t * simpleSyntax = &objectSyntax->choice.simple;
-simpleSyntax->present = SimpleSyntax_PR_number;
-asn_long2INTEGER(&simpleSyntax->choice.number, value);
-return true;
-}
-
-template <>
-inline
-bool ValueToOS<unsigned int>(const unsigned int & value, ObjectSyntax * objectSyntax)
-{
-objectSyntax->present = ObjectSyntax_PR_simple;
-SimpleSyntax_t * simpleSyntax = &objectSyntax->choice.simple;
-simpleSyntax->present = SimpleSyntax_PR_number;
-asn_long2INTEGER(&simpleSyntax->choice.number, value);
-return true;
-}
-
-template <>
-inline
-bool ValueToOS<long>(const long & value, ObjectSyntax * objectSyntax)
-{
-objectSyntax->present = ObjectSyntax_PR_simple;
-SimpleSyntax_t * simpleSyntax = &objectSyntax->choice.simple;
-simpleSyntax->present = SimpleSyntax_PR_number;
-asn_long2INTEGER(&simpleSyntax->choice.number, value);
-return true;
-}
-
-template <>
-inline
-bool ValueToOS<unsigned long>(const unsigned long & value, ObjectSyntax * objectSyntax)
-{
-objectSyntax->present = ObjectSyntax_PR_simple;
-SimpleSyntax_t * simpleSyntax = &objectSyntax->choice.simple;
-simpleSyntax->present = SimpleSyntax_PR_number;
-asn_long2INTEGER(&simpleSyntax->choice.number, value);
-return true;
-}
-
-template <>
-inline
-bool ValueToOS<std::string>(const std::string & value, ObjectSyntax * objectSyntax)
-{
-objectSyntax->present = ObjectSyntax_PR_simple;
-SimpleSyntax_t * simpleSyntax = &objectSyntax->choice.simple;
-simpleSyntax->present = SimpleSyntax_PR_string;
-OCTET_STRING_fromBuf(&simpleSyntax->choice.string, value.c_str(), static_cast<int>(value.length()));
-return true;
-}
-
-#endif
diff --git a/stargazer/plugins/store/files/file_store.cpp b/stargazer/plugins/store/files/file_store.cpp
deleted file mode 100644 (file)
index 3fd9e6d..0000000
+++ /dev/null
@@ -1,2208 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- */
-
-/*
- $Revision: 1.67 $
- $Date: 2010/10/07 19:53:11 $
- $Author: faust $
- */
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#include "file_store.h"
-
-#include "stg/common.h"
-#include "stg/user_ips.h"
-#include "stg/user_conf.h"
-#include "stg/user_stat.h"
-#include "stg/const.h"
-#include "stg/blowfish.h"
-#include "stg/logger.h"
-#include "stg/locker.h"
-#include "stg/admin_conf.h"
-#include "stg/tariff.h"
-#include "stg/tariff_conf.h"
-#include "stg/service_conf.h"
-
-#include <sstream>
-#include <algorithm>
-#include <cstdio>
-#include <ctime>
-#include <cerrno>
-#include <cstring>
-
-#include <pwd.h>
-#include <grp.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <sys/time.h>
-#include <fcntl.h>
-#include <dirent.h>
-
-#define DELETED_USERS_DIR   "deleted_users"
-
-#define adm_enc_passwd "cjeifY8m3"
-
-int GetFileList(std::vector<std::string> * fileList, const std::string & directory, mode_t mode, const std::string & ext);
-
-const int pt_mega = 1024 * 1024;
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-namespace
-{
-
-bool CheckAndCreate(const std::string & dir, mode_t mode)
-{
-if (access(dir.c_str(), F_OK) == 0)
-    return true;
-if (mkdir(dir.c_str(), mode) == 0)
-    return true;
-return false;
-}
-
-}
-
-extern "C" STG::Store* GetStore()
-{
-    static FILES_STORE plugin;
-    return &plugin;
-}
-//-----------------------------------------------------------------------------
-FILES_STORE_SETTINGS::FILES_STORE_SETTINGS()
-    : settings(NULL),
-      statMode(0),
-      statUID(0),
-      statGID(0),
-      confMode(0),
-      confUID(0),
-      confGID(0),
-      userLogMode(0),
-      userLogUID(0),
-      userLogGID(0),
-      removeBak(true),
-      readBak(true)
-{
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE_SETTINGS::ParseOwner(const std::vector<STG::ParamValue> & moduleParams, const std::string & owner, uid_t * uid)
-{
-STG::ParamValue pv;
-pv.param = owner;
-std::vector<STG::ParamValue>::const_iterator pvi;
-pvi = find(moduleParams.begin(), moduleParams.end(), pv);
-if (pvi == moduleParams.end() || pvi->value.empty())
-    {
-    errorStr = "Parameter \'" + owner + "\' not found.";
-    printfd(__FILE__, "%s\n", errorStr.c_str());
-    return -1;
-    }
-if (User2UID(pvi->value[0].c_str(), uid) < 0)
-    {
-    errorStr = "Parameter \'" + owner + "\': Unknown user \'" + pvi->value[0] + "\'";
-    printfd(__FILE__, "%s\n", errorStr.c_str());
-    return -1;
-    }
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE_SETTINGS::ParseGroup(const std::vector<STG::ParamValue> & moduleParams, const std::string & group, gid_t * gid)
-{
-STG::ParamValue pv;
-pv.param = group;
-std::vector<STG::ParamValue>::const_iterator pvi;
-pvi = find(moduleParams.begin(), moduleParams.end(), pv);
-if (pvi == moduleParams.end() || pvi->value.empty())
-    {
-    errorStr = "Parameter \'" + group + "\' not found.";
-    printfd(__FILE__, "%s\n", errorStr.c_str());
-    return -1;
-    }
-if (Group2GID(pvi->value[0].c_str(), gid) < 0)
-    {
-    errorStr = "Parameter \'" + group + "\': Unknown group \'" + pvi->value[0] + "\'";
-    printfd(__FILE__, "%s\n", errorStr.c_str());
-    return -1;
-    }
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE_SETTINGS::ParseYesNo(const std::string & value, bool * val)
-{
-if (0 == strcasecmp(value.c_str(), "yes"))
-    {
-    *val = true;
-    return 0;
-    }
-if (0 == strcasecmp(value.c_str(), "no"))
-    {
-    *val = false;
-    return 0;
-    }
-
-errorStr = "Incorrect value \'" + value + "\'.";
-return -1;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE_SETTINGS::ParseMode(const std::vector<STG::ParamValue> & moduleParams, const std::string & modeStr, mode_t * mode)
-{
-STG::ParamValue pv;
-pv.param = modeStr;
-std::vector<STG::ParamValue>::const_iterator pvi;
-pvi = find(moduleParams.begin(), moduleParams.end(), pv);
-if (pvi == moduleParams.end() || pvi->value.empty())
-    {
-    errorStr = "Parameter \'" + modeStr + "\' not found.";
-    printfd(__FILE__, "%s\n", errorStr.c_str());
-    return -1;
-    }
-if (Str2Mode(pvi->value[0].c_str(), mode) < 0)
-    {
-    errorStr = "Parameter \'" + modeStr + "\': Incorrect mode \'" + pvi->value[0] + "\'";
-    printfd(__FILE__, "%s\n", errorStr.c_str());
-    return -1;
-    }
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE_SETTINGS::ParseSettings(const STG::ModuleSettings & s)
-{
-if (ParseOwner(s.moduleParams, "StatOwner", &statUID) < 0)
-    return -1;
-if (ParseGroup(s.moduleParams, "StatGroup", &statGID) < 0)
-    return -1;
-if (ParseMode(s.moduleParams, "StatMode", &statMode) < 0)
-    return -1;
-
-if (ParseOwner(s.moduleParams, "ConfOwner", &confUID) < 0)
-    return -1;
-if (ParseGroup(s.moduleParams, "ConfGroup", &confGID) < 0)
-    return -1;
-if (ParseMode(s.moduleParams, "ConfMode", &confMode) < 0)
-    return -1;
-
-if (ParseOwner(s.moduleParams, "UserLogOwner", &userLogUID) < 0)
-    return -1;
-if (ParseGroup(s.moduleParams, "UserLogGroup", &userLogGID) < 0)
-    return -1;
-if (ParseMode(s.moduleParams, "UserLogMode", &userLogMode) < 0)
-    return -1;
-
-std::vector<STG::ParamValue>::const_iterator pvi;
-STG::ParamValue pv;
-pv.param = "RemoveBak";
-pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-if (pvi == s.moduleParams.end() || pvi->value.empty())
-    {
-    removeBak = true;
-    }
-else
-    {
-    if (ParseYesNo(pvi->value[0], &removeBak))
-        {
-        printfd(__FILE__, "Cannot parse parameter 'RemoveBak'\n");
-        return -1;
-        }
-    }
-
-pv.param = "ReadBak";
-pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-if (pvi == s.moduleParams.end() || pvi->value.empty())
-    {
-    readBak = false;
-    }
-else
-    {
-    if (ParseYesNo(pvi->value[0], &readBak))
-        {
-        printfd(__FILE__, "Cannot parse parameter 'ReadBak'\n");
-        return -1;
-        }
-    }
-
-pv.param = "WorkDir";
-pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
-if (pvi == s.moduleParams.end() || pvi->value.empty())
-    {
-    errorStr = "Parameter \'WorkDir\' not found.";
-    printfd(__FILE__, "Parameter 'WorkDir' not found\n");
-    return -1;
-    }
-
-workDir = pvi->value[0];
-if (workDir.size() && workDir[workDir.size() - 1] == '/')
-    {
-    workDir.resize(workDir.size() - 1);
-    }
-usersDir = workDir + "/users/";
-if (!CheckAndCreate(usersDir, GetConfModeDir()))
-    {
-    errorStr = usersDir + " doesn't exist. Failed to create.";
-    printfd(__FILE__, "%s\n", errorStr.c_str());
-    return -1;
-    }
-tariffsDir = workDir + "/tariffs/";
-if (!CheckAndCreate(tariffsDir, GetConfModeDir()))
-    {
-    errorStr = tariffsDir + " doesn't exist. Failed to create.";
-    printfd(__FILE__, "%s\n", errorStr.c_str());
-    return -1;
-    }
-adminsDir = workDir + "/admins/";
-if (!CheckAndCreate(adminsDir, GetConfModeDir()))
-    {
-    errorStr = adminsDir + " doesn't exist. Failed to create.";
-    printfd(__FILE__, "%s\n", errorStr.c_str());
-    return -1;
-    }
-servicesDir = workDir + "/services/";
-if (!CheckAndCreate(servicesDir, GetConfModeDir()))
-    {
-    errorStr = servicesDir + " doesn't exist. Failed to create.";
-    printfd(__FILE__, "%s\n", errorStr.c_str());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-const std::string & FILES_STORE_SETTINGS::GetStrError() const
-{
-return errorStr;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE_SETTINGS::User2UID(const char * user, uid_t * uid)
-{
-struct passwd * pw;
-pw = getpwnam(user);
-if (!pw)
-    {
-    errorStr = std::string("User \'") + std::string(user) + std::string("\' not found in system.");
-    printfd(__FILE__, "%s\n", errorStr.c_str());
-    return -1;
-    }
-
-*uid = pw->pw_uid;
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE_SETTINGS::Group2GID(const char * gr, gid_t * gid)
-{
-struct group * grp;
-grp = getgrnam(gr);
-if (!grp)
-    {
-    errorStr = std::string("Group \'") + std::string(gr) + std::string("\' not found in system.");
-    printfd(__FILE__, "%s\n", errorStr.c_str());
-    return -1;
-    }
-
-*gid = grp->gr_gid;
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE_SETTINGS::Str2Mode(const char * str, mode_t * mode)
-{
-char a;
-char b;
-char c;
-if (strlen(str) > 3)
-    {
-    errorStr = std::string("Error parsing mode \'") + str + std::string("\'");
-    printfd(__FILE__, "%s\n", errorStr.c_str());
-    return -1;
-    }
-
-for (int i = 0; i < 3; i++)
-    if (str[i] > '7' || str[i] < '0')
-        {
-        errorStr = std::string("Error parsing mode \'") + str + std::string("\'");
-        printfd(__FILE__, "%s\n", errorStr.c_str());
-        return -1;
-        }
-
-a = str[0] - '0';
-b = str[1] - '0';
-c = str[2] - '0';
-
-*mode = ((mode_t)c) + ((mode_t)b << 3) + ((mode_t)a << 6);
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-mode_t FILES_STORE_SETTINGS::GetStatModeDir() const
-{
-mode_t mode = statMode;
-if (statMode & S_IRUSR) mode |= S_IXUSR;
-if (statMode & S_IRGRP) mode |= S_IXGRP;
-if (statMode & S_IROTH) mode |= S_IXOTH;
-return mode;
-}
-//-----------------------------------------------------------------------------
-mode_t FILES_STORE_SETTINGS::GetConfModeDir() const
-{
-mode_t mode = confMode;
-if (confMode & S_IRUSR) mode |= S_IXUSR;
-if (confMode & S_IRGRP) mode |= S_IXGRP;
-if (confMode & S_IROTH) mode |= S_IXOTH;
-return mode;
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-FILES_STORE::FILES_STORE()
-    : version("file_store v.1.04"),
-      logger(STG::PluginLogger::get("store_files"))
-{
-pthread_mutexattr_t attr;
-pthread_mutexattr_init(&attr);
-pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
-pthread_mutex_init(&mutex, &attr);
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::ParseSettings()
-{
-int ret = storeSettings.ParseSettings(settings);
-if (ret)
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = storeSettings.GetStrError();
-    }
-return ret;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::GetUsersList(std::vector<std::string> * userList) const
-{
-std::vector<std::string> files;
-
-if (GetFileList(&files, storeSettings.GetUsersDir(), S_IFDIR, ""))
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "Failed to open '" + storeSettings.GetUsersDir() + "': " + std::string(strerror(errno));
-    return -1;
-    }
-
-STG_LOCKER lock(&mutex);
-
-userList->swap(files);
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::GetAdminsList(std::vector<std::string> * adminList) const
-{
-std::vector<std::string> files;
-
-if (GetFileList(&files, storeSettings.GetAdminsDir(), S_IFREG, ".adm"))
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "Failed to open '" + storeSettings.GetAdminsDir() + "': " + std::string(strerror(errno));
-    return -1;
-    }
-
-STG_LOCKER lock(&mutex);
-
-adminList->swap(files);
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::GetTariffsList(std::vector<std::string> * tariffList) const
-{
-std::vector<std::string> files;
-
-if (GetFileList(&files, storeSettings.GetTariffsDir(), S_IFREG, ".tf"))
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "Failed to open '" + storeSettings.GetTariffsDir() + "': " + std::string(strerror(errno));
-    return -1;
-    }
-
-STG_LOCKER lock(&mutex);
-
-tariffList->swap(files);
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::GetServicesList(std::vector<std::string> * list) const
-{
-std::vector<std::string> files;
-
-if (GetFileList(&files, storeSettings.GetServicesDir(), S_IFREG, ".serv"))
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "Failed to open '" + storeSettings.GetServicesDir() + "': " + std::string(strerror(errno));
-    return -1;
-    }
-
-STG_LOCKER lock(&mutex);
-
-list->swap(files);
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::RemoveDir(const char * path) const
-{
-DIR * d = opendir(path);
-
-if (!d)
-    {
-    errorStr = "failed to open dir. Message: '";
-    errorStr += strerror(errno);
-    errorStr += "'";
-    printfd(__FILE__, "FILE_STORE::RemoveDir() - Failed to open dir '%s': '%s'\n", path, strerror(errno));
-    return -1;
-    }
-
-dirent * entry;
-while ((entry = readdir(d)))
-    {
-    if (!(strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..")))
-        continue;
-
-    std::string str = path;
-    str += "/" + std::string(entry->d_name);
-
-    struct stat st;
-    if (stat(str.c_str(), &st))
-        continue;
-
-    if ((st.st_mode & S_IFREG))
-        {
-        if (unlink(str.c_str()))
-            {
-            STG_LOCKER lock(&mutex);
-            errorStr = "unlink failed. Message: '";
-            errorStr += strerror(errno);
-            errorStr += "'";
-            printfd(__FILE__, "FILES_STORE::RemoveDir() - unlink failed. Message: '%s'\n", strerror(errno));
-            closedir(d);
-            return -1;
-            }
-        }
-
-    if (!(st.st_mode & S_IFDIR))
-        {
-        if (RemoveDir(str.c_str()))
-            {
-            closedir(d);
-            return -1;
-            }
-
-        }
-    }
-
-closedir(d);
-
-if (rmdir(path))
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "rmdir failed. Message: '";
-    errorStr += strerror(errno);
-    errorStr += "'";
-    printfd(__FILE__, "FILES_STORE::RemoveDir() - rmdir failed. Message: '%s'\n", strerror(errno));
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::AddUser(const std::string & login) const
-{
-std::string fileName;
-
-strprintf(&fileName, "%s%s", storeSettings.GetUsersDir().c_str(), login.c_str());
-
-if (mkdir(fileName.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == -1)
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = std::string("mkdir failed. Message: '") + strerror(errno) + "'";
-    printfd(__FILE__, "FILES_STORE::AddUser - mkdir failed. Message: '%s'\n", strerror(errno));
-    return -1;
-    }
-
-strprintf(&fileName, "%s%s/conf", storeSettings.GetUsersDir().c_str(), login.c_str());
-if (Touch(fileName))
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "Cannot create file \"" + fileName + "\'";
-    printfd(__FILE__, "FILES_STORE::AddUser - fopen failed. Message: '%s'\n", strerror(errno));
-    return -1;
-    }
-
-strprintf(&fileName, "%s%s/stat", storeSettings.GetUsersDir().c_str(), login.c_str());
-if (Touch(fileName))
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "Cannot create file \"" + fileName + "\'";
-    printfd(__FILE__, "FILES_STORE::AddUser - fopen failed. Message: '%s'\n", strerror(errno));
-    return -1;
-    }
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::DelUser(const std::string & login) const
-{
-std::string dirName;
-std::string dirName1;
-
-strprintf(&dirName, "%s/%s", storeSettings.GetWorkDir().c_str(), DELETED_USERS_DIR);
-if (access(dirName.c_str(), F_OK) != 0)
-    {
-    if (mkdir(dirName.c_str(), 0700) != 0)
-        {
-        STG_LOCKER lock(&mutex);
-        errorStr = "Directory '" + dirName + "' cannot be created.";
-        printfd(__FILE__, "FILES_STORE::DelUser - mkdir failed. Message: '%s'\n", strerror(errno));
-        return -1;
-        }
-    }
-
-if (access(dirName.c_str(), F_OK) == 0)
-    {
-    strprintf(&dirName, "%s/%s/%s.%lu", storeSettings.GetWorkDir().c_str(), DELETED_USERS_DIR, login.c_str(), time(NULL));
-    strprintf(&dirName1, "%s/%s", storeSettings.GetUsersDir().c_str(), login.c_str());
-    if (rename(dirName1.c_str(), dirName.c_str()))
-        {
-        STG_LOCKER lock(&mutex);
-        errorStr = "Error moving dir from " + dirName1 + " to " + dirName;
-        printfd(__FILE__, "FILES_STORE::DelUser - rename failed. Message: '%s'\n", strerror(errno));
-        return -1;
-        }
-    }
-else
-    {
-    strprintf(&dirName, "%s/%s", storeSettings.GetUsersDir().c_str(), login.c_str());
-    if (RemoveDir(dirName.c_str()))
-        {
-        return -1;
-        }
-    }
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::RestoreUserConf(STG::UserConf * conf, const std::string & login) const
-{
-std::string fileName;
-fileName = storeSettings.GetUsersDir() + "/" + login + "/conf";
-if (RestoreUserConf(conf, login, fileName))
-    {
-    if (!storeSettings.GetReadBak())
-        {
-        return -1;
-        }
-    return RestoreUserConf(conf, login, fileName + ".bak");
-    }
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::RestoreUserConf(STG::UserConf * conf, const std::string & login, const std::string & fileName) const
-{
-CONFIGFILE cf(fileName);
-int e = cf.Error();
-
-if (e)
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "User \'" + login + "\' data not read.";
-    printfd(__FILE__, "FILES_STORE::RestoreUserConf - conf read failed for user '%s'\n", login.c_str());
-    return -1;
-    }
-
-if (cf.ReadString("Password", &conf->password, "") < 0)
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "User \'" + login + "\' data not read. Parameter Password.";
-    printfd(__FILE__, "FILES_STORE::RestoreUserConf - password read failed for user '%s'\n", login.c_str());
-    return -1;
-    }
-if (conf->password.empty())
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "User \'" + login + "\' password is blank.";
-    printfd(__FILE__, "FILES_STORE::RestoreUserConf - password is blank for user '%s'\n", login.c_str());
-    return -1;
-    }
-
-if (cf.ReadString("tariff", &conf->tariffName, "") < 0)
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "User \'" + login + "\' data not read. Parameter Tariff.";
-    printfd(__FILE__, "FILES_STORE::RestoreUserConf - tariff read failed for user '%s'\n", login.c_str());
-    return -1;
-    }
-if (conf->tariffName.empty())
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "User \'" + login + "\' tariff is blank.";
-    printfd(__FILE__, "FILES_STORE::RestoreUserConf - tariff is blank for user '%s'\n", login.c_str());
-    return -1;
-    }
-
-std::string ipStr;
-cf.ReadString("IP", &ipStr, "?");
-try
-    {
-    conf->ips = STG::UserIPs::parse(ipStr);
-    }
-catch (const std::string & s)
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "User \'" + login + "\' data not read. Parameter IP address. " + s;
-    printfd(__FILE__, "FILES_STORE::RestoreUserConf - ip read failed for user '%s'\n", login.c_str());
-    return -1;
-    }
-
-if (cf.ReadInt("alwaysOnline", &conf->alwaysOnline, 0) != 0)
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "User \'" + login + "\' data not read. Parameter AlwaysOnline.";
-    printfd(__FILE__, "FILES_STORE::RestoreUserConf - alwaysonline read failed for user '%s'\n", login.c_str());
-    return -1;
-    }
-
-if (cf.ReadInt("down", &conf->disabled, 0) != 0)
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "User \'" + login + "\' data not read. Parameter Down.";
-    printfd(__FILE__, "FILES_STORE::RestoreUserConf - down read failed for user '%s'\n", login.c_str());
-    return -1;
-    }
-
-if (cf.ReadInt("passive", &conf->passive, 0) != 0)
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "User \'" + login + "\' data not read. Parameter Passive.";
-    printfd(__FILE__, "FILES_STORE::RestoreUserConf - passive read failed for user '%s'\n", login.c_str());
-    return -1;
-    }
-
-cf.ReadInt("DisabledDetailStat", &conf->disabledDetailStat, 0);
-cf.ReadTime("CreditExpire", &conf->creditExpire, 0);
-cf.ReadString("TariffChange", &conf->nextTariff, "");
-cf.ReadString("Group", &conf->group, "");
-cf.ReadString("RealName", &conf->realName, "");
-cf.ReadString("Address", &conf->address, "");
-cf.ReadString("Phone", &conf->phone, "");
-cf.ReadString("Note", &conf->note, "");
-cf.ReadString("email", &conf->email, "");
-
-char userdataName[12];
-for (int i = 0; i < USERDATA_NUM; i++)
-    {
-    snprintf(userdataName, 12, "Userdata%d", i);
-    cf.ReadString(userdataName, &conf->userdata[i], "");
-    }
-
-if (cf.ReadDouble("Credit", &conf->credit, 0) != 0)
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "User \'" + login + "\' data not read. Parameter Credit.";
-    printfd(__FILE__, "FILES_STORE::RestoreUserConf - credit read failed for user '%s'\n", login.c_str());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::RestoreUserStat(STG::UserStat * stat, const std::string & login) const
-{
-std::string fileName;
-fileName = storeSettings.GetUsersDir() + "/" + login + "/stat";
-
-if (RestoreUserStat(stat, login, fileName))
-    {
-    if (!storeSettings.GetReadBak())
-        {
-        return -1;
-        }
-    return RestoreUserStat(stat, login, fileName + ".bak");
-    }
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::RestoreUserStat(STG::UserStat * stat, const std::string & login, const std::string & fileName) const
-{
-CONFIGFILE cf(fileName);
-
-int e = cf.Error();
-
-if (e)
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "User \'" + login + "\' stat not read. Cannot open file " + fileName + ".";
-    printfd(__FILE__, "FILES_STORE::RestoreUserStat - stat read failed for user '%s'\n", login.c_str());
-    return -1;
-    }
-
-char s[22];
-
-for (int i = 0; i < DIR_NUM; i++)
-    {
-    uint64_t traff;
-    snprintf(s, 22, "D%d", i);
-    if (cf.ReadULongLongInt(s, &traff, 0) != 0)
-        {
-        STG_LOCKER lock(&mutex);
-        errorStr = "User \'" + login + "\' stat not read. Parameter " + std::string(s);
-        printfd(__FILE__, "FILES_STORE::RestoreUserStat - download stat read failed for user '%s'\n", login.c_str());
-        return -1;
-        }
-    stat->monthDown[i] = traff;
-
-    snprintf(s, 22, "U%d", i);
-    if (cf.ReadULongLongInt(s, &traff, 0) != 0)
-        {
-        STG_LOCKER lock(&mutex);
-        errorStr =   "User \'" + login + "\' stat not read. Parameter " + std::string(s);
-        printfd(__FILE__, "FILES_STORE::RestoreUserStat - upload stat read failed for user '%s'\n", login.c_str());
-        return -1;
-        }
-    stat->monthUp[i] = traff;
-    }
-
-if (cf.ReadDouble("Cash", &stat->cash, 0) != 0)
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr =   "User \'" + login + "\' stat not read. Parameter Cash";
-    printfd(__FILE__, "FILES_STORE::RestoreUserStat - cash read failed for user '%s'\n", login.c_str());
-    return -1;
-    }
-
-if (cf.ReadDouble("FreeMb", &stat->freeMb, 0) != 0)
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr =   "User \'" + login + "\' stat not read. Parameter FreeMb";
-    printfd(__FILE__, "FILES_STORE::RestoreUserStat - freemb read failed for user '%s'\n", login.c_str());
-    return -1;
-    }
-
-if (cf.ReadTime("LastCashAddTime", &stat->lastCashAddTime, 0) != 0)
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr =   "User \'" + login + "\' stat not read. Parameter LastCashAddTime";
-    printfd(__FILE__, "FILES_STORE::RestoreUserStat - lastcashaddtime read failed for user '%s'\n", login.c_str());
-    return -1;
-    }
-
-if (cf.ReadTime("PassiveTime", &stat->passiveTime, 0) != 0)
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr =   "User \'" + login + "\' stat not read. Parameter PassiveTime";
-    printfd(__FILE__, "FILES_STORE::RestoreUserStat - passivetime read failed for user '%s'\n", login.c_str());
-    return -1;
-    }
-
-if (cf.ReadDouble("LastCashAdd", &stat->lastCashAdd, 0) != 0)
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr =   "User \'" + login + "\' stat not read. Parameter LastCashAdd";
-    printfd(__FILE__, "FILES_STORE::RestoreUserStat - lastcashadd read failed for user '%s'\n", login.c_str());
-    return -1;
-    }
-
-if (cf.ReadTime("LastActivityTime", &stat->lastActivityTime, 0) != 0)
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr =   "User \'" + login + "\' stat not read. Parameter LastActivityTime";
-    printfd(__FILE__, "FILES_STORE::RestoreUserStat - lastactivitytime read failed for user '%s'\n", login.c_str());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::SaveUserConf(const STG::UserConf & conf, const std::string & login) const
-{
-std::string fileName;
-fileName = storeSettings.GetUsersDir() + "/" + login + "/conf";
-
-CONFIGFILE cfstat(fileName, true);
-
-int e = cfstat.Error();
-
-if (e)
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = std::string("User \'") + login + "\' conf not written\n";
-    printfd(__FILE__, "FILES_STORE::SaveUserConf - conf write failed for user '%s'\n", login.c_str());
-    return -1;
-    }
-
-e = chmod(fileName.c_str(), storeSettings.GetConfMode());
-e += chown(fileName.c_str(), storeSettings.GetConfUID(), storeSettings.GetConfGID());
-
-if (e)
-    {
-    STG_LOCKER lock(&mutex);
-    printfd(__FILE__, "FILES_STORE::SaveUserConf - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
-    }
-
-cfstat.WriteString("Password",     conf.password);
-cfstat.WriteInt   ("Passive",      conf.passive);
-cfstat.WriteInt   ("Down",         conf.disabled);
-cfstat.WriteInt("DisabledDetailStat", conf.disabledDetailStat);
-cfstat.WriteInt   ("AlwaysOnline", conf.alwaysOnline);
-cfstat.WriteString("Tariff",       conf.tariffName);
-cfstat.WriteString("Address",      conf.address);
-cfstat.WriteString("Phone",        conf.phone);
-cfstat.WriteString("Email",        conf.email);
-cfstat.WriteString("Note",         conf.note);
-cfstat.WriteString("RealName",     conf.realName);
-cfstat.WriteString("Group",        conf.group);
-cfstat.WriteDouble("Credit",       conf.credit);
-cfstat.WriteString("TariffChange", conf.nextTariff);
-
-char userdataName[12];
-for (int i = 0; i < USERDATA_NUM; i++)
-    {
-    snprintf(userdataName, 12, "Userdata%d", i);
-    cfstat.WriteString(userdataName, conf.userdata[i]);
-    }
-cfstat.WriteInt("CreditExpire",    conf.creditExpire);
-
-std::ostringstream ipStr;
-ipStr << conf.ips;
-cfstat.WriteString("IP", ipStr.str());
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::SaveUserStat(const STG::UserStat & stat, const std::string & login) const
-{
-std::string fileName;
-fileName = storeSettings.GetUsersDir() + "/" + login + "/stat";
-
-    {
-    CONFIGFILE cfstat(fileName, true);
-    int e = cfstat.Error();
-
-    if (e)
-        {
-        STG_LOCKER lock(&mutex);
-        errorStr = std::string("User \'") + login + "\' stat not written\n";
-        printfd(__FILE__, "FILES_STORE::SaveUserStat - stat write failed for user '%s'\n", login.c_str());
-        return -1;
-        }
-
-    for (int i = 0; i < DIR_NUM; i++)
-        {
-        char s[22];
-        snprintf(s, 22, "D%d", i);
-        cfstat.WriteInt(s, stat.monthDown[i]);
-        snprintf(s, 22, "U%d", i);
-        cfstat.WriteInt(s, stat.monthUp[i]);
-        }
-
-    cfstat.WriteDouble("Cash", stat.cash);
-    cfstat.WriteDouble("FreeMb", stat.freeMb);
-    cfstat.WriteDouble("LastCashAdd", stat.lastCashAdd);
-    cfstat.WriteInt("LastCashAddTime", stat.lastCashAddTime);
-    cfstat.WriteInt("PassiveTime", stat.passiveTime);
-    cfstat.WriteInt("LastActivityTime", stat.lastActivityTime);
-    }
-
-int e = chmod(fileName.c_str(), storeSettings.GetStatMode());
-e += chown(fileName.c_str(), storeSettings.GetStatUID(), storeSettings.GetStatGID());
-
-if (e)
-    {
-    STG_LOCKER lock(&mutex);
-    printfd(__FILE__, "FILES_STORE::SaveUserStat - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::WriteLogString(const std::string & str, const std::string & login) const
-{
-FILE * f;
-time_t tm = time(NULL);
-std::string fileName;
-fileName = storeSettings.GetUsersDir() + "/" + login + "/log";
-f = fopen(fileName.c_str(), "at");
-
-if (f)
-    {
-    fprintf(f, "%s", LogDate(tm));
-    fprintf(f, " -- ");
-    fprintf(f, "%s", str.c_str());
-    fprintf(f, "\n");
-    fclose(f);
-    }
-else
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "Cannot open \'" + fileName + "\'";
-    printfd(__FILE__, "FILES_STORE::WriteLogString - log write failed for user '%s'\n", login.c_str());
-    return -1;
-    }
-
-int e = chmod(fileName.c_str(), storeSettings.GetLogMode());
-e += chown(fileName.c_str(), storeSettings.GetLogUID(), storeSettings.GetLogGID());
-
-if (e)
-    {
-    STG_LOCKER lock(&mutex);
-    printfd(__FILE__, "FILES_STORE::WriteLogString - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::WriteLog2String(const std::string & str, const std::string & login) const
-{
-FILE * f;
-time_t tm = time(NULL);
-std::string fileName;
-fileName = storeSettings.GetUsersDir() + "/" + login + "/log2";
-f = fopen(fileName.c_str(), "at");
-
-if (f)
-    {
-    fprintf(f, "%s", LogDate(tm));
-    fprintf(f, " -- ");
-    fprintf(f, "%s", str.c_str());
-    fprintf(f, "\n");
-    fclose(f);
-    }
-else
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "Cannot open \'" + fileName + "\'";
-    printfd(__FILE__, "FILES_STORE::WriteLogString - log write failed for user '%s'\n", login.c_str());
-    return -1;
-    }
-
-int e = chmod(fileName.c_str(), storeSettings.GetLogMode());
-e += chown(fileName.c_str(), storeSettings.GetLogUID(), storeSettings.GetLogGID());
-
-if (e)
-    {
-    STG_LOCKER lock(&mutex);
-    printfd(__FILE__, "FILES_STORE::WriteLogString - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::WriteUserChgLog(const std::string & login,
-                                 const std::string & admLogin,
-                                 uint32_t       admIP,
-                                 const std::string & paramName,
-                                 const std::string & oldValue,
-                                 const std::string & newValue,
-                                 const std::string & message) const
-{
-std::string userLogMsg = "Admin \'" + admLogin + "\', " + inet_ntostring(admIP) + ": \'"
-    + paramName + "\' parameter changed from \'" + oldValue +
-    "\' to \'" + newValue + "\'. " + message;
-
-return WriteLogString(userLogMsg, login);
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::WriteUserConnect(const std::string & login, uint32_t ip) const
-{
-std::string logStr = "Connect, " + inet_ntostring(ip);
-if (WriteLogString(logStr, login))
-    return -1;
-return WriteLog2String(logStr, login);
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::WriteUserDisconnect(const std::string & login,
-                                     const STG::DirTraff & monthUp,
-                                     const STG::DirTraff & monthDown,
-                                     const STG::DirTraff & sessionUp,
-                                     const STG::DirTraff & sessionDown,
-                                     double cash,
-                                     double freeMb,
-                                     const std::string & reason) const
-{
-std::ostringstream logStr;
-logStr << "Disconnect, "
-       << " session upload: \'"
-       << sessionUp
-       << "\' session download: \'"
-       << sessionDown
-       << "\' month upload: \'"
-       << monthUp
-       << "\' month download: \'"
-       << monthDown
-       << "\' cash: \'"
-       << cash
-       << "\'";
-
-if (WriteLogString(logStr.str(), login))
-    return -1;
-
-logStr << " freeMb: \'"
-       << freeMb
-       << "\'"
-       << " reason: \'"
-       << reason
-       << "\'";
-
-return WriteLog2String(logStr.str(), login);
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::SaveMonthStat(const STG::UserStat & stat, int month, int year, const std::string & login) const
-{
-// Classic stats
-std::string stat1;
-strprintf(&stat1,"%s/%s/stat.%d.%02d",
-        storeSettings.GetUsersDir().c_str(), login.c_str(), year + 1900, month + 1);
-
-CONFIGFILE s(stat1, true);
-
-if (s.Error())
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "Cannot create file '" + stat1 + "'";
-    printfd(__FILE__, "FILES_STORE::SaveMonthStat - month stat write failed for user '%s'\n", login.c_str());
-    return -1;
-    }
-
-// New stats
-std::string stat2;
-strprintf(&stat2,"%s/%s/stat2.%d.%02d",
-        storeSettings.GetUsersDir().c_str(), login.c_str(), year + 1900, month + 1);
-
-CONFIGFILE s2(stat2, true);
-
-if (s2.Error())
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "Cannot create file '" + stat2 + "'";
-    printfd(__FILE__, "FILES_STORE::SaveMonthStat - month stat write failed for user '%s'\n", login.c_str());
-    return -1;
-    }
-
-for (size_t i = 0; i < DIR_NUM; i++)
-    {
-    char dirName[3];
-    snprintf(dirName, 3, "U%llu", (unsigned long long)i);
-    s.WriteInt(dirName, stat.monthUp[i]); // Classic
-    s2.WriteInt(dirName, stat.monthUp[i]); // New
-    snprintf(dirName, 3, "D%llu", (unsigned long long)i);
-    s.WriteInt(dirName, stat.monthDown[i]); // Classic
-    s2.WriteInt(dirName, stat.monthDown[i]); // New
-    }
-
-// Classic
-s.WriteDouble("cash", stat.cash);
-
-// New
-s2.WriteDouble("Cash", stat.cash);
-s2.WriteDouble("FreeMb", stat.freeMb);
-s2.WriteDouble("LastCashAdd", stat.lastCashAdd);
-s2.WriteInt("LastCashAddTime", stat.lastCashAddTime);
-s2.WriteInt("PassiveTime", stat.passiveTime);
-s2.WriteInt("LastActivityTime", stat.lastActivityTime);
-
-return 0;
-}
-//-----------------------------------------------------------------------------*/
-int FILES_STORE::AddAdmin(const std::string & login) const
-{
-std::string fileName;
-strprintf(&fileName, "%s/%s.adm", storeSettings.GetAdminsDir().c_str(), login.c_str());
-
-if (Touch(fileName))
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "Cannot create file " + fileName;
-    printfd(__FILE__, "FILES_STORE::AddAdmin - failed to add admin '%s'\n", login.c_str());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------*/
-int FILES_STORE::DelAdmin(const std::string & login) const
-{
-std::string fileName;
-strprintf(&fileName, "%s/%s.adm", storeSettings.GetAdminsDir().c_str(), login.c_str());
-if (unlink(fileName.c_str()))
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "unlink failed. Message: '";
-    errorStr += strerror(errno);
-    errorStr += "'";
-    printfd(__FILE__, "FILES_STORE::DelAdmin - unlink failed. Message: '%s'\n", strerror(errno));
-    }
-return 0;
-}
-//-----------------------------------------------------------------------------*/
-int FILES_STORE::SaveAdmin(const STG::AdminConf & ac) const
-{
-std::string fileName;
-
-strprintf(&fileName, "%s/%s.adm", storeSettings.GetAdminsDir().c_str(), ac.login.c_str());
-
-    {
-    CONFIGFILE cf(fileName, true);
-
-    int e = cf.Error();
-
-    if (e)
-        {
-        STG_LOCKER lock(&mutex);
-        errorStr = "Cannot write admin " + ac.login + ". " + fileName;
-        printfd(__FILE__, "FILES_STORE::SaveAdmin - failed to save admin '%s'\n", ac.login.c_str());
-        return -1;
-        }
-
-    char pass[ADM_PASSWD_LEN + 1];
-    memset(pass, 0, sizeof(pass));
-
-    char adminPass[ADM_PASSWD_LEN + 1];
-    memset(adminPass, 0, sizeof(adminPass));
-
-    BLOWFISH_CTX ctx;
-    InitContext(adm_enc_passwd, strlen(adm_enc_passwd), &ctx);
-
-    strncpy(adminPass, ac.password.c_str(), ADM_PASSWD_LEN);
-    adminPass[ADM_PASSWD_LEN - 1] = 0;
-
-    for (int i = 0; i < ADM_PASSWD_LEN/8; i++)
-        {
-        EncryptBlock(pass + 8*i, adminPass + 8*i, &ctx);
-        }
-
-    pass[ADM_PASSWD_LEN - 1] = 0;
-    char passwordE[2 * ADM_PASSWD_LEN + 2];
-    Encode12(passwordE, pass, ADM_PASSWD_LEN);
-
-    cf.WriteString("password", passwordE);
-    cf.WriteInt("ChgConf",     ac.priv.userConf);
-    cf.WriteInt("ChgPassword", ac.priv.userPasswd);
-    cf.WriteInt("ChgStat",     ac.priv.userStat);
-    cf.WriteInt("ChgCash",     ac.priv.userCash);
-    cf.WriteInt("UsrAddDel",   ac.priv.userAddDel);
-    cf.WriteInt("ChgTariff",   ac.priv.tariffChg);
-    cf.WriteInt("ChgAdmin",    ac.priv.adminChg);
-    cf.WriteInt("ChgService",  ac.priv.serviceChg);
-    cf.WriteInt("ChgCorp",     ac.priv.corpChg);
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::RestoreAdmin(STG::AdminConf * ac, const std::string & login) const
-{
-std::string fileName;
-strprintf(&fileName, "%s/%s.adm", storeSettings.GetAdminsDir().c_str(), login.c_str());
-CONFIGFILE cf(fileName);
-char pass[ADM_PASSWD_LEN + 1];
-char password[ADM_PASSWD_LEN + 1];
-char passwordE[2 * ADM_PASSWD_LEN + 2];
-BLOWFISH_CTX ctx;
-
-std::string p;
-
-if (cf.Error())
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "Cannot open " + fileName;
-    printfd(__FILE__, "FILES_STORE::RestoreAdmin - failed to restore admin '%s'\n", ac->login.c_str());
-    return -1;
-    }
-
-if (cf.ReadString("password", &p, "*"))
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "Error in parameter password";
-    printfd(__FILE__, "FILES_STORE::RestoreAdmin - password read failed for admin '%s'\n", ac->login.c_str());
-    return -1;
-    }
-
-memset(passwordE, 0, sizeof(passwordE));
-strncpy(passwordE, p.c_str(), 2*ADM_PASSWD_LEN);
-
-memset(pass, 0, sizeof(pass));
-
-if (passwordE[0] != 0)
-    {
-    Decode21(pass, passwordE);
-    InitContext(adm_enc_passwd, strlen(adm_enc_passwd), &ctx);
-
-    for (int i = 0; i < ADM_PASSWD_LEN/8; i++)
-        {
-        DecryptBlock(password + 8*i, pass + 8*i, &ctx);
-        }
-    }
-else
-    {
-    password[0] = 0;
-    }
-
-ac->password = password;
-
-uint16_t a;
-
-if (cf.ReadUShortInt("ChgConf", &a, 0) == 0)
-    ac->priv.userConf = a;
-else
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "Error in parameter ChgConf";
-    printfd(__FILE__, "FILES_STORE::RestoreAdmin - chgconf read failed for admin '%s'\n", ac->login.c_str());
-    return -1;
-    }
-
-if (cf.ReadUShortInt("ChgPassword", &a, 0) == 0)
-    ac->priv.userPasswd = a;
-else
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "Error in parameter ChgPassword";
-    printfd(__FILE__, "FILES_STORE::RestoreAdmin - chgpassword read failed for admin '%s'\n", ac->login.c_str());
-    return -1;
-    }
-
-if (cf.ReadUShortInt("ChgStat", &a, 0) == 0)
-    ac->priv.userStat = a;
-else
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "Error in parameter ChgStat";
-    printfd(__FILE__, "FILES_STORE::RestoreAdmin - chgstat read failed for admin '%s'\n", ac->login.c_str());
-    return -1;
-    }
-
-if (cf.ReadUShortInt("ChgCash", &a, 0) == 0)
-    ac->priv.userCash = a;
-else
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "Error in parameter ChgCash";
-    printfd(__FILE__, "FILES_STORE::RestoreAdmin - chgcash read failed for admin '%s'\n", ac->login.c_str());
-    return -1;
-    }
-
-if (cf.ReadUShortInt("UsrAddDel", &a, 0) == 0)
-    ac->priv.userAddDel = a;
-else
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "Error in parameter UsrAddDel";
-    printfd(__FILE__, "FILES_STORE::RestoreAdmin - usradddel read failed for admin '%s'\n", ac->login.c_str());
-    return -1;
-    }
-
-if (cf.ReadUShortInt("ChgAdmin", &a, 0) == 0)
-    ac->priv.adminChg = a;
-else
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "Error in parameter ChgAdmin";
-    printfd(__FILE__, "FILES_STORE::RestoreAdmin - chgadmin read failed for admin '%s'\n", ac->login.c_str());
-    return -1;
-    }
-
-if (cf.ReadUShortInt("ChgTariff", &a, 0) == 0)
-    ac->priv.tariffChg = a;
-else
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "Error in parameter ChgTariff";
-    printfd(__FILE__, "FILES_STORE::RestoreAdmin - chgtariff read failed for admin '%s'\n", ac->login.c_str());
-    return -1;
-    }
-
-if (cf.ReadUShortInt("ChgService", &a, 0) == 0)
-    ac->priv.serviceChg = a;
-else
-    ac->priv.serviceChg = 0;
-
-if (cf.ReadUShortInt("ChgCorp", &a, 0) == 0)
-    ac->priv.corpChg = a;
-else
-    ac->priv.corpChg = 0;
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::AddTariff(const std::string & name) const
-{
-std::string fileName;
-strprintf(&fileName, "%s/%s.tf", storeSettings.GetTariffsDir().c_str(), name.c_str());
-if (Touch(fileName))
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "Cannot create file " + fileName;
-    printfd(__FILE__, "FILES_STORE::AddTariff - failed to add tariff '%s'\n", name.c_str());
-    return -1;
-    }
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::DelTariff(const std::string & name) const
-{
-std::string fileName;
-strprintf(&fileName, "%s/%s.tf", storeSettings.GetTariffsDir().c_str(), name.c_str());
-if (unlink(fileName.c_str()))
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "unlink failed. Message: '";
-    errorStr += strerror(errno);
-    errorStr += "'";
-    printfd(__FILE__, "FILES_STORE::DelTariff - unlink failed. Message: '%s'\n", strerror(errno));
-    }
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::RestoreTariff(STG::TariffData * td, const std::string & tariffName) const
-{
-std::string fileName = storeSettings.GetTariffsDir() + "/" + tariffName + ".tf";
-CONFIGFILE conf(fileName);
-std::string str;
-td->tariffConf.name = tariffName;
-
-if (conf.Error() != 0)
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "Cannot read file " + fileName;
-    printfd(__FILE__, "FILES_STORE::RestoreTariff - failed to read tariff '%s'\n", tariffName.c_str());
-    return -1;
-    }
-
-std::string param;
-for (int i = 0; i<DIR_NUM; i++)
-    {
-    strprintf(&param, "Time%d", i);
-    if (conf.ReadString(param, &str, "00:00-00:00") < 0)
-        {
-        STG_LOCKER lock(&mutex);
-        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
-        printfd(__FILE__, "FILES_STORE::RestoreTariff - time%d read failed for tariff '%s'\n", i, tariffName.c_str());
-        return -1;
-        }
-
-    ParseTariffTimeStr(str.c_str(),
-                       td->dirPrice[i].hDay,
-                       td->dirPrice[i].mDay,
-                       td->dirPrice[i].hNight,
-                       td->dirPrice[i].mNight);
-
-    strprintf(&param, "PriceDayA%d", i);
-    if (conf.ReadDouble(param, &td->dirPrice[i].priceDayA, 0.0) < 0)
-        {
-        STG_LOCKER lock(&mutex);
-        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
-        printfd(__FILE__, "FILES_STORE::RestoreTariff - pricedaya read failed for tariff '%s'\n", tariffName.c_str());
-        return -1;
-        }
-    td->dirPrice[i].priceDayA /= (1024*1024);
-
-    strprintf(&param, "PriceDayB%d", i);
-    if (conf.ReadDouble(param, &td->dirPrice[i].priceDayB, 0.0) < 0)
-        {
-        STG_LOCKER lock(&mutex);
-        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
-        printfd(__FILE__, "FILES_STORE::RestoreTariff - pricedayb read failed for tariff '%s'\n", tariffName.c_str());
-        return -1;
-        }
-    td->dirPrice[i].priceDayB /= (1024*1024);
-
-    strprintf(&param, "PriceNightA%d", i);
-    if (conf.ReadDouble(param, &td->dirPrice[i].priceNightA, 0.0) < 0)
-        {
-        STG_LOCKER lock(&mutex);
-        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
-        printfd(__FILE__, "FILES_STORE::RestoreTariff - pricenighta read failed for tariff '%s'\n", tariffName.c_str());
-        return -1;
-        }
-    td->dirPrice[i].priceNightA /= (1024*1024);
-
-    strprintf(&param, "PriceNightB%d", i);
-    if (conf.ReadDouble(param, &td->dirPrice[i].priceNightB, 0.0) < 0)
-        {
-        STG_LOCKER lock(&mutex);
-        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
-        printfd(__FILE__, "FILES_STORE::RestoreTariff - pricenightb read failed for tariff '%s'\n", tariffName.c_str());
-        return -1;
-        }
-    td->dirPrice[i].priceNightB /= (1024*1024);
-
-    strprintf(&param, "Threshold%d", i);
-    if (conf.ReadInt(param, &td->dirPrice[i].threshold, 0) < 0)
-        {
-        STG_LOCKER lock(&mutex);
-        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
-        printfd(__FILE__, "FILES_STORE::RestoreTariff - threshold read failed for tariff '%s'\n", tariffName.c_str());
-        return -1;
-        }
-
-    strprintf(&param, "SinglePrice%d", i);
-    if (conf.ReadInt(param, &td->dirPrice[i].singlePrice, 0) < 0)
-        {
-        STG_LOCKER lock(&mutex);
-        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
-        printfd(__FILE__, "FILES_STORE::RestoreTariff - singleprice read failed for tariff '%s'\n", tariffName.c_str());
-        return -1;
-        }
-
-    strprintf(&param, "NoDiscount%d", i);
-    if (conf.ReadInt(param, &td->dirPrice[i].noDiscount, 0) < 0)
-        {
-        STG_LOCKER lock(&mutex);
-        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
-        printfd(__FILE__, "FILES_STORE::RestoreTariff - nodiscount read failed for tariff '%s'\n", tariffName.c_str());
-        return -1;
-        }
-    }
-
-if (conf.ReadDouble("Fee", &td->tariffConf.fee, 0) < 0)
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "Cannot read tariff " + tariffName + ". Parameter Fee";
-    printfd(__FILE__, "FILES_STORE::RestoreTariff - fee read failed for tariff '%s'\n", tariffName.c_str());
-    return -1;
-    }
-
-if (conf.ReadDouble("Free", &td->tariffConf.free, 0) < 0)
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "Cannot read tariff " + tariffName + ". Parameter Free";
-    printfd(__FILE__, "FILES_STORE::RestoreTariff - free read failed for tariff '%s'\n", tariffName.c_str());
-    return -1;
-    }
-
-if (conf.ReadDouble("PassiveCost", &td->tariffConf.passiveCost, 0) < 0)
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "Cannot read tariff " + tariffName + ". Parameter PassiveCost";
-    printfd(__FILE__, "FILES_STORE::RestoreTariff - passivecost read failed for tariff '%s'\n", tariffName.c_str());
-    return -1;
-    }
-
-if (conf.ReadString("TraffType", &str, "") < 0)
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "Cannot read tariff " + tariffName + ". Parameter TraffType";
-    printfd(__FILE__, "FILES_STORE::RestoreTariff - trafftype read failed for tariff '%s'\n", tariffName.c_str());
-    return -1;
-    }
-
-td->tariffConf.traffType = STG::Tariff::parseTraffType(str);
-
-if (conf.ReadString("Period", &str, "month") < 0)
-    td->tariffConf.period = STG::Tariff::MONTH;
-else
-    td->tariffConf.period = STG::Tariff::parsePeriod(str);
-
-if (conf.ReadString("ChangePolicy", &str, "allow") < 0)
-    td->tariffConf.changePolicy = STG::Tariff::ALLOW;
-else
-    td->tariffConf.changePolicy = STG::Tariff::parseChangePolicy(str);
-
-conf.ReadTime("ChangePolicyTimeout", &td->tariffConf.changePolicyTimeout, 0);
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::SaveTariff(const STG::TariffData & td, const std::string & tariffName) const
-{
-std::string fileName = storeSettings.GetTariffsDir() + "/" + tariffName + ".tf";
-
-    {
-    CONFIGFILE cf(fileName, true);
-
-    int e = cf.Error();
-
-    if (e)
-        {
-        STG_LOCKER lock(&mutex);
-        errorStr = "Error writing tariff " + tariffName;
-        printfd(__FILE__, "FILES_STORE::RestoreTariff - failed to save tariff '%s'\n", tariffName.c_str());
-        return e;
-        }
-
-    std::string param;
-    for (int i = 0; i < DIR_NUM; i++)
-        {
-        strprintf(&param, "PriceDayA%d", i);
-        cf.WriteDouble(param, td.dirPrice[i].priceDayA * pt_mega);
-
-        strprintf(&param, "PriceDayB%d", i);
-        cf.WriteDouble(param, td.dirPrice[i].priceDayB * pt_mega);
-
-        strprintf(&param, "PriceNightA%d", i);
-        cf.WriteDouble(param, td.dirPrice[i].priceNightA * pt_mega);
-
-        strprintf(&param, "PriceNightB%d", i);
-        cf.WriteDouble(param, td.dirPrice[i].priceNightB * pt_mega);
-
-        strprintf(&param, "Threshold%d", i);
-        cf.WriteInt(param, td.dirPrice[i].threshold);
-
-        std::string s;
-        strprintf(&param, "Time%d", i);
-
-        strprintf(&s, "%0d:%0d-%0d:%0d",
-                td.dirPrice[i].hDay,
-                td.dirPrice[i].mDay,
-                td.dirPrice[i].hNight,
-                td.dirPrice[i].mNight);
-
-        cf.WriteString(param, s);
-
-        strprintf(&param, "NoDiscount%d", i);
-        cf.WriteInt(param, td.dirPrice[i].noDiscount);
-
-        strprintf(&param, "SinglePrice%d", i);
-        cf.WriteInt(param, td.dirPrice[i].singlePrice);
-        }
-
-    cf.WriteDouble("PassiveCost", td.tariffConf.passiveCost);
-    cf.WriteDouble("Fee", td.tariffConf.fee);
-    cf.WriteDouble("Free", td.tariffConf.free);
-    cf.WriteString("TraffType", STG::Tariff::toString(td.tariffConf.traffType));
-    cf.WriteString("Period", STG::Tariff::toString(td.tariffConf.period));
-    cf.WriteString("ChangePolicy", STG::Tariff::toString(td.tariffConf.changePolicy));
-    cf.WriteTime("ChangePolicyTimeout", td.tariffConf.changePolicyTimeout);
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------*/
-int FILES_STORE::AddService(const std::string & name) const
-{
-std::string fileName;
-strprintf(&fileName, "%s/%s.serv", storeSettings.GetServicesDir().c_str(), name.c_str());
-
-if (Touch(fileName))
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "Cannot create file " + fileName;
-    printfd(__FILE__, "FILES_STORE::AddService - failed to add service '%s'\n", name.c_str());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------*/
-int FILES_STORE::DelService(const std::string & name) const
-{
-std::string fileName;
-strprintf(&fileName, "%s/%s.serv", storeSettings.GetServicesDir().c_str(), name.c_str());
-if (unlink(fileName.c_str()))
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "unlink failed. Message: '";
-    errorStr += strerror(errno);
-    errorStr += "'";
-    printfd(__FILE__, "FILES_STORE::DelAdmin - unlink failed. Message: '%s'\n", strerror(errno));
-    }
-return 0;
-}
-//-----------------------------------------------------------------------------*/
-int FILES_STORE::SaveService(const STG::ServiceConf & conf) const
-{
-std::string fileName;
-
-strprintf(&fileName, "%s/%s.serv", storeSettings.GetServicesDir().c_str(), conf.name.c_str());
-
-    {
-    CONFIGFILE cf(fileName, true);
-
-    int e = cf.Error();
-
-    if (e)
-        {
-        STG_LOCKER lock(&mutex);
-        errorStr = "Cannot write service " + conf.name + ". " + fileName;
-        printfd(__FILE__, "FILES_STORE::SaveService - failed to save service '%s'\n", conf.name.c_str());
-        return -1;
-        }
-
-    cf.WriteString("name", conf.name);
-    cf.WriteString("comment", conf.comment);
-    cf.WriteDouble("cost", conf.cost);
-    cf.WriteInt("pay_day", conf.payDay);
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::RestoreService(STG::ServiceConf * conf, const std::string & name) const
-{
-std::string fileName;
-strprintf(&fileName, "%s/%s.serv", storeSettings.GetServicesDir().c_str(), name.c_str());
-CONFIGFILE cf(fileName);
-
-if (cf.Error())
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "Cannot open " + fileName;
-    printfd(__FILE__, "FILES_STORE::RestoreService - failed to restore service '%s'\n", name.c_str());
-    return -1;
-    }
-
-if (cf.ReadString("name", &conf->name, name))
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "Error in parameter 'name'";
-    printfd(__FILE__, "FILES_STORE::RestoreService - name read failed for service '%s'\n", name.c_str());
-    return -1;
-    }
-
-if (cf.ReadString("comment", &conf->comment, ""))
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "Error in parameter 'comment'";
-    printfd(__FILE__, "FILES_STORE::RestoreService - comment read failed for service '%s'\n", name.c_str());
-    return -1;
-    }
-
-if (cf.ReadDouble("cost", &conf->cost, 0.0))
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "Error in parameter 'cost'";
-    printfd(__FILE__, "FILES_STORE::RestoreService - cost read failed for service '%s'\n", name.c_str());
-    return -1;
-    }
-
-unsigned short value = 0;
-if (cf.ReadUShortInt("pay_day", &value, 0))
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "Error in parameter 'pay_day'";
-    printfd(__FILE__, "FILES_STORE::RestoreService - pay day read failed for service '%s'\n", name.c_str());
-    return -1;
-    }
-conf->payDay = value;
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::WriteDetailedStat(const STG::TraffStat & statTree,
-                                   time_t lastStat,
-                                   const std::string & login) const
-{
-char fn[FN_STR_LEN];
-char dn[FN_STR_LEN];
-FILE * statFile;
-time_t t;
-tm * lt;
-
-t = time(NULL);
-
-snprintf(dn, FN_STR_LEN, "%s/%s/detail_stat", storeSettings.GetUsersDir().c_str(), login.c_str());
-if (access(dn, F_OK) != 0)
-    {
-    if (mkdir(dn, 0700) != 0)
-        {
-        STG_LOCKER lock(&mutex);
-        errorStr = "Directory \'" + std::string(dn) + "\' cannot be created.";
-        printfd(__FILE__, "FILES_STORE::WriteDetailStat - mkdir failed. Message: '%s'\n", strerror(errno));
-        return -1;
-        }
-    }
-
-int e = chown(dn, storeSettings.GetStatUID(), storeSettings.GetStatGID());
-e += chmod(dn, storeSettings.GetStatModeDir());
-
-if (e)
-    {
-    STG_LOCKER lock(&mutex);
-    printfd(__FILE__, "FILES_STORE::WriteDetailStat - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
-    }
-
-lt = localtime(&t);
-
-if (lt->tm_hour == 0 && lt->tm_min <= 5)
-    {
-    t -= 3600 * 24;
-    lt = localtime(&t);
-    }
-
-snprintf(dn, FN_STR_LEN, "%s/%s/detail_stat/%d",
-         storeSettings.GetUsersDir().c_str(),
-         login.c_str(),
-         lt->tm_year+1900);
-
-if (access(dn, F_OK) != 0)
-    {
-    if (mkdir(dn, 0700) != 0)
-        {
-        STG_LOCKER lock(&mutex);
-        errorStr = "Directory \'" + std::string(dn) + "\' cannot be created.";
-        printfd(__FILE__, "FILES_STORE::WriteDetailStat - mkdir failed. Message: '%s'\n", strerror(errno));
-        return -1;
-        }
-    }
-
-e = chown(dn, storeSettings.GetStatUID(), storeSettings.GetStatGID());
-e += chmod(dn, storeSettings.GetStatModeDir());
-
-if (e)
-    {
-    STG_LOCKER lock(&mutex);
-    printfd(__FILE__, "FILES_STORE::WriteDetailStat - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
-    }
-
-snprintf(dn, FN_STR_LEN, "%s/%s/detail_stat/%d/%s%d", 
-         storeSettings.GetUsersDir().c_str(),
-         login.c_str(),
-         lt->tm_year+1900,
-         lt->tm_mon+1 < 10 ? "0" : "",
-         lt->tm_mon+1);
-if (access(dn, F_OK) != 0)
-    {
-    if (mkdir(dn, 0700) != 0)
-        {
-        STG_LOCKER lock(&mutex);
-        errorStr = "Directory \'" + std::string(dn) + "\' cannot be created.";
-        printfd(__FILE__, "FILES_STORE::WriteDetailStat - mkdir failed. Message: '%s'\n", strerror(errno));
-        return -1;
-        }
-    }
-
-e = chown(dn, storeSettings.GetStatUID(), storeSettings.GetStatGID());
-e += chmod(dn, storeSettings.GetStatModeDir());
-
-if (e)
-    {
-    STG_LOCKER lock(&mutex);
-    printfd(__FILE__, "FILES_STORE::WriteDetailStat - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
-    }
-
-snprintf(fn, FN_STR_LEN, "%s/%s%d", dn, lt->tm_mday < 10 ? "0" : "", lt->tm_mday);
-
-statFile = fopen (fn, "at");
-
-if (!statFile)
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "File \'" + std::string(fn) + "\' cannot be written.";
-    printfd(__FILE__, "FILES_STORE::WriteDetailStat - fopen failed. Message: '%s'\n", strerror(errno));
-    return -1;
-    }
-
-struct tm * lt1;
-struct tm * lt2;
-
-lt1 = localtime(&lastStat);
-
-int h1, m1, s1;
-int h2, m2, s2;
-
-h1 = lt1->tm_hour;
-m1 = lt1->tm_min;
-s1 = lt1->tm_sec;
-
-lt2 = localtime(&t);
-
-h2 = lt2->tm_hour;
-m2 = lt2->tm_min;
-s2 = lt2->tm_sec;
-
-if (fprintf(statFile, "-> %02d.%02d.%02d - %02d.%02d.%02d\n",
-            h1, m1, s1, h2, m2, s2) < 0)
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = std::string("fprint failed. Message: '") + strerror(errno) + "'";
-    printfd(__FILE__, "FILES_STORE::WriteDetailStat - fprintf failed. Message: '%s'\n", strerror(errno));
-    fclose(statFile);
-    return -1;
-    }
-
-auto stIter = statTree.begin();
-
-while (stIter != statTree.end())
-    {
-    const auto u = std::to_string(stIter->second.up);
-    const auto d = std::to_string(stIter->second.down);
-    #ifdef TRAFF_STAT_WITH_PORTS
-    if (fprintf(statFile, "%17s:%hu\t%15d\t%15s\t%15s\t%f\n",
-                inet_ntostring(stIter->first.ip).c_str(),
-                stIter->first.port,
-                stIter->first.dir,
-                d.c_str(),
-                u.c_str(),
-                stIter->second.cash) < 0)
-        {
-        STG_LOCKER lock(&mutex);
-        errorStr = "fprint failed. Message: '";
-        errorStr += strerror(errno);
-        errorStr += "'";
-        printfd(__FILE__, "FILES_STORE::WriteDetailStat - fprintf failed. Message: '%s'\n", strerror(errno));
-        fclose(statFile);
-        return -1;
-        }
-    #else
-    if (fprintf(statFile, "%17s\t%15d\t%15s\t%15s\t%f\n",
-                inet_ntostring(stIter->first.ip).c_str(),
-                stIter->first.dir,
-                d.c_str(),
-                u.c_str(),
-                stIter->second.cash) < 0)
-        {
-        STG_LOCKER lock(&mutex);
-        errorStr = std::string("fprint failed. Message: '");
-        errorStr += strerror(errno);
-        errorStr += "'";
-        printfd(__FILE__, "FILES_STORE::WriteDetailStat - fprintf failed. Message: '%s'\n", strerror(errno));
-        fclose(statFile);
-        return -1;
-        }
-    #endif
-
-    ++stIter;
-    }
-
-fclose(statFile);
-
-e = chown(fn, storeSettings.GetStatUID(), storeSettings.GetStatGID());
-e += chmod(fn, storeSettings.GetStatMode());
-
-if (e)
-    {
-    STG_LOCKER lock(&mutex);
-    printfd(__FILE__, "FILES_STORE::WriteDetailStat - chmod/chown failed for user '%s'. Error: '%s'\n", login.c_str(), strerror(errno));
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::AddMessage(STG::Message * msg, const std::string & login) const
-{
-std::string fn;
-std::string dn;
-struct timeval tv;
-
-strprintf(&dn, "%s/%s/messages", storeSettings.GetUsersDir().c_str(), login.c_str());
-if (access(dn.c_str(), F_OK) != 0)
-    {
-    if (mkdir(dn.c_str(), 0700) != 0)
-        {
-        STG_LOCKER lock(&mutex);
-        errorStr = "Directory \'";
-        errorStr += dn;
-        errorStr += "\' cannot be created.";
-        printfd(__FILE__, "FILES_STORE::AddMessage - mkdir failed. Message: '%s'\n", strerror(errno));
-        return -1;
-        }
-    }
-
-chmod(dn.c_str(), storeSettings.GetConfModeDir());
-
-gettimeofday(&tv, NULL);
-
-msg->header.id = ((long long)tv.tv_sec) * 1000000 + ((long long)tv.tv_usec);
-strprintf(&fn, "%s/%lld", dn.c_str(), msg->header.id);
-
-if (Touch(fn))
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "File \'";
-    errorStr += fn;
-    errorStr += "\' cannot be writen.";
-    printfd(__FILE__, "FILES_STORE::AddMessage - fopen failed. Message: '%s'\n", strerror(errno));
-    return -1;
-    }
-
-return EditMessage(*msg, login);
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::EditMessage(const STG::Message & msg, const std::string & login) const
-{
-std::string fileName;
-
-FILE * msgFile;
-strprintf(&fileName, "%s/%s/messages/%lld", storeSettings.GetUsersDir().c_str(), login.c_str(), msg.header.id);
-
-if (access(fileName.c_str(), F_OK) != 0)
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "Message for user \'";
-    errorStr += login + "\' with ID \'";
-    errorStr += std::to_string(msg.header.id) + "\' does not exist.";
-    printfd(__FILE__, "FILES_STORE::EditMessage - %s\n", errorStr.c_str());
-    return -1;
-    }
-
-Touch(fileName + ".new");
-
-msgFile = fopen((fileName + ".new").c_str(), "wt");
-if (!msgFile)
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "File \'" + fileName + "\' cannot be writen.";
-    printfd(__FILE__, "FILES_STORE::EditMessage - fopen failed. Message: '%s'\n", strerror(errno));
-    return -1;
-    }
-
-bool res = true;
-res &= (fprintf(msgFile, "%u\n", msg.header.type) >= 0);
-res &= (fprintf(msgFile, "%u\n", msg.header.lastSendTime) >= 0);
-res &= (fprintf(msgFile, "%u\n", msg.header.creationTime) >= 0);
-res &= (fprintf(msgFile, "%u\n", msg.header.showTime) >= 0);
-res &= (fprintf(msgFile, "%d\n", msg.header.repeat) >= 0);
-res &= (fprintf(msgFile, "%u\n", msg.header.repeatPeriod) >= 0);
-res &= (fprintf(msgFile, "%s", msg.text.c_str()) >= 0);
-
-if (!res)
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = std::string("fprintf failed. Message: '") + strerror(errno) + "'";
-    printfd(__FILE__, "FILES_STORE::EditMessage - fprintf failed. Message: '%s'\n", strerror(errno));
-    fclose(msgFile);
-    return -1;
-    }
-
-fclose(msgFile);
-
-chmod((fileName + ".new").c_str(), storeSettings.GetConfMode());
-
-if (rename((fileName + ".new").c_str(), fileName.c_str()) < 0)
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "Error moving dir from " + fileName + ".new to " + fileName;
-    printfd(__FILE__, "FILES_STORE::EditMessage - rename failed. Message: '%s'\n", strerror(errno));
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::GetMessage(uint64_t id, STG::Message * msg, const std::string & login) const
-{
-std::string fn;
-strprintf(&fn, "%s/%s/messages/%lld", storeSettings.GetUsersDir().c_str(), login.c_str(), id);
-msg->header.id = id;
-return ReadMessage(fn, &msg->header, &msg->text);
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::DelMessage(uint64_t id, const std::string & login) const
-{
-std::string fn;
-strprintf(&fn, "%s/%s/messages/%lld", storeSettings.GetUsersDir().c_str(), login.c_str(), id);
-
-return unlink(fn.c_str());
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::GetMessageHdrs(std::vector<STG::Message::Header> * hdrsList, const std::string & login) const
-{
-std::string dn(storeSettings.GetUsersDir() + "/" + login + "/messages/");
-
-if (access(dn.c_str(), F_OK) != 0)
-    {
-    return 0;
-    }
-
-std::vector<std::string> messages;
-GetFileList(&messages, dn, S_IFREG, "");
-
-for (unsigned i = 0; i < messages.size(); i++)
-    {
-    unsigned long long id = 0;
-
-    if (str2x(messages[i].c_str(), id))
-        {
-        if (unlink((dn + messages[i]).c_str()))
-            {
-            STG_LOCKER lock(&mutex);
-            errorStr = std::string("unlink failed. Message: '") + strerror(errno) + "'";
-            printfd(__FILE__, "FILES_STORE::GetMessageHdrs - unlink failed. Message: '%s'\n", strerror(errno));
-            return -1;
-            }
-        continue;
-        }
-
-    STG::Message::Header hdr;
-    if (ReadMessage(dn + messages[i], &hdr, NULL))
-        {
-        return -1;
-        }
-
-    if (hdr.repeat < 0)
-        {
-        if (unlink((dn + messages[i]).c_str()))
-            {
-            STG_LOCKER lock(&mutex);
-            errorStr = std::string("unlink failed. Message: '") + strerror(errno) + "'";
-            printfd(__FILE__, "FILES_STORE::GetMessageHdrs - unlink failed. Message: '%s'\n", strerror(errno));
-            return -1;
-            }
-        continue;
-        }
-
-    hdr.id = id;
-    hdrsList->push_back(hdr);
-    }
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::ReadMessage(const std::string & fileName,
-                             STG::Message::Header * hdr,
-                             std::string * text) const
-{
-FILE * msgFile;
-msgFile = fopen(fileName.c_str(), "rt");
-if (!msgFile)
-    {
-    STG_LOCKER lock(&mutex);
-    errorStr = "File \'";
-    errorStr += fileName;
-    errorStr += "\' cannot be openned.";
-    printfd(__FILE__, "FILES_STORE::ReadMessage - fopen failed. Message: '%s'\n", strerror(errno));
-    return -1;
-    }
-char p[20];
-unsigned * d[6];
-d[0] = &hdr->type;
-d[1] = &hdr->lastSendTime;
-d[2] = &hdr->creationTime;
-d[3] = &hdr->showTime;
-d[4] = (unsigned*)(&hdr->repeat);
-d[5] = &hdr->repeatPeriod;
-
-memset(p, 0, sizeof(p));
-
-for (int pos = 0; pos < 6; pos++)
-    {
-    if (fgets(p, sizeof(p) - 1, msgFile) == NULL) {
-        STG_LOCKER lock(&mutex);
-        errorStr = "Cannot read file \'";
-        errorStr += fileName;
-        errorStr += "\'. Missing data.";
-        printfd(__FILE__, "FILES_STORE::ReadMessage - cannot read file (missing data)\n");
-        printfd(__FILE__, "FILES_STORE::ReadMessage - position: %d\n", pos);
-        fclose(msgFile);
-        return -1;
-    }
-
-    char * ep;
-    ep = strrchr(p, '\r');
-    if (ep) *ep = 0;
-    ep = strrchr(p, '\n');
-    if (ep) *ep = 0;
-
-    if (feof(msgFile))
-        {
-        STG_LOCKER lock(&mutex);
-        errorStr = "Cannot read file \'";
-        errorStr += fileName;
-        errorStr += "\'. Missing data.";
-        printfd(__FILE__, "FILES_STORE::ReadMessage - cannot read file (feof)\n");
-        printfd(__FILE__, "FILES_STORE::ReadMessage - position: %d\n", pos);
-        fclose(msgFile);
-        return -1;
-        }
-
-    if (str2x(p, *(d[pos])))
-        {
-        STG_LOCKER lock(&mutex);
-        errorStr = "Cannot read file \'";
-        errorStr += fileName;
-        errorStr += "\'. Incorrect value. \'";
-        errorStr += p;
-        errorStr += "\'";
-        printfd(__FILE__, "FILES_STORE::ReadMessage - incorrect value\n");
-        fclose(msgFile);
-        return -1;
-        }
-    }
-
-char txt[2048];
-memset(txt, 0, sizeof(txt));
-if (text)
-    {
-    text->erase(text->begin(), text->end());
-    while (!feof(msgFile))
-        {
-        txt[0] = 0;
-        if (fgets(txt, sizeof(txt) - 1, msgFile) == NULL) {
-            break;
-        }
-
-        (*text) += txt;
-        }
-    }
-fclose(msgFile);
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FILES_STORE::Touch(const std::string & path) const
-{
-FILE * f = fopen(path.c_str(), "wb");
-if (f)
-    {
-    fclose(f);
-    return 0;
-    }
-return -1;
-}
-//-----------------------------------------------------------------------------
-int GetFileList(std::vector<std::string> * fileList, const std::string & directory, mode_t mode, const std::string & ext)
-{
-DIR * d = opendir(directory.c_str());
-
-if (!d)
-    {
-    printfd(__FILE__, "GetFileList - Failed to open dir '%s': '%s'\n", directory.c_str(), strerror(errno));
-    return -1;
-    }
-
-dirent * entry;
-while ((entry = readdir(d)))
-    {
-    if (!(strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..")))
-        continue;
-
-    std::string str = directory + "/" + std::string(entry->d_name);
-
-    struct stat st;
-    if (stat(str.c_str(), &st))
-        continue;
-
-    if (!(st.st_mode & mode)) // Filter by mode
-        continue;
-
-    if (!ext.empty())
-        {
-        // Check extension
-        size_t d_nameLen = strlen(entry->d_name);
-        if (d_nameLen <= ext.size())
-            continue;
-
-        if (ext == entry->d_name + (d_nameLen - ext.size()))
-            {
-            entry->d_name[d_nameLen - ext.size()] = 0;
-            fileList->push_back(entry->d_name);
-            }
-        }
-    else
-        {
-        fileList->push_back(entry->d_name);
-        }
-    }
-
-closedir(d);
-
-return 0;
-}
-//-----------------------------------------------------------------------------
diff --git a/stargazer/plugins/store/files/file_store.h b/stargazer/plugins/store/files/file_store.h
deleted file mode 100644 (file)
index 8bc2ab3..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- */
-
-#pragma once
-
-#include "stg/module_settings.h"
-#include "stg/store.h"
-#include "stg/conffiles.h"
-#include "stg/user_traff.h"
-#include "stg/logger.h"
-
-#include <string>
-
-#include <sys/types.h>
-#include <pthread.h>
-
-//-----------------------------------------------------------------------------
-class FILES_STORE_SETTINGS {
-public:
-    FILES_STORE_SETTINGS();
-    int ParseSettings(const STG::ModuleSettings & s);
-    const std::string & GetStrError() const;
-
-    std::string  GetWorkDir() const { return workDir; }
-    std::string  GetUsersDir() const { return usersDir; }
-    std::string  GetAdminsDir() const { return adminsDir; }
-    std::string  GetTariffsDir() const { return tariffsDir; }
-    std::string  GetServicesDir() const { return servicesDir; }
-
-    mode_t  GetStatMode() const { return statMode; }
-    mode_t  GetStatModeDir() const;
-    uid_t   GetStatUID() const { return statUID; }
-    gid_t   GetStatGID() const { return statGID; }
-
-    mode_t  GetConfMode() const { return confMode; }
-    mode_t  GetConfModeDir() const;
-    uid_t   GetConfUID() const { return confUID; }
-    gid_t   GetConfGID() const { return confGID; }
-
-    mode_t  GetLogMode() const { return userLogMode; }
-    uid_t   GetLogUID() const { return userLogUID; }
-    gid_t   GetLogGID() const { return userLogGID; }
-
-    bool    GetRemoveBak() const { return removeBak; }
-    bool    GetReadBak() const { return readBak; }
-
-private:
-    FILES_STORE_SETTINGS(const FILES_STORE_SETTINGS & rvalue);
-    FILES_STORE_SETTINGS & operator=(const FILES_STORE_SETTINGS & rvalue);
-
-    const STG::ModuleSettings * settings;
-
-    int     User2UID(const char * user, uid_t * uid);
-    int     Group2GID(const char * gr, gid_t * gid);
-    int     Str2Mode(const char * str, mode_t * mode);
-    int     ParseOwner(const std::vector<STG::ParamValue> & moduleParams, const std::string & owner, uid_t * uid);
-    int     ParseGroup(const std::vector<STG::ParamValue> & moduleParams, const std::string & group, uid_t * uid);
-    int     ParseMode(const std::vector<STG::ParamValue> & moduleParams, const std::string & modeStr, mode_t * mode);
-    int     ParseYesNo(const std::string & value, bool * val);
-
-    std::string  errorStr;
-
-    std::string  workDir;
-    std::string  usersDir;
-    std::string  adminsDir;
-    std::string  tariffsDir;
-    std::string  servicesDir;
-
-    mode_t  statMode;
-    uid_t   statUID;
-    gid_t   statGID;
-
-    mode_t  confMode;
-    uid_t   confUID;
-    gid_t   confGID;
-
-    mode_t  userLogMode;
-    uid_t   userLogUID;
-    gid_t   userLogGID;
-
-    bool    removeBak;
-    bool    readBak;
-};
-//-----------------------------------------------------------------------------
-class FILES_STORE: public STG::Store {
-public:
-    FILES_STORE();
-    const std::string & GetStrError() const override { return errorStr; }
-
-    //User
-    int GetUsersList(std::vector<std::string> * usersList) const override;
-    int AddUser(const std::string & login) const override;
-    int DelUser(const std::string & login) const override;
-    int SaveUserStat(const STG::UserStat & stat, const std::string & login) const override;
-    int SaveUserConf(const STG::UserConf & conf, const std::string & login) const override;
-
-    int RestoreUserStat(STG::UserStat * stat, const std::string & login) const override;
-    int RestoreUserConf(STG::UserConf * conf, const std::string & login) const override;
-
-    int WriteUserChgLog(const std::string & login,
-                        const std::string & admLogin,
-                        uint32_t admIP,
-                        const std::string & paramName,
-                        const std::string & oldValue,
-                        const std::string & newValue,
-                        const std::string & message = "") const override;
-    int WriteUserConnect(const std::string & login, uint32_t ip) const override;
-    int WriteUserDisconnect(const std::string & login,
-                            const STG::DirTraff & up,
-                            const STG::DirTraff & down,
-                            const STG::DirTraff & sessionUp,
-                            const STG::DirTraff & sessionDown,
-                            double cash,
-                            double freeMb,
-                            const std::string & reason) const override;
-
-    int WriteDetailedStat(const STG::TraffStat & statTree,
-                          time_t lastStat,
-                          const std::string & login) const override;
-
-    int AddMessage(STG::Message * msg, const std::string & login) const override;
-    int EditMessage(const STG::Message & msg, const std::string & login) const override;
-    int GetMessage(uint64_t id, STG::Message * msg, const std::string & login) const override;
-    int DelMessage(uint64_t id, const std::string & login) const override;
-    int GetMessageHdrs(std::vector<STG::Message::Header> * hdrsList, const std::string & login) const override;
-
-    int SaveMonthStat(const STG::UserStat & stat, int month, int year, const std::string & login) const override;
-
-    //Admin
-    int GetAdminsList(std::vector<std::string> * adminsList) const override;
-    int AddAdmin(const std::string & login) const override;
-    int DelAdmin(const std::string & login) const override;
-    int RestoreAdmin(STG::AdminConf * ac, const std::string & login) const override;
-    int SaveAdmin(const STG::AdminConf & ac) const override;
-
-    //Tariff
-    int GetTariffsList(std::vector<std::string> * tariffsList) const override;
-    int AddTariff(const std::string & name) const override;
-    int DelTariff(const std::string & name) const override;
-    int SaveTariff(const STG::TariffData & td, const std::string & tariffName) const override;
-    int RestoreTariff(STG::TariffData * td, const std::string & tariffName) const override;
-
-    //Corparation
-    int GetCorpsList(std::vector<std::string> *) const override { return 0; }
-    int SaveCorp(const STG::CorpConf &) const override { return 0; }
-    int RestoreCorp(STG::CorpConf *, const std::string &) const override { return 0; }
-    int AddCorp(const std::string &) const override { return 0; }
-    int DelCorp(const std::string &) const override { return 0; }
-
-    // Services
-    int GetServicesList(std::vector<std::string> *) const override;
-    int SaveService(const STG::ServiceConf &) const override;
-    int RestoreService(STG::ServiceConf *, const std::string &) const override;
-    int AddService(const std::string &) const override;
-    int DelService(const std::string &) const override;
-
-    void SetSettings(const STG::ModuleSettings & s) override { settings = s; }
-    int ParseSettings() override;
-    const std::string & GetVersion() const override { return version; }
-
-private:
-    FILES_STORE(const FILES_STORE & rvalue);
-    FILES_STORE & operator=(const FILES_STORE & rvalue);
-
-    int ReadMessage(const std::string & fileName,
-                    STG::Message::Header * hdr,
-                    std::string * text) const;
-
-    virtual int RestoreUserStat(STG::UserStat * stat, const std::string & login, const std::string & fileName) const;
-    virtual int RestoreUserConf(STG::UserConf * conf, const std::string & login, const std::string & fileName) const;
-
-    virtual int WriteLogString(const std::string & str, const std::string & login) const;
-    virtual int WriteLog2String(const std::string & str, const std::string & login) const;
-    int RemoveDir(const char * path) const;
-    int Touch(const std::string & path) const;
-
-    mutable std::string errorStr;
-    std::string version;
-    FILES_STORE_SETTINGS storeSettings;
-    STG::ModuleSettings settings;
-    mutable pthread_mutex_t mutex;
-
-    STG::PluginLogger logger;
-};
diff --git a/stargazer/plugins/store/firebird/firebird_store.cpp b/stargazer/plugins/store/firebird/firebird_store.cpp
deleted file mode 100644 (file)
index c11b442..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-/*
- *  This file contains a realization of a base firebird-storage plugin class
- *
- *  $Revision: 1.18 $
- *  $Date: 2010/01/08 16:00:45 $
- *
- */
-
-#include "firebird_store.h"
-
-#include "stg/common.h"
-
-#include <string>
-#include <vector>
-
-extern "C" STG::Store* GetStore()
-{
-    static FIREBIRD_STORE plugin;
-    return &plugin;
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-FIREBIRD_STORE::FIREBIRD_STORE()
-    : version("firebird_store v.1.4"),
-      db_server("localhost"),
-      db_database("/var/stg/stargazer.fdb"),
-      db_user("stg"),
-      db_password("123456"),
-      til(IBPP::ilConcurrency),
-      tlr(IBPP::lrWait),
-      schemaVersion(0),
-      logger(STG::PluginLogger::get("store_firebird"))
-{
-pthread_mutex_init(&mutex, NULL);
-}
-//-----------------------------------------------------------------------------
-FIREBIRD_STORE::~FIREBIRD_STORE()
-{
-db->Disconnect();
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::ParseSettings()
-{
-std::vector<STG::ParamValue>::iterator i;
-std::string s;
-
-for(i = settings.moduleParams.begin(); i != settings.moduleParams.end(); ++i)
-    {
-    if (i->value.empty())
-        continue;
-    s = ToLower(i->param);
-
-    if (s == "server")
-        db_server = i->value.front();
-
-    if (s == "database")
-        db_database = i->value.front();
-
-    if (s == "user")
-        db_user = i->value.front();
-
-    if (s == "password")
-        db_password = i->value.front();
-
-    // Advanced settings block
-
-    if (s == "isolationLevel")
-        {
-        if (i->value.front() == "Concurrency")
-            til = IBPP::ilConcurrency;
-        else if (i->value.front() == "DirtyRead")
-            til = IBPP::ilReadDirty;
-        else if (i->value.front() == "ReadCommitted")
-            til = IBPP::ilReadCommitted;
-        else if (i->value.front() == "Consistency")
-            til = IBPP::ilConsistency;
-        }
-
-    if (s == "lockResolution")
-        {
-        if (i->value.front() == "Wait")
-            tlr = IBPP::lrWait;
-        else if (i->value.front() == "NoWait")
-            tlr = IBPP::lrNoWait;
-        }
-    }
-
-try
-    {
-    db = IBPP::DatabaseFactory(db_server, db_database, db_user, db_password, "", "KOI8U", "");
-    db->Connect();
-    return CheckVersion();
-    }
-catch (IBPP::Exception & ex)
-    {
-    strError = "IBPP exception";
-    printfd(__FILE__, ex.what());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::CheckVersion()
-{
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
-    {
-    tr->Start();
-    st->Execute("SELECT RDB$RELATION_NAME FROM RDB$RELATIONS WHERE RDB$SYSTEM_FLAG=0 AND RDB$RELATION_NAME = 'TB_INFO'");
-    if (!st->Fetch())
-        {
-        schemaVersion = 0;
-        }
-    else
-        {
-        st->Execute("SELECT version FROM tb_info");
-        while (st->Fetch())
-            st->Get(1, schemaVersion);
-        }
-    tr->Commit();
-    logger("FIREBIRD_STORE: Current DB schema version: %d", schemaVersion);
-    }
-
-catch (IBPP::Exception & ex)
-    {
-    tr->Rollback();
-    strError = "IBPP exception";
-    printfd(__FILE__, ex.what());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
diff --git a/stargazer/plugins/store/firebird/firebird_store.h b/stargazer/plugins/store/firebird/firebird_store.h
deleted file mode 100644 (file)
index 14f0b26..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#pragma once
-
-#include "stg/store.h"
-#include "stg/locker.h"
-#include "stg/ibpp.h"
-#include "stg/logger.h"
-#include "stg/module_settings.h"
-
-#include <ctime>
-#include <string>
-#include <vector>
-
-struct ToLower {
-    char operator() (char c) const  { return static_cast<char>(std::tolower(c)); }
-};
-
-class FIREBIRD_STORE : public STG::Store {
-public:
-    FIREBIRD_STORE();
-    ~FIREBIRD_STORE() override;
-
-    int GetUsersList(std::vector<std::string> * usersList) const override;
-    int AddUser(const std::string & login) const override;
-    int DelUser(const std::string & login) const override;
-    int SaveUserStat(const STG::UserStat & stat, const std::string & login) const override;
-    int SaveUserConf(const STG::UserConf & conf, const std::string & login) const override;
-    int RestoreUserStat(STG::UserStat * stat, const std::string & login) const override;
-    int RestoreUserConf(STG::UserConf * conf, const std::string & login) const override;
-    int WriteUserChgLog(const std::string & login,
-                        const std::string & admLogin,
-                        uint32_t admIP,
-                        const std::string & paramName,
-                        const std::string & oldValue,
-                        const std::string & newValue,
-                        const std::string & message) const override;
-    int WriteUserConnect(const std::string & login, uint32_t ip) const override;
-    int WriteUserDisconnect(const std::string & login,
-                            const STG::DirTraff & up,
-                            const STG::DirTraff & down,
-                            const STG::DirTraff & sessionUp,
-                            const STG::DirTraff & sessionDown,
-                            double cash,
-                            double freeMb,
-                            const std::string & reason) const override;
-    int WriteDetailedStat(const STG::TraffStat & statTree,
-                          time_t lastStat,
-                          const std::string & login) const override;
-
-    int AddMessage(STG::Message * msg, const std::string & login) const override;
-    int EditMessage(const STG::Message & msg, const std::string & login) const override;
-    int GetMessage(uint64_t id, STG::Message * msg, const std::string & login) const override;
-    int DelMessage(uint64_t id, const std::string & login) const override;
-    int GetMessageHdrs(std::vector<STG::Message::Header> * hdrsList, const std::string & login) const override;
-
-    int SaveMonthStat(const STG::UserStat & stat, int month, int year, const std::string  & login) const override;
-
-    int GetAdminsList(std::vector<std::string> * adminsList) const override;
-    int SaveAdmin(const STG::AdminConf & ac) const override;
-    int RestoreAdmin(STG::AdminConf * ac, const std::string & login) const override;
-    int AddAdmin(const std::string & login) const override;
-    int DelAdmin(const std::string & login) const override;
-
-    int GetTariffsList(std::vector<std::string> * tariffsList) const override;
-    int AddTariff(const std::string & name) const override;
-    int DelTariff(const std::string & name) const override;
-    int SaveTariff(const STG::TariffData & td, const std::string & tariffName) const override;
-    int RestoreTariff(STG::TariffData * td, const std::string & tariffName) const override;
-
-    int GetCorpsList(std::vector<std::string> * corpsList) const override;
-    int SaveCorp(const STG::CorpConf & cc) const override;
-    int RestoreCorp(STG::CorpConf * cc, const std::string & name) const override;
-    int AddCorp(const std::string & name) const override;
-    int DelCorp(const std::string & name) const override;
-
-    inline void SetSettings(const STG::ModuleSettings & s) override { settings = s; }
-    int ParseSettings() override;
-
-    inline const std::string & GetStrError() const override { return strError; }
-
-    inline const std::string & GetVersion() const override { return version; }
-
-    int GetServicesList(std::vector<std::string> * servicesList) const override;
-    int SaveService(const STG::ServiceConf & sc) const override;
-    int RestoreService(STG::ServiceConf * sc, const std::string & name) const override;
-    int AddService(const std::string & name) const override;
-    int DelService(const std::string & name) const override;
-
-private:
-    FIREBIRD_STORE(const FIREBIRD_STORE & rvalue);
-    FIREBIRD_STORE & operator=(const FIREBIRD_STORE & rvalue);
-
-    std::string version;
-    mutable std::string strError;
-    std::string db_server, db_database, db_user, db_password;
-    STG::ModuleSettings settings;
-    mutable IBPP::Database db;
-    mutable pthread_mutex_t mutex;
-    IBPP::TIL til;
-    IBPP::TLR tlr;
-    int schemaVersion;
-    STG::PluginLogger logger;
-
-    int SaveStat(const STG::UserStat & stat, const std::string & login, int year = 0, int month = 0) const;
-    int CheckVersion();
-};
-
-time_t ts2time_t(const IBPP::Timestamp & ts);
-void time_t2ts(time_t t, IBPP::Timestamp * ts);
-void ym2date(int year, int month, IBPP::Date * date);
-
-template <typename T>
-inline
-T Get(IBPP::Statement st, size_t pos)
-{
-    T value;
-    st->Get(pos, value);
-    return value;
-}
diff --git a/stargazer/plugins/store/firebird/firebird_store_admins.cpp b/stargazer/plugins/store/firebird/firebird_store_admins.cpp
deleted file mode 100644 (file)
index bb0bc0f..0000000
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-/*
- *  Administrators manipulation methods
- *
- *  $Revision: 1.11 $
- *  $Date: 2008/12/04 17:10:06 $
- *
- */
-
-#include "firebird_store.h"
-
-#include "stg/ibpp.h"
-#include "stg/admin_conf.h"
-#include "stg/blowfish.h"
-#include "stg/common.h"
-
-#include <string>
-#include <vector>
-
-#define adm_enc_passwd "cjeifY8m3"
-
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::GetAdminsList(std::vector<std::string> * adminsList) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-std::string login;
-
-try
-    {
-    tr->Start();
-    st->Execute("select login from tb_admins");
-    while (st->Fetch())
-        {
-        st->Get(1, login);
-        adminsList->push_back(login);
-        }
-    tr->Commit();
-    }
-
-catch (IBPP::Exception & ex)
-    {
-    tr->Rollback();
-    strError = "IBPP exception";
-    printfd(__FILE__, ex.what());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::SaveAdmin(const STG::AdminConf & ac) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-char encodedPass[2 * ADM_PASSWD_LEN + 2];
-char cryptedPass[ADM_PASSWD_LEN + 1];
-char adminPass[ADM_PASSWD_LEN + 1];
-BLOWFISH_CTX ctx;
-
-memset(cryptedPass, 0, ADM_PASSWD_LEN + 1);
-strncpy(adminPass, ac.password.c_str(), ADM_PASSWD_LEN);
-InitContext(adm_enc_passwd, sizeof(adm_enc_passwd), &ctx);
-
-for (int i = 0; i < ADM_PASSWD_LEN / 8; i++)
-    EncryptBlock(cryptedPass + 8 * i, adminPass + 8 * i, &ctx);
-
-cryptedPass[ADM_PASSWD_LEN] = 0;
-Encode12(encodedPass, cryptedPass, ADM_PASSWD_LEN);
-
-try
-    {
-    tr->Start();
-    st->Prepare("update tb_admins set passwd=?, \
-               chg_conf=?, \
-               chg_password=?, \
-               chg_stat=?, \
-               chg_cash=?, \
-               usr_add_del=?, \
-               chg_tariff=?, \
-               chg_admin=? \
-               where login=?");
-    st->Set(1, encodedPass);
-    st->Set(2, static_cast<int16_t>(ac.priv.userConf));
-    st->Set(3, static_cast<int16_t>(ac.priv.userPasswd));
-    st->Set(4, static_cast<int16_t>(ac.priv.userStat));
-    st->Set(5, static_cast<int16_t>(ac.priv.userCash));
-    st->Set(6, static_cast<int16_t>(ac.priv.userAddDel));
-    st->Set(7, static_cast<int16_t>(ac.priv.tariffChg));
-    st->Set(8, static_cast<int16_t>(ac.priv.adminChg));
-    st->Set(9, ac.login);
-    st->Execute();
-    tr->Commit();
-    }
-
-catch (IBPP::Exception & ex)
-    {
-    tr->Rollback();
-    strError = "IBPP exception";
-    printfd(__FILE__, ex.what());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::RestoreAdmin(STG::AdminConf * ac, const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-char cryptedPass[ADM_PASSWD_LEN + 1];
-char adminPass[ADM_PASSWD_LEN + 1];
-BLOWFISH_CTX ctx;
-
-try
-    {
-    tr->Start();
-    st->Prepare("select * from tb_admins where login = ?");
-    st->Set(1, login);
-    st->Execute();
-    if (st->Fetch())
-        {
-        st->Get(2, ac->login);
-        st->Get(3, ac->password);
-        st->Get(4, (int16_t &)ac->priv.userConf);
-        st->Get(5, (int16_t &)ac->priv.userPasswd);
-        st->Get(6, (int16_t &)ac->priv.userStat);
-        st->Get(7, (int16_t &)ac->priv.userCash);
-        st->Get(8, (int16_t &)ac->priv.userAddDel);
-        st->Get(9, (int16_t &)ac->priv.tariffChg);
-        st->Get(10, (int16_t &)ac->priv.adminChg);
-        }
-    else
-        {
-        strError = "Admin \"" + login + "\" not found in database";
-    printfd(__FILE__, "Admin '%s' not found in database\n", login.c_str());
-    tr->Rollback();
-        return -1;
-        }
-    tr->Commit();
-    }
-
-catch (IBPP::Exception & ex)
-    {
-    tr->Rollback();
-    strError = "IBPP exception";
-    printfd(__FILE__, ex.what());
-    return -1;
-    }
-
-if (ac->password == "")
-    {
-    return 0;
-    }
-
-Decode21(cryptedPass, ac->password.c_str());
-InitContext(adm_enc_passwd, sizeof(adm_enc_passwd), &ctx);
-for (int i = 0; i < ADM_PASSWD_LEN / 8; i++)
-    {
-    DecryptBlock(adminPass + 8 * i, cryptedPass + 8 * i, &ctx);
-    }
-ac->password = adminPass;
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::AddAdmin(const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
-    {
-    tr->Start();
-    st->Prepare("insert into tb_admins(login, \
-                    passwd, \
-                    chg_conf, \
-                    chg_password, \
-                    chg_stat, \
-                    chg_cash, \
-                    usr_add_del, \
-                    chg_tariff, \
-                    chg_admin, \
-                    chg_service, \
-                    chg_corporation) \
-                 values (?, '', 0, 0, 0, 0, 0, 0, 0, 0, 0)");
-    st->Set(1, login);
-    st->Execute();
-    tr->Commit();
-    }
-
-catch (IBPP::Exception & ex)
-    {
-    tr->Rollback();
-    strError = "IBPP exception";
-    printfd(__FILE__, ex.what());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::DelAdmin(const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
-    {
-    tr->Start();
-    st->Prepare("delete from tb_admins where login = ?");
-    st->Set(1, login);
-    st->Execute();
-    tr->Commit();
-    }
-
-catch (IBPP::Exception & ex)
-    {
-    strError = "IBPP exception";
-    printfd(__FILE__, ex.what());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-
diff --git a/stargazer/plugins/store/firebird/firebird_store_corporations.cpp b/stargazer/plugins/store/firebird/firebird_store_corporations.cpp
deleted file mode 100644 (file)
index 3b9ad78..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-/*
- *  Corporations manipulation methods
- *
- *  $Revision: 1.5 $
- *  $Date: 2007/12/23 13:39:59 $
- *
- */
-
-#include "firebird_store.h"
-
-#include "stg/ibpp.h"
-#include "stg/corp_conf.h"
-#include "stg/common.h"
-
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::GetCorpsList(std::vector<std::string> * corpsList) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-std::string name;
-
-try
-    {
-    tr->Start();
-    st->Execute("select name from tb_corporations");
-    while (st->Fetch())
-        {
-        st->Get(1, name);
-        corpsList->push_back(name);
-        }
-    tr->Commit();
-    }
-
-catch (IBPP::Exception & ex)
-    {
-    tr->Rollback();
-    strError = "IBPP exception";
-    printfd(__FILE__, ex.what());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::SaveCorp(const STG::CorpConf & cc) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
-    {
-    tr->Start();
-    st->Execute("update tb_corporations set cash = ? where name = ?");
-    st->Set(1, cc.cash);
-    st->Set(2, cc.name);
-    st->Execute();
-    tr->Commit();
-    }
-
-catch (IBPP::Exception & ex)
-    {
-    tr->Rollback();
-    strError = "IBPP exception";
-    printfd(__FILE__, ex.what());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::RestoreCorp(STG::CorpConf * cc, const std::string & name) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
-    {
-    tr->Start();
-    st->Prepare("select cash from tb_corporations where name = ?");
-    st->Set(1, name);
-    st->Execute();
-    if (st->Fetch())
-        {
-        st->Get(1, cc->cash);
-        }
-    else
-        {
-        strError = "Corporation \"" + name + "\" not found in database";
-        tr->Rollback();
-    printfd(__FILE__, "Corporation '%s' not found in database\n", name.c_str());
-        return -1;
-        }
-    tr->Commit();
-    }
-
-catch (IBPP::Exception & ex)
-    {
-    tr->Rollback();
-    strError = "IBPP exception";
-    printfd(__FILE__, ex.what());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::AddCorp(const std::string & name) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
-    {
-    tr->Start();
-    st->Prepare("insert into tb_corporations (name, cash), values (?, 0)");
-    st->Set(1, name);
-    st->Execute();
-    tr->Commit();
-    }
-
-catch (IBPP::Exception & ex)
-    {
-    tr->Rollback();
-    strError = "IBPP exception";
-    printfd(__FILE__, ex.what());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::DelCorp(const std::string & name) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
-    {
-    tr->Start();
-    st->Prepare("delete from tb_corporations where name = ?");
-    st->Set(1, name);
-    st->Execute();
-    tr->Commit();
-    }
-
-catch (IBPP::Exception & ex)
-    {
-    tr->Rollback();
-    strError = "IBPP exception";
-    printfd(__FILE__, ex.what());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-
diff --git a/stargazer/plugins/store/firebird/firebird_store_messages.cpp b/stargazer/plugins/store/firebird/firebird_store_messages.cpp
deleted file mode 100644 (file)
index 90c3e57..0000000
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-
-/*
- *  Messages manipualtion methods
- *
- *  $Revision: 1.10 $
- *  $Date: 2009/03/03 16:16:23 $
- *
- */
-
-#include "firebird_store.h"
-
-#include "stg/ibpp.h"
-#include "stg/message.h"
-#include "stg/common.h"
-
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::AddMessage(STG::Message * msg, const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
-    {
-    tr->Start();
-    st->Prepare("execute procedure sp_add_message(NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
-    st->Set(1, login);
-    st->Set(2, (int32_t)msg->header.ver);
-    st->Set(3, (int32_t)msg->header.type);
-    st->Set(4, (int32_t)msg->header.lastSendTime);
-    st->Set(5, (int32_t)msg->header.creationTime);
-    st->Set(6, (int32_t)msg->header.showTime);
-    st->Set(7, msg->header.repeat);
-    st->Set(8, (int32_t)msg->header.repeatPeriod);
-    st->Set(9, msg->text);
-    st->Execute();
-    st->Get(1, (int64_t &)msg->header.id);
-    tr->Commit();
-    }
-
-catch (IBPP::Exception & ex)
-    {
-    tr->Rollback();
-    strError = "IBPP exception";
-    printfd(__FILE__, ex.what());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::EditMessage(const STG::Message & msg,
-                                const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
-    {
-    tr->Start();
-    st->Prepare("execute procedure sp_add_message(?, ?, ?, ?, ?, ?, ?, ?, ?)");
-    st->Set(1, (int64_t)msg.header.id);
-    st->Set(2, login);
-    st->Set(3, (int32_t)msg.header.ver);
-    st->Set(4, (int32_t)msg.header.type);
-    st->Set(5, (int32_t)msg.header.lastSendTime);
-    st->Set(6, (int32_t)msg.header.creationTime);
-    st->Set(7, (int32_t)msg.header.showTime);
-    st->Set(8, msg.header.repeat);
-    st->Set(9, (int32_t)msg.header.repeatPeriod);
-    st->Set(10, msg.text.c_str());
-    st->Execute();
-    tr->Commit();
-    }
-
-catch (IBPP::Exception & ex)
-    {
-    tr->Rollback();
-    strError = "IBPP exception";
-    printfd(__FILE__, ex.what());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::GetMessage(uint64_t id,
-                               STG::Message * msg,
-                               const std::string &) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
-    {
-    tr->Start();
-    st->Prepare("select * from tb_messages where pk_message = ?");
-    st->Set(1, (int64_t)id);
-    st->Execute();
-    if (st->Fetch())
-        {
-        st->Get(1, (int64_t &)msg->header.id);
-        st->Get(3, (int32_t &)msg->header.ver);
-        st->Get(4, (int32_t &)msg->header.type);
-        st->Get(5, (int32_t &)msg->header.lastSendTime);
-        st->Get(6, (int32_t &)msg->header.creationTime);
-        st->Get(7, (int32_t &)msg->header.showTime);
-        st->Get(8, msg->header.repeat);
-        st->Get(9, (int32_t &)msg->header.repeatPeriod);
-        st->Get(10, msg->text);
-        }
-    else
-        {
-        strprintf(&strError, "Message with id = %d not found in database", id);
-    printfd(__FILE__, "Message with id - %d not found in database\n", id);
-        tr->Rollback();
-        return -1;
-        }
-    tr->Commit();
-    }
-
-catch (IBPP::Exception & ex)
-    {
-    tr->Rollback();
-    strError = "IBPP exception";
-    printfd(__FILE__, ex.what());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::DelMessage(uint64_t id, const std::string &) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
-    {
-    tr->Start();
-    st->Prepare("delete from tb_messages where pk_message = ?");
-    st->Set(1, (int64_t)id);
-    st->Execute();
-    tr->Commit();
-    }
-
-catch (IBPP::Exception & ex)
-    {
-    tr->Rollback();
-    strError = "IBPP exception";
-    printfd(__FILE__, ex.what());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::GetMessageHdrs(std::vector<STG::Message::Header> * hdrsList,
-                                   const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-STG::Message::Header header;
-
-try
-    {
-    tr->Start();
-    st->Prepare("select pk_message, ver, msg_type, \
-                        last_send_time, creation_time, \
-            show_time, repeat, repeat_period \
-         from tb_messages where \
-                fk_user = (select pk_user from tb_users where name = ?)");
-    st->Set(1, login);
-    st->Execute();
-    while (st->Fetch())
-        {
-        st->Get(1, (int64_t &)header.id);
-        st->Get(2, (int32_t &)header.ver);
-        st->Get(3, (int32_t &)header.type);
-        st->Get(4, (int32_t &)header.lastSendTime);
-        st->Get(5, (int32_t &)header.creationTime);
-        st->Get(6, (int32_t &)header.showTime);
-        st->Get(7, header.repeat);
-        st->Get(8, (int32_t &)header.repeatPeriod);
-        hdrsList->push_back(header);
-        }
-    tr->Commit();
-    }
-
-catch (IBPP::Exception & ex)
-    {
-    tr->Rollback();
-    strError = "IBPP exception";
-    printfd(__FILE__, ex.what());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-
diff --git a/stargazer/plugins/store/firebird/firebird_store_services.cpp b/stargazer/plugins/store/firebird/firebird_store_services.cpp
deleted file mode 100644 (file)
index 0056879..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-
-/*
- *  Services manipulation methods
- *
- *  $Revision: 1.6 $
- *  $Date: 2009/05/13 13:19:33 $
- *
- */
-
-#include "firebird_store.h"
-
-#include "stg/ibpp.h"
-#include "stg/service_conf.h"
-#include "stg/common.h"
-
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::GetServicesList(std::vector<std::string> * servicesList) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-std::string name;
-
-try
-    {
-    tr->Start();
-    st->Execute("select name from tb_services");
-    while (st->Fetch())
-        {
-        st->Get(1, name);
-        servicesList->push_back(name);
-        }
-    tr->Commit();
-    }
-
-catch (IBPP::Exception & ex)
-    {
-    tr->Rollback();
-    strError = "IBPP exception";
-    printfd(__FILE__, ex.what());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::SaveService(const STG::ServiceConf & sc) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
-    {
-    tr->Start();
-    st->Prepare("update tb_services set \
-            comments = ?, \
-            cost = ?, \
-            pay_day = ? \
-         where name = ?");
-    st->Set(1, sc.comment);
-    st->Set(2, sc.cost);
-    st->Set(3, static_cast<int16_t>(sc.payDay));
-    st->Set(4, sc.name);
-    st->Execute();
-    tr->Commit();
-    }
-
-catch (IBPP::Exception & ex)
-    {
-    tr->Rollback();
-    strError = "IBPP exception";
-    printfd(__FILE__, ex.what());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::RestoreService(STG::ServiceConf * sc,
-                                   const std::string & name) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
-    {
-    tr->Start();
-    st->Prepare("select * from tb_services where name = ?");
-    st->Set(1, name);
-    st->Execute();
-    if (st->Fetch())
-        {
-        st->Get(3, sc->comment);
-        st->Get(4, sc->cost);
-        int16_t pd;
-        st->Get(5, pd);
-        sc->payDay = static_cast<uint8_t>(pd);
-        }
-    else
-        {
-        strError = "Service \"" + name + "\" not found in database";
-    printfd(__FILE__, "Service '%s' not found in database\n", name.c_str());
-        tr->Rollback();
-        return -1;
-        }
-    tr->Commit();
-    }
-
-catch (IBPP::Exception & ex)
-    {
-    tr->Rollback();
-    strError = "IBPP exception";
-    printfd(__FILE__, ex.what());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::AddService(const std::string & name) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
-    {
-    tr->Start();
-    st->Prepare("insert into tb_services (name, comment, cost, pay_day) \
-            values (?, '', 0, 0)");
-    st->Set(1, name);
-    st->Execute();
-    tr->Commit();
-    }
-
-catch (IBPP::Exception & ex)
-    {
-    tr->Rollback();
-    strError = "IBPP exception";
-    printfd(__FILE__, ex.what());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::DelService(const std::string & name) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
-    {
-    tr->Start();
-    st->Prepare("execute procedure sp_delete_service(?)");
-    st->Set(1, name);
-    st->Execute();
-    tr->Commit();
-    }
-
-catch (IBPP::Exception & ex)
-    {
-    tr->Rollback();
-    strError = "IBPP exception";
-    printfd(__FILE__, ex.what());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-
diff --git a/stargazer/plugins/store/firebird/firebird_store_tariffs.cpp b/stargazer/plugins/store/firebird/firebird_store_tariffs.cpp
deleted file mode 100644 (file)
index 10c45ab..0000000
+++ /dev/null
@@ -1,375 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-/*
- *  Tariffs manipulation methods
- *
- *  $Revision: 1.5 $
- *  $Date: 2007/12/23 13:39:59 $
- *
- */
-
-#include "firebird_store.h"
-
-#include "stg/ibpp.h"
-#include "stg/tariff.h"
-#include "stg/tariff_conf.h"
-#include "stg/common.h"
-
-#include <cmath>
-
-namespace
-{
-
-const int pt_mega = 1024 * 1024;
-
-}
-
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::GetTariffsList(std::vector<std::string> * tariffsList) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-std::string name;
-
-try
-    {
-    tr->Start();
-    st->Execute("select name from tb_tariffs");
-    while (st->Fetch())
-        {
-        st->Get(1, name);
-        tariffsList->push_back(name);
-        }
-    tr->Commit();
-    }
-
-catch (IBPP::Exception & ex)
-    {
-    tr->Rollback();
-    strError = "IBPP exception";
-    printfd(__FILE__, ex.what());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::AddTariff(const std::string & name) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
-    {
-    tr->Start();
-    st->Prepare("execute procedure sp_add_tariff(?, ?)");
-    st->Set(1, name);
-    st->Set(2, DIR_NUM);
-    st->Execute();
-    tr->Commit();
-    }
-
-catch (IBPP::Exception & ex)
-    {
-    tr->Rollback();
-    strError = "IBPP exception";
-    printfd(__FILE__, ex.what());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::DelTariff(const std::string & name) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
-    {
-    tr->Start();
-    st->Prepare("execute procedure sp_delete_tariff(?)");
-    st->Set(1, name);
-    st->Execute();
-    tr->Commit();
-    }
-
-catch (IBPP::Exception & ex)
-    {
-    tr->Rollback();
-    strError = "IBPP exception";
-    printfd(__FILE__, ex.what());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::SaveTariff(const STG::TariffData & td,
-                               const std::string & tariffName) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
-    {
-    tr->Start();
-    st->Prepare("select pk_tariff from tb_tariffs where name = ?");
-    st->Set(1, tariffName);
-    st->Execute();
-    if (!st->Fetch())
-    {
-    tr->Rollback();
-    strprintf(&strError, "Tariff \"%s\" not found in database", tariffName.c_str());
-    printfd(__FILE__, "Tariff '%s' not found in database\n", tariffName.c_str());
-    return -1;
-    }
-    int32_t id;
-    st->Get(1, id);
-    st->Close();
-
-    std::string query = "update tb_tariffs set \
-                            fee = ?, \
-                            free = ?, \
-                            passive_cost = ?, \
-                            traff_type = ?";
-
-    if (schemaVersion > 0)
-        query += ", period = ?";
-    if (schemaVersion > 1)
-        query += ", change_policy = ?, \
-                    change_policy_timeout = ?";
-
-    query += " where pk_tariff = ?";
-
-    unsigned num = 5;
-    st->Prepare(query);
-    st->Set(1, td.tariffConf.fee);
-    st->Set(2, td.tariffConf.free);
-    st->Set(3, td.tariffConf.passiveCost);
-    st->Set(4, td.tariffConf.traffType);
-
-    if (schemaVersion > 0)
-        {
-        st->Set(5, STG::Tariff::toString(td.tariffConf.period));
-        ++num;
-        }
-
-    if (schemaVersion > 1)
-        {
-        st->Set(6, STG::Tariff::toString(td.tariffConf.changePolicy));
-        IBPP::Timestamp policyTimeout;
-        time_t2ts(td.tariffConf.changePolicyTimeout, &policyTimeout);
-        st->Set(7, policyTimeout);
-        num += 2;
-        }
-
-    st->Set(num, id);
-    st->Execute();
-    st->Close();
-
-    IBPP::Time tb;
-    IBPP::Time te;
-
-    for(int i = 0; i < DIR_NUM; i++)
-        {
-
-        tb.SetTime(td.dirPrice[i].hDay, td.dirPrice[i].mDay, 0);
-        te.SetTime(td.dirPrice[i].hNight, td.dirPrice[i].mNight, 0);
-
-        double pda = td.dirPrice[i].priceDayA * 1024 * 1024;
-        double pdb = td.dirPrice[i].priceDayB * 1024 * 1024;
-        double pna = 0;
-        double pnb = 0;
-
-        if (td.dirPrice[i].singlePrice)
-            {
-            pna = pda;
-            pnb = pdb;
-            }
-        else
-            {
-            pna = td.dirPrice[i].priceNightA;
-            pnb = td.dirPrice[i].priceNightB;
-            }
-
-        int threshold = 0;
-        if (td.dirPrice[i].noDiscount)
-            {
-            threshold = 0xffFFffFF;
-            }
-        else
-            {
-            threshold = td.dirPrice[i].threshold;
-            }
-
-        st->Prepare("update tb_tariffs_params set \
-                price_day_a = ?, \
-                price_day_b = ?, \
-                price_night_a = ?, \
-                price_night_b = ?, \
-                threshold = ?, \
-                time_day_begins = ?, \
-                time_day_ends = ? \
-                where fk_tariff = ? and dir_num = ?");
-        st->Set(1, pda);
-        st->Set(2, pdb);
-        st->Set(3, pna);
-        st->Set(4, pnb);
-        st->Set(5, threshold);
-        st->Set(6, tb);
-        st->Set(7, te);
-        st->Set(8, id);
-        st->Set(9, i);
-        st->Execute();
-        st->Close();
-        }
-    tr->Commit();
-    }
-
-catch (IBPP::Exception & ex)
-    {
-    tr->Rollback();
-    strError = "IBPP exception";
-    printfd(__FILE__, ex.what());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::RestoreTariff(STG::TariffData * td,
-                                  const std::string & tariffName) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-
-td->tariffConf.name = tariffName;
-
-try
-    {
-    tr->Start();
-    st->Prepare("select * from tb_tariffs where name = ?"); // TODO: explicit field order!
-    st->Set(1, tariffName);
-    st->Execute();
-    if (!st->Fetch())
-        {
-        strError = "Tariff \"" + tariffName + "\" not found in database";
-    printfd(__FILE__, "Tariff '%s' not found in database\n", tariffName.c_str());
-        tr->Rollback();
-        return -1;
-        }
-    int32_t id;
-    st->Get(1, id);
-    st->Get(3, td->tariffConf.fee);
-    st->Get(4, td->tariffConf.free);
-    st->Get(5, td->tariffConf.passiveCost);
-    td->tariffConf.traffType = STG::Tariff::fromInt(Get<int>(st, 6));
-    if (schemaVersion > 0)
-        td->tariffConf.period = STG::Tariff::parsePeriod(Get<std::string>(st, 7));
-    if (schemaVersion > 1)
-        {
-        td->tariffConf.changePolicy = STG::Tariff::parseChangePolicy(Get<std::string>(st, 8));
-        td->tariffConf.changePolicyTimeout = ts2time_t(Get<IBPP::Timestamp>(st, 9));
-        }
-    st->Close();
-    st->Prepare("select * from tb_tariffs_params where fk_tariff = ?");
-    st->Set(1, id);
-    st->Execute();
-    int i = 0;
-    while (st->Fetch())
-    {
-    i++;
-    if (i > DIR_NUM)
-        {
-        strError = "Too mach params for tariff \"" + tariffName + "\"";
-        printfd(__FILE__, "Too mach params for tariff '%s'\n", tariffName.c_str());
-        tr->Rollback();
-        return -1;
-        }
-    int16_t dir;
-    st->Get(3, dir);
-    st->Get(4, td->dirPrice[dir].priceDayA);
-    td->dirPrice[dir].priceDayA /= 1024*1024;
-    st->Get(5, td->dirPrice[dir].priceDayB);
-    td->dirPrice[dir].priceDayB /= 1024*1024;
-    st->Get(6, td->dirPrice[dir].priceNightA);
-    td->dirPrice[dir].priceNightA /= 1024*1024;
-    st->Get(7, td->dirPrice[dir].priceNightB);
-    td->dirPrice[dir].priceNightB /= 1024*1024;
-    st->Get(8, td->dirPrice[dir].threshold);
-    if (std::fabs(td->dirPrice[dir].priceDayA - td->dirPrice[dir].priceNightA) < 1.0e-3 / pt_mega &&
-        std::fabs(td->dirPrice[dir].priceDayB - td->dirPrice[dir].priceNightB) < 1.0e-3 / pt_mega)
-        {
-        td->dirPrice[dir].singlePrice = true;
-        }
-    else
-        {
-        td->dirPrice[dir].singlePrice = false;
-        }
-    if (td->dirPrice[dir].threshold == (int)0xffFFffFF)
-        {
-        td->dirPrice[dir].noDiscount = true;
-        }
-    else
-        {
-
-        td->dirPrice[dir].noDiscount = false;
-        }
-    IBPP::Time tb;
-    st->Get(9, tb);
-    IBPP::Time te;
-    st->Get(10, te);
-    int h, m, s;
-    tb.GetTime(h, m, s);
-    td->dirPrice[dir].hDay = h;
-    td->dirPrice[dir].mDay = m;
-    te.GetTime(h, m, s);
-    td->dirPrice[dir].hNight = h;
-    td->dirPrice[dir].mNight = m;
-    }
-    tr->Commit();
-    }
-
-catch (IBPP::Exception & ex)
-    {
-    tr->Rollback();
-    strError = "IBPP exception";
-    printfd(__FILE__, ex.what());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-
diff --git a/stargazer/plugins/store/firebird/firebird_store_users.cpp b/stargazer/plugins/store/firebird/firebird_store_users.cpp
deleted file mode 100644 (file)
index ad28af3..0000000
+++ /dev/null
@@ -1,826 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-/*
- *  User manipulation methods
- *
- *  $Revision: 1.19 $
- *  $Date: 2010/01/19 11:07:25 $
- *
- */
-
-#include "firebird_store.h"
-
-#include "stg/ibpp.h"
-#include "stg/user_conf.h"
-#include "stg/user_stat.h"
-#include "stg/user_traff.h"
-#include "stg/user_ips.h"
-#include "stg/const.h"
-#include "stg/common.h"
-
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::GetUsersList(std::vector<std::string> * usersList) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-std::string name;
-
-try
-    {
-    tr->Start();
-    st->Execute("select name from tb_users");
-    while (st->Fetch())
-        {
-        st->Get(1, name);
-        usersList->push_back(name);
-        }
-    tr->Commit();
-    }
-
-catch (IBPP::Exception & ex)
-    {
-    tr->Rollback();
-    strError = "IBPP exception";
-    printfd(__FILE__, ex.what());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::AddUser(const std::string & name) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
-    {
-    tr->Start();
-    st->Prepare("execute procedure sp_add_user(?, ?)");
-    st->Set(1, name);
-    st->Set(2, DIR_NUM);
-    st->Execute();
-    tr->Commit();
-    }
-
-catch (IBPP::Exception & ex)
-    {
-    tr->Rollback();
-    strError = "IBPP exception";
-    printfd(__FILE__, ex.what());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::DelUser(const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
-    {
-    tr->Start();
-    st->Prepare("execute procedure sp_delete_user(?)");
-    st->Set(1, login);
-    st->Execute();
-    tr->Commit();
-    }
-
-catch (IBPP::Exception & ex)
-    {
-    tr->Rollback();
-    strError = "IBPP exception";
-    printfd(__FILE__, ex.what());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::SaveUserStat(const STG::UserStat & stat,
-                                 const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-return SaveStat(stat, login);
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::SaveStat(const STG::UserStat & stat,
-                             const std::string & login,
-                             int year,
-                             int month) const
-{
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
-    {
-    tr->Start();
-    st->Prepare("select pk_user from tb_users where name = ?");
-    st->Set(1, login);
-    st->Execute();
-    if (!st->Fetch())
-    {
-    strError = "User \"" + login + "\" not found in database";
-    printfd(__FILE__, "User '%s' not found in database\n", login.c_str());
-    tr->Rollback();
-    return -1;
-    }
-    int32_t uid = Get<int32_t>(st, 1);
-    st->Close();
-    st->Prepare("select first 1 pk_stat from tb_stats where fk_user = ? order by stats_date desc");
-    st->Set(1, uid);
-    st->Execute();
-    if (!st->Fetch())
-    {
-    tr->Rollback();
-    strError = "No stat info for user \"" + login + "\"";
-    printfd(__FILE__, "No stat info for user '%s'\n", login.c_str());
-    return -1;
-    }
-    int32_t sid;
-    st->Get(1, sid);
-    st->Close();
-
-    IBPP::Timestamp actTime;
-    time_t2ts(stat.lastActivityTime, &actTime);
-    IBPP::Timestamp addTime;
-    time_t2ts(stat.lastCashAddTime, &addTime);
-    IBPP::Date dt;
-    if (year != 0)
-        ym2date(year, month, &dt);
-    else
-        dt.Today();
-
-    st->Prepare("update tb_stats set \
-                    cash = ?, \
-                    free_mb = ?, \
-                    last_activity_time = ?, \
-                    last_cash_add = ?, \
-                    last_cash_add_time = ?, \
-                    passive_time = ?, \
-                    stats_date = ? \
-                 where pk_stat = ?");
-
-    st->Set(1, stat.cash);
-    st->Set(2, stat.freeMb);
-    st->Set(3, actTime);
-    st->Set(4, stat.lastCashAdd);
-    st->Set(5, addTime);
-    st->Set(6, (int32_t)stat.passiveTime);
-    st->Set(7, dt);
-    st->Set(8, sid);
-
-    st->Execute();
-    st->Close();
-
-    for(int i = 0; i < DIR_NUM; i++)
-        {
-        st->Prepare("update tb_stats_traffic set \
-                        upload = ?, \
-                        download = ? \
-                     where fk_stat = ? and dir_num = ?");
-        st->Set(1, (int64_t)stat.monthUp[i]);
-        st->Set(2, (int64_t)stat.monthDown[i]);
-        st->Set(3, sid);
-        st->Set(4, i);
-        st->Execute();
-        st->Close();
-        }
-
-    tr->Commit();
-    }
-
-catch (IBPP::Exception & ex)
-    {
-    tr->Rollback();
-    strError = "IBPP exception";
-    printfd(__FILE__, ex.what());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::SaveUserConf(const STG::UserConf & conf,
-                                 const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
-    {
-    tr->Start();
-    st->Prepare("select pk_user from tb_users where name = ?");
-    st->Set(1, login);
-    st->Execute();
-    if (!st->Fetch())
-        {
-        strError = "User \"" + login + "\" not found in database";
-        printfd(__FILE__, "User '%s' not found in database\n", login.c_str());
-        tr->Rollback();
-        return -1;
-        }
-    int32_t uid;
-    st->Get(1, uid);
-    st->Close();
-
-    IBPP::Timestamp creditExpire;
-    time_t2ts(conf.creditExpire, &creditExpire);
-
-    st->Prepare("update tb_users set \
-                    address = ?, \
-                    always_online = ?, \
-                    credit = ?, \
-                    credit_expire = ?, \
-                    disabled = ?, \
-                    disabled_detail_stat = ?, \
-                    email = ?, \
-                    grp = ?, \
-                    note = ?, \
-                    passive = ?, \
-                    passwd = ?, \
-                    phone = ?, \
-                    fk_tariff = (select pk_tariff from tb_tariffs \
-                                 where name = ?), \
-                    fk_tariff_change = (select pk_tariff from tb_tariffs \
-                                        where name = ?), \
-                    fk_corporation = (select pk_corporation from tb_corporations \
-                                      where name = ?), \
-                    real_name = ? \
-                 where pk_user = ?");
-
-    st->Set(1, conf.address);
-    st->Set(2, (bool)conf.alwaysOnline);
-    st->Set(3, conf.credit);
-    st->Set(4, creditExpire);
-    st->Set(5, (bool)conf.disabled);
-    st->Set(6, (bool)conf.disabledDetailStat);
-    st->Set(7, conf.email);
-    st->Set(8, conf.group);
-    st->Set(9, conf.note);
-    st->Set(10, (bool)conf.passive);
-    st->Set(11, conf.password);
-    st->Set(12, conf.phone);
-    st->Set(13, conf.tariffName);
-    st->Set(14, conf.nextTariff);
-    st->Set(15, conf.corp);
-    st->Set(16, conf.realName);
-    st->Set(17, uid);
-
-    st->Execute();
-    st->Close();
-
-    st->Prepare("delete from tb_users_services where fk_user = ?");
-    st->Set(1, uid);
-    st->Execute();
-    st->Close();
-
-    st->Prepare("insert into tb_users_services (fk_user, fk_service) \
-                    values (?, (select pk_service from tb_services \
-                                where name = ?))");
-    for(std::vector<std::string>::const_iterator it = conf.services.begin(); it != conf.services.end(); ++it)
-        {
-        st->Set(1, uid);
-        st->Set(2, *it);
-        st->Execute();
-        }
-    st->Close();
-
-    st->Prepare("delete from tb_users_data where fk_user = ?");
-    st->Set(1, uid);
-    st->Execute();
-    st->Close();
-
-    int i = 0;
-    st->Prepare("insert into tb_users_data (fk_user, data, num) values (?, ?, ?)");
-    for (std::vector<std::string>::const_iterator it = conf.userdata.begin(); it != conf.userdata.end(); ++it)
-        {
-        st->Set(1, uid);
-        st->Set(2, *it);
-        st->Set(3, i++);
-        st->Execute();
-        }
-    st->Close();
-
-    st->Prepare("delete from tb_allowed_ip where fk_user = ?");
-    st->Set(1, uid);
-    st->Execute();
-
-    st->Prepare("insert into tb_allowed_ip (fk_user, ip, mask) values (?, ?, ?)");
-    for(size_t i = 0; i < conf.ips.count(); i++)
-        {
-        st->Set(1, uid);
-        st->Set(2, (int32_t)conf.ips[i].ip);
-        st->Set(3, (int32_t)conf.ips[i].mask);
-        st->Execute();
-        }
-    tr->Commit();
-    }
-catch (IBPP::Exception & ex)
-    {
-    tr->Rollback();
-    strError = "IBPP exception";
-    printfd(__FILE__, ex.what());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::RestoreUserStat(STG::UserStat * stat,
-                                    const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
-    {
-    tr->Start();
-    st->Prepare("select pk_user from tb_users where name = ?");
-    st->Set(1, login);
-    st->Execute();
-    if (!st->Fetch())
-        {
-        strError = "User \"" + login + "\" not found in database";
-        printfd(__FILE__, "User '%s' not found in database\n", login.c_str());
-        return -1;
-        }
-    int32_t uid;
-    st->Get(1, uid);
-    st->Close();
-
-    st->Prepare("select first 1 pk_stat, cash, free_mb, last_activity_time, \
-                    last_cash_add, last_cash_add_time, passive_time from tb_stats \
-                 where fk_user = ? order by stats_date desc");
-    st->Set(1, uid);
-    st->Execute();
-    if (!st->Fetch())
-        {
-        strError = "No stat info for user \"" + login + "\"";
-        printfd(__FILE__, "No stat info for user '%s'\n", login.c_str());
-        tr->Rollback();
-        return -1;
-        }
-
-    int32_t sid;
-    st->Get(1, sid);
-    st->Get(2, stat->cash);
-    st->Get(3, stat->freeMb);
-    IBPP::Timestamp actTime;
-    st->Get(4, actTime);
-    st->Get(5, stat->lastCashAdd);
-    IBPP::Timestamp addTime;
-    st->Get(6, addTime);
-    int32_t passiveTime;
-    st->Get(7, passiveTime);
-
-    stat->passiveTime = passiveTime;
-
-    stat->lastActivityTime = ts2time_t(actTime);
-
-    stat->lastCashAddTime = ts2time_t(addTime);
-
-    st->Close();
-    st->Prepare("select * from tb_stats_traffic where fk_stat = ?");
-    st->Set(1, sid);
-    st->Execute();
-    for(int i = 0; i < DIR_NUM; i++)
-        {
-        if (st->Fetch())
-            {
-            int dir;
-            st->Get(3, dir);
-            st->Get(5, (int64_t &)stat->monthUp[dir]);
-            st->Get(4, (int64_t &)stat->monthDown[dir]);
-            }
-        else
-            {
-            break;
-            }
-        }
-    tr->Commit();
-    }
-
-catch (IBPP::Exception & ex)
-    {
-    tr->Rollback();
-    strError = "IBPP exception";
-    printfd(__FILE__, ex.what());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::RestoreUserConf(STG::UserConf * conf,
-                                    const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-try
-    {
-    tr->Start();
-    st->Prepare("select tb_users.pk_user, tb_users.address, tb_users.always_online, \
-                        tb_users.credit, tb_users.credit_expire, tb_users.disabled, \
-                        tb_users.disabled_detail_stat, tb_users.email, tb_users.grp, \
-                        tb_users.note, tb_users.passive, tb_users.passwd, tb_users.phone, \
-                        tb_users.real_name, tf1.name, tf2.name, tb_corporations.name \
-                 from tb_users left join tb_tariffs tf1 \
-                 on tf1.pk_tariff = tb_users.fk_tariff \
-                 left join tb_tariffs tf2 \
-                 on tf2.pk_tariff = tb_users.fk_tariff_change \
-                 left join tb_corporations \
-                 on tb_corporations.pk_corporation = tb_users.fk_corporation \
-                 where tb_users.name = ?");
-    st->Set(1, login);
-    st->Execute();
-    if (!st->Fetch())
-        {
-        strError = "User \"" + login + "\" not found in database";
-    printfd(__FILE__, "User '%s' not found in database", login.c_str());
-        tr->Rollback();
-        return -1;
-        }
-    int32_t uid;
-    st->Get(1, uid);
-    // Getting base config
-    st->Get(2, conf->address);
-    bool test;
-    st->Get(3, test);
-    conf->alwaysOnline = test;
-    st->Get(4, conf->credit);
-    IBPP::Timestamp timestamp;
-    st->Get(5, timestamp);
-
-    conf->creditExpire = ts2time_t(timestamp);
-
-    st->Get(6, test);
-    conf->disabled = test;
-    st->Get(7, test);
-    conf->disabledDetailStat = test;
-    st->Get(8, conf->email);
-    st->Get(9, conf->group);
-    st->Get(10, conf->note);
-    st->Get(11, test);
-    conf->passive = test;
-    st->Get(12, conf->password);
-    st->Get(13, conf->phone);
-    st->Get(14, conf->realName);
-    st->Get(15, conf->tariffName);
-    st->Get(16, conf->nextTariff);
-    st->Get(17, conf->corp);
-
-    if (conf->tariffName == "")
-        conf->tariffName = NO_TARIFF_NAME;
-    if (conf->corp == "")
-        conf->corp = NO_CORP_NAME;
-
-    // Services
-    st->Close();
-    st->Prepare("select name from tb_services \
-                 where pk_service in \
-                    (select fk_service from tb_users_services \
-                     where fk_user = ?)");
-    st->Set(1, uid);
-    st->Execute();
-    while (st->Fetch())
-        {
-        std::string name;
-        st->Get(1, name);
-        conf->services.push_back(name);
-        }
-
-    // User data
-    st->Close();
-    st->Prepare("select data, num from tb_users_data where fk_user = ? order by num");
-    st->Set(1, uid);
-    st->Execute();
-    while (st->Fetch())
-        {
-        int i;
-        st->Get(2, i);
-        st->Get(1, conf->userdata[i]);
-        }
-
-    // User IPs
-    st->Close();
-    st->Prepare("select ip, mask from tb_allowed_ip \
-                 where fk_user = ?");
-    st->Set(1, uid);
-    st->Execute();
-    STG::UserIPs ips;
-    while (st->Fetch())
-        {
-        STG::IPMask im;
-        st->Get(1, (int32_t &)im.ip);
-        st->Get(2, (int32_t &)im.mask);
-        ips.add(im);
-        }
-    conf->ips = ips;
-
-    tr->Commit();
-    }
-catch (IBPP::Exception & ex)
-    {
-    tr->Rollback();
-    strError = "IBPP exception";
-    printfd(__FILE__, ex.what());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::WriteUserChgLog(const std::string & login,
-                                    const std::string & admLogin,
-                                    uint32_t admIP,
-                                    const std::string & paramName,
-                                    const std::string & oldValue,
-                                    const std::string & newValue,
-                                    const std::string & message = "") const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-IBPP::Timestamp now;
-now.Now();
-
-std::string temp = ""; // Composed message for log
-
-try
-    {
-    tr->Start();
-    temp += "Admin \"" + admLogin + "\", ";
-    temp += inet_ntostring(admIP);
-    temp += ": ";
-    temp = temp + message;
-    //----------------------------------------------------------------------------------------
-    // Checking and inserting parameters in params table
-    st->Prepare("select pk_parameter from tb_parameters where name = ?");
-    st->Set(1, paramName);
-    st->Execute();
-    if (!st->Fetch())
-        {
-        st->Close();
-        st->Prepare("insert into tb_parameters (name) values (?)");
-        st->Set(1, paramName);
-        st->Execute();
-        }
-    st->Close();
-    //----------------------------------------------------------------------------------------
-    st->Prepare("insert into tb_params_log \
-                    (fk_user, fk_parameter, event_time, from_val, to_val, comment) \
-                 values ((select pk_user from tb_users \
-                          where name = ?), \
-                         (select pk_parameter from tb_parameters \
-                          where name = ?), \
-                         ?, ?, ?, ?)");
-    st->Set(1, login);
-    st->Set(2, paramName);
-    st->Set(3, now);
-    st->Set(4, oldValue);
-    st->Set(5, newValue);
-    st->Set(6, temp);
-    st->Execute();
-    tr->Commit();
-    }
-
-catch (IBPP::Exception & ex)
-    {
-    tr->Rollback();
-    strError = "IBPP exception";
-    printfd(__FILE__, ex.what());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::WriteUserConnect(const std::string & login, uint32_t ip) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-IBPP::Timestamp now;
-now.Now();
-
-try
-    {
-    tr->Start();
-    st->Prepare("execute procedure sp_append_session_log(?, ?, 'c', ?)");
-    st->Set(1, login);
-    st->Set(2, now);
-    st->Set(3, (int32_t)ip);
-    tr->Commit();
-    }
-
-catch (IBPP::Exception & ex)
-    {
-    tr->Rollback();
-    strError = "IBPP exception";
-    printfd(__FILE__, ex.what());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::WriteUserDisconnect(const std::string & login,
-                    const STG::DirTraff & up,
-                    const STG::DirTraff & down,
-                    const STG::DirTraff & sessionUp,
-                    const STG::DirTraff & sessionDown,
-                    double /*cash*/,
-                    double /*freeMb*/,
-                    const std::string & /*reason*/) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-IBPP::Timestamp now;
-now.Now();
-
-try
-    {
-    tr->Start();
-    st->Prepare("execute procedure sp_append_session_log(?, ?, 'd', 0)");
-    st->Set(1, login);
-    st->Set(2, now);
-    st->Execute();
-    int32_t id;
-    st->Get(1, id);
-    st->Prepare("insert into tb_sessions_data \
-                    (fk_session_log, dir_num, session_upload, \
-                     session_download, month_upload, month_download) \
-                 values (?, ?, ?, ?, ?, ?)");
-    for(int i = 0; i < DIR_NUM; i++)
-        {
-        st->Set(1, id);
-        st->Set(2, i);
-        st->Set(3, (int64_t)sessionUp[i]);
-        st->Set(4, (int64_t)sessionDown[i]);
-        st->Set(5, (int64_t)up[i]);
-        st->Set(6, (int64_t)down[i]);
-        st->Execute();
-        }
-    tr->Commit();
-    }
-
-catch (IBPP::Exception & ex)
-    {
-    tr->Rollback();
-    strError = "IBPP exception";
-    printfd(__FILE__, ex.what());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::WriteDetailedStat(const STG::TraffStat & statTree,
-                                      time_t lastStat,
-                                      const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-IBPP::Timestamp statTime, now;
-now.Now();
-
-time_t2ts(lastStat, &statTime);
-
-try
-    {
-    tr->Start();
-    STG::TraffStat::const_iterator it;
-    it = statTree.begin();
-    st->Prepare("insert into tb_detail_stats \
-                    (till_time, from_time, fk_user, dir_num, \
-                     ip, download, upload, cost) \
-                 values (?, ?, (select pk_user from tb_users \
-                                where name = ?), \
-                     ?, ?, ?, ?, ?)");
-    while (it != statTree.end())
-        {
-        st->Set(1, now);
-        st->Set(2, statTime);
-        st->Set(3, login);
-        st->Set(4, it->first.dir);
-        st->Set(5, (int32_t)it->first.ip);
-        st->Set(6, (int64_t)it->second.down);
-        st->Set(7, (int64_t)it->second.up);
-        st->Set(8, it->second.cash);
-        st->Execute();
-        ++it;
-        }
-    tr->Commit();
-    }
-
-catch (IBPP::Exception & ex)
-    {
-    tr->Rollback();
-    strError = "IBPP exception";
-    printfd(__FILE__, ex.what());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int FIREBIRD_STORE::SaveMonthStat(const STG::UserStat & stat, int month, int year, const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amWrite, til, tlr);
-IBPP::Statement st = IBPP::StatementFactory(db, tr);
-
-IBPP::Timestamp now;
-IBPP::Date nowDate;
-nowDate.Today();
-now.Now();
-
-if (SaveStat(stat, login, year, month))
-    {
-    return -1;
-    }
-
-try
-    {
-    tr->Start();
-
-    st->Prepare("execute procedure sp_add_stat(?, 0, 0, ?, 0, ?, 0, ?)");
-    st->Set(1, login);
-    st->Set(2, now);
-    st->Set(3, now);
-    st->Set(4, nowDate);
-
-    st->Execute();
-    int32_t id;
-    st->Get(1, id);
-    st->Close();
-
-    st->Prepare("insert into tb_stats_traffic \
-                    (fk_stat, dir_num, upload, download) \
-                 values (?, ?, 0, 0)");
-
-    for(int i = 0; i < DIR_NUM; i++)
-        {
-        st->Set(1, id);
-        st->Set(2, i);
-        st->Execute();
-        }
-
-    tr->Commit();
-    }
-catch (IBPP::Exception & ex)
-    {
-    tr->Rollback();
-    strError = "IBPP exception";
-    printfd(__FILE__, ex.what());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-
diff --git a/stargazer/plugins/store/firebird/firebird_store_utils.cpp b/stargazer/plugins/store/firebird/firebird_store_utils.cpp
deleted file mode 100644 (file)
index 582c544..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-/*
- *  Vairous utility methods
- *
- *  $Revision: 1.8 $
- *  $Date: 2010/03/04 12:20:32 $
- *
- */
-
-#include "firebird_store.h"
-
-#include "stg/ibpp.h"
-#include "stg/common.h"
-
-#include <cstdio>
-
-//-----------------------------------------------------------------------------
-time_t ts2time_t(const IBPP::Timestamp & ts)
-{
-    char buf[32];
-    int year, month, day, hour, min, sec;
-    struct tm time_tm;
-
-    memset(&time_tm, 0, sizeof(time_tm));
-    ts.GetDate(year, month, day);
-    ts.GetTime(hour, min, sec);
-    if (year < 1990)
-        return 0;
-    sprintf(buf, "%d-%d-%d %d:%d:%d", year, month, day, hour, min, sec);
-    stg_strptime(buf, "%Y-%m-%d %H:%M:%S", &time_tm);
-
-    return mktime(&time_tm);
-}
-//-----------------------------------------------------------------------------
-void time_t2ts(time_t t, IBPP::Timestamp * ts)
-{
-    struct tm res;
-
-    localtime_r(&t, &res); // Reenterable
-
-    *ts = IBPP::Timestamp(res.tm_year + 1900, res.tm_mon + 1, res.tm_mday, res.tm_hour, res.tm_min, res.tm_sec);
-}
-//-----------------------------------------------------------------------------
-void ym2date(int year, int month, IBPP::Date * date)
-{
-    date->SetDate(year + 1900, month + 1, 1);
-    date->EndOfMonth();
-}
-//-----------------------------------------------------------------------------
diff --git a/stargazer/plugins/store/mysql/mysql_store.cpp b/stargazer/plugins/store/mysql/mysql_store.cpp
deleted file mode 100644 (file)
index 3ad79b3..0000000
+++ /dev/null
@@ -1,2153 +0,0 @@
-#include "mysql_store.h"
-
-#include "stg/common.h"
-#include "stg/user_ips.h"
-#include "stg/user_conf.h"
-#include "stg/user_stat.h"
-#include "stg/admin_conf.h"
-#include "stg/tariff_conf.h"
-#include "stg/blowfish.h"
-#include "stg/logger.h"
-
-#include <algorithm>
-#include <sys/time.h>
-#include <cerrno>
-#include <cstdio>
-#include <cstdlib>
-
-#include <mysql/errmsg.h>
-
-#define adm_enc_passwd "cjeifY8m3"
-
-namespace
-{
-char qbuf[4096];
-
-const int pt_mega = 1024 * 1024;
-const std::string badSyms = "'`";
-const char repSym = '\"';
-const int RepitTimes = 3;
-
-template <typename T>
-int GetInt(const std::string & str, T * val, T defaultVal = T())
-{
-    char *res;
-    
-    *val = static_cast<T>(strtoll(str.c_str(), &res, 10));
-    
-    if (*res != 0) 
-    {
-        *val = defaultVal; //Error!
-        return EINVAL;
-    }
-
-    return 0;
-}
-
-int GetDouble(const std::string & str, double * val, double defaultVal)
-{
-    char *res;
-    
-    *val = strtod(str.c_str(), &res);
-    
-    if (*res != 0) 
-    {
-        *val = defaultVal; //Error!
-        return EINVAL;
-    }
-
-    return 0;
-}
-
-int GetTime(const std::string & str, time_t * val, time_t defaultVal)
-{
-    char *res;
-    
-    *val = strtol(str.c_str(), &res, 10);
-    
-    if (*res != 0) 
-    {
-        *val = defaultVal; //Error!
-        return EINVAL;
-    }
-
-    return 0;
-}
-
-//-----------------------------------------------------------------------------
-std::string ReplaceStr(std::string source, const std::string & symlist, const char chgsym)
-{
-    std::string::size_type pos=0;
-
-    while( (pos = source.find_first_of(symlist,pos)) != std::string::npos)
-        source.replace(pos, 1,1, chgsym);
-
-    return source;
-}
-
-int GetULongLongInt(const std::string & str, uint64_t * val, uint64_t defaultVal)
-{
-    char *res;
-    
-    *val = strtoull(str.c_str(), &res, 10);
-    
-    if (*res != 0) 
-    {
-        *val = defaultVal; //Error!
-        return EINVAL;
-    }
-
-    return 0;
-} 
-
-}
-
-extern "C" STG::Store* GetStore()
-{
-    static MYSQL_STORE plugin;
-    return &plugin;
-}
-//-----------------------------------------------------------------------------
-MYSQL_STORE_SETTINGS::MYSQL_STORE_SETTINGS()
-    : settings(NULL)
-{
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE_SETTINGS::ParseParam(const std::vector<STG::ParamValue> & moduleParams,
-                                     const std::string & name, std::string & result)
-{
-STG::ParamValue pv;
-pv.param = name;
-std::vector<STG::ParamValue>::const_iterator pvi;
-pvi = find(moduleParams.begin(), moduleParams.end(), pv);
-if (pvi == moduleParams.end() || pvi->value.empty())
-    {
-    errorStr = "Parameter \'" + name + "\' not found.";
-    return -1;
-    }
-
-result = pvi->value[0];
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE_SETTINGS::ParseSettings(const STG::ModuleSettings & s)
-{
-if (ParseParam(s.moduleParams, "user", dbUser) < 0 &&
-    ParseParam(s.moduleParams, "dbuser", dbUser) < 0)
-    return -1;
-if (ParseParam(s.moduleParams, "password", dbPass) < 0 &&
-    ParseParam(s.moduleParams, "rootdbpass", dbPass) < 0)
-    return -1;
-if (ParseParam(s.moduleParams, "database", dbName) < 0 &&
-    ParseParam(s.moduleParams, "dbname", dbName) < 0)
-    return -1;
-if (ParseParam(s.moduleParams, "server", dbHost) < 0 &&
-    ParseParam(s.moduleParams, "dbhost", dbHost) < 0)
-    return -1;
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-MYSQL_STORE::MYSQL_STORE()
-    : version("mysql_store v.0.67"),
-      schemaVersion(0),
-      logger(STG::PluginLogger::get("store_mysql"))
-{
-}
-//-----------------------------------------------------------------------------
-int    MYSQL_STORE::MysqlQuery(const char* sQuery,MYSQL * sock) const
-{
-    int ret;
-
-    if( (ret = mysql_query(sock,sQuery)) )
-    {
-        for(int i=0; i<RepitTimes; i++)
-        {
-            if( (ret = mysql_query(sock,sQuery)) )
-                ;//need to send error result
-            else
-                return 0;
-        }
-    }
-    
-    return ret;
-}
-//-----------------------------------------------------------------------------
-
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::ParseSettings()
-{
-int ret = storeSettings.ParseSettings(settings);
-MYSQL mysql;
-mysql_init(&mysql);
-if (ret)
-    errorStr = storeSettings.GetStrError();
-else
-{
-    if(storeSettings.GetDBPassword().length() == 0)
-    {
-        errorStr = "Database password must be not empty. Please read Manual.";
-        return -1;
-    }
-    MYSQL * sock;
-    if (!(sock = mysql_real_connect(&mysql,storeSettings.GetDBHost().c_str(),
-            storeSettings.GetDBUser().c_str(),storeSettings.GetDBPassword().c_str(),
-            0,0,NULL,0)))
-        {
-            errorStr = "Couldn't connect to mysql engine! With error:\n";
-            errorStr += mysql_error(&mysql);
-            mysql_close(sock);
-            ret = -1;
-        }
-    else
-    {
-         if(mysql_select_db(sock, storeSettings.GetDBName().c_str()))
-         {
-             std::string res = "CREATE DATABASE " + storeSettings.GetDBName();
-            
-            if(MysqlQuery(res.c_str(),sock))
-            {
-                errorStr = "Couldn't create database! With error:\n";
-                errorStr += mysql_error(sock);
-                mysql_close(sock);
-                ret = -1;
-            }
-            else
-            {
-                 if(mysql_select_db(sock, storeSettings.GetDBName().c_str()))
-                 {
-                     errorStr = "Couldn't select database! With error:\n";
-                     errorStr += mysql_error(sock);
-                     mysql_close(sock);
-                     ret = -1;
-                 }
-                 else
-                     ret = CheckAllTables(sock);
-            }
-        }
-        else
-        {
-            ret = CheckAllTables(sock);
-        }
-        if (!ret)
-        {
-            logger("MYSQL_STORE: Current DB schema version: %d", schemaVersion);
-            MakeUpdates(sock);
-        }
-        mysql_close(sock);
-    }
-}
-return ret;
-}
-//-----------------------------------------------------------------------------
-bool MYSQL_STORE::IsTablePresent(const std::string & str,MYSQL * sock)
-{
-MYSQL_RES* result;
-
-if (!(result=mysql_list_tables(sock,str.c_str() )))
-{
-    errorStr = "Couldn't get tables list With error:\n";
-    errorStr += mysql_error(sock);
-    mysql_close(sock);
-    return -1;
-}
-
-my_ulonglong num_rows =  mysql_num_rows(result);
-
-if(result)
-    mysql_free_result(result);
-
-return num_rows == 1;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::CheckAllTables(MYSQL * sock)
-{
-//info-------------------------------------------------------------------------
-if(!IsTablePresent("info",sock))
-{
-    sprintf(qbuf,"CREATE TABLE info (version INTEGER NOT NULL)");
-
-    if(MysqlQuery(qbuf,sock))
-        {
-        errorStr = "Couldn't create info table With error:\n";
-        errorStr += mysql_error(sock);
-        mysql_close(sock);
-        return -1;
-        }
-
-    sprintf(qbuf,"INSERT INTO info SET version=0");
-
-    if(MysqlQuery(qbuf,sock))
-        {
-        errorStr = "Couldn't write default version. With error:\n";
-        errorStr += mysql_error(sock);
-        mysql_close(sock);
-        return -1;
-        }
-    schemaVersion = 0;
-}
-else
-{
-    std::vector<std::string> info;
-    if (GetAllParams(&info, "info", "version"))
-        schemaVersion = 0;
-    else
-    {
-        if (info.empty())
-            schemaVersion = 0;
-        else
-            GetInt(info.front(), &schemaVersion, 0);
-    }
-}
-//admins-----------------------------------------------------------------------
-if(!IsTablePresent("admins",sock))
-{
-    sprintf(qbuf,"CREATE TABLE admins (login VARCHAR(40) DEFAULT '' PRIMARY KEY,"\
-        "password VARCHAR(150) DEFAULT '*',ChgConf TINYINT DEFAULT 0,"\
-        "ChgPassword TINYINT DEFAULT 0,ChgStat TINYINT DEFAULT 0,"\
-        "ChgCash TINYINT DEFAULT 0,UsrAddDel TINYINT DEFAULT 0,"\
-        "ChgTariff TINYINT DEFAULT 0,ChgAdmin TINYINT DEFAULT 0)");
-    
-    if(MysqlQuery(qbuf,sock))
-    {
-        errorStr = "Couldn't create admin table list With error:\n";
-        errorStr += mysql_error(sock);
-        mysql_close(sock);
-        return -1;
-    }
-
-    sprintf(qbuf,"INSERT INTO admins SET login='admin',"\
-        "password='geahonjehjfofnhammefahbbbfbmpkmkmmefahbbbfbmpkmkmmefahbbbfbmpkmkaa',"\
-        "ChgConf=1,ChgPassword=1,ChgStat=1,ChgCash=1,UsrAddDel=1,ChgTariff=1,ChgAdmin=1");
-    
-    if(MysqlQuery(qbuf,sock))
-    {
-        errorStr = "Couldn't create default admin. With error:\n";
-        errorStr += mysql_error(sock);
-        mysql_close(sock);
-        return -1;
-    }
-}
-
-//tariffs-----------------------------------------------------------------------
-std::string param, res;
-if(!IsTablePresent("tariffs",sock))
-{
-    res = "CREATE TABLE tariffs (name VARCHAR(40) DEFAULT '' PRIMARY KEY,";
-        
-    for (int i = 0; i < DIR_NUM; i++)
-        {
-        strprintf(&param, " PriceDayA%d DOUBLE DEFAULT 0.0,", i); 
-        res += param;
-    
-        strprintf(&param, " PriceDayB%d DOUBLE DEFAULT 0.0,", i);
-        res += param;
-            
-        strprintf(&param, " PriceNightA%d DOUBLE DEFAULT 0.0,", i);
-        res += param;
-    
-        strprintf(&param, " PriceNightB%d DOUBLE DEFAULT 0.0,", i);
-        res += param;
-            
-        strprintf(&param, " Threshold%d INT DEFAULT 0,", i);
-        res += param;
-    
-        strprintf(&param, " Time%d VARCHAR(15) DEFAULT '0:0-0:0',", i);
-        res += param;
-    
-        strprintf(&param, " NoDiscount%d INT DEFAULT 0,", i);
-        res += param;
-    
-        strprintf(&param, " SinglePrice%d INT DEFAULT 0,", i);
-        res += param;
-        }
-    
-    res += "PassiveCost DOUBLE DEFAULT 0.0, Fee DOUBLE DEFAULT 0.0,"
-        "Free DOUBLE DEFAULT 0.0, TraffType VARCHAR(10) DEFAULT '',"
-        "period VARCHAR(32) NOT NULL DEFAULT 'month',"
-        "change_policy VARCHAR(32) NOT NULL DEFAULT 'allow',"
-        "change_policy_timeout TIMESTAMP NOT NULL DEFAULT 0)";
-    
-    if(MysqlQuery(res.c_str(),sock))
-    {
-        errorStr = "Couldn't create tariffs table list With error:\n";
-        errorStr += mysql_error(sock);
-        mysql_close(sock);
-        return -1;
-    }
-
-    res = "INSERT INTO tariffs SET name='tariff',";
-        
-    for (int i = 0; i < DIR_NUM; i++)
-        {
-        strprintf(&param, " NoDiscount%d=1,", i);
-        res += param;
-    
-        strprintf(&param, " Threshold%d=0,", i);
-        res += param;
-    
-        strprintf(&param, " Time%d='0:0-0:0',", i);
-        res += param;
-    
-        if(i != 0 && i != 1)
-        {
-            strprintf(&param, " SinglePrice%d=0,", i);
-            res += param;        
-        }
-    
-        if(i != 1)
-        {
-            strprintf(&param, " PriceDayA%d=0.0,", i); 
-            res += param;        
-        }
-        if(i != 1)
-        {
-            strprintf(&param, " PriceDayB%d=0.0,", i);        
-            res += param;    
-        }
-    
-        if(i != 0)
-        {
-            strprintf(&param, " PriceNightA%d=0.0,", i); 
-            res += param;        
-        }
-        if(i != 0)
-        {
-            strprintf(&param, " PriceNightB%d=0.0,", i);        
-            res += param;    
-        }
-        }
-    
-    res += "PassiveCost=0.0, Fee=10.0, Free=0,"\
-        "SinglePrice0=1, SinglePrice1=1,PriceDayA1=0.75,PriceDayB1=0.75,"\
-        "PriceNightA0=1.0,PriceNightB0=1.0,TraffType='up+down',period='month',"\
-        "change_policy='allow', change_policy_timeout=0";
-    
-    if(MysqlQuery(res.c_str(),sock))
-    {
-        errorStr = "Couldn't create default tariff. With error:\n";
-        errorStr += mysql_error(sock);
-        mysql_close(sock);
-        return -1;
-    }
-
-    sprintf(qbuf,"UPDATE info SET version=1");
-
-    if(MysqlQuery(qbuf,sock))
-    {
-        errorStr = "Couldn't write default version. With error:\n";
-        errorStr += mysql_error(sock);
-        mysql_close(sock);
-        return -1;
-    }
-    schemaVersion = 2;
-}
-
-//users-----------------------------------------------------------------------
-if(!IsTablePresent("users",sock))
-{
-    res = "CREATE TABLE users (login VARCHAR(50) NOT NULL DEFAULT '' PRIMARY KEY, Password VARCHAR(150) NOT NULL DEFAULT '*',"\
-        "Passive INT(3) DEFAULT 0,Down INT(3) DEFAULT 0,DisabledDetailStat INT(3) DEFAULT 0,AlwaysOnline INT(3) DEFAULT 0,Tariff VARCHAR(40) NOT NULL DEFAULT '',"\
-        "Address VARCHAR(254) NOT NULL DEFAULT '',Phone VARCHAR(128) NOT NULL DEFAULT '',Email VARCHAR(50) NOT NULL DEFAULT '',"\
-        "Note TEXT NOT NULL,RealName VARCHAR(254) NOT NULL DEFAULT '',StgGroup VARCHAR(40) NOT NULL DEFAULT '',"\
-        "Credit DOUBLE DEFAULT 0, TariffChange VARCHAR(40) NOT NULL DEFAULT '',";
-    
-    for (int i = 0; i < USERDATA_NUM; i++)
-        {
-        strprintf(&param, " Userdata%d VARCHAR(254) NOT NULL,", i);
-        res += param;
-        }
-    
-    param = " CreditExpire INT(11) DEFAULT 0,";
-    res += param;
-    
-    strprintf(&param, " IP VARCHAR(254) DEFAULT '*',");
-    res += param;
-    
-    for (int i = 0; i < DIR_NUM; i++)
-        {
-        strprintf(&param, " D%d BIGINT(30) DEFAULT 0,", i);
-        res += param;
-    
-        strprintf(&param, " U%d BIGINT(30) DEFAULT 0,", i);
-        res += param;
-        }
-    
-    strprintf(&param, "Cash DOUBLE DEFAULT 0,FreeMb DOUBLE DEFAULT 0,LastCashAdd DOUBLE DEFAULT 0,"\
-        "LastCashAddTime INT(11) DEFAULT 0,PassiveTime INT(11) DEFAULT 0,LastActivityTime INT(11) DEFAULT 0,"\
-        "NAS VARCHAR(17) NOT NULL, INDEX (AlwaysOnline), INDEX (IP), INDEX (Address),"\
-        " INDEX (Tariff),INDEX (Phone),INDEX (Email),INDEX (RealName))");
-    res += param;
-        
-    if(MysqlQuery(res.c_str(),sock))
-    {
-        errorStr = "Couldn't create users table list With error:\n";
-        errorStr += mysql_error(sock);
-        errorStr += "\n\n" + res;
-        mysql_close(sock);
-        return -1;
-    }
-
-    res = "INSERT INTO users SET login='test',Address='',AlwaysOnline=0,"\
-        "Credit=0.0,CreditExpire=0,Down=0,Email='',DisabledDetailStat=0,"\
-        "StgGroup='',IP='192.168.1.1',Note='',Passive=0,Password='123456',"\
-        "Phone='', RealName='',Tariff='tariff',TariffChange='',NAS='',";
-    
-    for (int i = 0; i < USERDATA_NUM; i++)
-        {
-        strprintf(&param, " Userdata%d='',", i);
-        res += param;
-        }
-    
-    for (int i = 0; i < DIR_NUM; i++)
-        {
-        strprintf(&param, " D%d=0,", i);
-        res += param;
-    
-        strprintf(&param, " U%d=0,", i);
-        res += param;
-        }
-    
-    res += "Cash=10.0,FreeMb=0.0,LastActivityTime=0,LastCashAdd=0,"\
-        "LastCashAddTime=0, PassiveTime=0";
-        
-    if(MysqlQuery(res.c_str(),sock))
-    {
-        errorStr = "Couldn't create default user. With error:\n";
-        errorStr += mysql_error(sock);
-        mysql_close(sock);
-        return -1;
-    }
-}
-/*
-//logs-----------------------------------------------------------------------
-if(!IsTablePresent("logs"))
-{
-    sprintf(qbuf,"CREATE TABLE logs (unid INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, login VARCHAR(40),text TEXT)");
-    
-    if(MysqlQuery(qbuf))
-    {
-        errorStr = "Couldn't create admin table list With error:\n";
-        errorStr += mysql_error(sock);
-        return -1;
-    }
-}
-*/
-//messages---------------------------------------------------------------------
-if(!IsTablePresent("messages",sock))
-{
-    sprintf(qbuf,"CREATE TABLE messages (login VARCHAR(40) DEFAULT '', id BIGINT, "\
-            "type INT, lastSendTime INT, creationTime INT, showTime INT,"\
-            "stgRepeat INT, repeatPeriod INT, text TEXT)");
-    
-    if(MysqlQuery(qbuf,sock))
-    {
-        errorStr = "Couldn't create messages table. With error:\n";
-        errorStr += mysql_error(sock);
-        mysql_close(sock);
-        return -1;
-    }
-}
-
-//month_stat-------------------------------------------------------------------
-if(!IsTablePresent("stat",sock))
-{
-    res = "CREATE TABLE stat (login VARCHAR(50), month TINYINT, year SMALLINT,";
-    
-    for (int i = 0; i < DIR_NUM; i++)
-        {
-        strprintf(&param, " U%d BIGINT,", i); 
-        res += param;
-            
-        strprintf(&param, " D%d BIGINT,", i); 
-        res += param;
-        }
-        
-    res += " cash DOUBLE, INDEX (login))";
-    
-    if(MysqlQuery(res.c_str(),sock))
-    {
-        errorStr = "Couldn't create stat table. With error:\n";
-        errorStr += mysql_error(sock);
-        mysql_close(sock);
-        return -1;
-    }
-}
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::MakeUpdates(MYSQL * sock)
-{
-if (schemaVersion  < 1)
-    {
-    if (MysqlQuery("ALTER TABLE tariffs ADD period VARCHAR(32) NOT NULL DEFAULT 'month'", sock))
-        {
-        errorStr = "Couldn't update tariffs table to version 1. With error:\n";
-        errorStr += mysql_error(sock);
-        mysql_close(sock);
-        return -1;
-        }
-    if (MysqlQuery("UPDATE info SET version = 1", sock))
-        {
-        errorStr = "Couldn't update DB schema version to 1. With error:\n";
-        errorStr += mysql_error(sock);
-        mysql_close(sock);
-        return -1;
-        }
-    schemaVersion = 1;
-    logger("MYSQL_STORE: Updated DB schema to version %d", schemaVersion);
-    }
-
-if (schemaVersion  < 2)
-    {
-    if (MysqlQuery("ALTER TABLE tariffs ADD change_policy VARCHAR(32) NOT NULL DEFAULT 'allow'", sock) ||
-        MysqlQuery("ALTER TABLE tariffs ADD change_policy_timeout TIMESTAMP NOT NULL DEFAULT 0", sock))
-        {
-        errorStr = "Couldn't update tariffs table to version 2. With error:\n";
-        errorStr += mysql_error(sock);
-        mysql_close(sock);
-        return -1;
-        }
-    if (MysqlQuery("UPDATE info SET version = 2", sock))
-        {
-        errorStr = "Couldn't update DB schema version to 2. With error:\n";
-        errorStr += mysql_error(sock);
-        mysql_close(sock);
-        return -1;
-        }
-    schemaVersion = 2;
-    logger("MYSQL_STORE: Updated DB schema to version %d", schemaVersion);
-    }
-return 0;
-}
-//-----------------------------------------------------------------------------
-
-int MYSQL_STORE::GetAllParams(std::vector<std::string> * ParamList, 
-                            const std::string & table, const std::string & name) const
-{
-MYSQL_RES *res;
-MYSQL_ROW row;
-MYSQL * sock=NULL;
-my_ulonglong num, i;
-    
-ParamList->clear();
-    
-sprintf(qbuf,"SELECT %s FROM %s", name.c_str(), table.c_str());
-    
-if(MysqlGetQuery(qbuf,sock))
-{
-    errorStr = "Couldn't GetAllParams Query for: ";
-    errorStr += name + " - " + table + "\n";
-    errorStr += mysql_error(sock);
-    mysql_close(sock);
-    return -1;
-}
-
-if (!(res=mysql_store_result(sock)))
-{
-    errorStr = "Couldn't GetAllParams Results for: ";
-    errorStr += name + " - " + table + "\n";
-    errorStr += mysql_error(sock);
-    return -1;
-}
-
-num = mysql_num_rows(res);
-
-for(i = 0; i < num; i++)
-{
-    row = mysql_fetch_row(res);    
-    ParamList->push_back(row[0]);
-}
-
-mysql_free_result(res);
-mysql_close(sock);
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::GetUsersList(std::vector<std::string> * usersList) const
-{
-if(GetAllParams(usersList, "users", "login"))
-    return -1;
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::GetAdminsList(std::vector<std::string> * adminsList) const
-{
-if(GetAllParams(adminsList, "admins", "login"))
-    return -1;
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::GetTariffsList(std::vector<std::string> * tariffsList) const
-{
-if(GetAllParams(tariffsList, "tariffs", "name"))
-    return -1;
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::AddUser(const std::string & login) const
-{
-std::string query = "INSERT INTO users SET login='" + login + "',Note='',NAS=''";
-
-for (int i = 0; i < USERDATA_NUM; i++)
-    query += ",Userdata" + std::to_string(i) + "=''";
-
-if(MysqlSetQuery(query.c_str()))
-{
-    errorStr = "Couldn't add user:\n";
-    //errorStr += mysql_error(sock);
-    return -1;
-}
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::DelUser(const std::string & login) const
-{
-sprintf(qbuf,"DELETE FROM users WHERE login='%s' LIMIT 1", login.c_str());
-    
-if(MysqlSetQuery(qbuf))
-{
-    errorStr = "Couldn't delete user:\n";
-    //errorStr += mysql_error(sock);
-    return -1;
-}
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::RestoreUserConf(STG::UserConf * conf, const std::string & login) const
-{
-MYSQL_RES *res;
-MYSQL_ROW row;
-MYSQL * sock;
-std::string query;
-
-query = "SELECT login, Password, Passive, Down, DisabledDetailStat, \
-         AlwaysOnline, Tariff, Address, Phone, Email, Note, \
-         RealName, StgGroup, Credit, TariffChange, ";
-
-for (int i = 0; i < USERDATA_NUM; i++)
-{
-    sprintf(qbuf, "Userdata%d, ", i);
-    query += qbuf;
-}
-
-query += "CreditExpire, IP FROM users WHERE login='";
-query += login + "' LIMIT 1";
-
-//sprintf(qbuf,"SELECT * FROM users WHERE login='%s' LIMIT 1", login.c_str());
-    
-if(MysqlGetQuery(query.c_str(),sock))
-{
-    errorStr = "Couldn't restore Tariff(on query):\n";
-    errorStr += mysql_error(sock);
-    mysql_close(sock);
-    return -1;
-}
-
-if (!(res=mysql_store_result(sock)))
-{
-    errorStr = "Couldn't restore Tariff(on getting result):\n";
-    errorStr += mysql_error(sock);
-    mysql_close(sock);
-    return -1;
-}
-
-if (mysql_num_rows(res) != 1)
-{
-    errorStr = "User not found";
-    mysql_close(sock);
-    return -1;
-}
-
-row = mysql_fetch_row(res);
-
-conf->password = row[1];
-
-if (conf->password.empty())
-    {
-    mysql_free_result(res);
-    errorStr = "User \'" + login + "\' password is blank.";
-    mysql_close(sock);
-    return -1;
-    }
-
-if (GetInt(row[2],&conf->passive) != 0)
-    {
-    mysql_free_result(res);
-    errorStr = "User \'" + login + "\' data not read. Parameter Passive.";
-    mysql_close(sock);
-    return -1;
-    }
-
-if (GetInt(row[3], &conf->disabled) != 0)
-    {
-    mysql_free_result(res);
-    errorStr = "User \'" + login + "\' data not read. Parameter Down.";
-    mysql_close(sock);
-    return -1;
-    }
-
-if (GetInt(row[4], &conf->disabledDetailStat) != 0)
-    {
-    mysql_free_result(res);
-    errorStr = "User \'" + login + "\' data not read. Parameter DisabledDetailStat.";
-    mysql_close(sock);
-    return -1;
-    }
-
-if (GetInt(row[5], &conf->alwaysOnline) != 0)
-    {
-    mysql_free_result(res);
-    errorStr = "User \'" + login + "\' data not read. Parameter AlwaysOnline.";
-    mysql_close(sock);
-    return -1;
-    }
-
-conf->tariffName = row[6];
-
-if (conf->tariffName.empty()) 
-    {
-    mysql_free_result(res);
-    errorStr = "User \'" + login + "\' tariff is blank.";
-    mysql_close(sock);
-    return -1;
-    }
-
-conf->address = row[7];
-conf->phone = row[8];
-conf->email = row[9];
-conf->note = row[10];
-conf->realName = row[11];
-conf->group = row[12];
-
-if (GetDouble(row[13], &conf->credit, 0) != 0)
-    {
-    mysql_free_result(res);
-    errorStr = "User \'" + login + "\' data not read. Parameter Credit.";
-    mysql_close(sock);
-    return -1;
-    }
-
-conf->nextTariff = row[14];
-
-for (int i = 0; i < USERDATA_NUM; i++)
-    {
-    conf->userdata[i] = row[15+i];
-    }
-
-GetTime(row[15+USERDATA_NUM], &conf->creditExpire, 0);
-    
-std::string ipStr = row[16+USERDATA_NUM];
-STG::UserIPs i;
-try
-    {
-    i = STG::UserIPs::parse(ipStr);
-    }
-catch (const std::string & s)
-    {
-    mysql_free_result(res);
-    errorStr = "User \'" + login + "\' data not read. Parameter IP address. " + s;
-    mysql_close(sock);
-    return -1;
-    }
-conf->ips = i;
-
-mysql_free_result(res);
-mysql_close(sock);
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::RestoreUserStat(STG::UserStat * stat, const std::string & login) const
-{
-MYSQL_RES *res;
-MYSQL_ROW row;
-MYSQL * sock;
-
-std::string query;
-
-query = "SELECT ";
-
-for (int i = 0; i < DIR_NUM; i++)
-{
-    sprintf(qbuf, "D%d, U%d, ", i, i);
-    query += qbuf;
-}
-
-query += "Cash, FreeMb, LastCashAdd, LastCashAddTime, PassiveTime, LastActivityTime \
-          FROM users WHERE login = '";
-query += login + "'";
-
-//sprintf(qbuf,"SELECT * FROM users WHERE login='%s' LIMIT 1", login.c_str());
-    
-if(MysqlGetQuery(query.c_str() ,sock))
-{
-    errorStr = "Couldn't restore UserStat(on query):\n";
-    errorStr += mysql_error(sock);
-    mysql_close(sock);
-    return -1;
-}
-
-if (!(res=mysql_store_result(sock)))
-{
-    errorStr = "Couldn't restore UserStat(on getting result):\n";
-    errorStr += mysql_error(sock);
-    mysql_close(sock);
-    return -1;
-}
-
-row = mysql_fetch_row(res);
-
-unsigned int startPos=0;
-
-char s[22];
-
-for (int i = 0; i < DIR_NUM; i++)
-    {
-    uint64_t traff;
-    sprintf(s, "D%d", i);
-    if (GetULongLongInt(row[startPos+i*2], &traff, 0) != 0)
-        {
-        mysql_free_result(res);
-        errorStr = "User \'" + login + "\' stat not read. Parameter " + std::string(s);
-        mysql_close(sock);
-        return -1;
-        }
-    stat->monthDown[i] = traff;
-
-    sprintf(s, "U%d", i);
-    if (GetULongLongInt(row[startPos+i*2+1], &traff, 0) != 0)
-        {
-        mysql_free_result(res);
-        errorStr =   "User \'" + login + "\' stat not read. Parameter " + std::string(s);
-        mysql_close(sock);
-        return -1;
-        }
-    stat->monthUp[i] = traff;
-    }//for
-
-startPos += (2*DIR_NUM);
-
-if (GetDouble(row[startPos], &stat->cash, 0) != 0)
-    {
-    mysql_free_result(res);
-    errorStr =   "User \'" + login + "\' stat not read. Parameter Cash";
-    mysql_close(sock);
-    return -1;
-    }
-
-if (GetDouble(row[startPos+1],&stat->freeMb, 0) != 0)
-    {
-    mysql_free_result(res);
-    errorStr =   "User \'" + login + "\' stat not read. Parameter FreeMb";
-    mysql_close(sock);
-    return -1;
-    }
-
-if (GetDouble(row[startPos+2], &stat->lastCashAdd, 0) != 0)
-    {
-    mysql_free_result(res);
-    errorStr =   "User \'" + login + "\' stat not read. Parameter LastCashAdd";
-    mysql_close(sock);
-    return -1;
-    }
-
-if (GetTime(row[startPos+3], &stat->lastCashAddTime, 0) != 0)
-    {
-    mysql_free_result(res);
-    errorStr =   "User \'" + login + "\' stat not read. Parameter LastCashAddTime";
-    mysql_close(sock);
-    return -1;
-    }
-
-if (GetTime(row[startPos+4], &stat->passiveTime, 0) != 0)
-    {
-    mysql_free_result(res);
-    errorStr =   "User \'" + login + "\' stat not read. Parameter PassiveTime";
-    mysql_close(sock);
-    return -1;
-    }
-
-if (GetTime(row[startPos+5], &stat->lastActivityTime, 0) != 0)
-    {
-    mysql_free_result(res);
-    errorStr =   "User \'" + login + "\' stat not read. Parameter LastActivityTime";
-    mysql_close(sock);
-    return -1;
-    }
-
-mysql_free_result(res);
-mysql_close(sock);
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::SaveUserConf(const STG::UserConf & conf, const std::string & login) const
-{
-std::string param;
-std::string res;
-
-strprintf(&res,"UPDATE users SET Password='%s', Passive=%d, Down=%d, DisabledDetailStat = %d, "\
-    "AlwaysOnline=%d, Tariff='%s', Address='%s', Phone='%s', Email='%s', "\
-    "Note='%s', RealName='%s', StgGroup='%s', Credit=%f, TariffChange='%s', ", 
-    conf.password.c_str(),
-    conf.passive,
-    conf.disabled,
-    conf.disabledDetailStat,
-    conf.alwaysOnline,
-    conf.tariffName.c_str(),
-    (ReplaceStr(conf.address,badSyms,repSym)).c_str(),
-    (ReplaceStr(conf.phone,badSyms,repSym)).c_str(),
-    (ReplaceStr(conf.email,badSyms,repSym)).c_str(),
-    (ReplaceStr(conf.note,badSyms,repSym)).c_str(),
-    (ReplaceStr(conf.realName,badSyms,repSym)).c_str(),
-    (ReplaceStr(conf.group,badSyms,repSym)).c_str(),
-    conf.credit,
-    conf.nextTariff.c_str()
-    );
-
-for (int i = 0; i < USERDATA_NUM; i++)
-    {
-    strprintf(&param, " Userdata%d='%s',", i, 
-        (ReplaceStr(conf.userdata[i],badSyms,repSym)).c_str());
-    res += param;
-    }
-    
-strprintf(&param, " CreditExpire=%d,", conf.creditExpire);
-res += param;
-
-std::ostringstream ipStr;
-ipStr << conf.ips;
-
-strprintf(&param, " IP='%s'", ipStr.str().c_str());
-res += param;
-
-strprintf(&param, " WHERE login='%s' LIMIT 1", login.c_str());
-res += param;
-
-if(MysqlSetQuery(res.c_str()))
-{
-    errorStr = "Couldn't save user conf:\n";
-    //errorStr += mysql_error(sock);
-    return -1;
-}
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::SaveUserStat(const STG::UserStat & stat, const std::string & login) const
-{
-std::string param;
-std::string res;
-
-res = "UPDATE users SET";
-
-for (int i = 0; i < DIR_NUM; i++)
-    {
-    strprintf(&param, " D%d=%lld,", i, stat.monthDown[i]);
-    res += param;
-
-    strprintf(&param, " U%d=%lld,", i, stat.monthUp[i]);
-    res += param;
-    }
-
-strprintf(&param, " Cash=%f, FreeMb=%f, LastCashAdd=%f, LastCashAddTime=%d,"\
-    " PassiveTime=%d, LastActivityTime=%d", 
-    stat.cash,
-    stat.freeMb,
-    stat.lastCashAdd,
-    stat.lastCashAddTime,
-    stat.passiveTime,
-    stat.lastActivityTime
-    );
-res += param;
-
-strprintf(&param, " WHERE login='%s' LIMIT 1", login.c_str());
-res += param;
-
-if(MysqlSetQuery(res.c_str()))
-{
-    errorStr = "Couldn't save user stat:\n";
-//    errorStr += mysql_error(sock);
-    return -1;
-}
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::WriteLogString(const std::string & str, const std::string & login) const
-{
-std::string res, tempStr;
-time_t t;
-tm * lt;
-
-t = time(NULL);
-lt = localtime(&t);
-
-MYSQL_RES* result;
-MYSQL * sock;
-strprintf(&tempStr, "logs_%02d_%4d", lt->tm_mon+1, lt->tm_year+1900);
-if (!(sock=MysqlConnect())){
-    errorStr = "Couldn't connect to Server";
-    return -1;
-}
-if (!(result=mysql_list_tables(sock,tempStr.c_str() )))
-{
-    errorStr = "Couldn't get table " + tempStr + ":\n";
-    errorStr += mysql_error(sock);
-    mysql_close(sock);
-    return -1;
-}
-
-my_ulonglong num_rows =  mysql_num_rows(result);
-
-mysql_free_result(result);
-
-if (num_rows < 1)
-{
-    sprintf(qbuf,"CREATE TABLE logs_%02d_%4d (unid INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, login VARCHAR(40),text TEXT)",
-    lt->tm_mon+1, lt->tm_year+1900);
-    
-    if(MysqlQuery(qbuf,sock))
-    {
-        errorStr = "Couldn't create WriteDetailedStat table:\n";
-        errorStr += mysql_error(sock);
-        mysql_close(sock);
-        return -1;
-    }
-}
-
-strprintf(&res, "%s -- %s",LogDate(t), str.c_str());
-
-std::string send;
-
-strprintf(&send,"INSERT INTO logs_%02d_%4d SET login='%s', text='%s'",
-        lt->tm_mon+1, lt->tm_year+1900,
-    login.c_str(), (ReplaceStr(res,badSyms,repSym)).c_str());
-
-if(MysqlQuery(send.c_str(),sock))
-{
-    errorStr = "Couldn't write log string:\n";
-    errorStr += mysql_error(sock);
-    mysql_close(sock);
-    return -1;
-}
-mysql_close(sock);
-return 0;
-
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::WriteUserChgLog(const std::string & login,
-                                 const std::string & admLogin,
-                                 uint32_t       admIP,
-                                 const std::string & paramName,
-                                 const std::string & oldValue,
-                                 const std::string & newValue,
-                                 const std::string & message) const
-{
-std::string userLogMsg = "Admin \'" + admLogin + "\', " + inet_ntostring(admIP) + ": \'"
-    + paramName + "\' parameter changed from \'" + oldValue +
-    "\' to \'" + newValue + "\'. " + message;
-
-return WriteLogString(userLogMsg, login);
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::WriteUserConnect(const std::string & login, uint32_t ip) const
-{
-std::string logStr = "Connect, " + inet_ntostring(ip);
-return WriteLogString(logStr, login);
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::WriteUserDisconnect(const std::string & login,
-                                     const STG::DirTraff & up,
-                                     const STG::DirTraff & down,
-                                     const STG::DirTraff & sessionUp,
-                                     const STG::DirTraff & sessionDown,
-                                     double cash,
-                                     double /*freeMb*/,
-                                     const std::string & /*reason*/) const
-{
-std::string logStr = "Disconnect, ";
-std::ostringstream sssu;
-std::ostringstream sssd;
-std::ostringstream ssmu;
-std::ostringstream ssmd;
-std::ostringstream sscash;
-
-ssmu << up;
-ssmd << down;
-
-sssu << sessionUp;
-sssd << sessionDown;
-
-sscash << cash;
-
-logStr += " session upload: \'";
-logStr += sssu.str();
-logStr += "\' session download: \'";
-logStr += sssd.str();
-logStr += "\' month upload: \'";
-logStr += ssmu.str();
-logStr += "\' month download: \'";
-logStr += ssmd.str();
-logStr += "\' cash: \'";
-logStr += sscash.str();
-logStr += "\'";
-
-return WriteLogString(logStr, login);
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::SaveMonthStat(const STG::UserStat & stat, int month, int year, 
-                                const std::string & login) const
-{
-std::string param, res;
-
-strprintf(&res, "INSERT INTO stat SET login='%s', month=%d, year=%d,", 
-    login.c_str(), month+1, year+1900);
-    
-for (int i = 0; i < DIR_NUM; i++)
-    {
-    strprintf(&param, " U%d=%lld,", i, stat.monthUp[i]); 
-    res += param;
-
-    strprintf(&param, " D%d=%lld,", i, stat.monthDown[i]);        
-    res += param;
-    }
-    
-strprintf(&param, " cash=%f", stat.cash);        
-res += param;
-
-if(MysqlSetQuery(res.c_str()))
-{
-    errorStr = "Couldn't SaveMonthStat:\n";
-    //errorStr += mysql_error(sock);
-    return -1;
-}
-
-return 0;
-}
-//-----------------------------------------------------------------------------*/
-int MYSQL_STORE::AddAdmin(const std::string & login) const
-{
-sprintf(qbuf,"INSERT INTO admins SET login='%s'", login.c_str());
-    
-if(MysqlSetQuery(qbuf))
-{
-    errorStr = "Couldn't add admin:\n";
-    //errorStr += mysql_error(sock);
-    return -1;
-}
-
-return 0;
-}
-//-----------------------------------------------------------------------------*/
-int MYSQL_STORE::DelAdmin(const std::string & login) const
-{
-sprintf(qbuf,"DELETE FROM admins where login='%s' LIMIT 1", login.c_str());
-    
-if(MysqlSetQuery(qbuf))
-{
-    errorStr = "Couldn't delete admin:\n";
-    //errorStr += mysql_error(sock);
-    return -1;
-}
-
-return 0;
-}
-//-----------------------------------------------------------------------------*/
-int MYSQL_STORE::SaveAdmin(const STG::AdminConf & ac) const
-{
-char passwordE[2 * ADM_PASSWD_LEN + 2];
-char pass[ADM_PASSWD_LEN + 1];
-char adminPass[ADM_PASSWD_LEN + 1];
-
-memset(pass, 0, sizeof(pass));
-memset(adminPass, 0, sizeof(adminPass));
-
-BLOWFISH_CTX ctx;
-InitContext(adm_enc_passwd, strlen(adm_enc_passwd), &ctx);
-
-strncpy(adminPass, ac.password.c_str(), ADM_PASSWD_LEN);
-adminPass[ADM_PASSWD_LEN - 1] = 0;
-
-for (int i = 0; i < ADM_PASSWD_LEN/8; i++)
-    {
-    EncryptBlock(pass + 8*i, adminPass + 8*i, &ctx);
-    }
-
-pass[ADM_PASSWD_LEN - 1] = 0;
-Encode12(passwordE, pass, ADM_PASSWD_LEN);
-
-sprintf(qbuf,"UPDATE admins SET password='%s', ChgConf=%d, ChgPassword=%d, "\
-    "ChgStat=%d, ChgCash=%d, UsrAddDel=%d, ChgTariff=%d, ChgAdmin=%d "\
-    "WHERE login='%s' LIMIT 1", 
-    passwordE,
-    ac.priv.userConf,
-    ac.priv.userPasswd,
-    ac.priv.userStat,
-    ac.priv.userCash,
-    ac.priv.userAddDel,
-    ac.priv.tariffChg,
-    ac.priv.adminChg,
-    ac.login.c_str()
-    );
-
-if(MysqlSetQuery(qbuf))
-{
-    errorStr = "Couldn't save admin:\n";
-    //errorStr += mysql_error(sock);
-    return -1;
-}
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::RestoreAdmin(STG::AdminConf * ac, const std::string & login) const
-{
-char pass[ADM_PASSWD_LEN + 1];
-char password[ADM_PASSWD_LEN + 1];
-char passwordE[2*ADM_PASSWD_LEN + 2];
-BLOWFISH_CTX ctx;
-
-memset(password, 0, sizeof(password));
-
-std::string p;
-MYSQL_RES *res;
-MYSQL_ROW row;
-MYSQL * sock;
-sprintf(qbuf,"SELECT * FROM admins WHERE login='%s' LIMIT 1", login.c_str());
-    
-if(MysqlGetQuery(qbuf,sock))
-{
-    errorStr = "Couldn't restore admin:\n";
-    errorStr += mysql_error(sock);
-    mysql_close(sock);
-    return -1;
-}
-
-if (!(res=mysql_store_result(sock)))
-{
-    errorStr = "Couldn't restore admin:\n";
-    errorStr += mysql_error(sock);
-    mysql_close(sock);
-    return -1;
-}
-
-if ( mysql_num_rows(res) == 0)
-{
-    mysql_free_result(res);
-    errorStr = "Couldn't restore admin as couldn't found him in table.\n";
-    mysql_close(sock);
-    return -1;
-}
-  
-row = mysql_fetch_row(res);
-
-p = row[1];
-
-if(p.length() == 0)
-{
-    mysql_free_result(res);
-    errorStr = "Error in parameter password";
-    mysql_close(sock);
-    return -1;
-}
-
-memset(passwordE, 0, sizeof(passwordE));
-strncpy(passwordE, p.c_str(), 2*ADM_PASSWD_LEN);
-
-memset(pass, 0, sizeof(pass));
-
-if (passwordE[0] != 0)
-    {
-    Decode21(pass, passwordE);
-    InitContext(adm_enc_passwd, strlen(adm_enc_passwd), &ctx);
-
-    for (int i = 0; i < ADM_PASSWD_LEN/8; i++)
-        {
-        DecryptBlock(password + 8*i, pass + 8*i, &ctx);
-        }
-    }
-else
-    {
-    password[0] = 0;
-    }
-
-ac->password = password;
-
-uint16_t a;
-
-if (GetInt(row[2], &a) == 0) 
-    ac->priv.userConf = a;
-else
-    {
-    mysql_free_result(res);
-    errorStr = "Error in parameter ChgConf";
-    mysql_close(sock);
-    return -1;
-    }
-
-if (GetInt(row[3], &a) == 0) 
-    ac->priv.userPasswd = a;
-else
-    {
-    mysql_free_result(res);
-    errorStr = "Error in parameter ChgPassword";
-    mysql_close(sock);
-    return -1;
-    }
-
-if (GetInt(row[4], &a) == 0) 
-    ac->priv.userStat = a;
-else
-    {
-    mysql_free_result(res);
-    errorStr = "Error in parameter ChgStat";
-    mysql_close(sock);
-    return -1;
-    }
-
-if (GetInt(row[5], &a) == 0) 
-    ac->priv.userCash = a;
-else
-    {
-    mysql_free_result(res);
-    errorStr = "Error in parameter ChgCash";
-    mysql_close(sock);
-    return -1;
-    }
-
-if (GetInt(row[6], &a) == 0) 
-    ac->priv.userAddDel = a;
-else
-    {
-    mysql_free_result(res);
-    errorStr = "Error in parameter UsrAddDel";
-    mysql_close(sock);
-    return -1;
-    }
-
-if (GetInt(row[7], &a) == 0) 
-    ac->priv.tariffChg = a;
-else
-    {
-    mysql_free_result(res);
-    errorStr = "Error in parameter ChgTariff";
-    mysql_close(sock);
-    return -1;
-    }
-
-if (GetInt(row[8], &a) == 0) 
-    ac->priv.adminChg = a;
-else
-    {
-    mysql_free_result(res);
-    errorStr = "Error in parameter ChgAdmin";
-    mysql_close(sock);
-    return -1;
-    }
-
-mysql_free_result(res);
-mysql_close(sock);
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::AddTariff(const std::string & name) const
-{
-sprintf(qbuf,"INSERT INTO tariffs SET name='%s'", name.c_str());
-    
-if(MysqlSetQuery(qbuf))
-{
-    errorStr = "Couldn't add tariff:\n";
-//    errorStr += mysql_error(sock);
-    return -1;
-}
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::DelTariff(const std::string & name) const
-{
-sprintf(qbuf,"DELETE FROM tariffs WHERE name='%s' LIMIT 1", name.c_str());
-    
-if(MysqlSetQuery(qbuf))
-{
-    errorStr = "Couldn't delete tariff: ";
-//    errorStr += mysql_error(sock);
-    return -1;
-}
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::RestoreTariff(STG::TariffData * td, const std::string & tariffName) const
-{
-MYSQL_RES *res;
-MYSQL_ROW row;
-MYSQL * sock;
-sprintf(qbuf,"SELECT * FROM tariffs WHERE name='%s' LIMIT 1", tariffName.c_str());
-    
-if(MysqlGetQuery(qbuf,sock))
-{
-    errorStr = "Couldn't restore Tariff:\n";
-    errorStr += mysql_error(sock);
-    mysql_close(sock);
-    return -1;
-}
-
-if (!(res=mysql_store_result(sock)))
-{
-    errorStr = "Couldn't restore Tariff:\n";
-    errorStr += mysql_error(sock);
-    mysql_close(sock);
-    return -1;
-}
-
-std::string str;
-td->tariffConf.name = tariffName;
-
-row = mysql_fetch_row(res);
-
-std::string param;
-for (int i = 0; i<DIR_NUM; i++)
-    {
-    strprintf(&param, "Time%d", i);
-    str = row[6+i*8];
-    if (str.length() == 0)
-        {
-        mysql_free_result(res);
-        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
-        mysql_close(sock);
-        return -1;
-        }
-
-    ParseTariffTimeStr(str.c_str(), 
-                       td->dirPrice[i].hDay, 
-                       td->dirPrice[i].mDay, 
-                       td->dirPrice[i].hNight, 
-                       td->dirPrice[i].mNight);
-
-    strprintf(&param, "PriceDayA%d", i);
-    if (GetDouble(row[1+i*8], &td->dirPrice[i].priceDayA, 0.0) < 0)
-        {
-        mysql_free_result(res);
-        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
-        mysql_close(sock);
-        return -1;
-        }
-    td->dirPrice[i].priceDayA /= (1024*1024);
-
-    strprintf(&param, "PriceDayB%d", i);
-    if (GetDouble(row[2+i*8], &td->dirPrice[i].priceDayB, 0.0) < 0)
-        {
-        mysql_free_result(res);
-        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
-        mysql_close(sock);
-        return -1;
-        }
-    td->dirPrice[i].priceDayB /= (1024*1024);
-
-    strprintf(&param, "PriceNightA%d", i);
-    if (GetDouble(row[3+i*8], &td->dirPrice[i].priceNightA, 0.0) < 0)
-        {
-        mysql_free_result(res);
-        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
-        mysql_close(sock);
-        return -1;
-        }
-    td->dirPrice[i].priceNightA /= (1024*1024);
-
-    strprintf(&param, "PriceNightB%d", i);
-    if (GetDouble(row[4+i*8], &td->dirPrice[i].priceNightB, 0.0) < 0)
-        {
-        mysql_free_result(res);
-        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
-        mysql_close(sock);
-        return -1;
-        }
-    td->dirPrice[i].priceNightB /= (1024*1024);
-
-    strprintf(&param, "Threshold%d", i);
-    if (GetInt(row[5+i*8], &td->dirPrice[i].threshold) < 0)
-        {
-        mysql_free_result(res);
-        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
-        mysql_close(sock);
-        return -1;
-        }
-
-    strprintf(&param, "SinglePrice%d", i);
-    if (GetInt(row[8+i*8], &td->dirPrice[i].singlePrice) < 0)
-        {
-        mysql_free_result(res);
-        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
-        mysql_close(sock);
-        return -1;
-        }
-
-    strprintf(&param, "NoDiscount%d", i);
-    if (GetInt(row[7+i*8], &td->dirPrice[i].noDiscount) < 0)
-        {
-        mysql_free_result(res);
-        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
-        mysql_close(sock);
-        return -1;
-        }
-    }//main for
-
-if (GetDouble(row[2+8*DIR_NUM], &td->tariffConf.fee, 0.0) < 0)
-    {
-    mysql_free_result(res);
-    errorStr = "Cannot read tariff " + tariffName + ". Parameter Fee";
-    mysql_close(sock);
-    return -1;
-    }
-
-if (GetDouble(row[3+8*DIR_NUM], &td->tariffConf.free, 0.0) < 0)
-    {
-    mysql_free_result(res);
-    errorStr = "Cannot read tariff " + tariffName + ". Parameter Free";
-    mysql_close(sock);
-    return -1;
-    }
-
-if (GetDouble(row[1+8*DIR_NUM], &td->tariffConf.passiveCost, 0.0) < 0)
-    {
-    mysql_free_result(res);
-    errorStr = "Cannot read tariff " + tariffName + ". Parameter PassiveCost";
-    mysql_close(sock);
-    return -1;
-    }
-
-    str = row[4+8*DIR_NUM];
-    param = "TraffType";
-    
-    if (str.length() == 0)
-        {
-        mysql_free_result(res);
-        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
-        mysql_close(sock);
-        return -1;
-        }
-
-td->tariffConf.traffType = STG::Tariff::parseTraffType(str);
-
-if (schemaVersion > 0)
-{
-    str = row[5+8*DIR_NUM];
-    param = "Period";
-
-    if (str.length() == 0)
-        {
-        mysql_free_result(res);
-        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
-        mysql_close(sock);
-        return -1;
-        }
-
-    td->tariffConf.period = STG::Tariff::parsePeriod(str);
-    }
-else
-    {
-    td->tariffConf.period = STG::Tariff::MONTH;
-    }
-
-if (schemaVersion > 1)
-    {
-    str = row[6+8*DIR_NUM];
-    param = "ChangePolicy";
-
-    if (str.length() == 0)
-        {
-        mysql_free_result(res);
-        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
-        mysql_close(sock);
-        return -1;
-        }
-
-    td->tariffConf.changePolicy = STG::Tariff::parseChangePolicy(str);
-
-    str = row[7+8*DIR_NUM];
-    param = "ChangePolicyTimeout";
-
-    if (str.length() == 0)
-        {
-        mysql_free_result(res);
-        errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param;
-        mysql_close(sock);
-        return -1;
-        }
-
-    td->tariffConf.changePolicyTimeout = readTime(str);
-    }
-else
-    {
-    td->tariffConf.changePolicy = STG::Tariff::ALLOW;
-    td->tariffConf.changePolicyTimeout = 0;
-    }
-
-mysql_free_result(res);
-mysql_close(sock);
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::SaveTariff(const STG::TariffData & td, const std::string & tariffName) const
-{
-std::string param;
-
-std::string res="UPDATE tariffs SET";
-
-for (int i = 0; i < DIR_NUM; i++)
-    {
-    strprintf(&param, " PriceDayA%d=%f,", i, 
-        td.dirPrice[i].priceDayA * pt_mega);
-    res += param;
-
-    strprintf(&param, " PriceDayB%d=%f,", i, 
-        td.dirPrice[i].priceDayB * pt_mega);        
-    res += param;
-        
-    strprintf(&param, " PriceNightA%d=%f,", i,
-        td.dirPrice[i].priceNightA * pt_mega);
-    res += param;
-
-    strprintf(&param, " PriceNightB%d=%f,", i, 
-        td.dirPrice[i].priceNightB * pt_mega);
-    res += param;
-        
-    strprintf(&param, " Threshold%d=%d,", i, 
-        td.dirPrice[i].threshold);
-    res += param;
-
-    std::string s;
-    strprintf(&param, " Time%d", i);
-
-    strprintf(&s, "%0d:%0d-%0d:%0d", 
-            td.dirPrice[i].hDay,
-            td.dirPrice[i].mDay,
-            td.dirPrice[i].hNight,
-            td.dirPrice[i].mNight);
-
-    res += (param + "='" + s + "',");
-
-    strprintf(&param, " NoDiscount%d=%d,", i, 
-        td.dirPrice[i].noDiscount);
-    res += param;
-
-    strprintf(&param, " SinglePrice%d=%d,", i, 
-        td.dirPrice[i].singlePrice);
-    res += param;
-    }
-
-strprintf(&param, " PassiveCost=%f,", td.tariffConf.passiveCost);
-res += param;
-
-strprintf(&param, " Fee=%f,", td.tariffConf.fee);
-res += param;
-
-strprintf(&param, " Free=%f,", td.tariffConf.free);
-res += param;
-
-res += " TraffType='" + STG::Tariff::toString(td.tariffConf.traffType) + "'";
-
-if (schemaVersion > 0)
-    res += ", Period='" + STG::Tariff::toString(td.tariffConf.period) + "'";
-
-if (schemaVersion > 1)
-    res += ", change_policy='" + STG::Tariff::toString(td.tariffConf.changePolicy) + "'"\
-           ", change_policy_timeout='" + formatTime(td.tariffConf.changePolicy) + "'";
-
-strprintf(&param, " WHERE name='%s' LIMIT 1", tariffName.c_str());
-res += param;
-
-if(MysqlSetQuery(res.c_str()))
-{
-    errorStr = "Couldn't save tariff:\n";
-    //errorStr += mysql_error(sock);
-    return -1;
-}
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::WriteDetailedStat(const STG::TraffStat & statTree, 
-                                   time_t lastStat, 
-                                   const std::string & login) const
-{
-std::string res, stTime, endTime, tempStr;
-time_t t;
-tm * lt;
-
-t = time(NULL);
-lt = localtime(&t);
-
-if (lt->tm_hour == 0 && lt->tm_min <= 5)
-    {
-        t -= 3600 * 24;
-        lt = localtime(&t);
-    }
-
-MYSQL_RES* result;
-MYSQL * sock;
-strprintf(&tempStr, "detailstat_%02d_%4d", lt->tm_mon+1, lt->tm_year+1900);
-
-if (!(sock=MysqlConnect())){
-    mysql_close(sock);
-    return -1;
-}
-
-if (!(result=mysql_list_tables(sock,tempStr.c_str() )))
-{
-    errorStr = "Couldn't get table " + tempStr + ":\n";
-    errorStr += mysql_error(sock);
-    mysql_close(sock);
-    return -1;
-}
-
-my_ulonglong num_rows =  mysql_num_rows(result);
-
-mysql_free_result(result);
-
-if (num_rows < 1)
-{
-    sprintf(qbuf,"CREATE TABLE detailstat_%02d_%4d (login VARCHAR(40) DEFAULT '',"\
-        "day TINYINT DEFAULT 0,startTime TIME,endTime TIME,"\
-        "IP VARCHAR(17) DEFAULT '',dir INT DEFAULT 0,"\
-        "down BIGINT DEFAULT 0,up BIGINT DEFAULT 0, cash DOUBLE DEFAULT 0.0, INDEX (login), INDEX(dir), INDEX(day), INDEX(IP))",
-    lt->tm_mon+1, lt->tm_year+1900);
-    
-    if(MysqlQuery(qbuf,sock))
-    {
-        errorStr = "Couldn't create WriteDetailedStat table:\n";
-        errorStr += mysql_error(sock);
-        mysql_close(sock);
-        return -1;
-    }
-}
-
-struct tm * lt1;
-struct tm * lt2;
-
-lt1 = localtime(&lastStat);
-
-int h1, m1, s1;
-int h2, m2, s2;
-
-h1 = lt1->tm_hour;
-m1 = lt1->tm_min;
-s1 = lt1->tm_sec;
-
-lt2 = localtime(&t);
-
-h2 = lt2->tm_hour;
-m2 = lt2->tm_min;
-s2 = lt2->tm_sec;
-    
-strprintf(&stTime, "%02d:%02d:%02d", h1, m1, s1);
-strprintf(&endTime, "%02d:%02d:%02d", h2, m2, s2);
-
-strprintf(&res,"INSERT INTO detailstat_%02d_%4d SET login='%s',"\
-    "day=%d,startTime='%s',endTime='%s',", 
-    lt->tm_mon+1, lt->tm_year+1900,
-    login.c_str(),
-    lt->tm_mday,
-    stTime.c_str(),
-    endTime.c_str()
-    );
-
-STG::TraffStat::const_iterator stIter;
-stIter = statTree.begin();
-
-while (stIter != statTree.end())
-    {
-        strprintf(&tempStr,"IP='%s', dir=%d, down=%lld, up=%lld, cash=%f", 
-                inet_ntostring(stIter->first.ip).c_str(),
-                stIter->first.dir, 
-                stIter->second.down, 
-                stIter->second.up, 
-                stIter->second.cash
-            );
-    
-        if( MysqlQuery((res+tempStr).c_str(),sock) )
-        {
-            errorStr = "Couldn't insert data in WriteDetailedStat:\n";
-            errorStr += mysql_error(sock);
-            mysql_close(sock);
-            return -1;
-        }
-
-        result=mysql_store_result(sock);
-        if(result)
-            mysql_free_result(result);
-
-        ++stIter;
-    }
-mysql_close(sock);
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::AddMessage(STG::Message * msg, const std::string & login) const
-{
-struct timeval tv;
-
-gettimeofday(&tv, NULL);
-
-msg->header.id = static_cast<uint64_t>(tv.tv_sec) * 1000000 + static_cast<uint64_t>(tv.tv_usec);
-
-sprintf(qbuf,"INSERT INTO messages SET login='%s', id=%lld", 
-    login.c_str(),
-    static_cast<long long>(msg->header.id)
-    );
-    
-if(MysqlSetQuery(qbuf))
-{
-    errorStr = "Couldn't add message:\n";
-    //errorStr += mysql_error(sock);
-    return -1;
-}
-
-return EditMessage(*msg, login);
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::EditMessage(const STG::Message & msg, const std::string & login) const
-{
-std::string res;
-
-strprintf(&res,"UPDATE messages SET type=%d, lastSendTime=%u, creationTime=%u, "\
-    "showTime=%u, stgRepeat=%d, repeatPeriod=%u, text='%s' "\
-    "WHERE login='%s' AND id=%lld LIMIT 1", 
-    msg.header.type,
-    msg.header.lastSendTime,
-    msg.header.creationTime,
-    msg.header.showTime,
-    msg.header.repeat,
-    msg.header.repeatPeriod,
-    (ReplaceStr(msg.text,badSyms,repSym)).c_str(),
-    login.c_str(),
-    msg.header.id
-    );
-
-if(MysqlSetQuery(res.c_str()))
-{
-    errorStr = "Couldn't edit message:\n";
-    //errorStr += mysql_error(sock);
-    return -1;
-}
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::GetMessage(uint64_t id, STG::Message * msg, const std::string & login) const
-{
-MYSQL_RES *res;
-MYSQL_ROW row;
-MYSQL * sock;
-
-sprintf(qbuf,"SELECT * FROM messages WHERE login='%s' AND id=%llu LIMIT 1",
-        login.c_str(), static_cast<unsigned long long>(id));
-    
-if(MysqlGetQuery(qbuf,sock))
-{
-    errorStr = "Couldn't GetMessage:\n";
-    errorStr += mysql_error(sock);
-    mysql_close(sock);
-    return -1;
-}
-
-if (!(res=mysql_store_result(sock)))
-{
-    errorStr = "Couldn't GetMessage:\n";
-    errorStr += mysql_error(sock);
-    mysql_close(sock);
-    return -1;
-}
-
-row = mysql_fetch_row(res);
-
-if(row[2]&&str2x(row[2], msg->header.type))
-{
-    mysql_free_result(res);
-    errorStr = "Invalid value in message header for user: " + login;
-    mysql_close(sock);
-    return -1;
-}
-
-if(row[3] && str2x(row[3], msg->header.lastSendTime))
-{
-    mysql_free_result(res);
-    errorStr = "Invalid value in message header for user: " + login;
-    mysql_close(sock);
-    return -1;
-}
-
-if(row[4] && str2x(row[4], msg->header.creationTime))
-{
-    mysql_free_result(res);
-    errorStr = "Invalid value in message header for user: " + login;
-    mysql_close(sock);
-    return -1;
-}
-
-if(row[5] && str2x(row[5], msg->header.showTime))
-{
-    mysql_free_result(res);
-    errorStr = "Invalid value in message header for user: " + login;
-    mysql_close(sock);
-    return -1;
-}
-
-if(row[6] && str2x(row[6], msg->header.repeat))
-{
-    mysql_free_result(res);
-    errorStr = "Invalid value in message header for user: " + login;
-    mysql_close(sock);
-    return -1;
-}
-
-if(row[7] && str2x(row[7], msg->header.repeatPeriod))
-{
-    mysql_free_result(res);
-    errorStr = "Invalid value in message header for user: " + login;
-    mysql_close(sock);
-    return -1;
-}
-
-msg->header.id = id;
-msg->text = row[8];
-
-mysql_free_result(res);
-mysql_close(sock);
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::DelMessage(uint64_t id, const std::string & login) const
-{
-sprintf(qbuf,"DELETE FROM messages WHERE login='%s' AND id=%lld LIMIT 1", 
-        login.c_str(), static_cast<long long>(id));
-    
-if(MysqlSetQuery(qbuf))
-{
-    errorStr = "Couldn't delete Message:\n";
-    //errorStr += mysql_error(sock);
-    return -1;
-}
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int MYSQL_STORE::GetMessageHdrs(std::vector<STG::Message::Header> * hdrsList, const std::string & login) const
-{
-MYSQL_RES *res;
-MYSQL_ROW row;
-MYSQL * sock;
-sprintf(qbuf,"SELECT * FROM messages WHERE login='%s'", login.c_str());
-    
-if(MysqlGetQuery(qbuf,sock))
-{
-    errorStr = "Couldn't GetMessageHdrs:\n";
-    errorStr += mysql_error(sock);
-    mysql_close(sock);
-    return -1;
-}
-
-if (!(res=mysql_store_result(sock)))
-{
-    errorStr = "Couldn't GetMessageHdrs:\n";
-    errorStr += mysql_error(sock);
-    mysql_close(sock);
-    return -1;
-}
-
-unsigned int i;
-my_ulonglong num_rows = mysql_num_rows(res);
-uint64_t id = 0;
-
-for (i = 0; i < num_rows; i++)
-{
-    row = mysql_fetch_row(res);
-    if (str2x(row[1], id))
-        continue;
-    
-    STG::Message::Header hdr;
-    if (row[2]) 
-        if(str2x(row[2], hdr.type))
-            continue;
-
-    if (row[3])
-        if(str2x(row[3], hdr.lastSendTime))
-            continue;
-
-    if (row[4])
-        if(str2x(row[4], hdr.creationTime))
-            continue;
-
-    if (row[5])
-        if(str2x(row[5], hdr.showTime))
-            continue;
-
-    if (row[6])
-        if(str2x(row[6], hdr.repeat))
-            continue;
-
-    if (row[7])
-        if(str2x(row[7], hdr.repeatPeriod))
-            continue;
-
-    hdr.id = id;
-    hdrsList->push_back(hdr);
-}
-
-mysql_free_result(res);
-mysql_close(sock);
-return 0;
-}
-//-----------------------------------------------------------------------------
-
-int MYSQL_STORE::MysqlSetQuery(const char * Query) const {
-
-    MYSQL * sock;
-    int ret=MysqlGetQuery(Query,sock);
-    mysql_close(sock);
-    return ret;
-}
-//-----------------------------------------------------------------------------
-int  MYSQL_STORE::MysqlGetQuery(const char * Query,MYSQL * & sock) const {
-    if (!(sock=MysqlConnect())) {
-        return -1;
-    }
-    return   MysqlQuery(Query,sock);
-}
-//-----------------------------------------------------------------------------
-MYSQL *  MYSQL_STORE::MysqlConnect() const {
-    MYSQL * sock;
-    if ( !(sock=mysql_init(NULL)) ){
-        errorStr= "mysql init susck\n";
-        return NULL;
-    }
-    if (!(sock = mysql_real_connect(sock,storeSettings.GetDBHost().c_str(),
-            storeSettings.GetDBUser().c_str(),storeSettings.GetDBPassword().c_str(),
-            0,0,NULL,0)))
-        {
-            errorStr = "Couldn't connect to mysql engine! With error:\n";
-            errorStr += mysql_error(sock);
-            return NULL;
-        }
-    else{
-         if(mysql_select_db(sock, storeSettings.GetDBName().c_str())){
-             errorStr = "Database lost !\n";
-             return NULL;
-         }
-    }
-    return sock;
-}
-//-----------------------------------------------------------------------------
diff --git a/stargazer/plugins/store/mysql/mysql_store.h b/stargazer/plugins/store/mysql/mysql_store.h
deleted file mode 100644 (file)
index 6d09c47..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-#pragma once
-
-#include "stg/store.h"
-#include "stg/module_settings.h"
-#include "stg/user_traff.h"
-#include "stg/logger.h"
-
-#include <string>
-#include <vector>
-#include <map>
-
-#include <mysql/mysql.h>
-
-//-----------------------------------------------------------------------------
-class MYSQL_STORE_SETTINGS
-{
-public:
-    MYSQL_STORE_SETTINGS();
-    virtual ~MYSQL_STORE_SETTINGS() {}
-    virtual int ParseSettings(const STG::ModuleSettings & s);
-    virtual const std::string & GetStrError() const { return errorStr; }
-
-    const std::string & GetDBUser() const { return dbUser; }
-    const std::string & GetDBPassword() const { return dbPass; }
-    const std::string & GetDBHost() const { return dbHost; }
-    const std::string & GetDBName() const { return dbName; }
-
-private:
-    MYSQL_STORE_SETTINGS(const MYSQL_STORE_SETTINGS & rvalue);
-    MYSQL_STORE_SETTINGS & operator=(const MYSQL_STORE_SETTINGS & rvalue);
-
-    const STG::ModuleSettings * settings;
-
-    int     ParseParam(const std::vector<STG::ParamValue> & moduleParams, 
-                       const std::string & name, std::string & result);
-
-    std::string  errorStr;
-
-    std::string  dbUser;
-    std::string  dbPass;
-    std::string  dbName;
-    std::string  dbHost;
-};
-//-----------------------------------------------------------------------------
-class MYSQL_STORE: public STG::Store
-{
-public:
-    MYSQL_STORE();
-    const std::string & GetStrError() const override { return errorStr; }
-
-    //User
-    int GetUsersList(std::vector<std::string> * usersList) const override;
-    int AddUser(const std::string & login) const override;
-    int DelUser(const std::string & login) const override;
-    int SaveUserStat(const STG::UserStat & stat, const std::string & login) const override;
-    int SaveUserConf(const STG::UserConf & conf, const std::string & login) const override;
-    int RestoreUserStat(STG::UserStat * stat, const std::string & login) const override;
-    int RestoreUserConf(STG::UserConf * conf, const std::string & login) const override;
-    int WriteUserChgLog(const std::string & login,
-                        const std::string & admLogin,
-                        uint32_t       admIP,
-                        const std::string & paramName,
-                        const std::string & oldValue,
-                        const std::string & newValue,
-                        const std::string & message = "") const override;
-    int WriteUserConnect(const std::string & login, uint32_t ip) const override;
-    int WriteUserDisconnect(const std::string & login,
-                            const STG::DirTraff & up,
-                            const STG::DirTraff & down,
-                            const STG::DirTraff & sessionUp,
-                            const STG::DirTraff & sessionDown,
-                            double cash,
-                            double freeMb,
-                            const std::string & reason) const override;
-
-    int WriteDetailedStat(const STG::TraffStat & statTree,
-                          time_t lastStat,
-                          const std::string & login) const override;
-
-    int AddMessage(STG::Message * msg, const std::string & login) const override;
-    int EditMessage(const STG::Message & msg, const std::string & login) const override;
-    int GetMessage(uint64_t id, STG::Message * msg, const std::string & login) const override;
-    int DelMessage(uint64_t id, const std::string & login) const override;
-    int GetMessageHdrs(std::vector<STG::Message::Header> * hdrsList, const std::string & login) const override;
-
-    int SaveMonthStat(const STG::UserStat & stat, int month, int year, const std::string & login) const override;
-
-    //Admin
-    int GetAdminsList(std::vector<std::string> * adminsList) const override;
-    int AddAdmin(const std::string & login) const override;
-    int DelAdmin(const std::string & login) const override;
-    int RestoreAdmin(STG::AdminConf * ac, const std::string & login) const override;
-    int SaveAdmin(const STG::AdminConf & ac) const override;
-
-    //Tariff
-    int GetTariffsList(std::vector<std::string> * tariffsList) const override;
-    int AddTariff(const std::string & name) const override;
-    int DelTariff(const std::string & name) const override;
-    int SaveTariff(const STG::TariffData & td, const std::string & tariffName) const override;
-    int RestoreTariff(STG::TariffData * td, const std::string & tariffName) const override;
-
-    //Corparation
-    int GetCorpsList(std::vector<std::string> *) const override {return 0;}
-    int SaveCorp(const STG::CorpConf &) const override {return 0;}
-    int RestoreCorp(STG::CorpConf *, const std::string &) const override {return 0;}
-    int AddCorp(const std::string &) const override {return 0;}
-    int DelCorp(const std::string &) const override {return 0;}
-
-    // Services
-    int GetServicesList(std::vector<std::string> *) const override {return 0;}
-    int SaveService(const STG::ServiceConf &) const override {return 0;}
-    int RestoreService(STG::ServiceConf *, const std::string &) const override {return 0;}
-    int AddService(const std::string &) const override {return 0;}
-    int DelService(const std::string &) const override {return 0;}
-
-    void            SetSettings(const STG::ModuleSettings & s) override { settings = s; }
-    int             ParseSettings() override;
-    const std::string &  GetVersion() const override { return version; }
-
-private:
-    MYSQL_STORE(const MYSQL_STORE & rvalue);
-    MYSQL_STORE & operator=(const MYSQL_STORE & rvalue);
-
-    virtual int WriteLogString(const std::string & str, const std::string & login) const;
-    int GetAllParams(std::vector<std::string> * ParamList, const std::string & table, const std::string & name) const;
-    int CheckAllTables(MYSQL * sock);
-    int MakeUpdates(MYSQL * sock);
-    bool IsTablePresent(const std::string & str,MYSQL * sock);
-    mutable std::string          errorStr;
-    int                        MysqlQuery(const char* sQuery,MYSQL * sock) const;
-    int                     MysqlGetQuery(const char * Query,MYSQL * & sock) const;
-    int                     MysqlSetQuery(const char * Query) const;
-    MYSQL  *                MysqlConnect() const ;
-    std::string                  version;
-    MYSQL_STORE_SETTINGS    storeSettings;
-    STG::ModuleSettings         settings;
-    int                     schemaVersion;
-
-    STG::PluginLogger           logger;
-};
diff --git a/stargazer/plugins/store/postgresql/postgresql_store.cpp b/stargazer/plugins/store/postgresql/postgresql_store.cpp
deleted file mode 100644 (file)
index 2146d66..0000000
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-/*
- *  This file contains a realization of a base postgresql-storage plugin class
- *
- *  v. 1.3
- *  FreeMb logging on disconnects added
- *
- *  v. 1.2
- *  Reconnection on faults added
- *
- *  v. 1.1
- *  tb_stats removed
- *
- *  v. 1.0
- *  Initial implementation
- *
- *  $Revision: 1.5 $
- *  $Date: 2010/01/06 10:43:48 $
- *
- */
-
-#include "postgresql_store.h"
-
-#include "postgresql_store_utils.h"
-#include "postgresql_store.h"
-
-#include "stg/common.h" // str2x, printfd
-
-#include <string>
-#include <vector>
-
-#include <libpq-fe.h>
-
-extern "C" STG::Store* GetStore()
-{
-    static POSTGRESQL_STORE plugin;
-    return &plugin;
-}
-
-//-----------------------------------------------------------------------------
-POSTGRESQL_STORE::POSTGRESQL_STORE()
-    : versionString("postgresql_store v.1.3"),
-      server("localhost"),
-      database("stargazer"),
-      user("stg"),
-      password("123456"),
-      clientEncoding("KOI8"),
-      version(0),
-      retries(3),
-      connection(NULL),
-      logger(STG::PluginLogger::get("store_postgresql"))
-{
-pthread_mutex_init(&mutex, NULL);
-}
-//-----------------------------------------------------------------------------
-POSTGRESQL_STORE::~POSTGRESQL_STORE()
-{
-if (connection)
-    {
-    PQfinish(connection);
-    }
-pthread_mutex_destroy(&mutex);
-}
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::ParseSettings()
-{
-std::vector<STG::ParamValue>::iterator i;
-
-for(i = settings.moduleParams.begin(); i != settings.moduleParams.end(); ++i)
-    {
-    if (i->value.empty())
-        continue;
-    std::string s = ToLower(i->param);
-    if (s == "server")
-        {
-        server = i->value.front();
-        }
-    if (s == "database")
-        {
-        database = i->value.front();
-        }
-    if (s == "user")
-        {
-        user = i->value.front();
-        }
-    if (s == "password")
-        {
-        password = i->value.front();
-        }
-    if (s == "retries")
-        {
-        if (str2x(i->value.front(), retries))
-            {
-            strError = "Invalid 'retries' value";
-            printfd(__FILE__, "POSTGRESQL_STORE::ParseSettings(): '%s'\n", strError.c_str());
-            return -1;
-            }
-        }
-    }
-
-clientEncoding = "KOI8";
-
-return Connect();
-}
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::Connect()
-{
-std::string params;
-params = "host=" + server + " "
-       + "dbname=" + database + " "
-       + "user=" + user + " "
-       + "password=" + password;
-
-connection = PQconnectdb(params.c_str());
-
-if (PQstatus(connection) != CONNECTION_OK)
-    {
-    strError = PQerrorMessage(connection);
-    printfd(__FILE__, "POSTGRESQL_STORE::Connect(): '%s'\n", strError.c_str());
-    // Will try to connect later
-    return 0;
-    }
-
-if (PQsetClientEncoding(connection, clientEncoding.c_str()))
-    {
-    strError = PQerrorMessage(connection);
-    printfd(__FILE__, "POSTGRESQL_STORE::Connect(): '%s'\n", strError.c_str());
-    return 1;
-    }
-
-return CheckVersion();
-}
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::Reset() const
-{
-for (int i = 0; i < retries && PQstatus(connection) != CONNECTION_OK; ++i)
-    {
-    struct timespec ts = {1, 0};
-    nanosleep(&ts, NULL);
-    PQreset(connection);
-    }
-
-if (PQstatus(connection) != CONNECTION_OK)
-    {
-    strError = PQerrorMessage(connection);
-    printfd(__FILE__, "POSTGRESQL_STORE::Reset(): '%s'\n", strError.c_str());
-    return 1;
-    }
-
-if (PQsetClientEncoding(connection, clientEncoding.c_str()))
-    {
-    strError = PQerrorMessage(connection);
-    printfd(__FILE__, "POSTGRESQL_STORE::Reset(): '%s'\n", strError.c_str());
-    return -1;
-    }
-
-return CheckVersion();
-}
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::CheckVersion() const
-{
-
-if (StartTransaction())
-    {
-    strError = "Failed to start transaction";
-    printfd(__FILE__, "POSTGRESQL_STORE::CheckVersion(): '%s'\n", strError.c_str());
-    return -1;
-    }
-
-PGresult * result = PQexec(connection, "SELECT MAX(version) FROM tb_info");
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    PQclear(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::CheckVersion(): '%s'\n");
-    RollbackTransaction();
-    return -1;
-    }
-
-if (str2x(PQgetvalue(result, 0, 0), version))
-    {
-    strError = "Invalid DB version";
-    PQclear(result);
-    RollbackTransaction();
-    printfd(__FILE__, "POSTGRESQL_STORE::CheckVersion(): '%s'\n", strError.c_str());
-    return -1;
-    }
-
-PQclear(result);
-
-if (version < DB_MIN_VERSION)
-    {
-    strError = "DB version too old";
-    RollbackTransaction();
-    printfd(__FILE__, "POSTGRESQL_STORE::CheckVersion(): '%s'\n", strError.c_str());
-    return -1;
-    }
-
-if (version < 6)
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::CheckVersion(): I recommend you to upgrade your DB to higher version to support FreeMb logging on disconnect. Current version is %d\n", version);
-    }
-
-if (CommitTransaction())
-    {
-    strError = "Failed to commit transaction";
-    printfd(__FILE__, "POSTGRESQL_STORE::CheckVersion(): '%s'\n", strError.c_str());
-    return -1;
-    }
-
-logger("POSTGRESQL_STORE: Current DB schema version: %d", version);
-
-return 0;
-}
-//-----------------------------------------------------------------------------
diff --git a/stargazer/plugins/store/postgresql/postgresql_store.h b/stargazer/plugins/store/postgresql/postgresql_store.h
deleted file mode 100644 (file)
index 0e8b639..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#pragma once
-
-#include "stg/store.h"
-#include "stg/module_settings.h"
-#include "stg/logger.h"
-
-#include <string>
-#include <vector>
-
-#include <libpq-fe.h>
-
-// Minimal DB version is 5
-// Recommended DB version is 6 (support FreeMb logging on disconnects)
-#define DB_MIN_VERSION 5
-
-namespace STG
-{
-
-class UserIPs;
-
-}
-
-class POSTGRESQL_STORE : public STG::Store {
-public:
-    POSTGRESQL_STORE();
-    ~POSTGRESQL_STORE() override;
-
-    // Users
-    int GetUsersList(std::vector<std::string> * usersList) const override;
-    int AddUser(const std::string & login) const override;
-    int DelUser(const std::string & login) const override;
-    int SaveUserStat(const STG::UserStat & stat, const std::string & login) const override;
-    int SaveUserConf(const STG::UserConf & conf, const std::string & login) const override;
-    int RestoreUserStat(STG::UserStat * stat, const std::string & login) const override;
-    int RestoreUserConf(STG::UserConf * conf, const std::string & login) const override;
-    int WriteUserChgLog(const std::string & login,
-                        const std::string & admLogin,
-                        uint32_t admIP,
-                        const std::string & paramName,
-                        const std::string & oldValue,
-                        const std::string & newValue,
-                        const std::string & message) const override;
-    int WriteUserConnect(const std::string & login, uint32_t ip) const override;
-    int WriteUserDisconnect(const std::string & login,
-                            const STG::DirTraff & up,
-                            const STG::DirTraff & down,
-                            const STG::DirTraff & sessionUp,
-                            const STG::DirTraff & sessionDown,
-                            double cash,
-                            double freeMb,
-                            const std::string & reason) const override;
-    int WriteDetailedStat(const STG::TraffStat & statTree,
-                          time_t lastStat,
-                          const std::string & login) const override;
-
-    // Messages
-    int AddMessage(STG::Message * msg, const std::string & login) const override;
-    int EditMessage(const STG::Message & msg, const std::string & login) const override;
-    int GetMessage(uint64_t id, STG::Message * msg, const std::string & login) const override;
-    int DelMessage(uint64_t id, const std::string & login) const override;
-    int GetMessageHdrs(std::vector<STG::Message::Header> * hdrsList, const std::string & login) const override;
-
-    // Stats
-    int SaveMonthStat(const STG::UserStat & stat, int month, int year, const std::string  & login) const override;
-
-    // Admins
-    int GetAdminsList(std::vector<std::string> * adminsList) const override;
-    int SaveAdmin(const STG::AdminConf & ac) const override;
-    int RestoreAdmin(STG::AdminConf * ac, const std::string & login) const override;
-    int AddAdmin(const std::string & login) const override;
-    int DelAdmin(const std::string & login) const override;
-
-    // Tariffs
-    int GetTariffsList(std::vector<std::string> * tariffsList) const override;
-    int AddTariff(const std::string & name) const override;
-    int DelTariff(const std::string & name) const override;
-    int SaveTariff(const STG::TariffData & td, const std::string & tariffName) const override;
-    int RestoreTariff(STG::TariffData * td, const std::string & tariffName) const override;
-
-    // Corporations
-    int GetCorpsList(std::vector<std::string> * corpsList) const override;
-    int SaveCorp(const STG::CorpConf & cc) const override;
-    int RestoreCorp(STG::CorpConf * cc, const std::string & name) const override;
-    int AddCorp(const std::string & name) const override;
-    int DelCorp(const std::string & name) const override;
-
-    // Services
-    int GetServicesList(std::vector<std::string> * servicesList) const override;
-    int SaveService(const STG::ServiceConf & sc) const override;
-    int RestoreService(STG::ServiceConf * sc, const std::string & name) const override;
-    int AddService(const std::string & name) const override;
-    int DelService(const std::string & name) const override;
-
-    // Settings
-    void SetSettings(const STG::ModuleSettings & s) override { settings = s; }
-    int ParseSettings() override;
-
-    const std::string & GetStrError() const override { return strError; }
-    const std::string & GetVersion() const override { return versionString; }
-private:
-    POSTGRESQL_STORE(const POSTGRESQL_STORE & rvalue);
-    POSTGRESQL_STORE & operator=(const POSTGRESQL_STORE & rvalue);
-
-    int StartTransaction() const;
-    int CommitTransaction() const;
-    int RollbackTransaction() const;
-
-    int EscapeString(std::string & value) const;
-
-    int SaveStat(const STG::UserStat & stat, const std::string & login, int year = 0, int month = 0) const;
-
-    int SaveUserServices(uint32_t uid, const std::vector<std::string> & services) const;
-    int SaveUserData(uint32_t uid, const std::vector<std::string> & data) const;
-    int SaveUserIPs(uint32_t uid, const STG::UserIPs & ips) const;
-
-    void MakeDate(std::string & date, int year = 0, int month = 0) const;
-
-    int Connect();
-    int Reset() const;
-    int CheckVersion() const;
-
-    std::string versionString;
-    mutable std::string strError;
-    std::string server;
-    std::string database;
-    std::string user;
-    std::string password;
-    std::string clientEncoding;
-    STG::ModuleSettings settings;
-    mutable pthread_mutex_t mutex;
-    mutable int version;
-    int retries;
-
-    PGconn * connection;
-
-    STG::PluginLogger logger;
-};
diff --git a/stargazer/plugins/store/postgresql/postgresql_store_admins.cpp b/stargazer/plugins/store/postgresql/postgresql_store_admins.cpp
deleted file mode 100644 (file)
index b1c1203..0000000
+++ /dev/null
@@ -1,454 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-/*
- *  Administrators manipulation methods
- *
- *  $Revision: 1.3 $
- *  $Date: 2010/11/08 10:10:24 $
- *
- */
-
-#include "postgresql_store.h"
-
-#include "stg/locker.h"
-#include "stg/common.h"
-#include "stg/admin_conf.h"
-#include "stg/blowfish.h"
-
-#include <string>
-#include <vector>
-#include <sstream>
-
-#include <libpq-fe.h>
-
-#define adm_enc_passwd "cjeifY8m3"
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::GetAdminsList(std::vector<std::string> * adminsList) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::GetAdminsList(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
-    if (Reset())
-        {
-        strError = "Connection lost";
-        printfd(__FILE__, "POSTGRESQL_STORE::GetAdminsList(): '%s'\n", strError.c_str());
-        return -1;
-        }
-    }
-
-PGresult * result;
-
-if (StartTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::GetAdminsList(): 'Failed to start transaction'\n");
-    return -1;
-    }
-
-result = PQexec(connection, "SELECT login FROM tb_admins WHERE login <> '@stargazer'");
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    PQclear(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::GetAdminsList(): '%s'\n", strError.c_str());
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::GetAdminsList(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-int tuples = PQntuples(result);
-
-for (int i = 0; i < tuples; ++i)
-    {
-    adminsList->push_back(PQgetvalue(result, i, 0));
-    }
-
-PQclear(result);
-
-if (CommitTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::GetAdminsList(): 'Failed to commit transaction'\n");
-    return -1;
-    }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::SaveAdmin(const STG::AdminConf & ac) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
-    if (Reset())
-        {
-        strError = "Connection lost";
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): '%s'\n", strError.c_str());
-        return -1;
-        }
-    }
-
-PGresult * result;
-
-if (StartTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): 'Failed to start transaction'\n");
-    return -1;
-    }
-
-char encodedPass[2 * ADM_PASSWD_LEN + 2];
-char cryptedPass[ADM_PASSWD_LEN + 1];
-char adminPass[ADM_PASSWD_LEN + 1];
-BLOWFISH_CTX ctx;
-
-memset(cryptedPass, 0, ADM_PASSWD_LEN + 1);
-strncpy(adminPass, ac.password.c_str(), ADM_PASSWD_LEN);
-InitContext(adm_enc_passwd, sizeof(adm_enc_passwd), &ctx);
-
-for (int i = 0; i < ADM_PASSWD_LEN / 8; i++)
-    EncryptBlock(cryptedPass + 8 * i, adminPass + 8 * i, &ctx);
-
-cryptedPass[ADM_PASSWD_LEN] = 0;
-Encode12(encodedPass, cryptedPass, ADM_PASSWD_LEN);
-
-std::string pass = encodedPass;
-std::string login = ac.login;
-
-if (EscapeString(pass))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): 'Failed to escape password'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-if (EscapeString(login))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): 'Failed to escape login'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-std::stringstream query;
-query << "UPDATE tb_admins SET "
-          << "passwd = '" << pass << "', "
-          << "chg_conf = " << ac.priv.userConf << ", "
-          << "chg_password = " << ac.priv.userPasswd << ", "
-          << "chg_stat = " << ac.priv.userStat << ", "
-          << "chg_cash = " << ac.priv.userCash << ", "
-          << "usr_add_del = " << ac.priv.userAddDel << ", "
-          << "chg_tariff = " << ac.priv.tariffChg << ", "
-          << "chg_admin = " << ac.priv.adminChg << " "
-      << "WHERE login = '" << login << "'";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_COMMAND_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    PQclear(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): '%s'\n", strError.c_str());
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-PQclear(result);
-
-if (CommitTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveAdmin(): 'Failed to commit transaction'\n");
-    return -1;
-    }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::RestoreAdmin(STG::AdminConf * ac, const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
-    if (Reset())
-        {
-        strError = "Connection lost";
-        printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): '%s'\n", strError.c_str());
-        return -1;
-        }
-    }
-
-PGresult * result;
-
-if (StartTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): 'Failed to start transaction'\n");
-    return -1;
-    }
-
-char cryptedPass[ADM_PASSWD_LEN + 1];
-char adminPass[ADM_PASSWD_LEN + 1];
-BLOWFISH_CTX ctx;
-
-std::string elogin = login;
-
-if (EscapeString(elogin))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): 'Failed to escape login'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-std::ostringstream query;
-query << "SELECT login, passwd, \
-                 chg_conf, chg_password, chg_stat, \
-                 chg_cash, usr_add_del, chg_tariff, \
-                 chg_admin, chg_service, chg_corporation \
-          FROM tb_admins \
-          WHERE login = '" << elogin << "'";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): '%s'\n", strError.c_str());
-    PQclear(result);
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-int tuples = PQntuples(result);
-
-if (tuples != 1)
-    {
-    strError = "Failed to fetch admin's data";
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
-    PQclear(result);
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-ac->login = PQgetvalue(result, 0, 0);
-ac->password = PQgetvalue(result, 0, 1);
-
-std::stringstream tuple;
-tuple << PQgetvalue(result, 0, 2) << " "
-      << PQgetvalue(result, 0, 3) << " "
-      << PQgetvalue(result, 0, 4) << " "
-      << PQgetvalue(result, 0, 5) << " "
-      << PQgetvalue(result, 0, 6) << " "
-      << PQgetvalue(result, 0, 7) << " "
-      << PQgetvalue(result, 0, 8) << " "
-      << PQgetvalue(result, 0, 9) << " "
-      << PQgetvalue(result, 0, 10);
-
-PQclear(result);
-
-tuple >> ac->priv.userConf
-      >> ac->priv.userPasswd
-      >> ac->priv.userStat
-      >> ac->priv.userCash
-      >> ac->priv.userAddDel
-      >> ac->priv.tariffChg
-      >> ac->priv.adminChg;
-
-if (CommitTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreAdmin(): 'Failed to commit transacion'\n");
-    return -1;
-    }
-
-if (ac->password == "")
-    {
-    return 0;
-    }
-
-Decode21(cryptedPass, ac->password.c_str());
-InitContext(adm_enc_passwd, sizeof(adm_enc_passwd), &ctx);
-for (int i = 0; i < ADM_PASSWD_LEN / 8; i++)
-    {
-    DecryptBlock(adminPass + 8 * i, cryptedPass + 8 * i, &ctx);
-    }
-ac->password = adminPass;
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::AddAdmin(const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::AddAdmin(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
-    if (Reset())
-        {
-        strError = "Connection lost";
-        printfd(__FILE__, "POSTGRESQL_STORE::AddAdmin(): '%s'\n", strError.c_str());
-        return -1;
-        }
-    }
-
-PGresult * result;
-
-if (StartTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::AddAdmin(): 'Failed to start transaction'\n");
-    return -1;
-    }
-
-std::string elogin = login;
-
-if (EscapeString(elogin))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::AddAdmin(): 'Failed to escape login'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::AddAdmin(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-std::ostringstream query;
-query << "INSERT INTO tb_admins \
-              (login, passwd, \
-              chg_conf, chg_password, chg_stat, \
-              chg_cash, usr_add_del, chg_tariff, \
-              chg_admin, chg_service, chg_corporation) \
-          VALUES "
-          << "('" << elogin << "', \
-              '', 0, 0, 0, 0, 0, 0, 0, 0, 0)";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_COMMAND_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    PQclear(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::AddAdmin(): '%s'\n", strError.c_str());
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::AddAdmin(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-PQclear(result);
-
-if (CommitTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::AddAdmin(): 'Failed to commit transaction'\n");
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::DelAdmin(const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::DelAdmin(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
-    if (Reset())
-        {
-        strError = "Connection lost";
-        printfd(__FILE__, "POSTGRESQL_STORE::DelAdmin(): '%s'\n", strError.c_str());
-        return -1;
-        }
-    }
-
-PGresult * result;
-
-if (StartTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::DelAdmin(): 'Failed to start transaction'\n");
-    return -1;
-    }
-
-std::string elogin = login;
-
-if (EscapeString(elogin))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::DelAdmin(): 'Failed to escape login'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::DelAdmin(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-std::ostringstream query;
-query << "DELETE FROM tb_admins WHERE login = '" << elogin << "'";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_COMMAND_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    PQclear(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::DelAdmin(): '%s'\n", strError.c_str());
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::DelAdmin(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-PQclear(result);
-
-if (CommitTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::DelAdmin(): 'Failed to commit transaction'\n");
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-
diff --git a/stargazer/plugins/store/postgresql/postgresql_store_corporations.cpp b/stargazer/plugins/store/postgresql/postgresql_store_corporations.cpp
deleted file mode 100644 (file)
index 1387d41..0000000
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-/*
- *  Corporations manipulation methods
- *
- *  $Revision: 1.2 $
- *  $Date: 2009/06/09 12:32:39 $
- *
- */
-
-#include "postgresql_store.h"
-
-#include "stg/corp_conf.h"
-#include "stg/locker.h"
-#include "stg/common.h"
-
-#include <string>
-#include <vector>
-#include <sstream>
-
-#include <libpq-fe.h>
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::GetCorpsList(std::vector<std::string> * corpsList) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::GetCorpsList(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
-    if (Reset())
-        {
-        strError = "Connection lost";
-        printfd(__FILE__, "POSTGRESQL_STORE::GetCorpsList(): '%s'\n", strError.c_str());
-        return -1;
-        }
-    }
-
-PGresult * result;
-
-if (StartTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::GetCorpsList(): 'Failed to start transaction'\n");
-    return -1;
-    }
-
-result = PQexec(connection, "SELECT name FROM tb_corporations");
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    PQclear(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::GetCorpsList(): '%s'\n", strError.c_str());
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::GetCorpsList(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-int tuples = PQntuples(result);
-
-for (int i = 0; i < tuples; ++i)
-    {
-    corpsList->push_back(PQgetvalue(result, i, 0));
-    }
-
-PQclear(result);
-
-if (CommitTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::GetCorpsList(): 'Failed to commit transaction'\n");
-    return -1;
-    }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::SaveCorp(const STG::CorpConf & cc) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveCorp(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
-    if (Reset())
-        {
-        strError = "Connection lost";
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveCorp(): '%s'\n", strError.c_str());
-        return -1;
-        }
-    }
-
-PGresult * result;
-
-if (StartTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveCorp(): 'Failed to start transaction'\n");
-    return -1;
-    }
-
-std::string ename = cc.name;
-
-if (EscapeString(ename))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveCorp(): 'Failed to escape name'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveCorp(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-std::ostringstream query;
-query << "UPDATE tb_corporations SET "
-          << "cash = " << cc.cash
-      << "WHERE name = '" << ename << "'";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_COMMAND_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    PQclear(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveCorp(): '%s'\n", strError.c_str());
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveCorp(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-PQclear(result);
-
-if (CommitTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveCorp(): 'Failed to commit transaction'\n");
-    return -1;
-    }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::RestoreCorp(STG::CorpConf * cc, const std::string & name) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
-    if (Reset())
-        {
-        strError = "Connection lost";
-        printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): '%s'\n", strError.c_str());
-        return -1;
-        }
-    }
-
-PGresult * result;
-
-if (StartTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): 'Failed to start transaction'\n");
-    return -1;
-    }
-
-std::string ename = name;
-
-if (EscapeString(ename))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): 'Failed to escape name'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-std::ostringstream query;
-query << "SELECT cash FROM tb_corporations WHERE name = '" << ename << "'";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    PQclear(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): '%s'\n", strError.c_str());
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-int tuples = PQntuples(result);
-
-if (tuples != 1)
-    {
-    strError = "Failed to fetch corp's data";
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
-    PQclear(result);
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-std::stringstream tuple;
-tuple << PQgetvalue(result, 0, 0);
-
-PQclear(result);
-
-tuple >> cc->cash;
-
-if (CommitTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreCorp(): 'Failed to commit transaction'\n");
-    return -1;
-    }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::AddCorp(const std::string & name) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::AddCorp(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
-    if (Reset())
-        {
-        strError = "Connection lost";
-        printfd(__FILE__, "POSTGRESQL_STORE::AddCorp(): '%s'\n", strError.c_str());
-        return -1;
-        }
-    }
-
-PGresult * result;
-
-if (StartTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::AddCorp(): 'Failed to start transaction'\n");
-    return -1;
-    }
-
-std::string ename = name;
-
-if (EscapeString(ename))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::AddCorp(): 'Failed to escape name'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::AddCorp(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-std::ostringstream query;
-query << "INSERT INTO tb_corporations \
-              (name, cash) \
-          VALUES \
-              ('" << ename << "', 0)";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_COMMAND_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    PQclear(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::AddCorp(): '%s'\n", strError.c_str());
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::AddCorp(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-PQclear(result);
-
-if (CommitTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::AddCorp(): 'Failed to commit transaction'\n");
-    return -1;
-    }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::DelCorp(const std::string & name) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::DelCorp(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
-    if (Reset())
-        {
-        strError = "Connection lost";
-        printfd(__FILE__, "POSTGRESQL_STORE::DelCorp(): '%s'\n", strError.c_str());
-        return -1;
-        }
-    }
-
-PGresult * result;
-
-if (StartTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::DelCorp(): 'Failed to start transaction'\n");
-    return -1;
-    }
-
-std::string ename = name;
-
-if (EscapeString(ename))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::DelCorp(): 'Failed to escape name'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::DelCorp(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-std::ostringstream query;
-query << "DELETE FROM tb_corporations WHERE name = '" << ename << "'";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_COMMAND_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    PQclear(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::DelCorp(): '%s'\n", strError.c_str());
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::DelCorp(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-PQclear(result);
-
-if (CommitTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::DelCorp(): 'Failed to commit transaction'\n");
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-
diff --git a/stargazer/plugins/store/postgresql/postgresql_store_messages.cpp b/stargazer/plugins/store/postgresql/postgresql_store_messages.cpp
deleted file mode 100644 (file)
index 905b467..0000000
+++ /dev/null
@@ -1,455 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-
-/*
- *  Messages manipualtion methods
- *
- *  $Revision: 1.6 $
- *  $Date: 2009/07/15 11:19:42 $
- *
- */
-
-#include "postgresql_store.h"
-
-#include "stg/common.h"
-#include "stg/locker.h"
-#include "stg/message.h"
-
-#include <string>
-#include <vector>
-#include <sstream>
-
-#include <libpq-fe.h>
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::AddMessage(STG::Message * msg, const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
-    if (Reset())
-        {
-        strError = "Connection lost";
-        printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): '%s'\n", strError.c_str());
-        return -1;
-        }
-    }
-
-PGresult * result;
-
-if (StartTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Failed to start transaction'\n");
-    return -1;
-    }
-
-std::string elogin = login;
-std::string etext = msg->text;
-
-if (EscapeString(elogin))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Failed to escape login'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-if (EscapeString(etext))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Failed to escape message text'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-std::ostringstream query;
-query << "SELECT sp_add_message("
-      << "'" << elogin << "', "
-      << "CAST(1 AS SMALLINT), " // Here need to be a version, but, it's uninitiated actually
-      << "CAST(" << msg->header.type << " AS SMALLINT), "
-      << "CAST('" << formatTime(msg->header.lastSendTime) << "' AS TIMESTAMP), "
-      << "CAST('" << formatTime(msg->header.creationTime) << "' AS TIMESTAMP), "
-      << msg->header.showTime << ", "
-      << "CAST(" << msg->header.repeat << " AS SMALLINT), "
-      << msg->header.repeatPeriod << ", "
-      << "'" << etext << "')";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    PQclear(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): '%s'\n", strError.c_str());
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-int tuples = PQntuples(result);
-
-if (tuples != 1)
-    {
-    strError = "Failed to fetch newlly added message ID";
-    printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
-    PQclear(result);
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-std::stringstream tuple;
-tuple << PQgetvalue(result, 0, 0);
-
-PQclear(result);
-
-tuple >> msg->header.id;
-
-if (CommitTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::AddMessage(): 'Failed to commit transaction'\n");
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::EditMessage(const STG::Message & msg,
-                                  const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
-    if (Reset())
-        {
-        strError = "Connection lost";
-        printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): '%s'\n", strError.c_str());
-        return -1;
-        }
-    }
-
-PGresult * result;
-
-if (StartTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): 'Failed to start transaction'\n");
-    return -1;
-    }
-
-std::string elogin = login;
-std::string etext = msg.text;
-
-if (EscapeString(elogin))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): 'Failed to escape login'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-if (EscapeString(etext))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): 'Failed to escape message text'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-std::ostringstream query;
-query << "UPDATE tb_messages SET "
-          << "fk_user = (SELECT pk_user FROM tb_users WHERE name = '" << elogin << "'), "
-          << "ver = " << msg.header.ver << ", "
-          << "msg_type = " << msg.header.type << ", "
-          << "last_send_time = CAST('" << formatTime(msg.header.lastSendTime) << "' AS TIMESTAMP), "
-          << "creation_time = CAST('" << formatTime(msg.header.creationTime) << "' AS TIMESTAMP), "
-          << "show_time = " << msg.header.showTime << ", "
-          << "repeat = " << msg.header.repeat << ", "
-          << "repeat_period = " << msg.header.repeatPeriod << ", "
-          << "msg_text = '" << etext << "' "
-      << "WHERE pk_message = " << msg.header.id;
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_COMMAND_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    PQclear(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): '%s'\n", strError.c_str());
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-PQclear(result);
-
-if (CommitTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::EditMessage(): 'Failed to commit transaction'\n");
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::GetMessage(uint64_t id,
-                                 STG::Message * msg,
-                                 const std::string &) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::GetMessage(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
-    if (Reset())
-        {
-        strError = "Connection lost";
-        printfd(__FILE__, "POSTGRESQL_STORE::GetMessage(): '%s'\n", strError.c_str());
-        return -1;
-        }
-    }
-
-PGresult * result;
-
-if (StartTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::GetMessage(): 'Failed to start transaction'\n");
-    return -1;
-    }
-
-std::ostringstream query;
-query << "SELECT ver, msg_type, last_send_time, \
-                 creation_time, show_time, repeat, \
-                 repeat_period, msg_text \
-          FROM tb_messages \
-          WHERE pk_message = " << id;
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    PQclear(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::GetMessage(): '%s'\n", strError.c_str());
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::GetMessage(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-int tuples = PQntuples(result);
-
-if (tuples != 1)
-    {
-    strError = "Failed to fetch message data";
-    printfd(__FILE__, "POSTGRESQL_STORE::GetMessage(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
-    PQclear(result);
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::GetMessage(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-str2x(PQgetvalue(result, 0, 0), msg->header.ver);
-str2x(PQgetvalue(result, 0, 1), msg->header.type);
-msg->header.lastSendTime = static_cast<unsigned int>(readTime(PQgetvalue(result, 0, 2)));
-msg->header.creationTime = static_cast<unsigned int>(readTime(PQgetvalue(result, 0, 3)));
-str2x(PQgetvalue(result, 0, 4), msg->header.showTime);
-str2x(PQgetvalue(result, 0, 5), msg->header.repeat);
-str2x(PQgetvalue(result, 0, 6), msg->header.repeatPeriod);
-msg->text = PQgetvalue(result, 0, 7);
-
-PQclear(result);
-
-if (CommitTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::GetMessage(): 'Failed to commit transaction'\n");
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::DelMessage(uint64_t id, const std::string &) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::DelMessage(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
-    if (Reset())
-        {
-        strError = "Connection lost";
-        printfd(__FILE__, "POSTGRESQL_STORE::DelMessage(): '%s'\n", strError.c_str());
-        return -1;
-        }
-    }
-
-PGresult * result;
-
-if (StartTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::DelMessage(): 'Failed to start transaction'\n");
-    return -1;
-    }
-
-std::ostringstream query;
-query << "DELETE FROM tb_messages WHERE pk_message = " << id;
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_COMMAND_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    PQclear(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::DelMessage(): '%s'\n", strError.c_str());
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::DelMessage(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-PQclear(result);
-
-if (CommitTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::DelMessage(): 'Failed to commit transaction'\n");
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::GetMessageHdrs(std::vector<STG::Message::Header> * hdrsList,
-                                   const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::GetMessageHdrs(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
-    if (Reset())
-        {
-        strError = "Connection lost";
-        printfd(__FILE__, "POSTGRESQL_STORE::GetMessageHdrs(): '%s'\n", strError.c_str());
-        return -1;
-        }
-    }
-
-PGresult * result;
-
-if (StartTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::GetMessageHdrs(): 'Failed to start transaction'\n");
-    return -1;
-    }
-
-std::string elogin = login;
-
-if (EscapeString(elogin))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::GetMessageHdrs(): 'Failed to escape login'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::GetMessageHdrs(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-std::ostringstream query;
-query << "SELECT pk_message, ver, msg_type, \
-                 last_send_time, creation_time, show_time, \
-                 repeat, repeat_period \
-          FROM tb_messages \
-          WHERE fk_user IN \
-                (SELECT pk_user FROM tb_users \
-          WHERE name = '" << elogin << "')";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    PQclear(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::GetMessageHdrs(): '%s'\n", strError.c_str());
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::GetMessageHdrs(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-int tuples = PQntuples(result);
-
-for (int i = 0; i < tuples; ++i)
-    {
-    std::stringstream tuple;
-    STG::Message::Header header;
-    tuple << PQgetvalue(result, i, 0) << " ";
-    tuple << PQgetvalue(result, i, 1) << " ";
-    tuple << PQgetvalue(result, i, 2) << " ";
-    header.lastSendTime = static_cast<unsigned int>(readTime(PQgetvalue(result, i, 3)));
-    header.creationTime = static_cast<unsigned int>(readTime(PQgetvalue(result, i, 4)));
-    tuple << PQgetvalue(result, i, 5) << " ";
-    tuple << PQgetvalue(result, i, 6) << " ";
-    tuple << PQgetvalue(result, i, 7) << " ";
-
-    tuple >> header.id;
-    tuple >> header.ver;
-    tuple >> header.type;
-    tuple >> header.showTime;
-    tuple >> header.repeat;
-    tuple >> header.repeatPeriod;
-    hdrsList->push_back(header);
-    }
-
-PQclear(result);
-
-if (CommitTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::GetMessageHdrs(): 'Failed to commit transaction'\n");
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-
diff --git a/stargazer/plugins/store/postgresql/postgresql_store_services.cpp b/stargazer/plugins/store/postgresql/postgresql_store_services.cpp
deleted file mode 100644 (file)
index 3d09816..0000000
+++ /dev/null
@@ -1,396 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-
-/*
- *  Services manipulation methods
- *
- *  $Revision: 1.2 $
- *  $Date: 2009/06/09 12:32:40 $
- *
- */
-
-#include "postgresql_store.h"
-
-#include "stg/service_conf.h"
-#include "stg/common.h"
-#include "stg/locker.h"
-
-#include <string>
-#include <vector>
-#include <sstream>
-
-#include <libpq-fe.h>
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::GetServicesList(std::vector<std::string> * servicesList) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::GetServicesList(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
-    if (Reset())
-        {
-        strError = "Connection lost";
-        printfd(__FILE__, "POSTGRESQL_STORE::GetServicesList(): '%s'\n", strError.c_str());
-        return -1;
-        }
-    }
-
-PGresult * result;
-
-if (StartTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::GetServicesList(): 'Failed to start transaction'\n");
-    return -1;
-    }
-
-result = PQexec(connection, "SELECT name FROM tb_services");
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    PQclear(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::GetServicesList(): '%s'\n", strError.c_str());
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::GetServicesList(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-int tuples = PQntuples(result);
-
-for (int i = 0; i < tuples; ++i)
-    {
-    servicesList->push_back(PQgetvalue(result, i, 0));
-    }
-
-PQclear(result);
-
-if (CommitTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::GetServicesList(): 'Failed to commit transaction'\n");
-    return -1;
-    }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::SaveService(const STG::ServiceConf & sc) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
-    if (Reset())
-        {
-        strError = "Connection lost";
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): '%s'\n", strError.c_str());
-        return -1;
-        }
-    }
-
-PGresult * result;
-
-if (StartTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to start transaction'\n");
-    return -1;
-    }
-
-std::string ename = sc.name;
-std::string ecomment = sc.comment;
-
-if (EscapeString(ename))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to escape name'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-if (EscapeString(ecomment))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to escape comment'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-std::ostringstream query;
-query << "UPDATE tb_services SET "
-          << "comment = '" << ecomment << "', "
-          << "cost = " << sc.cost << ", "
-          << "pay_day = " << sc.payDay << " "
-      << "WHERE name = '" << ename << "'";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_COMMAND_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    PQclear(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): '%s'\n", strError.c_str());
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-PQclear(result);
-
-if (CommitTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveService(): 'Failed to commit transaction'\n");
-    return -1;
-    }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::RestoreService(STG::ServiceConf * sc,
-                                     const std::string & name) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
-    if (Reset())
-        {
-        strError = "Connection lost";
-        printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): '%s'\n", strError.c_str());
-        return -1;
-        }
-    }
-
-PGresult * result;
-
-if (StartTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Failed to start transaction'\n");
-    return -1;
-    }
-
-std::string ename = name;
-
-if (EscapeString(ename))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Failed to escape name'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-std::ostringstream query;
-query << "SELECT comment, cost, pay_day FROM tb_services WHERE name = '" << ename << "'";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    PQclear(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): '%s'\n", strError.c_str());
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-int tuples = PQntuples(result);
-
-if (tuples != 1)
-    {
-    strError = "Failed to fetch service's data";
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
-    PQclear(result);
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-std::stringstream tuple;
-tuple << PQgetvalue(result, 0, 0) << " "
-      << PQgetvalue(result, 0, 1) << " "
-      << PQgetvalue(result, 0, 2);
-
-PQclear(result);
-
-tuple >> sc->comment
-      >> sc->cost
-      >> sc->payDay;
-
-if (CommitTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreService(): 'Failed to commit transaction'\n");
-    return -1;
-    }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::AddService(const std::string & name) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::AddService(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
-    if (Reset())
-        {
-        strError = "Connection lost";
-        printfd(__FILE__, "POSTGRESQL_STORE::AddService(): '%s'\n", strError.c_str());
-        return -1;
-        }
-    }
-
-PGresult * result;
-
-if (StartTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::AddService(): 'Failed to start transaction'\n");
-    return -1;
-    }
-
-std::string ename = name;
-
-if (EscapeString(ename))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::AddService(): 'Failed to escape name'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::AddService(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-std::ostringstream query;
-query << "INSERT INTO tb_services \
-              (name, comment, cost, pay_day) \
-          VALUES \
-              ('" << ename << "', '', 0, 0)";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_COMMAND_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    PQclear(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::AddService(): '%s'\n", strError.c_str());
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::AddService(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-PQclear(result);
-
-if (CommitTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::AddService(): 'Failed to commit transaction'\n");
-    return -1;
-    }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::DelService(const std::string & name) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::DelService(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
-    if (Reset())
-        {
-        strError = "Connection lost";
-        printfd(__FILE__, "POSTGRESQL_STORE::DelService(): '%s'\n", strError.c_str());
-        return -1;
-        }
-    }
-
-PGresult * result;
-
-if (StartTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::DelService(): 'Failed to start transaction'\n");
-    return -1;
-    }
-
-std::string ename = name;
-
-if (EscapeString(ename))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::DelService(): 'Failed to escape name'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::DelService(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-std::ostringstream query;
-query << "DELETE FROM tb_services WHERE name = '" << ename << "'";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_COMMAND_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    PQclear(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::DelService(): '%s'\n", strError.c_str());
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::DelService(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-PQclear(result);
-
-if (CommitTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::DelService(): 'Failed to commit transaction'\n");
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-
diff --git a/stargazer/plugins/store/postgresql/postgresql_store_tariffs.cpp b/stargazer/plugins/store/postgresql/postgresql_store_tariffs.cpp
deleted file mode 100644 (file)
index 6a67598..0000000
+++ /dev/null
@@ -1,629 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-/*
- *  Tariffs manipulation methods
- *
- *  $Revision: 1.2 $
- *  $Date: 2009/06/09 12:32:40 $
- *
- */
-
-#include "postgresql_store.h"
-
-#include "stg/tariff_conf.h"
-#include "stg/common.h"
-#include "stg/locker.h"
-
-#include <string>
-#include <vector>
-#include <sstream>
-#include <cmath>
-
-#include <libpq-fe.h>
-
-namespace
-{
-
-const int pt_mega = 1024 * 1024;
-
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::GetTariffsList(std::vector<std::string> * tariffsList) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
-    if (Reset())
-        {
-        strError = "Connection lost";
-        printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): '%s'\n", strError.c_str());
-        return -1;
-        }
-    }
-
-PGresult * result;
-
-if (StartTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): 'Failed to start transaction'\n");
-    return -1;
-    }
-
-result = PQexec(connection, "SELECT name FROM tb_tariffs");
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    PQclear(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): '%s'\n", strError.c_str());
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-int tuples = PQntuples(result);
-
-for (int i = 0; i < tuples; ++i)
-    {
-    tariffsList->push_back(PQgetvalue(result, i, 0));
-    }
-
-PQclear(result);
-
-if (CommitTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::GetTariffsList(): 'Failed to commit transaction'\n");
-    return -1;
-    }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::AddTariff(const std::string & name) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
-    if (Reset())
-        {
-        strError = "Connection lost";
-        printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): '%s'\n", strError.c_str());
-        return -1;
-        }
-    }
-
-PGresult * result;
-
-if (StartTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to start transaction'\n");
-    return -1;
-    }
-
-std::string ename = name;
-
-if (EscapeString(ename))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to escape name'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-std::ostringstream query;
-query << "SELECT sp_add_tariff('" << ename << "', " << DIR_NUM << ")";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    PQclear(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): '%s'\n", strError.c_str());
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-PQclear(result);
-
-if (CommitTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to commit transaction'\n");
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::DelTariff(const std::string & name) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
-    if (Reset())
-        {
-        strError = "Connection lost";
-        printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): '%s'\n", strError.c_str());
-        return -1;
-        }
-    }
-
-PGresult * result;
-
-if (StartTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): 'Failed to start transaction'\n");
-    return -1;
-    }
-
-std::string ename = name;
-
-if (EscapeString(ename))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to escape name'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::AddTariff(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-std::ostringstream query;
-query << "DELETE FROM tb_tariffs WHERE name = '" << ename << "'";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_COMMAND_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    PQclear(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): '%s'\n", strError.c_str());
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-PQclear(result);
-
-if (CommitTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::DelTariff(): 'Failed to commit transaction'\n");
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::SaveTariff(const STG::TariffData & td,
-                                 const std::string & tariffName) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
-    if (Reset())
-        {
-        strError = "Connection lost";
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): '%s'\n", strError.c_str());
-        return -1;
-        }
-    }
-
-PGresult * result;
-
-if (StartTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to start transaction'\n");
-    return -1;
-    }
-
-std::string ename = tariffName;
-
-if (EscapeString(ename))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to escape name'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-    {
-    std::ostringstream query;
-    query << "SELECT pk_tariff FROM tb_tariffs WHERE name = '" << ename << "'";
-
-    result = PQexec(connection, query.str().c_str());
-    }
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    PQclear(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): '%s'\n", strError.c_str());
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-int tuples = PQntuples(result);
-
-if (tuples != 1)
-    {
-    strError = "Failed to fetch tariff ID";
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
-    PQclear(result);
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-int32_t id;
-
-    {
-    std::stringstream tuple;
-    tuple << PQgetvalue(result, 0, 0);
-
-    PQclear(result);
-
-    tuple >> id;
-    }
-
-    {
-    std::ostringstream query;
-    query << "UPDATE tb_tariffs SET \
-                  fee = " << td.tariffConf.fee << ", \
-                  free = " << td.tariffConf.free << ", \
-                  passive_cost = " << td.tariffConf.passiveCost << ", \
-                  traff_type = " << td.tariffConf.traffType;
-
-    if (version > 6)
-        query << ", period = '" << STG::Tariff::toString(td.tariffConf.period) << "'";
-
-    if (version > 7)
-        query << ", change_policy = '" << STG::Tariff::toString(td.tariffConf.changePolicy) << "', \
-                  change_policy_timeout = CAST('" << formatTime(td.tariffConf.changePolicyTimeout) << "' AS TIMESTAMP)";
-
-    query << " WHERE pk_tariff = " << id;
-
-    result = PQexec(connection, query.str().c_str());
-    }
-
-if (PQresultStatus(result) != PGRES_COMMAND_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    PQclear(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): '%s'\n", strError.c_str());
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-PQclear(result);
-
-for(int i = 0; i < DIR_NUM; i++)
-    {
-    double pda = td.dirPrice[i].priceDayA * 1024 * 1024;
-    double pdb = td.dirPrice[i].priceDayB * 1024 * 1024;
-    double pna = 0;
-    double pnb = 0;
-
-    if (td.dirPrice[i].singlePrice)
-        {
-        pna = pda;
-        pnb = pdb;
-        }
-    else
-        {
-        pna = td.dirPrice[i].priceNightA * 1024 * 1024;
-        pnb = td.dirPrice[i].priceNightB * 1024 * 1024;
-        }
-
-    int threshold = 0;
-    if (td.dirPrice[i].noDiscount)
-        {
-        threshold = 0xffFFffFF;
-        }
-    else
-        {
-        threshold = td.dirPrice[i].threshold;
-        }
-
-        {
-        std::ostringstream query;
-        query << "UPDATE tb_tariffs_params SET \
-                      price_day_a = " << pda << ", \
-                      price_day_b = " << pdb << ", \
-                      price_night_a = " << pna << ", \
-                      price_night_b = " << pnb << ", \
-                      threshold = " << threshold << ", \
-                      time_day_begins = CAST('" << td.dirPrice[i].hDay
-                                                << ":"
-                                                << td.dirPrice[i].mDay << "' AS TIME), \
-                      time_day_ends = CAST('" << td.dirPrice[i].hNight
-                                              << ":"
-                                              << td.dirPrice[i].mNight << "' AS TIME) \
-                 WHERE fk_tariff = " << id << " AND dir_num = " << i;
-
-        result = PQexec(connection, query.str().c_str());
-        }
-
-    if (PQresultStatus(result) != PGRES_COMMAND_OK)
-        {
-        strError = PQresultErrorMessage(result);
-        PQclear(result);
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): '%s'\n", strError.c_str());
-        if (RollbackTransaction())
-            {
-            printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to rollback transaction'\n");
-            }
-        return -1;
-        }
-
-    PQclear(result);
-    }
-
-if (CommitTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveTariff(): 'Failed to commit transaction'\n");
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::RestoreTariff(STG::TariffData * td,
-                                    const std::string & tariffName) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
-    if (Reset())
-        {
-        strError = "Connection lost";
-        printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): '%s'\n", strError.c_str());
-        return -1;
-        }
-    }
-
-PGresult * result;
-
-if (StartTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to start transaction'\n");
-    return -1;
-    }
-
-std::string ename = tariffName;
-
-if (EscapeString(ename))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to escape name'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-td->tariffConf.name = tariffName;
-
-std::ostringstream query;
-query << "SELECT pk_tariff, \
-                 fee, \
-                 free, \
-                 passive_cost, \
-                 traff_type";
-
-if (version > 6)
-    query << ", period";
-
-if (version > 7)
-    query << ", change_policy \
-              , change_policy_timeout";
-
-query << " FROM tb_tariffs WHERE name = '" << ename << "'";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    PQclear(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): '%s'\n", strError.c_str());
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-int tuples = PQntuples(result);
-
-if (tuples != 1)
-    {
-    strError = "Failed to fetch tariff data";
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
-    PQclear(result);
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-int id;
-
-    {
-    std::stringstream tuple;
-    tuple << PQgetvalue(result, 0, 0) << " ";
-    tuple << PQgetvalue(result, 0, 1) << " ";
-    tuple << PQgetvalue(result, 0, 2) << " ";
-    tuple << PQgetvalue(result, 0, 3) << " ";
-    tuple << PQgetvalue(result, 0, 4) << " ";
-
-    tuple >> id;
-    tuple >> td->tariffConf.fee;
-    tuple >> td->tariffConf.free;
-    tuple >> td->tariffConf.passiveCost;
-    unsigned traffType;
-    tuple >> traffType;
-    td->tariffConf.traffType = static_cast<STG::Tariff::TraffType>(traffType);
-    }
-
-if (version > 6)
-    td->tariffConf.period = STG::Tariff::parsePeriod(PQgetvalue(result, 0, 5));
-
-if (version > 7)
-    {
-    td->tariffConf.changePolicy = STG::Tariff::parseChangePolicy(PQgetvalue(result, 0, 6));
-    td->tariffConf.changePolicyTimeout = readTime(PQgetvalue(result, 0, 7));
-    }
-
-PQclear(result);
-
-query.str("");
-query << "SELECT dir_num, \
-                 price_day_a, \
-                 price_day_b, \
-                 price_night_a, \
-                 price_night_b, \
-                 threshold, \
-                 EXTRACT(hour FROM time_day_begins), \
-                 EXTRACT(minute FROM time_day_begins), \
-                 EXTRACT(hour FROM time_day_ends), \
-                 EXTRACT(minute FROM time_day_ends) \
-          FROM tb_tariffs_params \
-          WHERE fk_tariff = " << id;
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    PQclear(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): '%s'\n", strError.c_str());
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-tuples = PQntuples(result);
-
-if (tuples != DIR_NUM)
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Tariff params count and DIR_NUM does not feet (wanted %d, actually %d)'\n", DIR_NUM, tuples);
-    }
-
-for (int i = 0; i < std::min(tuples, DIR_NUM); ++i)
-    {
-    int dir;
-
-        {
-        std::stringstream tuple;
-        tuple << PQgetvalue(result, i, 0) << " ";
-        tuple << PQgetvalue(result, i, 1) << " ";
-        tuple << PQgetvalue(result, i, 2) << " ";
-        tuple << PQgetvalue(result, i, 3) << " ";
-        tuple << PQgetvalue(result, i, 4) << " ";
-        tuple << PQgetvalue(result, i, 5) << " ";
-        tuple << PQgetvalue(result, i, 6) << " ";
-        tuple << PQgetvalue(result, i, 7) << " ";
-        tuple << PQgetvalue(result, i, 8) << " ";
-        tuple << PQgetvalue(result, i, 9) << " ";
-
-        tuple >> dir;
-        tuple >> td->dirPrice[dir].priceDayA;
-        td->dirPrice[dir].priceDayA /= 1024 * 1024;
-        tuple >> td->dirPrice[dir].priceDayB;
-        td->dirPrice[dir].priceDayB /= 1024 * 1024;
-        tuple >> td->dirPrice[dir].priceNightA;
-        td->dirPrice[dir].priceNightA /= 1024 * 1024;
-        tuple >> td->dirPrice[dir].priceNightB;
-        td->dirPrice[dir].priceNightB /= 1024 * 1024;
-        tuple >> td->dirPrice[dir].threshold;
-        tuple >> td->dirPrice[dir].hDay;
-        tuple >> td->dirPrice[dir].mDay;
-        tuple >> td->dirPrice[dir].hNight;
-        tuple >> td->dirPrice[dir].mNight;
-        }
-
-    if (std::fabs(td->dirPrice[dir].priceDayA - td->dirPrice[dir].priceNightA) < 1.0e-3 / pt_mega &&
-        std::fabs(td->dirPrice[dir].priceDayB - td->dirPrice[dir].priceNightB) < 1.0e-3 / pt_mega)
-        {
-        td->dirPrice[dir].singlePrice = true;
-        }
-    else
-        {
-        td->dirPrice[dir].singlePrice = false;
-        }
-    if (td->dirPrice[dir].threshold == (int)0xffFFffFF)
-        {
-        td->dirPrice[dir].noDiscount = true;
-        }
-    else
-        {
-
-        td->dirPrice[dir].noDiscount = false;
-        }
-
-    }
-
-PQclear(result);
-
-if (CommitTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreTariff(): 'Failed to commit transaction'\n");
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-
diff --git a/stargazer/plugins/store/postgresql/postgresql_store_users.cpp b/stargazer/plugins/store/postgresql/postgresql_store_users.cpp
deleted file mode 100644 (file)
index 6919ed0..0000000
+++ /dev/null
@@ -1,1591 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-/*
- *  User manipulation methods
- *
- *  $Revision: 1.14 $
- *  $Date: 2010/05/07 07:26:36 $
- *
- */
-
-#include "postgresql_store.h"
-
-#include "stg/user_conf.h"
-#include "stg/user_stat.h"
-#include "stg/user_ips.h"
-#include "stg/user_traff.h"
-#include "stg/common.h"
-#include "stg/const.h"
-#include "stg/locker.h"
-#include "../../../stg_timer.h"
-
-#include <string>
-#include <vector>
-#include <sstream>
-#include <ctime>
-
-#include <libpq-fe.h>
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::GetUsersList(std::vector<std::string> * usersList) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::GetUsersList(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
-    if (Reset())
-        {
-        strError = "Connection lost";
-        printfd(__FILE__, "POSTGRESQL_STORE::GetUsersList(): '%s'\n", strError.c_str());
-        return -1;
-        }
-    }
-
-PGresult * result;
-
-if (StartTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::GetUsersList(): 'Failed to start transaction'\n");
-    return -1;
-    }
-
-result = PQexec(connection, "SELECT name FROM tb_users");
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    PQclear(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::GetUsersList(): '%s'\n", strError.c_str());
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::GetUsersList(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-int tuples = PQntuples(result);
-
-for (int i = 0; i < tuples; ++i)
-    {
-    usersList->push_back(PQgetvalue(result, i, 0));
-    }
-
-PQclear(result);
-
-if (CommitTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::GetUsersList(): 'Failed to commit transaction'\n");
-    return -1;
-    }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::AddUser(const std::string & name) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::AddUser(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
-    if (Reset())
-        {
-        strError = "Connection lost";
-        printfd(__FILE__, "POSTGRESQL_STORE::AddUser(): '%s'\n", strError.c_str());
-        return -1;
-        }
-    }
-
-PGresult * result;
-
-if (StartTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::AddUser(): 'Failed to start transaction'\n");
-    return -1;
-    }
-
-std::string elogin = name;
-
-if (EscapeString(elogin))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::AddUser(): 'Failed to escape login'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::AddUser(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-std::ostringstream query;
-query << "SELECT sp_add_user('" << elogin << "')";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    PQclear(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::AddUser(): '%s'\n", strError.c_str());
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::AddUser(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-PQclear(result);
-
-if (CommitTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::AddUser(): 'Failed to commit transaction'\n");
-    return -1;
-    }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::DelUser(const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::DelUser(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
-    if (Reset())
-        {
-        strError = "Connection lost";
-        printfd(__FILE__, "POSTGRESQL_STORE::DelUser(): '%s'\n", strError.c_str());
-        return -1;
-        }
-    }
-
-PGresult * result;
-
-if (StartTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::DelUser(): 'Failed to start transaction'\n");
-    return -1;
-    }
-
-std::string elogin = login;
-
-if (EscapeString(elogin))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::DelUser(): 'Failed to escape login'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::DelUser(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-std::ostringstream query;
-query << "DELETE FROM tb_users WHERE name = '" << elogin << "'";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_COMMAND_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    PQclear(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::DelUser(): '%s'\n", strError.c_str());
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::DelUser(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-PQclear(result);
-
-if (CommitTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::DelUser(): 'Failed to commit transaction'\n");
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::SaveUserStat(const STG::UserStat & stat,
-                                   const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-return SaveStat(stat, login);
-}
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::SaveStat(const STG::UserStat & stat,
-                               const std::string & login,
-                               int year,
-                               int month) const
-{
-if (PQstatus(connection) != CONNECTION_OK)
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
-    if (Reset())
-        {
-        strError = "Connection lost";
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): '%s'\n", strError.c_str());
-        return -1;
-        }
-    }
-
-PGresult * result;
-
-if (StartTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Failed to start transaction'\n");
-    return -1;
-    }
-
-std::string elogin = login;
-
-if (EscapeString(elogin))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Failed to escape login'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-std::ostringstream query;
-query << "UPDATE tb_users SET "
-            "cash = " << stat.cash << ", "
-            "free_mb = " << stat.freeMb << ", "
-            "last_activity_time = CAST('" << formatTime(stat.lastActivityTime) << "' AS TIMESTAMP), "
-            "last_cash_add = " << stat.lastCashAdd << ", "
-            "last_cash_add_time = CAST('" << formatTime(stat.lastCashAddTime) << "' AS TIMESTAMP), "
-            "passive_time = " << stat.passiveTime << " "
-         "WHERE name = '" << elogin << "'";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_COMMAND_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    PQclear(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): '%s'\n", strError.c_str());
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-PQclear(result);
-
-std::string date;
-
-MakeDate(date, year, month);
-
-for (int dir = 0; dir < DIR_NUM; ++dir)
-    {
-    query.str("");
-    query << "SELECT sp_add_stats_traffic ("
-                "'" << elogin << "', "
-                "CAST('" << date << "' AS DATE), "
-                "CAST(" << dir << " AS SMALLINT), "
-                "CAST(" << stat.monthUp[dir] << " AS BIGINT), "
-                "CAST(" << stat.monthDown[dir] << " AS BIGINT))";
-
-    result = PQexec(connection, query.str().c_str());
-
-    if (PQresultStatus(result) != PGRES_TUPLES_OK)
-        {
-        strError = PQresultErrorMessage(result);
-        PQclear(result);
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): '%s'\n", strError.c_str());
-        if (RollbackTransaction())
-            {
-            printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Failed to rollback transaction'\n");
-            }
-        return -1;
-        }
-
-    PQclear(result);
-    }
-
-if (CommitTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveStat(): 'Failed to commit transaction'\n");
-    return -1;
-    }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::SaveUserConf(const STG::UserConf & conf,
-                                 const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
-    if (Reset())
-        {
-        strError = "Connection lost";
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): '%s'\n", strError.c_str());
-        return -1;
-        }
-    }
-
-PGresult * result;
-
-if (StartTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to start transaction'\n");
-    return -1;
-    }
-
-std::string elogin = login;
-
-if (EscapeString(elogin))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape login'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-std::ostringstream query;
-query << "SELECT pk_user FROM tb_users WHERE name = '" << elogin << "'";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    PQclear(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): '%s'\n", strError.c_str());
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-int tuples = PQntuples(result);
-
-if (tuples != 1)
-    {
-    strError = "Failed to fetch user's ID";
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
-    PQclear(result);
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-uint32_t uid;
-
-    {
-    std::stringstream tuple;
-    tuple << PQgetvalue(result, 0, 0);
-
-    PQclear(result);
-
-    tuple >> uid;
-    }
-
-std::string eaddress = conf.address;
-std::string eemail = conf.email;
-std::string egroup = conf.group;
-std::string enote = conf.note;
-std::string epassword = conf.password;
-std::string ephone = conf.phone;
-std::string erealname = conf.realName;
-std::string etariffname = conf.tariffName;
-std::string enexttariff = conf.nextTariff;
-std::string ecorporation = conf.corp;
-
-if (EscapeString(eaddress))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape address'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-if (EscapeString(eemail))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape email'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-if (EscapeString(egroup))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape group'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-if (EscapeString(enote))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape note'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-if (EscapeString(epassword))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape password'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-if (EscapeString(ephone))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape phone'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-if (EscapeString(erealname))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape real name'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-if (EscapeString(etariffname))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape tariff name'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-if (EscapeString(enexttariff))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape next tariff name'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-if (EscapeString(ecorporation))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to escape corporation name'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-query.str("");
-query << "UPDATE tb_users SET "
-             "address = '" << eaddress << "', "
-             "always_online = " << (conf.alwaysOnline ? "'t'" : "'f'") << ", "
-             "credit = " << conf.credit << ", "
-             "credit_expire = CAST('" << formatTime(conf.creditExpire) << "' AS TIMESTAMP), "
-             "disabled = " << (conf.disabled ? "'t'" : "'f'") << ", "
-             "disabled_detail_stat = " << (conf.disabledDetailStat ? "'t'" : "'f'") << ", "
-             "email = '" << eemail << "', "
-             "grp = '" << egroup << "', "
-             "note = '" << enote << "', "
-             "passive = " << (conf.passive ? "'t'" : "'f'") << ", "
-             "passwd = '" << epassword << "', "
-             "phone = '" << ephone << "', "
-             "real_name = '" << erealname << "', "
-             "fk_tariff = (SELECT pk_tariff "
-                   "FROM tb_tariffs "
-                   "WHERE name = '" << etariffname << "'), "
-             "fk_tariff_change = (SELECT pk_tariff "
-                   "FROM tb_tariffs "
-                   "WHERE name = '" << enexttariff << "'), "
-             "fk_corporation = (SELECT pk_corporation "
-                   "FROM tb_corporations "
-                   "WHERE name = '" << ecorporation << "') "
-         "WHERE pk_user = " << uid;
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_COMMAND_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    PQclear(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): '%s'\n", strError.c_str());
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-PQclear(result);
-
-if (SaveUserServices(uid, conf.services))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to save user's services'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-if (SaveUserData(uid, conf.userdata))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to save user's data'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-if (SaveUserIPs(uid, conf.ips))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to save user's IPs'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-if (CommitTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserConf(): 'Failed to commit transaction'\n");
-    return -1;
-    }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::RestoreUserStat(STG::UserStat * stat,
-                                    const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
-    if (Reset())
-        {
-        strError = "Connection lost";
-        printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): '%s'\n", strError.c_str());
-        return -1;
-        }
-    }
-
-PGresult * result;
-
-if (StartTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to start transaction'\n");
-    return -1;
-    }
-
-std::string elogin = login;
-
-if (EscapeString(elogin))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to escape login'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-    {
-    std::ostringstream query;
-    query << "SELECT cash, free_mb, "
-                "last_activity_time, last_cash_add, "
-                "last_cash_add_time, passive_time "
-             "FROM tb_users "
-             "WHERE name = '" << elogin << "'";
-
-    result = PQexec(connection, query.str().c_str());
-    }
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): '%s'\n", strError.c_str());
-    PQclear(result);
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-int tuples = PQntuples(result);
-
-if (tuples != 1)
-    {
-    strError = "Failed to fetch user's stat";
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
-    PQclear(result);
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-    {
-    std::stringstream tuple;
-    tuple << PQgetvalue(result, 0, 0) << " ";
-    tuple << PQgetvalue(result, 0, 1) << " ";
-    stat->lastActivityTime = readTime(PQgetvalue(result, 0, 2));
-    tuple << PQgetvalue(result, 0, 3) << " ";
-    stat->lastCashAddTime = readTime(PQgetvalue(result, 0, 4));
-    tuple << PQgetvalue(result, 0, 5) << " ";
-
-    PQclear(result);
-
-    tuple >> stat->cash
-          >> stat->freeMb
-          >> stat->lastCashAdd
-          >> stat->passiveTime;
-    }
-
-    {
-    std::ostringstream query;
-    query << "SELECT dir_num, upload, download "
-             "FROM tb_stats_traffic "
-             "WHERE fk_user IN (SELECT pk_user FROM tb_users WHERE name = '" << elogin << "') AND "
-                   "DATE_TRUNC('month', stats_date) = DATE_TRUNC('month', CAST('" << formatTime(stgTime) << "' AS TIMESTAMP))";
-
-    result = PQexec(connection, query.str().c_str());
-    }
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): '%s'\n", strError.c_str());
-    PQclear(result);
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-tuples = PQntuples(result);
-
-for (int i = 0; i < tuples; ++i)
-    {
-    std::stringstream tuple;
-    tuple << PQgetvalue(result, i, 0) << " ";
-    tuple << PQgetvalue(result, i, 1) << " ";
-    tuple << PQgetvalue(result, i, 2) << " ";
-
-    int dir;
-
-    tuple >> dir;
-    tuple >> stat->monthUp[dir];
-    tuple >> stat->monthDown[dir];
-    }
-
-PQclear(result);
-
-if (CommitTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to commit transaction'\n");
-    return -1;
-    }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::RestoreUserConf(STG::UserConf * conf,
-                                    const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
-    if (Reset())
-        {
-        strError = "Connection lost";
-        printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): '%s'\n", strError.c_str());
-        return -1;
-        }
-    }
-
-PGresult * result;
-
-if (StartTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to start transaction'\n");
-    return -1;
-    }
-
-std::string elogin = login;
-
-if (EscapeString(elogin))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to escape login'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserStat(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-    {
-    std::ostringstream query;
-    query << "SELECT tb_users.pk_user, tb_users.address, tb_users.always_online, "
-                    "tb_users.credit, tb_users.credit_expire, tb_users.disabled, "
-                    "tb_users.disabled_detail_stat, tb_users.email, tb_users.grp, "
-                    "tb_users.note, tb_users.passive, tb_users.passwd, tb_users.phone, "
-                    "tb_users.real_name, tf1.name, tf2.name, tb_corporations.name "
-             "FROM tb_users LEFT JOIN tb_tariffs AS tf1 "
-                                "ON tf1.pk_tariff = tb_users.fk_tariff "
-                           "LEFT JOIN tb_tariffs AS tf2 "
-                                "ON tf2.pk_tariff = tb_users.fk_tariff_change "
-                           "LEFT JOIN tb_corporations "
-                                "ON tb_corporations.pk_corporation = tb_users.fk_corporation "
-             "WHERE tb_users.name = '" << elogin << "'";
-
-    result = PQexec(connection, query.str().c_str());
-    }
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): '%s'\n", strError.c_str());
-    PQclear(result);
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-int tuples = PQntuples(result);
-
-if (tuples != 1)
-    {
-    strError = "Failed to fetch user's stat";
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
-    PQclear(result);
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-uint32_t uid;
-
-    {
-    std::stringstream tuple;
-    tuple << PQgetvalue(result, 0, 0) << " ";               // uid
-    conf->address = PQgetvalue(result, 0, 1);               // address
-    conf->alwaysOnline = !strncmp(PQgetvalue(result, 0, 2), "t", 1);
-    tuple << PQgetvalue(result, 0, 3) << " ";               // credit
-    conf->creditExpire = readTime(PQgetvalue(result, 0, 4));  // creditExpire
-    conf->disabled = !strncmp(PQgetvalue(result, 0, 5), "t", 1);
-    conf->disabledDetailStat = !strncmp(PQgetvalue(result, 0, 6), "t", 1);
-    conf->email = PQgetvalue(result, 0, 7);                 // email
-    conf->group = PQgetvalue(result, 0, 8);                 // group
-    conf->note = PQgetvalue(result, 0, 9);                  // note
-    conf->passive = !strncmp(PQgetvalue(result, 0, 10), "t", 1);
-    conf->password = PQgetvalue(result, 0, 11);             // password
-    conf->phone = PQgetvalue(result, 0, 12);                // phone
-    conf->realName = PQgetvalue(result, 0, 13);             // realName
-    conf->tariffName = PQgetvalue(result, 0, 14);           // tariffName
-    conf->nextTariff = PQgetvalue(result, 0, 15);           // nextTariff
-    conf->corp = PQgetvalue(result, 0, 16);                 // corp
-
-    PQclear(result);
-
-    if (conf->tariffName == "")
-        conf->tariffName = NO_TARIFF_NAME;
-    if (conf->corp == "")
-        conf->corp = NO_CORP_NAME;
-
-    tuple >> uid
-          >> conf->credit;
-    }
-
-    {
-    std::ostringstream query;
-    query << "SELECT name FROM tb_services "
-             "WHERE pk_service IN (SELECT fk_service "
-                                  "FROM tb_users_services "
-                                  "WHERE fk_user = " << uid << ")";
-
-    result = PQexec(connection, query.str().c_str());
-    }
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): '%s'\n", strError.c_str());
-    PQclear(result);
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-tuples = PQntuples(result);
-
-for (int i = 0; i < tuples; ++i)
-    {
-    conf->services.push_back(PQgetvalue(result, i, 0));
-    }
-
-PQclear(result);
-
-    {
-    std::ostringstream query;
-    query << "SELECT num, data "
-             "FROM tb_users_data "
-             "WHERE fk_user = " << uid;
-
-    result = PQexec(connection, query.str().c_str());
-    }
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): '%s'\n", strError.c_str());
-    PQclear(result);
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-tuples = PQntuples(result);
-
-for (int i = 0; i < tuples; ++i)
-    {
-    int num;
-    if (str2x(PQgetvalue(result, i, 0), num))
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Failed to convert string to int'\n");
-        }
-    else
-        {
-        if (num < USERDATA_NUM &&
-            num >= 0)
-            {
-            conf->userdata[num] = PQgetvalue(result, i, 1);
-            }
-        }
-    }
-
-PQclear(result);
-
-    {
-    std::ostringstream query;
-    query << "SELECT host(ip), masklen(ip) "
-             "FROM tb_allowed_ip "
-             "WHERE fk_user = " << uid;
-
-    result = PQexec(connection, query.str().c_str());
-    }
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): '%s'\n", strError.c_str());
-    PQclear(result);
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-tuples = PQntuples(result);
-
-STG::UserIPs ips;
-for (int i = 0; i < tuples; ++i)
-    {
-    STG::IPMask im;
-
-    im.ip = inet_strington(PQgetvalue(result, i, 0));
-
-    if (str2x(PQgetvalue(result, i, 1), im.mask))
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Failed to fetch mask'\n");
-        continue;
-        }
-
-    ips.add(im);
-    }
-conf->ips = ips;
-
-PQclear(result);
-
-if (CommitTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::RestoreUserConf(): 'Failed to commit transaction'\n");
-    return -1;
-    }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::WriteUserChgLog(const std::string & login,
-                                    const std::string & admLogin,
-                                    uint32_t admIP,
-                                    const std::string & paramName,
-                                    const std::string & oldValue,
-                                    const std::string & newValue,
-                                    const std::string & message = "") const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
-    if (Reset())
-        {
-        strError = "Connection lost";
-        printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): '%s'\n", strError.c_str());
-        return -1;
-        }
-    }
-
-PGresult * result;
-
-if (StartTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to start transaction'\n");
-    return -1;
-    }
-
-std::string elogin(login);
-std::string eadminLogin(admLogin);
-std::string eparam(paramName);
-std::string eold(oldValue);
-std::string enew(newValue);
-std::string emessage(message);
-
-if (EscapeString(elogin))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to escape login'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-if (EscapeString(eadminLogin))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to escape admin's login'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-if (EscapeString(eparam))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to escape param's name'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-if (EscapeString(eold))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to escape old value'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-if (EscapeString(enew))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to escape new value'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-std::ostringstream query;
-query << "SELECT sp_add_param_log_entry("
-            "'" << elogin << "', "
-            "'" << eadminLogin << "', CAST('"
-            << inet_ntostring(admIP) << "/32' AS INET), "
-            "'" << eparam << "', "
-            "CAST('" << formatTime(stgTime) << "' AS TIMESTAMP), "
-            "'" << eold << "', "
-            "'" << enew << "', "
-            "'" << emessage << "')";
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    PQclear(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): '%s'\n", strError.c_str());
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-PQclear(result);
-
-if (CommitTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserChgLog(): 'Failed to commit transaction'\n");
-    return -1;
-    }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::WriteUserConnect(const std::string & login, uint32_t ip) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserConnect(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
-    if (Reset())
-        {
-        strError = "Connection lost";
-        printfd(__FILE__, "POSTGRESQL_STORE::WriteUserConnect(): '%s'\n", strError.c_str());
-        return -1;
-        }
-    }
-
-PGresult * result;
-
-if (StartTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserConnect(): 'Failed to start transaction'\n");
-    return -1;
-    }
-
-std::string elogin(login);
-
-if (EscapeString(elogin))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserConnect(): 'Failed to escape login'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::WriteUserConnect(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-std::ostringstream query;
-if (version < 6)
-    {
-    query << "SELECT sp_add_session_log_entry("
-                 "'" << elogin << "', "
-                 "CAST('" << formatTime(stgTime) << "' AS TIMESTAMP), "
-                 "'c', CAST('"
-                 << inet_ntostring(ip) << "/32' AS INET), 0)";
-    }
-else
-    {
-    query << "SELECT sp_add_session_log_entry("
-                 "'" << elogin << "', "
-                 "CAST('" << formatTime(stgTime) << "' AS TIMESTAMP), "
-                 "'c', CAST('"
-                 << inet_ntostring(ip) << "/32' AS INET), 0, 0, '')";
-    }
-
-result = PQexec(connection, query.str().c_str());
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    PQclear(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserConnect(): '%s'\n", strError.c_str());
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::WriteUserConnect(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-PQclear(result);
-
-if (CommitTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserConnect(): 'Failed to commit transaction'\n");
-    return -1;
-    }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::WriteUserDisconnect(const std::string & login,
-                    const STG::DirTraff & monthUp,
-                    const STG::DirTraff & monthDown,
-                    const STG::DirTraff & sessionUp,
-                    const STG::DirTraff & sessionDown,
-                    double cash,
-                    double freeMb,
-                    const std::string & reason) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
-    if (Reset())
-        {
-        strError = "Connection lost";
-        printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): '%s'\n", strError.c_str());
-        return -1;
-        }
-    }
-
-PGresult * result;
-
-if (StartTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to start transaction'\n");
-    return -1;
-    }
-
-std::string elogin(login);
-
-if (EscapeString(elogin))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to escape login'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-std::string ereason(reason);
-
-if (EscapeString(ereason))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to escape reason'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-    {
-    std::ostringstream query;
-    if (version < 6)
-        {
-        // Old database version - no freeMb logging support
-        query << "SELECT sp_add_session_log_entry("
-                    "'" << elogin << "', "
-                    "CAST('" << formatTime(stgTime) << "' AS TIMESTAMP), "
-                    "'d', CAST('0.0.0.0/0' AS INET), "
-                    << cash << ")";
-        }
-    else
-        {
-        query << "SELECT sp_add_session_log_entry("
-                    "'" << elogin << "', "
-                    "CAST('" << formatTime(stgTime) << "' AS TIMESTAMP), "
-                    "'d', CAST('0.0.0.0/0' AS INET), "
-                    << cash << ", " << freeMb << ", '" << ereason << "')";
-        }
-
-    result = PQexec(connection, query.str().c_str());
-    }
-
-if (PQresultStatus(result) != PGRES_TUPLES_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    PQclear(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): '%s'\n", strError.c_str());
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-int tuples = PQntuples(result);
-
-if (tuples != 1)
-    {
-    strError = "Failed to fetch session's log ID";
-    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Invalid number of tuples. Wanted 1, actulally %d'\n", tuples);
-    PQclear(result);
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-uint32_t lid;
-
-if (str2x(PQgetvalue(result, 0, 0), lid))
-    {
-    strError = "Failed to convert string to int";
-    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): '%s'\n", strError.c_str());
-    PQclear(result);
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-PQclear(result);
-
-for (int i = 0; i < DIR_NUM; ++i)
-    {
-    std::ostringstream query;
-    query << "INSERT INTO tb_sessions_data "
-                "(fk_session_log, "
-                 "dir_num, "
-                 "session_upload, "
-                 "session_download, "
-                 "month_upload, "
-                 "month_download)"
-             "VALUES ("
-                << lid << ", "
-                << i << ", "
-                << sessionUp[i] << ", "
-                << sessionDown[i] << ", "
-                << monthUp[i] << ", "
-                << monthDown[i] << ")";
-
-    result = PQexec(connection, query.str().c_str());
-
-    if (PQresultStatus(result) != PGRES_COMMAND_OK)
-        {
-        strError = PQresultErrorMessage(result);
-        PQclear(result);
-        printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): '%s'\n", strError.c_str());
-        if (RollbackTransaction())
-            {
-            printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to rollback transaction'\n");
-            }
-        return -1;
-        }
-
-    PQclear(result);
-    }
-
-if (CommitTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::WriteUserDisconnect(): 'Failed to commit transaction'\n");
-    return -1;
-    }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::WriteDetailedStat(const STG::TraffStat & statTree,
-                                      time_t lastStat,
-                                      const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-if (PQstatus(connection) != CONNECTION_OK)
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::WriteDetailedStat(): 'Connection lost. Trying to reconnect...'\n", strError.c_str());
-    if (Reset())
-        {
-        strError = "Connection lost";
-        printfd(__FILE__, "POSTGRESQL_STORE::WriteDetailedStat(): '%s'\n", strError.c_str());
-        return -1;
-        }
-    }
-
-if (StartTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::WriteDetailedStat(): 'Failed to start transaction'\n");
-    return -1;
-    }
-
-std::string elogin(login);
-
-if (EscapeString(elogin))
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::WriteDetailedStat(): 'Failed to escape login'\n");
-    if (RollbackTransaction())
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::WriteDetailedStat(): 'Failed to rollback transaction'\n");
-        }
-    return -1;
-    }
-
-STG::TraffStat::const_iterator it;
-time_t currTime = time(NULL);
-
-for (it = statTree.begin(); it != statTree.end(); ++it)
-    {
-    std::ostringstream query;
-    query << "INSERT INTO tb_detail_stats "
-                "(till_time, from_time, fk_user, "
-                 "dir_num, ip, download, upload, cost) "
-             "VALUES ("
-                "CAST('" << formatTime(currTime) << "' AS TIMESTAMP), "
-                "CAST('" << formatTime(lastStat) << "' AS TIMESTAMP), "
-                "(SELECT pk_user FROM tb_users WHERE name = '" << elogin << "'), "
-                << it->first.dir << ", "
-                << "CAST('" << inet_ntostring(it->first.ip) << "' AS INET), "
-                << it->second.down << ", "
-                << it->second.up << ", "
-                << it->second.cash << ")";
-
-    PGresult * result = PQexec(connection, query.str().c_str());
-
-    if (PQresultStatus(result) != PGRES_COMMAND_OK)
-        {
-        strError = PQresultErrorMessage(result);
-        PQclear(result);
-        printfd(__FILE__, "POSTGRESQL_STORE::WriteDetailedStat(): '%s'\n", strError.c_str());
-        if (RollbackTransaction())
-            {
-            printfd(__FILE__, "POSTGRESQL_STORE::WriteDetailedStat(): 'Failed to rollback transaction'\n");
-            }
-        return -1;
-        }
-
-    PQclear(result);
-    }
-
-if (CommitTransaction())
-    {
-    printfd(__FILE__, "POSTGRESQL_STORE::WriteDetailedStat(): 'Failed to commit transaction'\n");
-    return -1;
-    }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::SaveMonthStat(const STG::UserStat & stat, int month, int year, const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-
-return SaveStat(stat, login, year, month);
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::SaveUserServices(uint32_t uid,
-                                       const std::vector<std::string> & services) const
-{
-PGresult * result;
-
-    {
-    std::ostringstream query;
-    query << "DELETE FROM tb_users_services WHERE fk_user = " << uid;
-
-    result = PQexec(connection, query.str().c_str());
-
-    if (PQresultStatus(result) != PGRES_COMMAND_OK)
-        {
-        strError = PQresultErrorMessage(result);
-        PQclear(result);
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserServices(): '%s'\n", strError.c_str());
-        return -1;
-        }
-
-    PQclear(result);
-    }
-
-std::vector<std::string>::const_iterator it;
-
-for (it = services.begin(); it != services.end(); ++it)
-    {
-    std::string ename = *it;
-
-    if (EscapeString(ename))
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserServices(): 'Failed to escape service name'\n");
-        return -1;
-        }
-
-    std::ostringstream query;
-    query << "INSERT INTO tb_users_services "
-                "(fk_user, fk_service) "
-             "VALUES "
-                "(" << uid << ", "
-                  "(SELECT pk_service "
-                   "FROM tb_services "
-                   "WHERE name = '" << ename << "'))";
-
-    result = PQexec(connection, query.str().c_str());
-
-    if (PQresultStatus(result) != PGRES_COMMAND_OK)
-        {
-        strError = PQresultErrorMessage(result);
-        PQclear(result);
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserServices(): '%s'\n", strError.c_str());
-        return -1;
-        }
-
-    PQclear(result);
-    }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::SaveUserIPs(uint32_t uid,
-                                  const STG::UserIPs & ips) const
-{
-PGresult * result;
-
-    {
-    std::ostringstream query;
-    query << "DELETE FROM tb_allowed_ip WHERE fk_user = " << uid;
-
-    result = PQexec(connection, query.str().c_str());
-    }
-
-if (PQresultStatus(result) != PGRES_COMMAND_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    PQclear(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::SaveUserIPs(): '%s'\n", strError.c_str());
-    return -1;
-    }
-
-PQclear(result);
-
-for (size_t i = 0; i < ips.count(); ++i)
-    {
-    std::ostringstream query;
-    query << "INSERT INTO tb_allowed_ip "
-                "(fk_user, ip) "
-             "VALUES "
-                "(" << uid << ", CAST('"
-                    << inet_ntostring(ips[i].ip) << "/"
-                    << static_cast<int>(ips[i].mask) << "' AS INET))";
-
-    result = PQexec(connection, query.str().c_str());
-
-    if (PQresultStatus(result) != PGRES_COMMAND_OK)
-        {
-        strError = PQresultErrorMessage(result);
-        PQclear(result);
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserIPs(): '%s'\n", strError.c_str());
-        return -1;
-        }
-
-    PQclear(result);
-    }
-
-return 0;
-}
-
-//-----------------------------------------------------------------------------
-int POSTGRESQL_STORE::SaveUserData(uint32_t uid,
-                                   const std::vector<std::string> & data) const
-{
-for (unsigned i = 0; i < data.size(); ++i)
-    {
-    std::string edata = data[i];
-
-    if (EscapeString(edata))
-        {
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserData(): 'Failed to escape userdata field'\n");
-        return -1;
-        }
-
-    PGresult * result;
-
-    std::ostringstream query;
-    query << "SELECT sp_set_user_data("
-                << uid << ", "
-                << "CAST(" << i << " AS SMALLINT), "
-                << "'" << edata << "')";
-
-    result = PQexec(connection, query.str().c_str());
-
-    if (PQresultStatus(result) != PGRES_TUPLES_OK)
-        {
-        strError = PQresultErrorMessage(result);
-        PQclear(result);
-        printfd(__FILE__, "POSTGRESQL_STORE::SaveUserData(): '%s'\n", strError.c_str());
-        return -1;
-        }
-
-    PQclear(result);
-    }
-
-return 0;
-}
-
diff --git a/stargazer/plugins/store/postgresql/postgresql_store_utils.cpp b/stargazer/plugins/store/postgresql/postgresql_store_utils.cpp
deleted file mode 100644 (file)
index 9a5101e..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-/*
- *  Vairous utility methods
- *
- *  $Revision: 1.3 $
- *  $Date: 2009/10/22 10:01:08 $
- *
- */
-
-#include "postgresql_store.h"
-
-#include "stg/common.h"
-
-#include <string>
-#include <ctime>
-
-#include <libpq-fe.h>
-
-extern volatile time_t stgTime;
-
-int POSTGRESQL_STORE::StartTransaction() const
-{
-PGresult * result = PQexec(connection, "BEGIN");
-
-if (PQresultStatus(result) != PGRES_COMMAND_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    PQclear(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::StartTransaction(): '%s'\n", strError.c_str());
-    return -1;
-    }
-
-PQclear(result);
-
-return 0;
-}
-
-int POSTGRESQL_STORE::CommitTransaction() const
-{
-PGresult * result = PQexec(connection, "COMMIT");
-
-if (PQresultStatus(result) != PGRES_COMMAND_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    PQclear(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::CommitTransaction(): '%s'\n", strError.c_str());
-    return -1;
-    }
-
-PQclear(result);
-
-return 0;
-}
-
-int POSTGRESQL_STORE::RollbackTransaction() const
-{
-PGresult * result = PQexec(connection, "ROLLBACK");
-
-if (PQresultStatus(result) != PGRES_COMMAND_OK)
-    {
-    strError = PQresultErrorMessage(result);
-    PQclear(result);
-    printfd(__FILE__, "POSTGRESQL_STORE::RollbackTransaction(): '%s'\n", strError.c_str());
-    return -1;
-    }
-
-PQclear(result);
-
-return 0;
-}
-
-int POSTGRESQL_STORE::EscapeString(std::string & value) const
-{
-int error = 0;
-char * buf = new char[(value.length() << 1) + 1];
-
-PQescapeStringConn(connection,
-                   buf,
-                   value.c_str(),
-                   value.length(),
-                   &error);
-
-if (error)
-    {
-    strError = PQerrorMessage(connection);
-    printfd(__FILE__, "POSTGRESQL_STORE::EscapeString(): '%s'\n", strError.c_str());
-    delete[] buf;
-    return -1;
-    }
-
-value = buf;
-
-delete[] buf;
-return 0;
-}
-
-void POSTGRESQL_STORE::MakeDate(std::string & date, int year, int month) const
-{
-struct tm brokenTime;
-
-brokenTime.tm_wday = 0;
-brokenTime.tm_yday = 0;
-brokenTime.tm_isdst = 0;
-
-if (year)
-    {
-    brokenTime.tm_hour = 0;
-    brokenTime.tm_min = 0;
-    brokenTime.tm_sec = 0;
-    brokenTime.tm_year = year;
-    brokenTime.tm_mon = month;
-    }
-else
-    {
-    time_t curTime = stgTime;
-    localtime_r(&curTime, &brokenTime);
-    }
-
-brokenTime.tm_mday = DaysInMonth(brokenTime.tm_year + 1900, brokenTime.tm_mon);
-
-char buf[32];
-
-strftime(buf, 32, "%Y-%m-%d", &brokenTime);
-
-date = buf;
-}
diff --git a/stargazer/plugins/store/postgresql/postgresql_store_utils.h b/stargazer/plugins/store/postgresql/postgresql_store_utils.h
deleted file mode 100644 (file)
index 4ffa6ec..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef POSTGRESQL_UTILS_STORE_H
-#define POSTGRESQL_UTILS_STORE_H
-
-#include <functional>
-
-struct ToLower : public std::unary_function<char, char>
-{
-char operator() (char c) const  { return static_cast<char>(std::tolower(c)); }
-};
-
-#endif
diff --git a/stargazer/scripts/clean_db b/stargazer/scripts/clean_db
deleted file mode 100755 (executable)
index 31a85a9..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/bin/bash
-
-# Этот скрипт производит очистку файловой БД stargazer-а.
-# Его можно вызывать вручную или покрону, к примеру раз в неделю или раз в месяц.
-
-
-# Эта переменная задает сколько месяцев детальной статистики оставить в БД
-SAVE_MONTHS=3
-
-# Эта переменная задает сколько строк оставить в логах юзеров
-MAX_LOG_LINES=5000
-
-# Тут определяется путь к БД
-DB=/var/stargazer/
-
-
-
-
-declare -i NOW=`date +%s`
-declare -i DT=SAVE_MONTHS*31*24*3600
-declare -i stat_time=0
-
-for usr in $DB/users/*
-do
-    echo cleaning `basename $usr`
-    for ys in $usr/detail_stat/*
-    do
-       year=`basename $ys`
-       
-       for ms in $ys/*
-       do
-           month=`basename $ms`
-            stat_time=`date --date="$year/$month/01" +%s`          
-           
-           if (( $NOW - $stat_time > $DT ))
-           then
-               rm -fr $ms
-           fi
-       done
-    done
-    tail -n $MAX_LOG_LINES $usr/log > /tmp/stg_usr_log.`basename $usr`
-    mv -f /tmp/stg_usr_log.`basename $usr` $usr/log
-done
-
diff --git a/stargazer/scripts/monitor b/stargazer/scripts/monitor
deleted file mode 100755 (executable)
index 1f608a7..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/bin/bash
-
-# Данный скрипт производит мониторинг СТГ-сервера на зависание и в 
-# случае его зависания перезапускает.
-# Для работы скрипта в настройках СТГ должен быть указан параметер
-# MonitorDir 
-# Скрипт отрабатывает один раз и выходит. Т.е. он не работает постоянно 
-# и следит за СТГ. Его нужно вызывать по крону или как-то еще с нужной
-# периодичностью!!!
-
-
-# Путь к файлам монитора. Должен совпадать со значением MonitorDir 
-# в настройках сервера
-MONITOR_DIR=/var/stargazer/monitor/
-
-
-# Максимальная задержка обновления файлов монитора в секундах.
-# При привышении этого значения сервер считается зависшим и будет 
-# перезапущен
-DT=300
-
-
-
-
-declare -i now=`date +%s`
-declare -i DT=300
-declare -i file_time=0
-
-stg_running=`ps ax | grep stargazer`
-if [ -z "$stg_running" ]
-then
-    echo "Stargazer is not running"
-    exit 0
-fi
-
-#wakeuper for traffcounter
-ping -c 1 127.0.0.1 > /dev/null
-sleep 1
-
-for mon in $MONITOR_DIR/*
-do
-    if [ ! -r $mon ]
-    then
-        echo "no monitor files"
-        exit 0
-    fi
-    file_time=`stat -c%Y $mon`
-
-    if (( $now - $file_time > $DT )) 
-    then
-        echo "Stargazer is deadlocked!"
-               
-       # Команда остаовки СТГ
-       killall -KILL stargazer
-               
-       rm -f $MONITOR_DIR/*
-       sleep 15
-       
-       # Команда запуска СТГ
-       /etc/init.d/stargazer start
-       
-    fi
-    
-done
-
-
diff --git a/stargazer/scripts/shaper/OnConnect b/stargazer/scripts/shaper/OnConnect
deleted file mode 100755 (executable)
index 67bf32b..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/bin/bash
-
-int_iface=eth1
-
-# Login
-LOGIN=$1
-
-#user IP
-IP=$2
-
-#cash
-CASH=$3
-
-#user ID
-ID=$4
-
-#Selected dirs to connect
-DIRS=$5
-
-default_speed=32kbit
-
-# =========== shaping by tariff ===========
-#tariff=$(grep -i "^tariff=" /var/stargazer/users/$LOGIN/conf | cut -f 2 -d"=")
-#echo "tariff=$tariff" > /var/stargazer/users/$LOGIN/connect.log
-#case $tariff in
-#    minimum)  speedkb=128kbit;;  # 128 kbit
-#    middle)   speedkb=256kbit;;  # 256 kbi
-#    maximum)  speedkb=512kbit;;        # 512 kbit
-#    *)        speedkb=$default_speed;;  # default speed
-#esac
-# ========= shaping by tariff end ========= 
-
-# ========= shaping by userdata0 ==========
-speedR=$(grep -i "^Userdata0=" /var/stargazer/users/$LOGIN/conf | cut -f 2 -d"=")
-speed=$(echo $speedR | grep "^[0-9]*[0-9]$")
-
-if [ -z "$speed" ] 
-then
-    speedkb=$default_speed
-else
-    speedkb="$speed"kbit
-fi
-# ======= shaping by userdata0 end ========
-
-declare -i mark=$ID+10
-
-echo "$mark" > /var/stargazer/users/$LOGIN/shaper_mark
-echo "$speedkb" > /var/stargazer/users/$LOGIN/shaper_rate
-
-iptables -t mangle -A FORWARD -d $IP -j MARK --set-mark $mark
-
-tc class add dev $int_iface parent 1:1 classid 1:$mark htb rate $speedkb burst 40k
-tc filter add dev $int_iface parent 1: protocol ip prio 3 handle $mark fw classid 1:$mark
-
diff --git a/stargazer/scripts/shaper/OnDisconnect b/stargazer/scripts/shaper/OnDisconnect
deleted file mode 100755 (executable)
index e015eec..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/bin/bash
-
-int_iface=eth1
-
-# Login
-LOGIN=$1
-
-#user IP
-IP=$2
-
-#cash
-CASH=$3
-
-#user ID
-ID=$4
-
-#Selected dirs to disconnect
-DIRS=$4
-
-mark=$(cat /var/stargazer/users/$LOGIN/shaper_mark)
-rate=$(cat /var/stargazer/users/$LOGIN/shaper_rate)
-
-if [ -n "$mark" ]
-then
-    iptables -t mangle -D FORWARD -d $IP -j MARK --set-mark $mark
-    while [ $? == 0 ]
-    do
-           iptables -t mangle -D FORWARD -d $IP -j MARK --set-mark $mark
-    done
-fi
-
-tc filter del dev $int_iface parent 1: protocol ip prio 3 handle $mark fw classid 1:$mark
-tc class del dev $int_iface parent 1:1 classid 1:$mark htb rate $rate burst 40k
-
-#echo "D `date +%Y.%m.%d-%H.%M.%S` $IP $CASH" >> /var/stargazer/users/$LOGIN/connect.log
-
-
diff --git a/stargazer/scripts/shaper/Readme.txt b/stargazer/scripts/shaper/Readme.txt
deleted file mode 100644 (file)
index a5fd925..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-Настройка шейпера для STG в Linux.
-
-По мотивам форума:
-http://local.com.ua/forum/index.php?showtopic=7920
-
-Настройка сводится к указанию сетевого интерфейса, обращенного к пользователю 
-в скриптах shaper.sh, shaper.stop.sh, OnConnect и OnDisconnect, и уточнению 
-скоростоей и тарифов в скрипте OnConnect (если нужно).
-
-Скрипты сделаны для БД на файлах, однако, сделать их для БД на Firebird или 
-MySQL не составит большого труда.
-
-В OnConnect есть два типа шейпинга.
-1. На основании тарифа. Т.е. для каждого тарифа у задана скорость и задано 
-дефолтное значение, на случай отсутсвия тарифа в списке скоростей или 
-забывчивости админа.
-2. На основании Userdata0. В этом поле просто прописывается число равное 
-скорости в kbit/sec. Также есть дефолтное значение скорости в 32 kbit/sec 
-на случай отсутсвия в Userdata0 корректного значения.
-
-В скрипте первый способ закомментирован. Для того чтобы выбрать один из них нужно
-либо удалить, либо закомментировать строчики между
-
-# ========= shaping by tariff ==========
-.........
-# ======= shaping by tariff end ========
-
-
-# ========= shaping by userdata0 ==========
-.........
-# ======= shaping by userdata0 end ========
-
-
-и нужную часть расскоментировать, если она закомментрована.
-
-Скрипт shaper.sh должен быть выполнен один раз при загрузке системы.
-
-Интерфейс обращенный к пользователю определяется в переменной
-int_iface= 
-(присутствует во всех 4-х файлах shaper.sh, shaper.stop.sh, OnConnect и 
-OnDisconnect !!!)
-
-Скорость по умолчанию в OnConnect в переменной default_speed
-
-Зависимость скорости от тарифа задается в следующем фрагменте кода:
-case $tariff in
-    minimum)  speedkb=128kbit;;
-    middle)   speedkb=256kbit;;
-    maximum)  speedkb=512kbit;;
-    *)        speedkb=$default_speed;;
-esac
-
-Т.е. тут нужно вместо minimum, ... maximum подставить имена ваших тарифов 
-и соотв. скорость. Пользователи с тарифами не указанными в списке будут иметь 
-дефолтную скорость.
-
-Скорость ограничевается только для входящего тарафика, однако расширить 
-эти скрипты для исходящего не составит труда.
diff --git a/stargazer/scripts/shaper/shaper.sh b/stargazer/scripts/shaper/shaper.sh
deleted file mode 100755 (executable)
index 2b4f042..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/bash
-
-int_iface=eth1
-
-iptables -t mangle --flush
-
-tc qdisc add dev $int_iface root handle 1: htb
-tc class add dev $int_iface parent 1: classid 1:1 htb rate 100mbit ceil 100mbit burst 200k
-
diff --git a/stargazer/scripts/shaper/shaper.stop.sh b/stargazer/scripts/shaper/shaper.stop.sh
deleted file mode 100755 (executable)
index 993a13a..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/bash
-
-int_iface=eth1
-
-#iptables -t mangle --flush
-
-tc qdisc del dev $int_iface root handle 1: htb
-
diff --git a/stargazer/scripts/shaper_vpn_radius/Readme b/stargazer/scripts/shaper_vpn_radius/Readme
deleted file mode 100644 (file)
index 772dddd..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-Настройка такой конфигурации происходит в 3 этапа:
-1. Настройка VPN с использованием pptpd;
-2. Настройка авторизации VPN через FreeRADIUS;
-3. Настройка шейпера;
-
-1. Настройка VPN
-
-Необходимо установить пакеты ppp и pptpd. Также необходима поддержка PPP в ядре:
-    Device Drivers  --->
-        Network device support  --->
-            <M> PPP (point-to-point protocol) support
-            <M>   PPP support for sync tty ports
-            <M>   PPP Deflate compression
-            <M>   PPP BSD-Compress compression
-            <M>   PPP MPPE compression (encryption) (EXPERIMENTAL)
-            <M>   PPP over Ethernet (EXPERIMENTAL)
-В файле /etc/pptpd.conf прописываем файл настроек PPP (параметр option). Также
-указываем адреса сервера внутри сети VPN (параметр localip) и диапазон адресов 
-клиентов (параметр remoteip). См. пример файла конфигурации.
-В настройках PPP указываем имя сервера (параметр name), параметры шифрования. 
-Для использования шифрования MPPE необходима его поддержка в ядре. Кроме того, 
-в процессе аутентификации MPPE использует MS-CHAPv2. По этому при 
-использовании шифрования MPPE также необходимо указать необходимость 
-поддержки MS-CHAPv2 клиентом. По желанию указываем proxyarp (для того чтобы 
-клиенты в сети VPN "видели" друг друга) и defaultroute. Прописываем в файле 
-/etc/ppp/chap-secrets тестового пользователя и проверяем работоспособность 
-VPN.
-
-2. Настройка авторизации VPN через FreeRADIUS
-
-Необходимо установить пакет freeradius.
-Настройку сервера (файл radiusd.conf) проводим в соответствии с документацией 
-на модуль rlm_stg.so (см. документацию на систему Stargazer).
-Настройку Stargazer с плагином для FreeRADIUS проводим в соответствиии с 
-документацией на модуль mod_radius.so (см. документацию на систему Stargazer).
-В файле clients.conf, расположенном в дирректории с конфигурационными файлами 
-FreeRADIUS, описываем, какие клиенты могут использовать FreeRADIUS. 
-Рекомендуется заменить стандартный пароль, которым шифруется обмен информации 
-с клиентом, "testing123" на что-то более приемлимое с точки зрения безопасности. 
-После этого запускаем FreeRADIUS и удостоверяемся, что он работает строчкой 
-"Mon Mar 31 16:06:17 2008 : Info: Ready to process requests." в журнале 
-(обычно, /var/log/radius/radius.log). Если журнал FreeRADIUS не позволяет 
-определить проблему - можно запустить сервер в отладочном режме с ключем -X. 
-В этом режиме более детальное журналирование проводится в консоль.
-Если на данном этапе все работает - в файл насттроек PPP прописываем строчку 
-plugin radius.so. После этого VPN должен нормально авторизоваться 
-пользователями системы Stargazer.
-
-3. Настройка шейпера
-
-Собственно настройки шейпер не требует. Всё, что нужно прописано в скриптах 
-OnConnect и OnDisconnect. Шейпер предназначен для работы с хранилищем на 
-файлах, однако, переделать скипт под MySQL или Firebird не составит труда.
-Скорость для пользоватлея задается в поле Userdata0 в kbit/sec. В этом поле 
-должно быть прописано просто число без всяких kbit/sec и т.п. Если в этом поле
-у пользователя нет данных или стоит некорректное значение, пользователь будет 
-ограничен скоростью определенной в переменной default_speed в скрипте 
-OnConnect.
diff --git a/stargazer/scripts/shaper_vpn_radius/firewall/firewall b/stargazer/scripts/shaper_vpn_radius/firewall/firewall
deleted file mode 100755 (executable)
index 36a2703..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-#!/bin/bash
-
-#adsl-start
-
-modprobe ip_queue
-
-int_addr=10.0.0.2
-ext_addr=192.168.1.34
-
-int_net=10.0.0.0/16
-ext_net=192.168.1.0/24
-
-echo 1 > /proc/sys/net/ipv4/ip_forward
-
-iptables -P INPUT DROP
-iptables -P OUTPUT ACCEPT
-iptables -P FORWARD ACCEPT
-
-iptables -t nat -F
-iptables -t filter -F
-
-# 
-#iptables -A INPUT  -d $ip1 -j ACCEPT
-#iptables -A OUTPUT -s $ip1 -j ACCEPT
-
-# Разрешам говорить самому с собой
-iptables -A INPUT  -d 127.0.0.1 -j ACCEPT
-iptables -A OUTPUT -s 127.0.0.1 -j ACCEPT
-
-#iptables -A INPUT  -d $ip4 -j ACCEPT
-#iptables -A INPUT  -s $ip4 -j ACCEPT
-#iptables -A OUTPUT -s $ip4 -j ACCEPT
-#iptables -A OUTPUT -d $ip4 -j ACCEPT
-
-iptables -A INPUT  -p icmp -j ACCEPT
-iptables -A OUTPUT -p icmp -j ACCEPT
-
-iptables -A INPUT  -p 47 -j ACCEPT
-iptables -A FORWARD -p 47 -j ACCEPT
-iptables -A OUTPUT -p 47 -j ACCEPT
-
-#SSH On this machine
-iptables -A INPUT  -p tcp -d $int_addr --dport 22 -j ACCEPT
-iptables -A OUTPUT -p tcp -s $int_addr --sport 22 -j ACCEPT
-iptables -A INPUT  -p tcp -d $ext_addr --dport 22 -j ACCEPT
-iptables -A OUTPUT -p tcp -s $ext_addr --sport 22 -j ACCEPT
-
-#WEB On this machine
-#iptables -A INPUT  -p tcp -d $ip2 --dport 80 -j ACCEPT
-#iptables -A OUTPUT -p tcp -s $ip2 --sport 80 -j ACCEPT
-#iptables -A INPUT  -p tcp -d $ip3 --dport 80 -j ACCEPT
-#iptables -A OUTPUT -p tcp -s $ip3 --sport 80 -j ACCEPT
-
-#PPTP
-iptables -A INPUT   -p tcp --dport 1723 -j ACCEPT
-iptables -A OUTPUT  -p tcp --sport 1723 -j ACCEPT
-iptables -A INPUT  -p udp --dport 1723 -j ACCEPT
-iptables -A OUTPUT -p udp --sport 1723 -j ACCEPT
-
-#FTP
-#iptables -A INPUT  -p tcp -d $ip2 -j ACCEPT
-#iptables -A OUTPUT -p tcp -s $ip2 -j ACCEPT
-#iptables -A INPUT  -p tcp -d $ip3 -j ACCEPT
-#iptables -A OUTPUT -p tcp -s $ip3 -j ACCEPT
-
-#iptables -A INPUT  -p tcp -d $ip2 --dport 20:21 -j ACCEPT
-#iptables -A OUTPUT -p tcp -s $ip2 --sport 20:21 -j ACCEPT
-#iptables -A INPUT  -p tcp -d $ip3 --dport 20:21 -j ACCEPT
-#iptables -A OUTPUT -p tcp -s $ip3 --sport 20:21 -j ACCEPT
-
-#iptables -A INPUT  -p tcp -d $ip2 --dport 1024:65535 --sport 1024:65535 -j ACCEPT
-#iptables -A INPUT  -p tcp -d $ip3 --dport 1024:65535 --sport 1024:65535 -j ACCEPT
-#iptables -A OUTPUT -p tcp -s $ip2 --sport 1024:65535 --dport 1024:65535 -j ACCEPT
-#iptables -A OUTPUT -p tcp -s $ip3 --sport 1024:65535 --dport 1024:65535 -j ACCEPT
-
-#DNS
-iptables -A INPUT  -p tcp --sport 53 -j ACCEPT
-iptables -A OUTPUT -p tcp --dport 53 -j ACCEPT
-iptables -A INPUT  -p udp --sport 53 -j ACCEPT
-iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
-
-#iptables -t nat -A PREROUTING -p tcp -d $ip1 --dport 80 -j ACCEPT
-#iptables -t nat -A PREROUTING -p tcp -d $ip2 --dport 80 -j ACCEPT
-#iptables -t nat -A PREROUTING -p tcp -d $ip3 --dport 80 -j ACCEPT
-#iptables -t nat -A PREROUTING -p tcp -d $ip4 --dport 80 -j ACCEPT
-
-#iptables -t nat -A PREROUTING -p tcp -s 192.168.1.7 -j ACCEPT
-#iptables -t nat -A PREROUTING -p tcp -s 192.168.1.16 -j ACCEPT
-#iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 3128
-
-iptables -t nat -A POSTROUTING -d 0.0.0.0/0 -s 192.168.2.0/24 -j MASQUERADE
-
-
-
diff --git a/stargazer/scripts/shaper_vpn_radius/freeradius/clients.conf b/stargazer/scripts/shaper_vpn_radius/freeradius/clients.conf
deleted file mode 100644 (file)
index a855b2d..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-#
-# clients.conf - client configuration directives
-#
-#######################################################################
-
-#######################################################################
-#
-#  Definition of a RADIUS client (usually a NAS).
-#
-#  The information given here over rides anything given in the
-#  'clients' file, or in the 'naslist' file.  The configuration here
-#  contains all of the information from those two files, and allows
-#  for more configuration items.
-#
-#  The "shortname" is be used for logging.  The "nastype", "login" and
-#  "password" fields are mainly used for checkrad and are optional.
-#
-
-#
-#  Defines a RADIUS client.  The format is 'client [hostname|ip-address]'
-#
-#  '127.0.0.1' is another name for 'localhost'.  It is enabled by default,
-#  to allow testing of the server after an initial installation.  If you
-#  are not going to be permitting RADIUS queries from localhost, we suggest
-#  that you delete, or comment out, this entry.
-#
-client 127.0.0.1 {
-       #
-       #  The shared secret use to "encrypt" and "sign" packets between
-       #  the NAS and FreeRADIUS.  You MUST change this secret from the
-       #  default, otherwise it's not a secret any more!
-       #
-       #  The secret can be any string, up to 31 characters in length.
-       #
-       secret          = testing123
-
-       #
-       #  The short name is used as an alias for the fully qualified
-       #  domain name, or the IP address.
-       #
-       shortname       = localhost
-
-       #
-       # the following three fields are optional, but may be used by
-       # checkrad.pl for simultaneous use checks
-       #
-
-       #
-       # The nastype tells 'checkrad.pl' which NAS-specific method to
-       #  use to query the NAS for simultaneous use.
-       #
-       #  Permitted NAS types are:
-       #
-       #       cisco
-       #       computone
-       #       livingston
-       #       max40xx
-       #       multitech
-       #       netserver
-       #       pathras
-       #       patton
-       #       portslave
-       #       tc
-       #       usrhiper
-       #       other           # for all other types
-
-       #
-       nastype     = other     # localhost isn't usually a NAS...
-
-       #
-       #  The following two configurations are for future use.
-       #  The 'naspasswd' file is currently used to store the NAS
-       #  login name and password, which is used by checkrad.pl
-       #  when querying the NAS for simultaneous use.
-       #
-#      login       = !root
-#      password    = someadminpas
-}
diff --git a/stargazer/scripts/shaper_vpn_radius/freeradius/radiusd.conf b/stargazer/scripts/shaper_vpn_radius/freeradius/radiusd.conf
deleted file mode 100644 (file)
index c41d28d..0000000
+++ /dev/null
@@ -1,1119 +0,0 @@
-##
-## radiusd.conf        -- FreeRADIUS server configuration file.
-##
-##     http://www.freeradius.org/
-##     $Id: radiusd.conf,v 1.1 2008/03/31 13:54:59 faust Exp $
-##
-
-#      The location of other config files and
-#      logfiles are declared in this file
-#
-#      Also general configuration for modules can be done
-#      in this file, it is exported through the API to
-#      modules that ask for it.
-#
-#      The configuration variables defined here are of the form ${foo}
-#      They are local to this file, and do not change from request to
-#      request.
-#
-#      The per-request variables are of the form %{Attribute-Name}, and
-#      are taken from the values of the attribute in the incoming
-#      request.  See 'doc/variables.txt' for more information.
-
-prefix = /usr
-exec_prefix = /usr
-sysconfdir = /etc
-localstatedir = /var
-sbindir = ${exec_prefix}/sbin
-logdir = /var/log/freeradius
-raddbdir = /etc/freeradius
-radacctdir = ${logdir}/radacct
-
-#  Location of config and logfiles.
-confdir = ${raddbdir}
-run_dir = ${localstatedir}/run/freeradius
-
-#
-#  The logging messages for the server are appended to the
-#  tail of this file.
-#
-log_file = ${logdir}/radius.log
-
-#
-# libdir: Where to find the rlm_* modules.
-#
-#   This should be automatically set at configuration time.
-#
-#   If the server builds and installs, but fails at execution time
-#   with an 'undefined symbol' error, then you can use the libdir
-#   directive to work around the problem.
-#
-#   The cause is usually that a library has been installed on your
-#   system in a place where the dynamic linker CANNOT find it.  When
-#   executing as root (or another user), your personal environment MAY
-#   be set up to allow the dynamic linker to find the library.  When
-#   executing as a daemon, FreeRADIUS MAY NOT have the same
-#   personalized configuration.
-#
-#   To work around the problem, find out which library contains that symbol,
-#   and add the directory containing that library to the end of 'libdir',
-#   with a colon separating the directory names.  NO spaces are allowed.
-#
-#   e.g. libdir = /usr/local/lib:/opt/package/lib
-#
-#   You can also try setting the LD_LIBRARY_PATH environment variable
-#   in a script which starts the server.
-#
-#   If that does not work, then you can re-configure and re-build the
-#   server to NOT use shared libraries, via:
-#
-#      ./configure --disable-shared
-#      make
-#      make install
-#
-libdir = /usr/lib/freeradius
-
-#  pidfile: Where to place the PID of the RADIUS server.
-#
-#  The server may be signalled while it's running by using this
-#  file.
-#
-#  This file is written when ONLY running in daemon mode.
-#
-#  e.g.:  kill -HUP `cat /var/run/freeradius/freeradius.pid`
-#
-pidfile = ${run_dir}/freeradius.pid
-
-
-# user/group: The name (or #number) of the user/group to run radiusd as.
-#
-#   If these are commented out, the server will run as the user/group
-#   that started it.  In order to change to a different user/group, you
-#   MUST be root ( or have root privleges ) to start the server.
-#
-#   We STRONGLY recommend that you run the server with as few permissions
-#   as possible.  That is, if you're not using shadow passwords, the
-#   user and group items below should be set to 'nobody'.
-#
-#    On SCO (ODT 3) use "user = nouser" and "group = nogroup".
-#
-#  NOTE that some kernels refuse to setgid(group) when the value of
-#  (unsigned)group is above 60000; don't use group nobody on these systems!
-#
-#  On systems with shadow passwords, you might have to set 'group = shadow'
-#  for the server to be able to read the shadow password file.  If you can
-#  authenticate users while in debug mode, but not in daemon mode, it may be
-#  that the debugging mode server is running as a user that can read the
-#  shadow info, and the user listed below can not.
-#
-user = freerad
-group = freerad
-
-#  max_request_time: The maximum time (in seconds) to handle a request.
-#
-#  Requests which take more time than this to process may be killed, and
-#  a REJECT message is returned.
-#
-#  WARNING: If you notice that requests take a long time to be handled,
-#  then this MAY INDICATE a bug in the server, in one of the modules
-#  used to handle a request, OR in your local configuration.
-#
-#  This problem is most often seen when using an SQL database.  If it takes
-#  more than a second or two to receive an answer from the SQL database,
-#  then it probably means that you haven't indexed the database.  See your
-#  SQL server documentation for more information.
-#
-#  Useful range of values: 5 to 120
-#
-max_request_time = 30
-
-#  delete_blocked_requests: If the request takes MORE THAN 'max_request_time'
-#  to be handled, then maybe the server should delete it.
-#
-#  If you're running in threaded, or thread pool mode, this setting
-#  should probably be 'no'.  Setting it to 'yes' when using a threaded
-#  server MAY cause the server to crash!
-#
-delete_blocked_requests = no
-
-#  cleanup_delay: The time to wait (in seconds) before cleaning up
-#  a reply which was sent to the NAS.
-#
-#  The RADIUS request is normally cached internally for a short period
-#  of time, after the reply is sent to the NAS.  The reply packet may be
-#  lost in the network, and the NAS will not see it.  The NAS will then
-#  re-send the request, and the server will respond quickly with the
-#  cached reply.
-#
-#  If this value is set too low, then duplicate requests from the NAS
-#  MAY NOT be detected, and will instead be handled as seperate requests.
-#
-#  If this value is set too high, then the server will cache too many
-#  requests, and some new requests may get blocked.  (See 'max_requests'.)
-#
-#  Useful range of values: 2 to 10
-#
-cleanup_delay = 5
-
-#  max_requests: The maximum number of requests which the server keeps
-#  track of.  This should be 256 multiplied by the number of clients.
-#  e.g. With 4 clients, this number should be 1024.
-#
-#  If this number is too low, then when the server becomes busy,
-#  it will not respond to any new requests, until the 'cleanup_delay'
-#  time has passed, and it has removed the old requests.
-#
-#  If this number is set too high, then the server will use a bit more
-#  memory for no real benefit.
-#
-#  If you aren't sure what it should be set to, it's better to set it
-#  too high than too low.  Setting it to 1000 per client is probably
-#  the highest it should be.
-#
-#  Useful range of values: 256 to infinity
-#
-max_requests = 1024
-
-#  bind_address:  Make the server listen on a particular IP address, and
-#  send replies out from that address.  This directive is most useful
-#  for machines with multiple IP addresses on one interface.
-#
-#  It can either contain "*", or an IP address, or a fully qualified
-#  Internet domain name.  The default is "*"
-#
-#  As of 1.0, you can also use the "listen" directive.  See below for
-#  more information.
-#
-bind_address = *
-
-#  port: Allows you to bind FreeRADIUS to a specific port.
-#
-#  The default port that most NAS boxes use is 1645, which is historical.
-#  RFC 2138 defines 1812 to be the new port.  Many new servers and
-#  NAS boxes use 1812, which can create interoperability problems.
-#
-#  The port is defined here to be 0 so that the server will pick up
-#  the machine's local configuration for the radius port, as defined
-#  in /etc/services.
-#
-#  If you want to use the default RADIUS port as defined on your server,
-#  (usually through 'grep radius /etc/services') set this to 0 (zero).
-#
-#  A port given on the command-line via '-p' over-rides this one.
-#
-#  As of 1.0, you can also use the "listen" directive.  See below for
-#  more information.
-#
-port = 0
-
-#
-#  By default, the server uses "bind_address" to listen to all IP's
-#  on a machine, or just one IP.  The "port" configuration is used
-#  to select the authentication port used when listening on those
-#  addresses.
-#
-#  If you want the server to listen on additional addresses, you can
-#  use the "listen" section.  A sample section (commented out) is included
-#  below.  This "listen" section duplicates the functionality of the
-#  "bind_address" and "port" configuration entries, but it only listens
-#  for authentication packets.
-#
-#  If you comment out the "bind_address" and "port" configuration entries,
-#  then it becomes possible to make the server accept only accounting,
-#  or authentication packets.  Previously, it always listened for both
-#  types of packets, and it was impossible to make it listen for only
-#  one type of packet.
-#
-#listen {
-       #  IP address on which to listen.
-       #  Allowed values are:
-       #       dotted quad (1.2.3.4)
-       #       hostname    (radius.example.com)
-       #       wildcard    (*)
-#      ipaddr = *
-
-       #  Port on which to listen.
-       #  Allowed values are:
-       #       integer port number (1812)
-       #       0 means "use /etc/services for the proper port"
-#      port = 0
-
-       #  Type of packets to listen for.
-       #  Allowed values are:
-       #       auth    listen for authentication packets
-       #       acct    listen for accounting packets
-       #
-#      type = auth
-#}
-
-
-#  hostname_lookups: Log the names of clients or just their IP addresses
-#  e.g., www.freeradius.org (on) or 206.47.27.232 (off).
-#
-#  The default is 'off' because it would be overall better for the net
-#  if people had to knowingly turn this feature on, since enabling it
-#  means that each client request will result in AT LEAST one lookup
-#  request to the nameserver.   Enabling hostname_lookups will also
-#  mean that your server may stop randomly for 30 seconds from time
-#  to time, if the DNS requests take too long.
-#
-#  Turning hostname lookups off also means that the server won't block
-#  for 30 seconds, if it sees an IP address which has no name associated
-#  with it.
-#
-#  allowed values: {no, yes}
-#
-hostname_lookups = no
-
-#  Core dumps are a bad thing.  This should only be set to 'yes'
-#  if you're debugging a problem with the server.
-#
-#  allowed values: {no, yes}
-#
-allow_core_dumps = no
-
-#  Regular expressions
-#
-#  These items are set at configure time.  If they're set to "yes",
-#  then setting them to "no" turns off regular expression support.
-#
-#  If they're set to "no" at configure time, then setting them to "yes"
-#  WILL NOT WORK.  It will give you an error.
-#
-regular_expressions    = yes
-extended_expressions   = yes
-
-#  Log the full User-Name attribute, as it was found in the request.
-#
-# allowed values: {no, yes}
-#
-log_stripped_names = no
-
-#  Log authentication requests to the log file.
-#
-#  allowed values: {no, yes}
-#
-log_auth = no
-
-#  Log passwords with the authentication requests.
-#  log_auth_badpass  - logs password if it's rejected
-#  log_auth_goodpass - logs password if it's correct
-#
-#  allowed values: {no, yes}
-#
-log_auth_badpass = no
-log_auth_goodpass = no
-
-# usercollide:  Turn "username collision" code on and off.  See the
-# "doc/duplicate-users" file
-#
-#  WARNING
-#  !!!!!!!  Setting this to "yes" may result in the server behaving
-#  !!!!!!!  strangely.  The "username collision" code will ONLY work
-#  !!!!!!!  with clear-text passwords.  Even then, it may not do what
-#  !!!!!!!  you want, or what you expect.
-#  !!!!!!!
-#  !!!!!!!  We STRONGLY RECOMMEND that you do not use this feature,
-#  !!!!!!!  and that you find another way of acheiving the same goal.
-#  !!!!!!!
-#  !!!!!!!  e,g. module fail-over.  See 'doc/configurable_failover'
-#  WARNING
-#
-usercollide = no
-
-# lower_user / lower_pass:  
-# Lower case the username/password "before" or "after"
-# attempting to authenticate.  
-#
-#  If "before", the server will first modify the request and then try
-#  to auth the user.  If "after", the server will first auth using the
-#  values provided by the user.  If that fails it will reprocess the
-#  request after modifying it as you specify below.
-#
-#  This is as close as we can get to case insensitivity.  It is the
-#  admin's job to ensure that the username on the auth db side is
-#  *also* lowercase to make this work
-#
-# Default is 'no' (don't lowercase values)
-# Valid values = "before" / "after" / "no"
-#
-lower_user = no
-lower_pass = no
-
-# nospace_user / nospace_pass:
-#
-#  Some users like to enter spaces in their username or password
-#  incorrectly.  To save yourself the tech support call, you can
-#  eliminate those spaces here:
-#
-# Default is 'no' (don't remove spaces)
-# Valid values = "before" / "after" / "no" (explanation above)
-#
-nospace_user = no
-nospace_pass = no
-
-#  The program to execute to do concurrency checks.
-checkrad = ${sbindir}/checkrad
-
-# SECURITY CONFIGURATION
-#
-#  There may be multiple methods of attacking on the server.  This
-#  section holds the configuration items which minimize the impact
-#  of those attacks
-#
-security {
-       #
-       #  max_attributes: The maximum number of attributes
-       #  permitted in a RADIUS packet.  Packets which have MORE
-       #  than this number of attributes in them will be dropped.
-       #
-       #  If this number is set too low, then no RADIUS packets
-       #  will be accepted.
-       #
-       #  If this number is set too high, then an attacker may be
-       #  able to send a small number of packets which will cause
-       #  the server to use all available memory on the machine.
-       #
-       #  Setting this number to 0 means "allow any number of attributes"
-       max_attributes = 200
-
-       #
-       #  reject_delay: When sending an Access-Reject, it can be
-       #  delayed for a few seconds.  This may help slow down a DoS
-       #  attack.  It also helps to slow down people trying to brute-force
-       #  crack a users password.
-       #
-       #  Setting this number to 0 means "send rejects immediately"
-       #
-       #  If this number is set higher than 'cleanup_delay', then the
-       #  rejects will be sent at 'cleanup_delay' time, when the request
-       #  is deleted from the internal cache of requests.
-       #
-       #  Useful ranges: 1 to 5
-       reject_delay = 1
-
-       #
-       #  status_server: Whether or not the server will respond
-       #  to Status-Server requests.
-       #
-       #  Normally this should be set to "no", because they're useless.
-       #  See: http://www.freeradius.org/rfc/rfc2865.html#Keep-Alives
-       #
-       #  However, certain NAS boxes may require them. 
-       #
-       #  When sent a Status-Server message, the server responds with
-       #  an Access-Accept packet, containing a Reply-Message attribute,
-       #  which is a string describing how long the server has been
-       #  running.
-       #
-       status_server = no
-}
-
-# PROXY CONFIGURATION
-#
-#  proxy_requests: Turns proxying of RADIUS requests on or off.
-#
-#  The server has proxying turned on by default.  If your system is NOT
-#  set up to proxy requests to another server, then you can turn proxying
-#  off here.  This will save a small amount of resources on the server.
-#
-#  If you have proxying turned off, and your configuration files say
-#  to proxy a request, then an error message will be logged.
-#
-#  To disable proxying, change the "yes" to "no", and comment the
-#  $INCLUDE line.
-#
-#  allowed values: {no, yes}
-#
-proxy_requests  = yes
-$INCLUDE  ${confdir}/proxy.conf
-
-
-# CLIENTS CONFIGURATION
-#
-#  Client configuration is defined in "clients.conf".  
-#
-
-#  The 'clients.conf' file contains all of the information from the old
-#  'clients' and 'naslist' configuration files.  We recommend that you
-#  do NOT use 'client's or 'naslist', although they are still
-#  supported.
-#
-#  Anything listed in 'clients.conf' will take precedence over the
-#  information from the old-style configuration files.
-#
-$INCLUDE  ${confdir}/clients.conf
-
-
-# SNMP CONFIGURATION
-#
-#  Snmp configuration is only valid if SNMP support was enabled
-#  at compile time.
-#
-#  To enable SNMP querying of the server, set the value of the
-#  'snmp' attribute to 'yes'
-#
-snmp   = no
-$INCLUDE  ${confdir}/snmp.conf
-
-
-# THREAD POOL CONFIGURATION
-#
-#  The thread pool is a long-lived group of threads which
-#  take turns (round-robin) handling any incoming requests.
-#
-#  You probably want to have a few spare threads around,
-#  so that high-load situations can be handled immediately.  If you
-#  don't have any spare threads, then the request handling will
-#  be delayed while a new thread is created, and added to the pool.
-#
-#  You probably don't want too many spare threads around,
-#  otherwise they'll be sitting there taking up resources, and
-#  not doing anything productive.
-#
-#  The numbers given below should be adequate for most situations.
-#
-thread pool {
-       #  Number of servers to start initially --- should be a reasonable
-       #  ballpark figure.
-       start_servers = 5
-
-       #  Limit on the total number of servers running.
-       #
-       #  If this limit is ever reached, clients will be LOCKED OUT, so it
-       #  should NOT BE SET TOO LOW.  It is intended mainly as a brake to
-       #  keep a runaway server from taking the system with it as it spirals
-       #  down...
-       #
-       #  You may find that the server is regularly reaching the
-       #  'max_servers' number of threads, and that increasing
-       #  'max_servers' doesn't seem to make much difference.
-       #
-       #  If this is the case, then the problem is MOST LIKELY that
-       #  your back-end databases are taking too long to respond, and
-       #  are preventing the server from responding in a timely manner.
-       #
-       #  The solution is NOT do keep increasing the 'max_servers'
-       #  value, but instead to fix the underlying cause of the
-       #  problem: slow database, or 'hostname_lookups=yes'.
-       #
-       #  For more information, see 'max_request_time', above.
-       #
-       max_servers = 32
-
-       #  Server-pool size regulation.  Rather than making you guess
-       #  how many servers you need, FreeRADIUS dynamically adapts to
-       #  the load it sees, that is, it tries to maintain enough
-       #  servers to handle the current load, plus a few spare
-       #  servers to handle transient load spikes.
-       #
-       #  It does this by periodically checking how many servers are
-       #  waiting for a request.  If there are fewer than
-       #  min_spare_servers, it creates a new spare.  If there are
-       #  more than max_spare_servers, some of the spares die off.
-       #  The default values are probably OK for most sites.
-       #
-       min_spare_servers = 3
-       max_spare_servers = 10
-
-       #  There may be memory leaks or resource allocation problems with
-       #  the server.  If so, set this value to 300 or so, so that the
-       #  resources will be cleaned up periodically.
-       #
-       #  This should only be necessary if there are serious bugs in the
-       #  server which have not yet been fixed.
-       #
-       #  '0' is a special value meaning 'infinity', or 'the servers never
-       #  exit'
-       max_requests_per_server = 0
-}
-
-# MODULE CONFIGURATION
-#
-#  The names and configuration of each module is located in this section.
-#
-#  After the modules are defined here, they may be referred to by name,
-#  in other sections of this configuration file.
-#
-modules {
-       #
-       #  Each module has a configuration as follows:
-       #
-       #       name [ instance ] {
-       #               config_item = value
-       #               ...
-       #       }
-       #
-       #  The 'name' is used to load the 'rlm_name' library
-       #  which implements the functionality of the module.
-       #
-       #  The 'instance' is optional.  To have two different instances
-       #  of a module, it first must be referred to by 'name'.
-       #  The different copies of the module are then created by
-       #  inventing two 'instance' names, e.g. 'instance1' and 'instance2'
-       #
-       #  The instance names can then be used in later configuration
-       #  INSTEAD of the original 'name'.  See the 'radutmp' configuration
-       #  below for an example.
-       #
-
-       # PAP module to authenticate users based on their stored password
-       #
-       #  Supports multiple encryption schemes
-       #  clear: Clear text
-       #  crypt: Unix crypt
-       #    md5: MD5 ecnryption
-       #   sha1: SHA1 encryption.
-       #  DEFAULT: crypt
-       pap {
-               encryption_scheme = crypt
-       }
-
-       # CHAP module
-       #
-       #  To authenticate requests containing a CHAP-Password attribute.
-       #
-       chap {
-               authtype = CHAP
-       }
-
-       #  Extensible Authentication Protocol
-       #
-       #  For all EAP related authentications.
-       #  Now in another file, because it is very large.
-       #
-$INCLUDE ${confdir}/eap.conf
-
-       # Microsoft CHAP authentication
-       #
-       #  This module supports MS-CHAP and MS-CHAPv2 authentication.
-       #  It also enforces the SMB-Account-Ctrl attribute.
-       #
-       mschap {
-               #
-               #  As of 0.9, the mschap module does NOT support
-               #  reading from /etc/smbpasswd.
-               #
-               #  If you are using /etc/smbpasswd, see the 'passwd'
-               #  module for an example of how to use /etc/smbpasswd
-
-               # if use_mppe is not set to no mschap will
-               # add MS-CHAP-MPPE-Keys for MS-CHAPv1 and
-               # MS-MPPE-Recv-Key/MS-MPPE-Send-Key for MS-CHAPv2
-               #
-               use_mppe = yes
-               authtype = MS-CHAP
-
-               # if mppe is enabled require_encryption makes
-               # encryption moderate
-               #
-               #require_encryption = yes
-
-               # require_strong always requires 128 bit key
-               # encryption
-               #
-               #require_strong = yes
-
-               # Windows sends us a username in the form of
-               # DOMAIN\user, but sends the challenge response
-               # based on only the user portion.  This hack
-               # corrects for that incorrect behavior.
-               #
-               #with_ntdomain_hack = no
-
-               # The module can perform authentication itself, OR
-               # use a Windows Domain Controller.  This configuration
-               # directive tells the module to call the ntlm_auth
-               # program, which will do the authentication, and return
-               # the NT-Key.  Note that you MUST have "winbindd" and
-               # "nmbd" running on the local machine for ntlm_auth
-               # to work.  See the ntlm_auth program documentation
-               # for details.
-               #
-               # Be VERY careful when editing the following line!
-               #
-               #ntlm_auth = "/path/to/ntlm_auth --request-nt-key --username=%{Stripped-User-Name:-%{User-Name:-None}} --challenge=%{mschap:Challenge:-00} --nt-response=%{mschap:NT-Response:-00}"
-       }
-
-       # Preprocess the incoming RADIUS request, before handing it off
-       # to other modules.
-       #
-       #  This module processes the 'huntgroups' and 'hints' files.
-       #  In addition, it re-writes some weird attributes created
-       #  by some NASes, and converts the attributes into a form which
-       #  is a little more standard.
-       #
-       preprocess {
-               huntgroups = ${confdir}/huntgroups
-               hints = ${confdir}/hints
-
-               # This hack changes Ascend's wierd port numberings
-               # to standard 0-??? port numbers so that the "+" works
-               # for IP address assignments.
-               with_ascend_hack = no
-               ascend_channels_per_line = 23
-
-               # Windows NT machines often authenticate themselves as
-               # NT_DOMAIN\username
-               #
-               # If this is set to 'yes', then the NT_DOMAIN portion
-               # of the user-name is silently discarded.
-               #
-               # This configuration entry SHOULD NOT be used.
-               # See the "realms" module for a better way to handle
-               # NT domains.
-               with_ntdomain_hack = no
-
-               # Specialix Jetstream 8500 24 port access server.
-               #
-               # If the user name is 10 characters or longer, a "/"
-               # and the excess characters after the 10th are
-               # appended to the user name.
-               #
-               # If you're not running that NAS, you don't need
-               # this hack.
-               with_specialix_jetstream_hack = no
-
-               # Cisco (and Quintum in Cisco mode) sends it's VSA attributes
-               # with the attribute name *again* in the string, like:
-               #
-               #   H323-Attribute = "h323-attribute=value".
-               #
-               # If this configuration item is set to 'yes', then
-               # the redundant data in the the attribute text is stripped
-               # out.  The result is:
-               #
-               #  H323-Attribute = "value"
-               #
-               # If you're not running a Cisco or Quintum NAS, you don't
-               # need this hack.
-               with_cisco_vsa_hack = no
-       }
-
-       # Write a detailed log of all accounting records received.
-       #
-       detail {
-               #  Note that we do NOT use NAS-IP-Address here, as
-               #  that attribute MAY BE from the originating NAS, and
-               #  NOT from the proxy which actually sent us the
-               #  request.  The Client-IP-Address attribute is ALWAYS
-               #  the address of the client which sent us the
-               #  request.
-               #
-               #  The following line creates a new detail file for
-               #  every radius client (by IP address or hostname).
-               #  In addition, a new detail file is created every
-               #  day, so that the detail file doesn't have to go
-               #  through a 'log rotation'
-               #
-               #  If your detail files are large, you may also want
-               #  to add a ':%H' (see doc/variables.txt) to the end
-               #  of it, to create a new detail file every hour, e.g.:
-               #
-               #   ..../detail-%Y%m%d:%H
-               #
-               #  This will create a new detail file for every hour.
-               #
-               detailfile = ${radacctdir}/%{Client-IP-Address}/detail-%Y%m%d
-
-               #
-               #  The Unix-style permissions on the 'detail' file.
-               #
-               #  The detail file often contains secret or private
-               #  information about users.  So by keeping the file
-               #  permissions restrictive, we can prevent unwanted
-               #  people from seeing that information.
-               detailperm = 0600
-
-               #
-               # Certain attributes such as User-Password may be
-               # "sensitive", so they should not be printed in the
-               # detail file.  This section lists the attributes
-               # that should be suppressed.
-               #
-               # The attributes should be listed one to a line.
-               #
-               #suppress {
-                       # User-Password
-               #}
-       }
-
-       #
-       #  Create a unique accounting session Id.  Many NASes re-use
-       #  or repeat values for Acct-Session-Id, causing no end of
-       #  confusion.
-       #
-       #  This module will add a (probably) unique session id 
-       #  to an accounting packet based on the attributes listed
-       #  below found in the packet.  See doc/rlm_acct_unique for
-       #  more information.
-       #
-       acct_unique {
-               key = "User-Name, Acct-Session-Id, NAS-IP-Address, Client-IP-Address, NAS-Port"
-       }
-
-       #  Write a 'utmp' style file, of which users are currently
-       #  logged in, and where they've logged in from.
-       #
-       #  This file is used mainly for Simultaneous-Use checking,
-       #  and also 'radwho', to see who's currently logged in.
-       #
-       radutmp {
-               #  Where the file is stored.  It's not a log file,
-               #  so it doesn't need rotating.
-               #
-               filename = ${logdir}/radutmp
-
-               #  The field in the packet to key on for the
-               #  'user' name,  If you have other fields which you want
-               #  to use to key on to control Simultaneous-Use,
-               #  then you can use them here.
-               #
-               #  Note, however, that the size of the field in the
-               #  'utmp' data structure is small, around 32
-               #  characters, so that will limit the possible choices
-               #  of keys.
-               #
-               #  You may want instead: %{Stripped-User-Name:-%{User-Name}}
-               username = %{User-Name}
-
-
-               #  Whether or not we want to treat "user" the same
-               #  as "USER", or "User".  Some systems have problems
-               #  with case sensitivity, so this should be set to
-               #  'no' to enable the comparisons of the key attribute
-               #  to be case insensitive.
-               #
-               case_sensitive = yes
-
-               #  Accounting information may be lost, so the user MAY
-               #  have logged off of the NAS, but we haven't noticed.
-               #  If so, we can verify this information with the NAS,
-               #
-               #  If we want to believe the 'utmp' file, then this
-               #  configuration entry can be set to 'no'.
-               #
-               check_with_nas = yes            
-
-               # Set the file permissions, as the contents of this file
-               # are usually private.
-               perm = 0600
-
-               callerid = "yes"
-       }
-
-       # "Safe" radutmp - does not contain caller ID, so it can be
-       # world-readable, and radwho can work for normal users, without
-       # exposing any information that isn't already exposed by who(1).
-       #
-       # This is another 'instance' of the radutmp module, but it is given
-       # then name "sradutmp" to identify it later in the "accounting"
-       # section.
-       radutmp sradutmp {
-               filename = ${logdir}/sradutmp
-               perm = 0644
-               callerid = "no"
-       }
-
-       # attr_filter - filters the attributes received in replies from
-       # proxied servers, to make sure we send back to our RADIUS client
-       # only allowed attributes.
-       attr_filter {
-               attrsfile = ${confdir}/attrs
-       }
-
-       #  counter module:
-       #  This module takes an attribute (count-attribute).
-       #  It also takes a key, and creates a counter for each unique
-       #  key.  The count is incremented when accounting packets are
-       #  received by the server.  The value of the increment depends
-       #  on the attribute type.
-       #  If the attribute is Acct-Session-Time or of an integer type we add the
-       #  value of the attribute. If it is anything else we increase the
-       #  counter by one.
-       #
-       #  The 'reset' parameter defines when the counters are all reset to
-       #  zero.  It can be hourly, daily, weekly, monthly or never.
-       #
-       #  hourly: Reset on 00:00 of every hour
-       #  daily: Reset on 00:00:00 every day
-       #  weekly: Reset on 00:00:00 on sunday
-       #  monthly: Reset on 00:00:00 of the first day of each month
-       #
-       #  It can also be user defined. It should be of the form:
-       #  num[hdwm] where:
-       #  h: hours, d: days, w: weeks, m: months
-       #  If the letter is ommited days will be assumed. In example:
-       #  reset = 10h (reset every 10 hours)
-       #  reset = 12  (reset every 12 days)
-       #
-       #
-       #  The check-name attribute defines an attribute which will be
-       #  registered by the counter module and can be used to set the
-       #  maximum allowed value for the counter after which the user
-       #  is rejected.
-       #  Something like:
-       #
-       #  DEFAULT Max-Daily-Session := 36000
-       #          Fall-Through = 1
-       #
-       #  You should add the counter module in the instantiate
-       #  section so that it registers check-name before the files
-       #  module reads the users file.
-       #
-       #  If check-name is set and the user is to be rejected then we
-       #  send back a Reply-Message and we log a Failure-Message in
-       #  the radius.log
-       #  If the count attribute is Acct-Session-Time then on each login
-       #  we send back the remaining online time as a Session-Timeout attribute
-       #
-       #  The counter-name can also be used instead of using the check-name
-       #  like below:
-       #
-       #  DEFAULT  Daily-Session-Time > 3600, Auth-Type = Reject
-       #      Reply-Message = "You've used up more than one hour today"
-       #
-       #  The allowed-servicetype attribute can be used to only take
-       #  into account specific sessions. For example if a user first
-       #  logs in through a login menu and then selects ppp there will
-       #  be two sessions. One for Login-User and one for Framed-User
-       #  service type. We only need to take into account the second one.
-       #
-       #  The module should be added in the instantiate, authorize and
-       #  accounting sections.  Make sure that in the authorize
-       #  section it comes after any module which sets the
-       #  'check-name' attribute.
-       #
-       counter daily {
-               filename = ${raddbdir}/db.daily
-               key = User-Name
-               count-attribute = Acct-Session-Time
-               reset = daily
-               counter-name = Daily-Session-Time
-               check-name = Max-Daily-Session
-               allowed-servicetype = Framed-User
-               cache-size = 5000
-       }
-
-       #
-       # The "always" module is here for debugging purposes. Each
-       # instance simply returns the same result, always, without
-       # doing anything.
-       always fail {
-               rcode = fail
-       }
-       always reject {
-               rcode = reject
-       }
-       always ok {
-               rcode = ok
-               simulcount = 0
-               mpp = no
-       }
-
-       stg {
-               local_port = 6667
-               server = localhost
-               port = 6666
-               password = 123456
-       }
-
-}
-
-# Instantiation
-#
-#  This section orders the loading of the modules.  Modules
-#  listed here will get loaded BEFORE the later sections like
-#  authorize, authenticate, etc. get examined.
-#
-#  This section is not strictly needed.  When a section like
-#  authorize refers to a module, it's automatically loaded and
-#  initialized.  However, some modules may not be listed in any
-#  of the following sections, so they can be listed here.
-#
-#  Also, listing modules here ensures that you have control over
-#  the order in which they are initalized.  If one module needs
-#  something defined by another module, you can list them in order
-#  here, and ensure that the configuration will be OK.
-#
-instantiate {
-       stg
-}
-
-#  Authorization. First preprocess (hints and huntgroups files),
-#  then realms, and finally look in the "users" file.
-#
-#  The order of the realm modules will determine the order that
-#  we try to find a matching realm.
-#
-#  Make *sure* that 'preprocess' comes before any realm if you 
-#  need to setup hints for the remote radius server
-authorize {
-       #
-       #  The preprocess module takes care of sanitizing some bizarre
-       #  attributes in the request, and turning them into attributes
-       #  which are more standard.
-       #
-       #  It takes care of processing the 'raddb/hints' and the
-       #  'raddb/huntgroups' files.
-       #
-       #  It also adds the %{Client-IP-Address} attribute to the request.
-       preprocess
-
-       #
-       #  The chap module will set 'Auth-Type := CHAP' if we are
-       #  handling a CHAP request and Auth-Type has not already been set
-       chap
-
-       #
-       #  If the users are logging in with an MS-CHAP-Challenge
-       #  attribute for authentication, the mschap module will find
-       #  the MS-CHAP-Challenge attribute, and add 'Auth-Type := MS-CHAP'
-       #  to the request, which will cause the server to then use
-       #  the mschap module for authentication.
-       mschap
-
-       #
-       #  This module takes care of EAP-MD5, EAP-TLS, and EAP-LEAP
-       #  authentication.
-       #
-       #  It also sets the EAP-Type attribute in the request
-       #  attribute list to the EAP type from the packet.
-       eap
-
-       stg
-}
-
-
-#  Authentication.
-#
-#
-#  This section lists which modules are available for authentication.
-#  Note that it does NOT mean 'try each module in order'.  It means
-#  that a module from the 'authorize' section adds a configuration
-#  attribute 'Auth-Type := FOO'.  That authentication type is then
-#  used to pick the apropriate module from the list below.
-#
-
-#  In general, you SHOULD NOT set the Auth-Type attribute.  The server
-#  will figure it out on its own, and will do the right thing.  The
-#  most common side effect of erroneously setting the Auth-Type
-#  attribute is that one authentication method will work, but the
-#  others will not.
-#
-#  The common reasons to set the Auth-Type attribute by hand
-#  is to either forcibly reject the user, or forcibly accept him.
-#
-authenticate {
-       #
-       #  PAP authentication, when a back-end database listed
-       #  in the 'authorize' section supplies a password.  The
-       #  password can be clear-text, or encrypted.
-       Auth-Type PAP {
-               stg
-               pap
-       }
-
-       #
-       #  Most people want CHAP authentication
-       #  A back-end database listed in the 'authorize' section
-       #  MUST supply a CLEAR TEXT password.  Encrypted passwords
-       #  won't work.
-       Auth-Type CHAP {
-               stg
-               chap
-       }
-
-       #
-       #  MSCHAP authentication.
-       Auth-Type MS-CHAP {
-               stg
-               mschap
-       }
-
-       #
-       #  Allow EAP authentication.
-       eap
-}
-
-
-#
-#  Pre-accounting.  Decide which accounting type to use.
-#
-preacct {
-       preprocess
-
-       #
-       #  Ensure that we have a semi-unique identifier for every
-       #  request, and many NAS boxes are broken.
-       acct_unique
-}
-
-#
-#  Accounting.  Log the accounting data.
-#
-accounting {
-       #
-       #  Create a 'detail'ed log of the packets.
-       #  Note that accounting requests which are proxied
-       #  are also logged in the detail file.
-       detail
-#      daily
-
-       #
-       #  For Simultaneous-Use tracking.
-       #
-       #  Due to packet losses in the network, the data here
-       #  may be incorrect.  There is little we can do about it.
-       radutmp
-
-       stg
-
-}
-
-
-#  Session database, used for checking Simultaneous-Use. Either the radutmp 
-#  or rlm_sql module can handle this.
-#  The rlm_sql module is *much* faster
-session {
-       radutmp
-}
-
-
-#  Post-Authentication
-#  Once we KNOW that the user has been authenticated, there are
-#  additional steps we can take.
-post-auth {
-       stg
-}
-
-#
-#  When the server decides to proxy a request to a home server,
-#  the proxied request is first passed through the pre-proxy
-#  stage.  This stage can re-write the request, or decide to
-#  cancel the proxy.
-#
-#  Only a few modules currently have this method.
-#
-pre-proxy {
-}
-
-#
-#  When the server receives a reply to a request it proxied
-#  to a home server, the request may be massaged here, in the
-#  post-proxy stage.
-#
-post-proxy {
-       #
-       #  If you are proxying LEAP, you MUST configure the EAP
-       #  module, and you MUST list it here, in the post-proxy
-       #  stage.
-       #
-       #  You MUST also use the 'nostrip' option in the 'realm'
-       #  configuration.  Otherwise, the User-Name attribute
-       #  in the proxied request will not match the user name
-       #  hidden inside of the EAP packet, and the end server will
-       #  reject the EAP request.
-       #
-       eap
-}
diff --git a/stargazer/scripts/shaper_vpn_radius/ppp/ip-down.d/stg b/stargazer/scripts/shaper_vpn_radius/ppp/ip-down.d/stg
deleted file mode 100755 (executable)
index e9c7eaf..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-rm -f /var/stargazer/ifaces/$PPP_REMOTE
\ No newline at end of file
diff --git a/stargazer/scripts/shaper_vpn_radius/ppp/ip-up.d/stg b/stargazer/scripts/shaper_vpn_radius/ppp/ip-up.d/stg
deleted file mode 100755 (executable)
index 6a0b645..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-echo $PPP_IFACE > /var/stargazer/ifaces/$PPP_REMOTE
\ No newline at end of file
diff --git a/stargazer/scripts/shaper_vpn_radius/ppp/pptpd-options b/stargazer/scripts/shaper_vpn_radius/ppp/pptpd-options
deleted file mode 100644 (file)
index af58ba4..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-###############################################################################
-# $Id: pptpd-options,v 1.1 2008/03/31 13:55:20 faust Exp $
-#
-# Sample Poptop PPP options file /etc/ppp/pptpd-options
-# Options used by PPP when a connection arrives from a client.
-# This file is pointed to by /etc/pptpd.conf option keyword.
-# Changes are effective on the next connection.  See "man pppd".
-#
-# You are expected to change this file to suit your system.  As
-# packaged, it requires PPP 2.4.2 and the kernel MPPE module.
-###############################################################################
-
-
-# Authentication
-
-# Name of the local system for authentication purposes 
-# (must match the second field in /etc/ppp/chap-secrets entries)
-name pptpd
-
-# Optional: domain name to use for authentication
-# domain mydomain.net
-
-# Strip the domain prefix from the username before authentication.
-# (applies if you use pppd with chapms-strip-domain patch)
-#chapms-strip-domain
-
-
-# Encryption
-# Debian: on systems with a kernel built with the package
-# kernel-patch-mppe >= 2.4.2 and using ppp >= 2.4.2, ...
-# {{{
-refuse-pap
-refuse-chap
-refuse-mschap
-# Require the peer to authenticate itself using MS-CHAPv2 [Microsoft
-# Challenge Handshake Authentication Protocol, Version 2] authentication.
-require-mschap-v2
-# Require MPPE 128-bit encryption
-# (note that MPPE requires the use of MSCHAP-V2 during authentication)
-require-mppe-128
-# }}}
-
-
-
-
-# Network and Routing
-
-# If pppd is acting as a server for Microsoft Windows clients, this
-# option allows pppd to supply one or two DNS (Domain Name Server)
-# addresses to the clients.  The first instance of this option
-# specifies the primary DNS address; the second instance (if given)
-# specifies the secondary DNS address.
-# Attention! This information may not be taken into account by a Windows
-# client. See KB311218 in Microsoft's knowledge base for more information.
-#ms-dns 10.0.0.1
-#ms-dns 10.0.0.2
-
-# If pppd is acting as a server for Microsoft Windows or "Samba"
-# clients, this option allows pppd to supply one or two WINS (Windows
-# Internet Name Services) server addresses to the clients.  The first
-# instance of this option specifies the primary WINS address; the
-# second instance (if given) specifies the secondary WINS address.
-#ms-wins 10.0.0.3
-#ms-wins 10.0.0.4
-
-# Add an entry to this system's ARP [Address Resolution Protocol]
-# table with the IP address of the peer and the Ethernet address of this
-# system.  This will have the effect of making the peer appear to other
-# systems to be on the local ethernet.
-# (you do not need this if your PPTP server is responsible for routing
-# packets to the clients -- James Cameron)
-proxyarp
-
-# Debian: do not replace the default route
-defaultroute
-
-
-# Logging
-
-# Enable connection debugging facilities.
-# (see your syslog configuration for where pppd sends to)
-#debug
-
-# Print out all the option values which have been set.
-# (often requested by mailing list to verify options)
-#dump
-
-
-# Miscellaneous
-
-# Create a UUCP-style lock file for the pseudo-tty to ensure exclusive
-# access.
-lock
-
-# Disable BSD-Compress compression
-nobsdcomp 
-plugin radius.so
\ No newline at end of file
diff --git a/stargazer/scripts/shaper_vpn_radius/pptpd.conf b/stargazer/scripts/shaper_vpn_radius/pptpd.conf
deleted file mode 100644 (file)
index 5c64b83..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-###############################################################################
-# $Id: pptpd.conf,v 1.1 2008/03/31 13:54:13 faust Exp $
-#
-# Sample Poptop configuration file /etc/pptpd.conf
-#
-# Changes are effective when pptpd is restarted.
-###############################################################################
-
-# TAG: ppp
-#      Path to the pppd program, default '/usr/sbin/pppd' on Linux
-#
-#ppp /usr/sbin/pppd
-
-# TAG: option
-#      Specifies the location of the PPP options file.
-#      By default PPP looks in '/etc/ppp/options'
-#
-option /etc/ppp/pptpd-options
-
-# TAG: debug
-#      Turns on (more) debugging to syslog
-#
-#debug
-
-# TAG: stimeout
-#      Specifies timeout (in seconds) on starting ctrl connection
-#
-# stimeout 10
-
-# TAG: noipparam
-#       Suppress the passing of the client's IP address to PPP, which is
-#       done by default otherwise.
-#
-#noipparam
-
-# TAG: logwtmp
-#      Use wtmp(5) to record client connections and disconnections.
-#
-logwtmp
-
-# TAG: bcrelay <if>
-#      Turns on broadcast relay to clients from interface <if>
-#
-#bcrelay eth1
-
-# TAG: localip
-# TAG: remoteip
-#      Specifies the local and remote IP address ranges.
-#
-#       Any addresses work as long as the local machine takes care of the
-#       routing.  But if you want to use MS-Windows networking, you should
-#       use IP addresses out of the LAN address space and use the proxyarp
-#       option in the pppd options file, or run bcrelay.
-#
-#      You can specify single IP addresses seperated by commas or you can
-#      specify ranges, or both. For example:
-#
-#              192.168.0.234,192.168.0.245-249,192.168.0.254
-#
-#      IMPORTANT RESTRICTIONS:
-#
-#      1. No spaces are permitted between commas or within addresses.
-#
-#      2. If you give more IP addresses than MAX_CONNECTIONS, it will
-#         start at the beginning of the list and go until it gets 
-#         MAX_CONNECTIONS IPs. Others will be ignored.
-#
-#      3. No shortcuts in ranges! ie. 234-8 does not mean 234 to 238,
-#         you must type 234-238 if you mean this.
-#
-#      4. If you give a single localIP, that's ok - all local IPs will
-#         be set to the given one. You MUST still give at least one remote
-#         IP for each simultaneous client.
-#
-# (Recommended)
-#localip 192.168.0.1
-#remoteip 192.168.0.234-238,192.168.0.245
-# or
-#localip 192.168.0.234-238,192.168.0.245
-#remoteip 192.168.1.234-238,192.168.1.245
-localip 192.168.2.1
-remoteip 192.168.2.2-254
diff --git a/stargazer/scripts/shaper_vpn_radius/radiusclient/servers b/stargazer/scripts/shaper_vpn_radius/radiusclient/servers
deleted file mode 100644 (file)
index 03a1d94..0000000
+++ /dev/null
@@ -1 +0,0 @@
-localhost testing123
diff --git a/stargazer/scripts/shaper_vpn_radius/stargazer/OnChange b/stargazer/scripts/shaper_vpn_radius/stargazer/OnChange
deleted file mode 100755 (executable)
index 6d99f17..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#! /bin/sh
-
-login=$1
-param=$2
-oldValue=$3
-newValue=$4
-
-#echo "User: '$login'. Parameter $param changed from '$oldValue' to '$newValue'" >> /var/stargazer/users.chg.log
diff --git a/stargazer/scripts/shaper_vpn_radius/stargazer/OnConnect b/stargazer/scripts/shaper_vpn_radius/stargazer/OnConnect
deleted file mode 100755 (executable)
index 099a219..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-#!/bin/bash
-
-#Этот скрипт вызывается в момент, когда пользователь
-#успешно прошел авторизацию на сервере. Задача скрипта - перестроить 
-#файрвол так, что бы пользователь получил доступ в интернет
-
-# Login
-LOGIN=$1
-
-#user IP
-IP=$2
-
-#cash
-CASH=$3
-
-#user ID
-ID=$4
-
-#Selected dirs to connect
-DIRS=$5
-
-iptables -A INPUT -s $IP -j QUEUE
-iptables -A OUTPUT -d $IP -j QUEUE
-iptables -A FORWARD -s $IP -j QUEUE
-iptables -A FORWARD -d $IP -j QUEUE
-
-# shaper
-
-default_speed=32
-
-speedR=$(grep -i "^Userdata0=" /var/stargazer/users/$LOGIN/conf | cut -f 2 -d"=")
-#echo "speedR=$speedR" >> /var/stargazer/users/$LOGIN/connect.log
-speed=$(echo $speedR | grep "^[0-9]*[0-9]$")
-
-if [ -z "$speed" ] 
-then
-    speed=$default_speed
-fi
-
-speedkbit=$speed"kbit"
-
-#echo "speed=$speedkbit" >> /var/stargazer/users/$LOGIN/connect.log
-declare -i mark=$ID+1
-
-iptables -t mangle -A FORWARD -d $IP -j MARK --set-mark $mark
-
-sleep 1
-
-if [ -f "/var/stargazer/ifaces/$IP" ]
-then
-    #echo "1" >> /var/stargazer/users/$LOGIN/connect.log
-    ppp_iface=$(cat /var/stargazer/ifaces/$IP)
-else
-    #echo "2" >> /var/stargazer/users/$LOGIN/connect.log
-    exit 0
-fi
-
-tc qdisc add dev $ppp_iface root handle 1: htb
-tc class add dev $ppp_iface parent 1: classid 1:1 htb rate 100mbit ceil 100mbit burst 200k
-tc class add dev $ppp_iface parent 1:1 classid 1:10 htb rate $speedkbit burst 20k
-tc filter add dev $ppp_iface parent 1: protocol ip prio 3 handle $mark fw classid 1:10
-
-#echo "C `date +%Y.%m.%d-%H.%M.%S` $IP $CASH $ID $mark $speed $ppp_iface" >> /var/stargazer/users/$LOGIN/connect.log
-
diff --git a/stargazer/scripts/shaper_vpn_radius/stargazer/OnDisconnect b/stargazer/scripts/shaper_vpn_radius/stargazer/OnDisconnect
deleted file mode 100755 (executable)
index 482e926..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/bin/bash
-
-# Этот скрипт вызывается в момент, когда пользователь
-# желает отключится от интернета или вышел таймаут у пользователя
-# и сервер сам отключает пользователя
-# Задача скрипта подобна задаче скрипта OnConnect - перестроить 
-# файрвол так, что бы пользователю закрыть доступ в интернет
-
-# Login
-LOGIN=$1
-
-#user IP
-IP=$2
-
-#cash
-CASH=$3
-
-#user ID
-ID=$4
-
-#Selected dirs to disconnect
-DIRS=$4
-
-#echo "D `date +%Y.%m.%d-%H.%M.%S` $IP $CASH" >> /var/stargazer/users/$LOGIN/connect.log
-
-iptables -D INPUT -s $IP -j QUEUE
-while [ $? == 0 ]
-do
-    iptables -D INPUT -s $IP -j QUEUE
-done
-
-iptables -D OUTPUT -d $IP -j QUEUE
-while [ $? == 0 ]
-do
-    iptables -D OUTPUT -d $IP -j QUEUE
-done
-
-iptables -D FORWARD -s $IP -j QUEUE
-while [ $? == 0 ]
-do
-    iptables -D FORWARD -s $IP -j QUEUE
-done
-
-iptables -D FORWARD -d $IP -j QUEUE
-while [ $? == 0 ]
-do
-    iptables -D FORWARD -d $IP -j QUEUE
-done
-
-
-
-declare -i mark=$ID+1
-
-iptables -t mangle -D FORWARD -d $IP -j MARK --set-mark $mark
-while [ $? == 0 ]
-do
-    iptables -t mangle -D FORWARD -d $IP -j MARK --set-mark $mark
-done
-
-
-if [ -f /var/stargazer/ifaces/$IP ]
-then
-    ppp_iface=$(cat /var/stargazer/ifaces/$IP)
-else
-    exit 0
-fi
-
-tc qdisc del dev $ppp_iface root
-
-
diff --git a/stargazer/scripts/shaper_vpn_radius/stargazer/OnUserAdd b/stargazer/scripts/shaper_vpn_radius/stargazer/OnUserAdd
deleted file mode 100755 (executable)
index 22d321c..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#! /bin/sh
-
-# Использование (неиспользование) этого скрипта дело вкуса.
-# Он не выполняет критических функций. Его задача автматизировать
-# действия характерные при добавлении пользователя сети, например добавлекние 
-# пользователю почты
-
-# Login
-login=$1
-
-#echo "added user $login" >> /var/stargazer/add_del.log
-
-
-
diff --git a/stargazer/scripts/shaper_vpn_radius/stargazer/OnUserDel b/stargazer/scripts/shaper_vpn_radius/stargazer/OnUserDel
deleted file mode 100755 (executable)
index 248e5b3..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#! /bin/sh
-
-# Login
-login=$1
-
-#echo "deleted user $login" >> /var/stargazer/add_del.log
-
diff --git a/stargazer/scripts/shaper_vpn_radius/stargazer/rules b/stargazer/scripts/shaper_vpn_radius/stargazer/rules
deleted file mode 100644 (file)
index 3fb4828..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-ALL     192.168.0.0/16  DIR1 
-ALL     10.0.0.0/8      DIR2
-ALL     0.0.0.0/0       DIR0
\ No newline at end of file
diff --git a/stargazer/scripts/shaper_vpn_radius/stargazer/stargazer.conf b/stargazer/scripts/shaper_vpn_radius/stargazer/stargazer.conf
deleted file mode 100644 (file)
index 221c85c..0000000
+++ /dev/null
@@ -1,298 +0,0 @@
-
-# Имя лог-файла куда пишутся события
-LogFile = /var/log/stargazer.log
-
-
-
-# Имя файла в котором определяются правила подсчета трафика
-Rules = /etc/stargazer/rules
-
-
-
-# Время через которое пишется d БД детальная статистика пользователя
-# Значения: 1, 1/2, 1/4, 1/6.
-# 1 - раз в чаc, 1/2 - раз в пол часа, 1/4 - раз в 15 мин, 1/6 - раз в 10 мин
-DetailStatWritePeriod=1/6
-
-
-
-# Периодичность записи записи в БД информации о статистике пользователя (минуты)
-# При большом кол-ве пользователей эту величину стоит увеличить, т.к.
-# запись в БД может занимать длительное время.
-# Значения: 1...1440 (минуты)
-StatWritePeriod = 10
-
-
-
-# День снятия абонплаты
-# Значения: 0...31. 0 - Последний день месяца
-DayFee = 1
-
-
-
-# Абонплата снимается в последний (yes) или первый (no) день учетного периода.
-# Это влияет на то, как будет снята абонплата (АП) при переходе на новый тариф.
-# Если у пользователя был тариф A с АП=100 и он хочет перейти на тариф B с АП=200,
-# то при переходе на новый тариф со счета пользователя снимется 100, если
-# DayFeeIsLastDay = yes и 200, если DayFeeIsLastDay = no
-DayFeeIsLastDay = yes
-
-
-
-# День сброса данных о трафике за месяц и день перехода пользователей на новые тарифы
-# Значения: 0...31. 0 - Последний день месяца
-DayResetTraff = 1
-
-
-
-# "Размазанное" снятие абонплаты. Снятие АП не раз в месяц, а каждый
-# день 1/30 или 1/31 части АП
-# Значения: yes, no
-SpreadFee = no
-
-
-
-# Данная опция определяет может ли пользователь получить доступ в интерент
-# если у него на счету нет денег, но остался предоплаченный трафик
-# Значения: yes, no
-FreeMbAllowInet = no
-
-
-
-# Эта опция определяет что будет писаться в стоимость трафика в detail_stat.
-# Если у пользователя еще есть предоплаченный трафик и WriteFreeMbTraffCost = no,
-# то в detail_stat стоимость будет 0. Если у пользователя уже нет
-# предоплаченного трафика и WriteFreeMbTraffCost = no, то в detail_stat
-# будет записана стоиость трафика. При WriteFreeMbTraffCost = yes стоимость
-# трафика будет записана в любом случае.
-WriteFreeMbTraffCost = no
-
-
-
-# Необязательный параметр. Указывает снимать полную абонплату у пользователя даже
-# если он быз заморожен только часть учетного периода.
-# По умолчанию установлен в no
-# FullFee=no
-
-# Необязательный параметр указывающий показывать на счету и позволять 
-# использовать пользователю абонплату. По умолчанию установлен в yes
-# ShowFeeInCash=yes
-
-
-
-# Названия направлений. Направления без названий не будут отображаться в
-# авторизаторе и конфигураторе. Названия состоящие из нескольких слов должны
-# быть взяты в кавычки
-<DirNames>
-    DirName0 = Local
-    DirName1 = City
-    DirName2 = World
-    DirName3 =
-    DirName4 =
-    DirName5 =
-    DirName6 =
-    DirName7 =
-    DirName8 =
-    DirName9 =
-</DirNames>
-
-
-
-# Кол-во запускаемых процессов stg-exec.
-# Эти процессы отвечают за выполнение скриптов OnConnect, OnDisconnect, ...
-# Кол-во процессов означает сколько скриптов могут выполнятся одновременно.
-# Значения: 1...1024
-ExecutersNum = 2
-
-
-
-# Message Key для stg-exec.
-# Идентификатор очереди сообщений для выполнятеля скриптов.
-# Его изменение может понадобится если есть необходимость запустить несколько
-# экземпляров stg. Если вы не понимаете, что это, не трогайте этот параметр!
-# Значения: 0...2^32
-# Значение по умолчанию: 5555
-# ExecMsgKey = 5555
-
-
-
-# Путь к директории, в которой находятся модули сервера
-ModulesPath = /usr/lib/stg
-
-# Определяет директорию, в которой будут находится файлы "монитора"
-# работы сервера. В этой директории будут созданы пустые файлы, время 
-# модификации которых будет меняться примерно раз в минуту. Если какой-то 
-# компонент сервера зависнет, файл(ы) перестанет обновлятся, и по этому 
-# признаку можно определить сбой в работе сервера и при надобности 
-# перезапустить. Если параметр не указан или пустой, мониторинг производится 
-# не будет. Параметр не является обязательным, по умолчанию пустой.
-# MonitorDir=/var/stargazer/monitor
-
-
-################################################################################
-# Store module
-# Настройки плагина работающего с БД сервера
-
-# Второй параметр - это имя модуля без mod_ в начале и .so в конце
-# Т.е. полное имя модуля mod_store_files.so
-<StoreModule store_files>
-
-    # Рабочая директория сервера, тут содержатся данные о тарифах, пользователях,
-    # администраторах и т.д.
-    WorkDir = /var/stargazer
-
-
-    # Владелец, группа и права доступа на файлы статистики (stat) пользователя
-    ConfOwner = root
-    ConfGroup = root
-    ConfMode = 600
-
-
-    # Владелец, группа и права доступа на файлы конфигурации (conf) пользователя
-    StatOwner = root
-    StatGroup = root
-    StatMode = 640
-
-    # Владелец, группа и права доступа на лог-файлы (log) пользователя
-    UserLogOwner = root
-    UserLogGroup = root
-    UserLogMode = 640
-
-</StoreModule>
-
-#<StoreModule store_firebird>
-#    # Адрес сервера БД
-#    server=localhost
-#
-#    # Путь к БД на сервере или ее алиас
-#    path=/var/stg/stargazer.fdb
-#
-#    # Имя пользователя БД
-#    user=stg
-#
-#    # Пароль пользователя БД
-#    password=123456
-#</StoreModule>
-
-#<StoreModule store_mysql>
-#    # Имя пользователя БД
-#    dbuser = stg
-#
-#    # Пароль пользователя БД
-#    rootdbpass = 123456
-#
-#    # Имя БД на сервере
-#    dbname = stg
-#
-#    # Адрес сервера БД
-#    dbhost = localhost
-#</StoreModule>
-
-
-
-################################################################################
-# Прочие модули
-
-<Modules>
-
-    # Настройки плагина авторизации Always Online "mod_auth_ao.so"
-    # Второй параметр - это имя модуля без mod_ в начале и .so в конце
-    # Т.е. полное имя модуля mod_auth_ao.so
-    #<Module auth_ao>
-    #</Module>
-
-
-
-    # Настройки плагина авторизации InetAccess "mod_auth_ia.so"
-    # Второй параметр - это имя модуля без mod_ в начале и .so в конце
-    # Т.е. полное имя модуля mod_auth_ia.so
-    #<Module auth_ia>
-    #    Port = 5555
-    #    UserDelay = 15
-    #    UserTimeout = 65
-    #    FreeMb = 0
-    #</Module>
-
-
-
-    # Настройки модуля конфигурации SgConfig "mod_conf_sg.so"
-    # Второй параметр - это имя модуля без mod_ в начале и .so в конце
-    <Module conf_sg>
-
-        # Порт по которому сервер взаимодействует с конфигуратором
-        # Значения: 1...65535
-        Port = 5555
-
-    </Module>
-
-
-
-    # Модуль захвата трафика "mod_cap_ether.so"
-    # Второй параметер - это имя модуля без mod_ в начале и .so в конце
-    # Без параметров. Только имя модуля.
-    <Module cap_ipq>
-        # Модуль без параметров
-    </Module>
-
-
-
-    # Настройки модуля пингующего пользователей "mod_ping.so"
-    # Второй параметр - это имя модуля без mod_ в начале и .so в конце
-    <Module ping>
-
-        # Время, в секундах, между пингами одного и того же пользователя
-        # Значения: 10...3600
-        PingDelay = 15
-
-    </Module>
-    
-    <Module radius>
-       Password = 123456
-       ServerIP = 127.0.0.1
-       Port = 6666
-       AuthServices = Login-User
-       AcctServices = Framed-User
-    </Module>
-
-#    # Настройки модуля для удаленного выполнения скриптов OnConnect и
-#    # OnDisconnect "mod_remote_script.so"
-#    # Второй параметр - это имя модуля без mod_ в начале и .so в конце
-#    <Module remote_script>
-#
-#        # Время, в секундах, между посылками подтверждений, того, что пользователь
-#        # всё еще онлайн
-#        # Значения: 10...600
-#        SendPeriod = 15
-#
-#        # Соответствие подсетей, в которой находится пользователь и
-#        # соответствующего роутера. Первая часть строки - подсеть, заданная
-#        # как IP-адрес и маска, через пробел - IP-адрес роутера на котором
-#        # должны выполняться скрипты
-#        # Например эта запись "192.168.1.0/24 192.168.1.1" означает, что для
-#        # всех пользователей из подсети 192.168.1.0/24, скрипты будут
-#        # выполняться на роутере с адресом 192.168.1.1
-#        # Subnet0...Subnet100
-#        Subnet0 = 192.168.1.0/24 192.168.1.7
-#        Subnet1 = 192.168.2.0/24 192.168.2.5
-#        Subnet2 = 192.168.3.0/24 192.168.2.5
-#        Subnet3 = 192.168.4.0/24 192.168.2.5
-#
-#        # Пароль для шифрования пакетов между stg-сервером и сервером,
-#        # выполняющим скрипты
-#        Password = 123456
-#
-#        # Этот параметр определяет какие параметры пользователя передаются
-#        # на удаленный сервер
-#        # Cash, FreeMb, Passive, Disabled, AlwaysOnline, TariffName, NextTariff, Address,
-#        # Note, Group, Email, RealName, Credit, EnabledDirs, Userdata0...Userdata9
-#        UserParams=Cash Tariff EnabledDirs
-#
-#        # Порт по которому сервер отсылает сообщения на роутер
-#        # Значения: 1...65535
-#        Port = 9999
-#
-#    </Module>
-
-</Modules>
-################################################################################
-
diff --git a/stargazer/services_impl.cpp b/stargazer/services_impl.cpp
deleted file mode 100644 (file)
index 36640c8..0000000
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#include "services_impl.h"
-
-#include "stg/admin.h"
-#include "stg/admin_conf.h"
-#include "stg/store.h"
-#include "stg/common.h"
-
-#include <algorithm>
-#include <cassert>
-
-using STG::ServicesImpl;
-
-//-----------------------------------------------------------------------------
-ServicesImpl::ServicesImpl(Store * st)
-    : store(st),
-      WriteServLog(Logger::get()),
-      searchDescriptors(),
-      handle(0)
-{
-Read();
-}
-//-----------------------------------------------------------------------------
-int ServicesImpl::Add(const ServiceConf & service, const Admin * admin)
-{
-std::lock_guard<std::mutex> lock(mutex);
-const auto& priv = admin->priv();
-
-if (!priv.serviceChg)
-    {
-    std::string s = admin->logStr() + " Add service \'" + service.name + "\'. Access denied.";
-    strError = "Access denied.";
-    WriteServLog(s.c_str());
-    return -1;
-    }
-
-iterator si(std::find(data.begin(), data.end(), service));
-
-if (si != data.end())
-    {
-    strError = "Service \'" + service.name + "\' cannot not be added. Service already exist.";
-    WriteServLog("%s %s", admin->logStr().c_str(), strError.c_str());
-
-    return -1;
-    }
-
-data.push_back(service);
-
-if (store->AddService(service.name) == 0)
-    {
-    WriteServLog("%s Service \'%s\' added.",
-                 admin->logStr().c_str(), service.name.c_str());
-    return 0;
-    }
-
-strError = "Service \'" + service.name + "\' was not added. Error: " + store->GetStrError();
-WriteServLog("%s %s", admin->logStr().c_str(), strError.c_str());
-
-return -1;
-}
-//-----------------------------------------------------------------------------
-int ServicesImpl::Del(const std::string & name, const Admin * admin)
-{
-std::lock_guard<std::mutex> lock(mutex);
-const auto& priv = admin->priv();
-
-if (!priv.serviceChg)
-    {
-    std::string s = admin->logStr() + " Delete service \'" + name + "\'. Access denied.";
-    strError = "Access denied.";
-    WriteServLog(s.c_str());
-    return -1;
-    }
-
-iterator si(std::find(data.begin(), data.end(), ServiceConf(name)));
-
-if (si == data.end())
-    {
-    strError = "Service \'" + name + "\' cannot be deleted. Service does not exist.";
-    WriteServLog("%s %s", admin->logStr().c_str(), strError.c_str());
-    return -1;
-    }
-
-std::map<int, const_iterator>::iterator csi;
-csi = searchDescriptors.begin();
-while (csi != searchDescriptors.end())
-    {
-    if (csi->second == si)
-        (csi->second)++;
-    ++csi;
-    }
-
-data.erase(si);
-if (store->DelService(name) < 0)
-    {
-    strError = "Service \'" + name + "\' was not deleted. Error: " + store->GetStrError();
-    WriteServLog("%s %s", admin->logStr().c_str(), strError.c_str());
-
-    return -1;
-    }
-
-WriteServLog("%s Service \'%s\' deleted.", admin->logStr().c_str(), name.c_str());
-return 0;
-}
-//-----------------------------------------------------------------------------
-int ServicesImpl::Change(const ServiceConf & service, const Admin * admin)
-{
-std::lock_guard<std::mutex> lock(mutex);
-const auto& priv = admin->priv();
-
-if (!priv.serviceChg)
-    {
-    std::string s = admin->logStr() + " Change service \'" + service.name + "\'. Access denied.";
-    strError = "Access denied.";
-    WriteServLog(s.c_str());
-    return -1;
-    }
-
-iterator si(std::find(data.begin(), data.end(), service));
-
-if (si == data.end())
-    {
-    strError = "Service \'" + service.name + "\' cannot be changed " + ". Service does not exist.";
-    WriteServLog("%s %s", admin->logStr().c_str(), strError.c_str());
-    return -1;
-    }
-
-printfd(__FILE__, "Old cost = %f, old pay day = %u\n", si->cost, static_cast<unsigned>(si->payDay));
-*si = service;
-printfd(__FILE__, "New cost = %f, New pay day = %u\n", si->cost, static_cast<unsigned>(si->payDay));
-if (store->SaveService(service))
-    {
-    WriteServLog("Cannot write service %s.", service.name.c_str());
-    WriteServLog("%s", store->GetStrError().c_str());
-    return -1;
-    }
-
-WriteServLog("%s Service \'%s\' changed.",
-             admin->logStr().c_str(), service.name.c_str());
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-bool ServicesImpl::Read()
-{
-std::lock_guard<std::mutex> lock(mutex);
-std::vector<std::string> servicesList;
-if (store->GetServicesList(&servicesList) < 0)
-    {
-    WriteServLog(store->GetStrError().c_str());
-    return true;
-    }
-
-for (size_t i = 0; i < servicesList.size(); i++)
-    {
-    ServiceConf service;
-
-    if (store->RestoreService(&service, servicesList[i]))
-        {
-        WriteServLog(store->GetStrError().c_str());
-        return true;
-        }
-
-    data.push_back(service);
-    }
-return false;
-}
-//-----------------------------------------------------------------------------
-bool ServicesImpl::Find(const std::string & name, ServiceConf * service) const
-{
-assert(service != NULL && "Pointer to service is not null");
-
-std::lock_guard<std::mutex> lock(mutex);
-if (data.empty())
-    return true;
-
-const_iterator si(std::find(data.begin(), data.end(), ServiceConf(name)));
-
-if (si != data.end())
-    {
-    *service = *si;
-    return false;
-    }
-
-return true;
-}
-//-----------------------------------------------------------------------------
-bool ServicesImpl::Find(const std::string & name, ServiceConfOpt * service) const
-{
-assert(service != NULL && "Pointer to service is not null");
-
-std::lock_guard<std::mutex> lock(mutex);
-if (data.empty())
-    return true;
-
-const_iterator si(std::find(data.begin(), data.end(), ServiceConf(name)));
-
-if (si != data.end())
-    {
-    *service = *si;
-    return false;
-    }
-
-return true;
-}
-//-----------------------------------------------------------------------------
-bool ServicesImpl::Exists(const std::string & name) const
-{
-std::lock_guard<std::mutex> lock(mutex);
-if (data.empty())
-    {
-    printfd(__FILE__, "No services in the system!\n");
-    return true;
-    }
-
-const_iterator si(std::find(data.begin(), data.end(), ServiceConf(name)));
-
-if (si != data.end())
-    return true;
-
-return false;
-}
-//-----------------------------------------------------------------------------
-int ServicesImpl::OpenSearch() const
-{
-std::lock_guard<std::mutex> lock(mutex);
-handle++;
-searchDescriptors[handle] = data.begin();
-return handle;
-}
-//-----------------------------------------------------------------------------
-int ServicesImpl::SearchNext(int h, ServiceConf * service) const
-{
-std::lock_guard<std::mutex> lock(mutex);
-if (searchDescriptors.find(h) == searchDescriptors.end())
-    {
-    WriteServLog("SERVICES. Incorrect search handle.");
-    return -1;
-    }
-
-if (searchDescriptors[h] == data.end())
-    return -1;
-
-*service = *searchDescriptors[h]++;
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int ServicesImpl::CloseSearch(int h) const
-{
-std::lock_guard<std::mutex> lock(mutex);
-if (searchDescriptors.find(h) != searchDescriptors.end())
-    {
-    searchDescriptors.erase(searchDescriptors.find(h));
-    return 0;
-    }
-
-WriteServLog("SERVICES. Incorrect search handle.");
-return -1;
-}
-//-----------------------------------------------------------------------------
diff --git a/stargazer/services_impl.h b/stargazer/services_impl.h
deleted file mode 100644 (file)
index 8a66f63..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#pragma once
-
-#include "stg/services.h"
-#include "stg/service_conf.h"
-#include "stg/locker.h"
-#include "stg/noncopyable.h"
-#include "stg/logger.h"
-
-#include <vector>
-#include <map>
-#include <string>
-#include <mutex>
-
-namespace STG
-{
-
-struct Admin;
-struct Store;
-
-class ServicesImpl : public Services {
-    public:
-        explicit ServicesImpl(Store* st);
-
-        int Add(const ServiceConf& service, const Admin* admin) override;
-        int Del(const std::string& name, const Admin* admin) override;
-        int Change(const ServiceConf& service, const Admin* admin) override;
-        bool Find(const std::string& name, ServiceConf* service) const override;
-        bool Find(const std::string& name, ServiceConfOpt* service) const override;
-        bool Exists(const std::string& name) const override;
-        const std::string& GetStrError() const override { return strError; }
-
-        size_t Count() const override { return data.size(); }
-
-        int OpenSearch() const override;
-        int SearchNext(int, ServiceConf* service) const override;
-        int CloseSearch(int) const override;
-
-    private:
-        typedef std::vector<ServiceConf>::iterator       iterator;
-        typedef std::vector<ServiceConf>::const_iterator const_iterator;
-
-        bool Read();
-
-        std::vector<ServiceConf> data;
-        Store*                 store;
-        Logger&            WriteServLog;
-        mutable std::map<int, const_iterator> searchDescriptors;
-        mutable unsigned int    handle;
-        mutable std::mutex mutex;
-        std::string             strError;
-};
-
-}
diff --git a/stargazer/settings_impl.cpp b/stargazer/settings_impl.cpp
deleted file mode 100644 (file)
index 656198f..0000000
+++ /dev/null
@@ -1,452 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- */
-
-#include "settings_impl.h"
-
-#include "stg/logger.h"
-#include "stg/dotconfpp.h"
-#include "stg/common.h"
-#include "stg/const.h"
-
-#include <stdexcept>
-#include <cstring>
-#include <cerrno>
-
-using STG::SettingsImpl;
-using STG::ParamValue;
-
-namespace
-{
-
-struct Error : public std::runtime_error
-{
-    Error(const std::string& message) : runtime_error(message) {}
-};
-
-std::vector<std::string> toValues(const DOTCONFDocumentNode& node)
-{
-    std::vector<std::string> values;
-
-    size_t i = 0;
-    const char* value = NULL;
-    while ((value = node.getValue(i++)) != NULL)
-        values.push_back(value);
-
-    return values;
-}
-
-std::vector<ParamValue> toPVS(const DOTCONFDocumentNode& node)
-{
-    std::vector<ParamValue> pvs;
-
-    const DOTCONFDocumentNode* child = node.getChildNode();
-    while (child != NULL)
-        {
-        if (child->getName() == NULL)
-            continue;
-
-        if (child->getChildNode() == NULL)
-            pvs.push_back(ParamValue(child->getName(), toValues(*child)));
-        else
-            pvs.push_back(ParamValue(child->getName(), toValues(*child), toPVS(*child)));
-
-        child = child->getNextNode();
-        }
-
-    return pvs;
-}
-
-unsigned toPeriod(const char* value)
-{
-    if (value == NULL)
-        throw Error("No detail stat period value.");
-
-    std::string period(value);
-    if (period == "1")
-        return STG::dsPeriod_1;
-    else if (period == "1/2")
-        return STG::dsPeriod_1_2;
-    else if (period == "1/4")
-        return STG::dsPeriod_1_4;
-    else if (period == "1/6")
-        return STG::dsPeriod_1_6;
-
-    throw Error("Invalid detail stat period value: '" + period + "'. Should be one of '1', '1/2', '1/4' or '1/6'.");
-}
-
-void errorCallback(void* /*data*/, const char* buf)
-{
-    printfd(__FILE__, "SettingsImpl::errorCallback() - %s\n", buf);
-    STG::Logger::get()("%s", buf);
-}
-
-}
-
-//-----------------------------------------------------------------------------
-SettingsImpl::SettingsImpl(const std::string & cd)
-    : modulesPath("/usr/lib/stg"),
-      dirName(DIR_NUM),
-      confDir(cd.empty() ? "/etc/stargazer" : cd),
-      scriptsDir(confDir),
-      rules(confDir + "/rules"),
-      logFile("/var/log/stargazer.log"),
-      pidFile("/var/run/stargazer.pid"),
-      monitorDir("/var/stargazer/monitoring"),
-      monitoring(false),
-      detailStatWritePeriod(dsPeriod_1_6),
-      statWritePeriod(10),
-      stgExecMsgKey(5555),
-      executersNum(1),
-      fullFee(false),
-      dayFee(0),
-      dayResetTraff(0),
-      spreadFee(false),
-      freeMbAllowInet(false),
-      dayFeeIsLastDay(false),
-      stopOnError(true),
-      writeFreeMbTraffCost(false),
-      showFeeInCash(true),
-      messageTimeout(0),
-      feeChargeType(0),
-      reconnectOnTariffChange(false),
-      disableSessionLog(false)
-{
-    filterParamsLog.push_back("*");
-}
-//-----------------------------------------------------------------------------
-int SettingsImpl::ReadSettings()
-{
-const char * requiredOptions[] = {
-    "ModulesPath",
-    "Modules",
-    "StoreModule",
-    "Rules",
-    "LogFile",
-    "DetailStatWritePeriod",
-    "DayFee",
-    "DayResetTraff",
-    "SpreadFee",
-    "FreeMbAllowInet",
-    "DayFeeIsLastDay",
-    "WriteFreeMbTraffCost",
-    NULL
-    };
-int storeModulesCount = 0;
-modulesSettings.clear();
-
-DOTCONFDocument conf(DOTCONFDocument::CASEINSENSITIVE);
-conf.setErrorCallback(errorCallback, nullptr);
-conf.setRequiredOptionNames(requiredOptions);
-std::string confFile = confDir + "/stargazer.conf";
-
-if(conf.setContent(confFile.c_str()) != 0)
-    {
-    strError = "Cannot read file " + confFile;
-    return -1;
-    }
-
-auto node = conf.getFirstNode();
-
-while (node)
-    {
-    if (strcasecmp(node->getName(), "ScriptDir") == 0)
-        {
-        scriptsDir = node->getValue(0);
-        }
-
-    if (strcasecmp(node->getName(), "LogFile") == 0)
-        {
-        logFile = node->getValue(0);
-        }
-
-    if (strcasecmp(node->getName(), "PIDFile") == 0)
-        {
-        pidFile = node->getValue(0);
-        }
-
-    if (strcasecmp(node->getName(), "ModulesPath") == 0)
-        {
-        modulesPath = node->getValue(0);
-        }
-
-    if (strcasecmp(node->getName(), "Rules") == 0)
-        {
-        rules = node->getValue(0);
-        }
-
-    if (strcasecmp(node->getName(), "DetailStatWritePeriod") == 0)
-        {
-        try
-        {
-            detailStatWritePeriod = toPeriod(node->getValue(0));
-        }
-        catch (const Error& error)
-        {
-            strError = error.what();
-            return -1;
-        }
-        }
-
-    if (strcasecmp(node->getName(), "StatWritePeriod") == 0)
-        {
-        if (ParseUnsignedInRange(node->getValue(0), 1, 1440, &statWritePeriod) != 0)
-            {
-            strError = "Incorrect StatWritePeriod value: \'" + std::string(node->getValue(0)) + "\'";
-            return -1;
-            }
-        }
-
-    if (strcasecmp(node->getName(), "ExecMsgKey") == 0)
-        {
-        if (ParseInt(node->getValue(0), &stgExecMsgKey) != 0)
-            {
-            strError = "Incorrect ExecMsgKey value: \'" + std::string(node->getValue(0)) + "\'";
-            return -1;
-            }
-        }
-
-    if (strcasecmp(node->getName(), "ExecutersNum") == 0)
-        {
-        if (ParseUnsignedInRange(node->getValue(0), 1, 1024, &executersNum) != 0)
-            {
-            strError = "Incorrect ExecutersNum value: \'" + std::string(node->getValue(0)) + "\'";
-            return -1;
-            }
-        }
-
-    if (strcasecmp(node->getName(), "DayFee") == 0)
-        {
-        if (ParseUnsignedInRange(node->getValue(0), 0, 31, &dayFee) != 0)
-            {
-            strError = "Incorrect DayFee value: \'" + std::string(node->getValue(0)) + "\'";
-            return -1;
-            }
-        }
-
-    if (strcasecmp(node->getName(), "FullFee") == 0)
-        {
-        if (ParseYesNo(node->getValue(0), &fullFee) != 0)
-            {
-            strError = "Incorrect FullFee value: \'" + std::string(node->getValue(0)) + "\'";
-            return -1;
-            }
-        }
-
-    if (strcasecmp(node->getName(), "DayResetTraff") == 0)
-        {
-        if (ParseUnsignedInRange(node->getValue(0), 0, 31, &dayResetTraff) != 0)
-            {
-            strError = "Incorrect DayResetTraff value: \'" + std::string(node->getValue(0)) + "\'";
-            return -1;
-            }
-        }
-
-    if (strcasecmp(node->getName(), "SpreadFee") == 0)
-        {
-        if (ParseYesNo(node->getValue(0), &spreadFee) != 0)
-            {
-            strError = "Incorrect SpreadFee value: \'" + std::string(node->getValue(0)) + "\'";
-            return -1;
-            }
-        }
-
-    if (strcasecmp(node->getName(), "FreeMbAllowInet") == 0)
-        {
-        if (ParseYesNo(node->getValue(0), &freeMbAllowInet) != 0)
-            {
-            strError = "Incorrect FreeMbAllowInet value: \'" + std::string(node->getValue(0)) + "\'";
-            return -1;
-            }
-        }
-
-    if (strcasecmp(node->getName(), "DayFeeIsLastDay") == 0)
-        {
-        if (ParseYesNo(node->getValue(0), &dayFeeIsLastDay) != 0)
-            {
-            strError = "Incorrect DayFeeIsLastDay value: \'" + std::string(node->getValue(0)) + "\'";
-            return -1;
-            }
-        }
-
-    if (strcasecmp(node->getName(), "StopOnError") == 0)
-        {
-        if (ParseYesNo(node->getValue(0), &stopOnError) != 0)
-            {
-            strError = "Incorrect StopOnError value: \'" + std::string(node->getValue(0)) + "\'";
-            return -1;
-            }
-        }
-
-    if (strcasecmp(node->getName(), "WriteFreeMbTraffCost") == 0)
-        {
-        if (ParseYesNo(node->getValue(0), &writeFreeMbTraffCost) != 0)
-            {
-            strError = "Incorrect WriteFreeMbTraffCost value: \'" + std::string(node->getValue(0)) + "\'";
-            return -1;
-            }
-        }
-
-    if (strcasecmp(node->getName(), "ShowFeeInCash") == 0)
-        {
-        if (ParseYesNo(node->getValue(0), &showFeeInCash) != 0)
-            {
-            strError = "Incorrect ShowFeeInCash value: \'" + std::string(node->getValue(0)) + "\'";
-            return -1;
-            }
-        }
-
-    if (strcasecmp(node->getName(), "MonitorDir") == 0)
-        {
-        monitorDir = node->getValue(0);
-        struct stat stat;
-        monitoring = false;
-
-        if (!lstat(monitorDir.c_str(), &stat) && S_ISDIR(stat.st_mode))
-            {
-            monitoring = true;
-            }
-        }
-
-    if (strcasecmp(node->getName(), "MessageTimeout") == 0)
-        {
-        if (ParseUnsigned(node->getValue(0), &messageTimeout) != 0)
-            {
-            strError = "Incorrect MessageTimeout value: \'" + std::string(node->getValue(0)) + "\'";
-            return -1;
-            }
-        }
-
-    if (strcasecmp(node->getName(), "FeeChargeType") == 0)
-        {
-        if (ParseUnsignedInRange(node->getValue(0), 0, 3, &feeChargeType) != 0)
-            {
-            strError = "Incorrect FeeChargeType value: \'" + std::string(node->getValue(0)) + "\'";
-            return -1;
-            }
-        }
-
-    if (strcasecmp(node->getName(), "ReconnectOnTariffChange") == 0)
-        {
-        if (ParseYesNo(node->getValue(0), &reconnectOnTariffChange) != 0)
-            {
-            strError = "Incorrect ReconnectOnTariffChange value: \'" + std::string(node->getValue(0)) + "\'";
-            return -1;
-            }
-        }
-
-    if (strcasecmp(node->getName(), "DisableSessionLog") == 0)
-        {
-        if (ParseYesNo(node->getValue(0), &disableSessionLog) != 0)
-            {
-            strError = "Incorrect DisableSessionLog value: \'" + std::string(node->getValue(0)) + "\'";
-            return -1;
-            }
-        }
-
-    if (strcasecmp(node->getName(), "FilterParamsLog") == 0)
-        {
-        filterParamsLog.clear();
-        for (int i = 0; node->getValue(i) != NULL; ++i)
-            filterParamsLog.push_back(node->getValue(i));
-        }
-
-    if (strcasecmp(node->getName(), "DirNames") == 0)
-        {
-        const DOTCONFDocumentNode * child = node->getChildNode();
-        if (child)
-            {
-            const DOTCONFDocumentNode * dirNameNode;
-            dirName.reserve(DIR_NUM);
-            for (int i = 0; i < DIR_NUM; i++)
-                {
-                char strDirName[12];
-                sprintf(strDirName, "DirName%d", i);
-                dirNameNode = conf.findNode(strDirName, node);
-                if (dirNameNode && dirNameNode->getValue(0))
-                    {
-                    dirName[i] = dirNameNode->getValue(0);
-                    }
-                }
-            }
-        }
-
-    if (strcasecmp(node->getName(), "StoreModule") == 0)
-        {
-        if (node->getValue(1))
-            {
-            strError = "Unexpected \'" + std::string(node->getValue(1)) + "\'.";
-            return -1;
-            }
-
-        if (storeModulesCount)
-            {
-            strError = "Should be only one StoreModule.";
-            return -1;
-            }
-        storeModulesCount++;
-
-        if (node->getValue(0) == NULL)
-            {
-            strError = "No module name in the StoreModule section.";
-            return -1;
-            }
-        storeModuleSettings.moduleName = node->getValue(0);
-        storeModuleSettings.moduleParams = toPVS(*node);
-        }
-
-    if (strcasecmp(node->getName(), "Modules") == 0)
-        {
-        if (node->getValue(0))
-            {
-            strError = "Unexpected \'" + std::string(node->getValue(0)) + "\'.";
-            return -1;
-            }
-        const DOTCONFDocumentNode * child = node->getChildNode();
-        while (child)
-            {
-            if (strcasecmp(child->getName(), "Module") != 0)
-                {
-                child = child->getNextNode();
-                continue;
-                }
-
-            if (child->getValue(0) == NULL)
-                {
-                strError = "No module name in the Module section.";
-                return -1;
-                }
-
-            modulesSettings.push_back(ModuleSettings(child->getValue(0), toPVS(*child)));
-
-            child = child->getNextNode();
-            }
-        }
-
-    if (strcasecmp(node->getName(), "ScriptParams") == 0)
-        {
-        for (int i = 0; node->getValue(i) != NULL; ++i)
-            scriptParams.push_back(node->getValue(i));
-        }
-    node = node->getNextNode();
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
diff --git a/stargazer/settings_impl.h b/stargazer/settings_impl.h
deleted file mode 100644 (file)
index 4b73dcd..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- */
-
-#pragma once
-
-#include "stg/settings.h"
-#include "stg/common.h"
-#include "stg/module_settings.h"
-
-#include <string>
-#include <vector>
-
-class DOTCONFDocumentNode;
-
-namespace STG
-{
-
-//-----------------------------------------------------------------------------
-enum DETAIL_STAT_PERIOD {
-    dsPeriod_1,
-    dsPeriod_1_2,
-    dsPeriod_1_4,
-    dsPeriod_1_6
-};
-//-----------------------------------------------------------------------------
-class SettingsImpl : public Settings {
-    public:
-        explicit SettingsImpl(const std::string &);
-
-        SettingsImpl(const SettingsImpl&) = default;
-        SettingsImpl& operator=(const SettingsImpl&) = default;
-        SettingsImpl(SettingsImpl&&) = default;
-        SettingsImpl& operator=(SettingsImpl&&) = default;
-
-        int Reload() { return ReadSettings(); }
-        int ReadSettings();
-
-        std::string GetStrError() const { return strError; }
-
-        int                 GetExecMsgKey() const { return stgExecMsgKey; }
-        unsigned            GetExecutersNum() const { return executersNum; }
-        const std::string & GetDirName(size_t num) const { return dirName[num]; }
-        const std::string & GetConfDir() const { return confDir; }
-        const std::string & GetScriptsDir() const { return scriptsDir; }
-        const std::string & GetRulesFileName() const { return rules; }
-        const std::string & GetLogFileName() const { return logFile; }
-        const std::string & GetPIDFileName() const { return pidFile; }
-        unsigned            GetDetailStatWritePeriod() const
-            { return detailStatWritePeriod; }
-        unsigned            GetStatWritePeriod() const { return statWritePeriod * 60; }
-        unsigned            GetDayFee() const { return dayFee; }
-        bool                GetFullFee() const { return fullFee; }
-        unsigned            GetDayResetTraff() const { return dayResetTraff; }
-        bool                GetSpreadFee() const { return spreadFee; }
-        bool                GetFreeMbAllowInet() const { return freeMbAllowInet; }
-        bool                GetDayFeeIsLastDay() const { return dayFeeIsLastDay; }
-        bool                GetStopOnError() const { return stopOnError; }
-        bool                GetWriteFreeMbTraffCost() const
-            { return writeFreeMbTraffCost; }
-        bool                GetShowFeeInCash() const { return showFeeInCash; }
-        const std::string & GetMonitorDir() const { return monitorDir; }
-        bool                GetMonitoring() const { return monitoring; }
-        unsigned            GetMessageTimeout() const { return messageTimeout * 3600 * 24; }
-        unsigned            GetFeeChargeType() const { return feeChargeType; }
-        bool                GetReconnectOnTariffChange() const { return reconnectOnTariffChange; }
-        bool                GetDisableSessionLog() const { return disableSessionLog; }
-        const std::vector<std::string> & GetFilterParamsLog() const { return filterParamsLog; }
-
-        const std::string & GetModulesPath() const { return modulesPath; }
-        const ModuleSettings & GetStoreModuleSettings() const
-        { return storeModuleSettings; }
-        const std::vector<ModuleSettings> & GetModulesSettings() const
-        { return modulesSettings; }
-        const std::vector<std::string> & GetScriptParams() const { return scriptParams; }
-
-    private:
-        std::string strError;
-
-        //////////settings
-        std::string modulesPath;
-        std::vector<std::string> dirName;
-        std::string confDir;
-        std::string scriptsDir;
-        std::string rules;
-        std::string logFile;
-        std::string pidFile;
-        std::string monitorDir;
-        std::vector<std::string> scriptParams;
-        bool        monitoring;
-        unsigned    detailStatWritePeriod;
-        unsigned    statWritePeriod;
-        int         stgExecMsgKey;
-        unsigned    executersNum;
-        bool        fullFee;
-        unsigned    dayFee;
-        unsigned    dayResetTraff;
-        bool        spreadFee;
-        bool        freeMbAllowInet;
-        bool        dayFeeIsLastDay;
-        bool        stopOnError;
-        bool        writeFreeMbTraffCost;
-        bool        showFeeInCash;
-        unsigned    messageTimeout;
-        unsigned    feeChargeType;
-        bool        reconnectOnTariffChange;
-        bool        disableSessionLog;
-        std::vector<std::string> filterParamsLog;
-
-        std::vector<ModuleSettings> modulesSettings;
-        ModuleSettings storeModuleSettings;
-};
-//-----------------------------------------------------------------------------
-
-}
diff --git a/stargazer/stg_timer.cpp b/stargazer/stg_timer.cpp
deleted file mode 100644 (file)
index 572b069..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-#include "stg_timer.h"
-
-#include "stg/common.h"
-
-#include <ctime>
-#include <cstring>
-#include <csignal>
-
-#include <pthread.h>
-
-void * StgTimer(void *);
-
-static int nonstop;
-static pthread_t thrStgTimer;
-static bool isTimerRunning = false;
-volatile time_t stgTime;
-
-#ifdef STG_TIMER_DEBUG
-const int TIME_SPEED = 1;
-/*
- 1  - 1x  speed
- 2  - 2x  speed
- 5  - 5x  speed
- 10 - 10x speed
- */
-
-const int START_TIME = 2;
-/*
- 0 - as is
- 1 - start before new day (3 min before)   29.11.2005 23:57:00
- 2 - start before new month (3 min before) 30.11.2005 23:57:00
- */
-#endif
-
-//-----------------------------------------------------------------------------
-void * StgTimer(void *)
-{
-#ifdef STG_TIMER_DEBUG
-struct tm lt;
-memset(&lt, 0, sizeof(lt));
-
-lt.tm_year = 2016 - 1900; // 2005
-lt.tm_mon  = 7 - 1;      // Nov
-lt.tm_hour = 23;          // 23 h
-lt.tm_min = 57;           // 50 min
-lt.tm_sec = 0;            // 00 sec
-lt.tm_isdst = -1;
-
-switch (START_TIME)
-    {
-    case 0:
-        stgTime = time(NULL);
-        break;
-
-    case 1:
-        lt.tm_mday = 29;
-        stgTime = mktime(&lt);
-        break;
-
-    case 2:
-        lt.tm_mday = 31;
-        stgTime = mktime(&lt);
-        break;
-    }
-#else
-stgTime = time(NULL);
-#endif
-
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-nonstop = 1;
-isTimerRunning = true;
-while (nonstop)
-    {
-    #ifdef STG_TIMER_DEBUG
-    struct timespec ts;
-    if (TIME_SPEED == 1)
-        {
-        ts.tv_sec = 1;
-        ts.tv_nsec = 0;
-        }
-    else
-        {
-        ts.tv_sec = 0;
-        ts.tv_nsec = 1000000000 / TIME_SPEED;
-        }
-    nanosleep(&ts, NULL);
-    stgTime++;
-    #else
-    struct timespec ts = {0, 500000000};
-    nanosleep(&ts, NULL);
-    stgTime = time(NULL);
-    #endif
-    }
-isTimerRunning = false;
-
-return NULL;
-}
-//-----------------------------------------------------------------------------
-int RunStgTimer()
-{
-static int a = 0;
-isTimerRunning = false;
-
-if (a == 0)
-    if (pthread_create(&thrStgTimer, NULL, &StgTimer, NULL))
-        {
-        isTimerRunning = false;
-        return -1;
-        }
-
-a = 1;
-return 0;
-}
-//-----------------------------------------------------------------------------
-void StopStgTimer()
-{
-nonstop = 0;
-pthread_join(thrStgTimer, NULL); // Cleanup thread resources
-printfd(__FILE__, "STG_TIMER stopped\n");
-}
-//-----------------------------------------------------------------------------
-bool IsStgTimerRunning()
-{
-return isTimerRunning;
-}
-//-----------------------------------------------------------------------------
-int stgUsleep(unsigned long t)
-{
-#ifdef STG_TIMER_DEBUG
-struct timespec ts = {static_cast<time_t>((t / TIME_SPEED) / 1000000), static_cast<long>(((t / TIME_SPEED) % 1000000) * 1000)};
-return nanosleep(&ts, NULL);
-#else
-struct timespec ts = {static_cast<time_t>(t / 1000000), static_cast<long>((t % 1000000) * 1000)};
-return nanosleep(&ts, NULL);
-#endif
-}
-//-----------------------------------------------------------------------------
-void WaitTimer()
-{
-    for (int i = 0; i < 5 && !isTimerRunning; i++)
-        stgUsleep(200000);
-}
-//-----------------------------------------------------------------------------
diff --git a/stargazer/stg_timer.h b/stargazer/stg_timer.h
deleted file mode 100644 (file)
index 75553b3..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
- /*
- $Revision: 1.9 $
- $Date: 2010/11/03 10:37:52 $
- $Author: faust $
- */
-
-#ifndef STG_TIMER_H
-#define STG_TIMER_H
-
-#include <ctime>
-
-extern volatile time_t stgTime;
-int RunStgTimer();
-void StopStgTimer();
-void WaitTimer();
-bool IsStgTimerRunning();
-int stgUsleep(unsigned long t);
-
-#endif //STG_TIMER_H
-
-
diff --git a/stargazer/store_loader.cpp b/stargazer/store_loader.cpp
deleted file mode 100644 (file)
index 9164685..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#include <dlfcn.h>
-
-#include "stg/common.h"
-#include "stg/store.h"
-#include "store_loader.h"
-#include "settings_impl.h"
-
-using STG::StoreLoader;
-
-StoreLoader::StoreLoader(const SettingsImpl& settings) noexcept
-    : isLoaded(false),
-      handle(NULL),
-      plugin(NULL),
-      storeSettings(settings.GetStoreModuleSettings()),
-      pluginFileName(settings.GetModulesPath() + "/mod_" + storeSettings.moduleName + ".so")
-{
-}
-
-StoreLoader::~StoreLoader()
-{
-    unload();
-}
-
-bool StoreLoader::load() noexcept
-{
-    if (isLoaded)
-    {
-        errorStr = "Store plugin '" + pluginFileName + "' was already loaded!";
-        printfd(__FILE__, "StoreLoader::load() - %s\n", errorStr.c_str());
-        return false;
-    }
-
-    if (pluginFileName.empty())
-    {
-        errorStr = "Empty store plugin filename";
-        printfd(__FILE__, "StoreLoader::load() - %s\n", errorStr.c_str());
-        return true;
-    }
-
-    handle = dlopen(pluginFileName.c_str(), RTLD_NOW);
-
-    if (!handle)
-    {
-        errorStr = "Error loading plugin '"
-            + pluginFileName + "': '" + dlerror() + "'";
-        printfd(__FILE__, "StoreLoader::Load() - %s\n", errorStr.c_str());
-        return true;
-    }
-
-    isLoaded = true;
-
-    using Getter = Store* (*)();
-    auto GetStore = reinterpret_cast<Getter>(dlsym(handle, "GetStore"));
-    if (!GetStore)
-    {
-        errorStr = std::string("GetStore() not found! ") + dlerror();
-        printfd(__FILE__, "StoreLoader::load() - %s\n", errorStr.c_str());
-        return true;
-    }
-
-    plugin = GetStore();
-
-    if (!plugin)
-    {
-        errorStr = "Plugin was not created!";
-        printfd(__FILE__, "StoreLoader::Load() - %s\n");
-        return true;
-    }
-
-    plugin->SetSettings(storeSettings);
-    if (plugin->ParseSettings())
-    {
-        errorStr = plugin->GetStrError();
-        printfd(__FILE__, "StoreLoader::Load() - Failed to parse settings. Plugin reports: '%s'\n", errorStr.c_str());
-        return true;
-    }
-
-    return false;
-}
-
-bool StoreLoader::unload() noexcept
-{
-    if (!isLoaded)
-        return true;
-
-    delete plugin;
-
-    if (dlclose(handle))
-    {
-        errorStr = "Failed to unload plugin '";
-        errorStr += pluginFileName + "': ";
-        errorStr += dlerror();
-        printfd(__FILE__, "StoreLoader::Unload() - %s\n", errorStr.c_str());
-        return true;
-    }
-
-    isLoaded = false;
-
-    return false;
-}
diff --git a/stargazer/store_loader.h b/stargazer/store_loader.h
deleted file mode 100644 (file)
index c187b54..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-#pragma once
-
-#include "stg/module_settings.h"
-
-#include <string>
-
-namespace STG
-{
-
-struct Store;
-class SettingsImpl;
-
-class StoreLoader {
-    public:
-        explicit StoreLoader(const SettingsImpl& settings) noexcept;
-        ~StoreLoader();
-
-        StoreLoader(const StoreLoader&) = delete;
-        StoreLoader& operator=(const StoreLoader&) = delete;
-
-        bool load() noexcept;
-        bool unload() noexcept;
-
-        Store& get() noexcept { return *plugin; }
-
-        const std::string& GetStrError() const noexcept { return errorStr; }
-
-    private:
-        bool isLoaded;
-        void* handle;
-        Store* plugin;
-        std::string errorStr;
-        ModuleSettings storeSettings;
-        std::string pluginFileName;
-};
-
-}
diff --git a/stargazer/tariff_impl.cpp b/stargazer/tariff_impl.cpp
deleted file mode 100644 (file)
index 7d85462..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Date: 07.11.2007
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- */
-
-/*
- $Revision: 1.11 $
- $Date: 2010/10/07 16:57:21 $
- $Author: faust $
- */
-
-#include "tariff_impl.h"
-
-#include "stg_timer.h"
-#include "stg/common.h"
-
-#include <ctime>
-#include <algorithm> // std::max
-
-using STG::TariffImpl;
-
-//-----------------------------------------------------------------------------
-TariffImpl & TariffImpl::operator=(const TariffData & td)
-{
-tariffData = td;
-return *this;
-}
-//-----------------------------------------------------------------------------
-double TariffImpl::GetPriceWithTraffType(uint64_t up,
-                                     uint64_t down,
-                                     int dir,
-                                     time_t t) const
-{
-return GetPriceWithoutFreeMb(dir, GetTraffByType(up, down) / (1024 * 1024), t);
-}
-//-----------------------------------------------------------------------------
-int64_t TariffImpl::GetTraffByType(uint64_t up, uint64_t down) const
-{
-switch (tariffData.tariffConf.traffType)
-    {
-    case TRAFF_UP:
-        return up;
-
-    case TRAFF_DOWN:
-        return down;
-
-    case TRAFF_MAX:
-        return std::max(up, down);
-
-    default:  //TRAFF_UP_DOWN:
-        return up + down;
-    }
-}
-//-----------------------------------------------------------------------------
-int TariffImpl::GetThreshold(int dir) const
-{
-    return tariffData.dirPrice[dir].threshold;
-}
-//-----------------------------------------------------------------------------
-void TariffImpl::Print() const
-{
-printfd(__FILE__, "Traiff name: %s\n", tariffData.tariffConf.name.c_str());
-}
-//-----------------------------------------------------------------------------
-int TariffImpl::Interval(int dir, time_t t) const
-{
-// Start of the day (and end of the night) in sec from 00:00:00
-int s1 = tariffData.dirPrice[dir].hDay * 3600 +
-         tariffData.dirPrice[dir].mDay * 60;
-// Start of the night (and end of the day) in sec from 00:00:00
-int s2 = tariffData.dirPrice[dir].hNight * 3600 +
-         tariffData.dirPrice[dir].mNight * 60;
-
-struct tm * lt;
-
-lt = localtime(&t);
-
-// Position of time t in sec from 00:00:00
-// Ignoring seconds due to minute precision
-int lts = lt->tm_hour * 3600 + lt->tm_min * 60;
-
-if (s1 < s2)
-    {
-    // Normal situation (00:00:00 is a night)
-    if (lts > s1 && lts < s2)
-        return TARIFF_DAY;
-    else
-        return TARIFF_NIGHT;
-    }
-else
-    {
-    // Not so common but possible situation (00:00:00 is a day)
-    if (lts < s1 && lts > s2)
-        return TARIFF_NIGHT;
-    else
-        return TARIFF_DAY;
-    }
-}
-//-----------------------------------------------------------------------------
-double TariffImpl::GetPriceWithoutFreeMb(int dir, int64_t mb, time_t t) const
-{
-int interval = Interval(dir, t);
-
-/*
- * 0011 - NB
- * *01* - NA
- * 0**1 - DB
- * **** - DA
- */
-
-bool nd = tariffData.dirPrice[dir].noDiscount;
-bool sp = tariffData.dirPrice[dir].singlePrice;
-bool th = (interval == TARIFF_NIGHT);
-bool tr = (mb > tariffData.dirPrice[dir].threshold);
-
-if (!nd && !sp && th && tr)
-    return tariffData.dirPrice[dir].priceNightB;
-else if (!nd && tr)
-    return tariffData.dirPrice[dir].priceDayB;
-else if (!sp && th)
-    return tariffData.dirPrice[dir].priceNightA;
-else
-    return tariffData.dirPrice[dir].priceDayA;
-}
-//-----------------------------------------------------------------------------
-std::string TariffImpl::TariffChangeIsAllowed(const Tariff & to, time_t currentTime) const
-{
-time_t timeout = GetChangePolicyTimeout();
-if (currentTime > timeout && timeout != 0)
-    return "";
-switch (GetChangePolicy())
-    {
-    case Tariff::ALLOW:
-        return "";
-    case Tariff::TO_CHEAP:
-        if (to.GetFee() < GetFee())
-            return "";
-        else
-            return "New tariff '" + to.GetName() + "' is more expensive than current tariff '" + GetName() + "'. The policy is '" + Tariff::toString(GetChangePolicy()) + "'.";
-    case Tariff::TO_EXPENSIVE:
-        if (to.GetFee() >= GetFee())
-            return "";
-        else
-            return "New tariff '" + to.GetName() + "' is more cheap than current tariff '" + GetName() + "'. The policy is '" + Tariff::toString(GetChangePolicy()) + "'.";
-    case Tariff::DENY:
-        return "Current tariff '" + GetName() + "', new tariff '" + to.GetName() + "'. The policy is '" + Tariff::toString(GetChangePolicy()) + "'.";
-    }
-return "";
-}
-//-----------------------------------------------------------------------------
diff --git a/stargazer/tariff_impl.h b/stargazer/tariff_impl.h
deleted file mode 100644 (file)
index a45df06..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Date: 07.11.2007
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- */
-
-#pragma once
-
-#include "stg/tariff.h"
-#include "stg/tariff_conf.h"
-
-#include <string>
-
-#include <ctime>
-#include <cstdint>
-
-#define TARIFF_DAY     0
-#define TARIFF_NIGHT   1
-
-namespace STG
-{
-
-class TariffImpl : public Tariff {
-    public:
-        explicit TariffImpl(const std::string & name)
-            : tariffData(name)
-        {}
-        explicit TariffImpl(const TariffData & td)
-            : tariffData(td)
-        {}
-
-        TariffImpl(const TariffImpl&) = default;
-        TariffImpl& operator=(const TariffImpl&) = default;
-        TariffImpl(TariffImpl&&) = default;
-        TariffImpl& operator=(TariffImpl&&) = default;
-
-        double  GetPriceWithTraffType(uint64_t up,
-                                      uint64_t down,
-                                      int dir,
-                                      time_t t) const;
-        double  GetFreeMb() const { return tariffData.tariffConf.free; }
-        double  GetPassiveCost() const { return tariffData.tariffConf.passiveCost; }
-        double  GetFee() const { return tariffData.tariffConf.fee; }
-        double  GetFree() const { return tariffData.tariffConf.free; }
-        Period  GetPeriod() const { return tariffData.tariffConf.period; }
-        ChangePolicy GetChangePolicy() const { return tariffData.tariffConf.changePolicy; }
-        time_t GetChangePolicyTimeout() const { return tariffData.tariffConf.changePolicyTimeout; }
-
-        void    Print() const;
-
-        const   std::string & GetName() const { return tariffData.tariffConf.name; }
-        void    SetName(const std::string & name) { tariffData.tariffConf.name = name; }
-
-        int     GetTraffType() const { return tariffData.tariffConf.traffType; }
-        int64_t GetTraffByType(uint64_t up, uint64_t down) const;
-        int     GetThreshold(int dir) const;
-        const TariffData & GetTariffData() const { return tariffData; }
-
-        TariffImpl & operator=(const TariffData & td);
-        bool     operator==(const TariffImpl & rhs) const { return GetName() == rhs.GetName(); }
-        bool     operator!=(const TariffImpl & rhs) const { return GetName() != rhs.GetName(); }
-        std::string TariffChangeIsAllowed(const Tariff & to, time_t currentTime) const;
-
-    private:
-        TariffData     tariffData;
-
-        double  GetPriceWithoutFreeMb(int dir, int64_t mb, time_t t) const;
-        int     Interval(int dir, time_t t) const;
-};
-
-}
diff --git a/stargazer/tariffs_impl.cpp b/stargazer/tariffs_impl.cpp
deleted file mode 100644 (file)
index 9cc829d..0000000
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Date: 07.11.2007
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- */
-
-/*
- $Revision: 1.9 $
- $Date: 2010/10/07 18:43:21 $
- $Author: faust $
- */
-
-#include <cassert>
-#include <algorithm>
-#include <vector>
-
-#include "stg/locker.h"
-#include "stg/logger.h"
-#include "stg/store.h"
-#include "stg/admin.h"
-#include "stg/admin_conf.h"
-#include "tariffs_impl.h"
-
-using STG::TariffsImpl;
-
-//-----------------------------------------------------------------------------
-TariffsImpl::TariffsImpl(Store * st)
-    : store(st),
-      WriteServLog(Logger::get()),
-      noTariff(NO_TARIFF_NAME)
-{
-ReadTariffs();
-}
-//-----------------------------------------------------------------------------
-int TariffsImpl::ReadTariffs()
-{
-std::lock_guard<std::mutex> lock(m_mutex);
-
-std::vector<std::string> tariffsList;
-if (store->GetTariffsList(&tariffsList))
-    {
-    WriteServLog("Cannot get tariffs list.");
-    WriteServLog("%s", store->GetStrError().c_str());
-    }
-
-Data::size_type tariffsNum = tariffsList.size();
-
-for (Data::size_type i = 0; i < tariffsNum; i++)
-    {
-    TariffData td;
-    if (store->RestoreTariff(&td, tariffsList[i]))
-        {
-        WriteServLog("Cannot read tariff %s.", tariffsList[i].c_str());
-        WriteServLog("%s", store->GetStrError().c_str());
-        return -1;
-        }
-    tariffs.push_back(TariffImpl(td));
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-size_t TariffsImpl::Count() const
-{
-std::lock_guard<std::mutex> lock(m_mutex);
-return tariffs.size();
-}
-//-----------------------------------------------------------------------------
-const STG::Tariff* TariffsImpl::FindByName(const std::string & name) const
-{
-if (name == NO_TARIFF_NAME)
-    return &noTariff;
-
-std::lock_guard<std::mutex> lock(m_mutex);
-const auto ti = find(tariffs.begin(), tariffs.end(), TariffImpl(name));
-
-if (ti != tariffs.end())
-    return &(*ti);
-
-return NULL;
-}
-//-----------------------------------------------------------------------------
-int TariffsImpl::Chg(const TariffData & td, const Admin * admin)
-{
-const auto& priv = admin->priv();
-
-if (!priv.tariffChg)
-    {
-    std::string s = admin->logStr() + " Change tariff \'"
-               + td.tariffConf.name + "\'. Access denied.";
-    strError = "Access denied.";
-    WriteServLog(s.c_str());
-    return -1;
-    }
-
-std::lock_guard<std::mutex> lock(m_mutex);
-
-auto ti = find(tariffs.begin(), tariffs.end(), TariffImpl(td.tariffConf.name));
-
-if (ti == tariffs.end())
-    {
-    strError = "Tariff \'" + td.tariffConf.name + "\' cannot be changed. Tariff does not exist.";
-    WriteServLog("%s %s", admin->logStr().c_str(), strError.c_str());
-    return -1;
-    }
-
-*ti = td;
-
-if (store->SaveTariff(td, td.tariffConf.name))
-    {
-    std::string error = "Tariff " + td.tariffConf.name + " writing error. " + store->GetStrError();
-    WriteServLog(error.c_str());
-    return -1;
-    }
-
-WriteServLog("%s Tariff \'%s\' changed.",
-             admin->logStr().c_str(), td.tariffConf.name.c_str());
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int TariffsImpl::Del(const std::string & name, const Admin * admin)
-{
-const auto& priv = admin->priv();
-
-if (!priv.tariffChg)
-    {
-    std::string s = admin->logStr() + " Delete tariff \'"
-               + name + "\'. Access denied.";
-    strError = "Access denied.";
-    WriteServLog(s.c_str());
-    return -1;
-    }
-
-TariffData td;
-
-    {
-    std::lock_guard<std::mutex> lock(m_mutex);
-
-    const auto ti = find(tariffs.begin(), tariffs.end(), TariffImpl(name));
-
-    if (ti == tariffs.end())
-        {
-        strError = "Tariff \'" + name + "\' cannot be deleted. Tariff does not exist.";
-        WriteServLog("%s %s", admin->logStr().c_str(), strError.c_str());
-        return -1;
-        }
-
-    if (store->DelTariff(name))
-        {
-        WriteServLog("Cannot delete tariff %s.", name.c_str());
-        WriteServLog("%s", store->GetStrError().c_str());
-        return -1;
-        }
-
-    td = ti->GetTariffData();
-
-    tariffs.erase(ti);
-    }
-
-auto ni = onDelNotifiers.begin();
-while (ni != onDelNotifiers.end())
-    {
-    (*ni)->Notify(td);
-    ++ni;
-    }
-
-WriteServLog("%s Tariff \'%s\' deleted.",
-             admin->logStr().c_str(),
-             name.c_str());
-return 0;
-}
-//-----------------------------------------------------------------------------
-int TariffsImpl::Add(const std::string & name, const Admin * admin)
-{
-const auto& priv = admin->priv();
-
-if (!priv.tariffChg)
-    {
-    std::string s = admin->logStr() + " Add tariff \'"
-               + name + "\'. Access denied.";
-    strError = "Access denied.";
-    WriteServLog(s.c_str());
-    return -1;
-    }
-
-    {
-    std::lock_guard<std::mutex> lock(m_mutex);
-
-    const auto ti = find(tariffs.begin(), tariffs.end(), TariffImpl(name));
-
-    if (ti != tariffs.end())
-        {
-        strError = "Tariff \'" + name + "\' cannot be added. Tariff already exist.";
-        WriteServLog("%s %s", admin->logStr().c_str(), strError.c_str());
-        return -1;
-        }
-
-    tariffs.push_back(TariffImpl(name));
-    }
-
-if (store->AddTariff(name) < 0)
-    {
-    strError = "Tariff " + name + " adding error. " + store->GetStrError();
-    WriteServLog(strError.c_str());
-    return -1;
-    }
-
-// Fire all "on add" notifiers
-auto ni = onAddNotifiers.begin();
-while (ni != onAddNotifiers.end())
-    {
-    (*ni)->Notify(tariffs.back().GetTariffData());
-    ++ni;
-    }
-
-WriteServLog("%s Tariff \'%s\' added.",
-                 admin->logStr().c_str(), name.c_str());
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-void TariffsImpl::GetTariffsData(std::vector<TariffData> * tdl) const
-{
-assert(tdl != NULL && "Tariffs data list is not null");
-std::lock_guard<std::mutex> lock(m_mutex);
-
-auto it = tariffs.begin();
-for (; it != tariffs.end(); ++it)
-    {
-    tdl->push_back(it->GetTariffData());
-    }
-}
-//-----------------------------------------------------------------------------
-void TariffsImpl::AddNotifierAdd(NotifierBase<TariffData> * n)
-{
-std::lock_guard<std::mutex> lock(m_mutex);
-onAddNotifiers.insert(n);
-}
-//-----------------------------------------------------------------------------
-void TariffsImpl::DelNotifierAdd(NotifierBase<TariffData> * n)
-{
-std::lock_guard<std::mutex> lock(m_mutex);
-onAddNotifiers.erase(n);
-}
-//-----------------------------------------------------------------------------
-void TariffsImpl::AddNotifierDel(NotifierBase<TariffData> * n)
-{
-std::lock_guard<std::mutex> lock(m_mutex);
-onDelNotifiers.insert(n);
-}
-//-----------------------------------------------------------------------------
-void TariffsImpl::DelNotifierDel(NotifierBase<TariffData> * n)
-{
-std::lock_guard<std::mutex> lock(m_mutex);
-onDelNotifiers.erase(n);
-}
-//-----------------------------------------------------------------------------
diff --git a/stargazer/tariffs_impl.h b/stargazer/tariffs_impl.h
deleted file mode 100644 (file)
index 4b554b4..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Date: 07.11.2007
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- */
-
-#pragma once
-
-#include "stg/tariff.h"
-#include "stg/tariffs.h"
-#include "stg/tariff_conf.h"
-#include "tariff_impl.h"
-
-#include <string>
-#include <vector>
-#include <set>
-#include <mutex>
-
-namespace STG
-{
-
-struct Store;
-class Logger;
-struct Admin;
-
-class TariffsImpl : public Tariffs {
-    public:
-        using Data = std::vector<TariffImpl>;
-
-        explicit TariffsImpl(Store * store);
-
-        int ReadTariffs () override;
-        const Tariff * FindByName(const std::string & name) const override;
-        const Tariff * GetNoTariff() const override { return &noTariff; }
-        size_t Count() const override;
-        int Del(const std::string & name, const Admin * admin) override;
-        int Add(const std::string & name, const Admin * admin) override;
-        int Chg(const TariffData & td, const Admin * admin) override;
-
-        void AddNotifierAdd(NotifierBase<TariffData> * notifier) override;
-        void DelNotifierAdd(NotifierBase<TariffData> * notifier) override;
-
-        void AddNotifierDel(NotifierBase<TariffData> * notifier) override;
-        void DelNotifierDel(NotifierBase<TariffData> * notifier) override;
-
-        void GetTariffsData(std::vector<TariffData> * tdl) const override;
-
-        const std::string & GetStrError() const override { return strError; }
-
-    private:
-        Data               tariffs;
-        Store*             store;
-        Logger&            WriteServLog;
-        mutable std::mutex m_mutex;
-        std::string        strError;
-        TariffImpl         noTariff;
-
-        std::set<NotifierBase<TariffData>*> onAddNotifiers;
-        std::set<NotifierBase<TariffData>*> onDelNotifiers;
-};
-
-}
diff --git a/stargazer/traffcounter_impl.cpp b/stargazer/traffcounter_impl.cpp
deleted file mode 100644 (file)
index 0897d6b..0000000
+++ /dev/null
@@ -1,857 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Date: 27.10.2002
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- */
-
-/*
- $Revision: 1.58 $
- $Date: 2010/11/03 11:28:07 $
- $Author: faust $
- */
-
-/* inet_aton */
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <csignal>
-#include <cassert>
-#include <cstdio> // fopen and similar
-#include <cstdlib> // strtol
-
-#include "stg/common.h"
-#include "stg/locker.h"
-#include "stg/const.h" // MONITOR_TIME_DELAY_SEC
-#include "traffcounter_impl.h"
-#include "stg_timer.h"
-#include "users_impl.h"
-
-#define FLUSH_TIME  (10)
-#define REMOVE_TIME  (31)
-
-using STG::TraffCounterImpl;
-
-const char protoName[PROTOMAX][8] =
-{"TCP", "UDP", "ICMP", "TCP_UDP", "ALL"};
-
-enum protoNum
-{
-tcp = 0, udp, icmp, tcp_udp, all
-};
-
-//-----------------------------------------------------------------------------
-TraffCounterImpl::TraffCounterImpl(UsersImpl * u, const std::string & fn)
-    : WriteServLog(Logger::get()),
-      rulesFileName(fn),
-      monitoring(false),
-      touchTimeP(stgTime - MONITOR_TIME_DELAY_SEC),
-      users(u),
-      running(false),
-      stopped(true),
-      addUserNotifier(*this),
-      delUserNotifier(*this)
-{
-for (int i = 0; i < DIR_NUM; i++)
-    strprintf(&dirName[i], "DIR%d", i);
-
-dirName[DIR_NUM] = "NULL";
-
-users->AddNotifierUserAdd(&addUserNotifier);
-users->AddNotifierUserDel(&delUserNotifier);
-
-pthread_mutex_init(&mutex, NULL);
-}
-//-----------------------------------------------------------------------------
-TraffCounterImpl::~TraffCounterImpl()
-{
-pthread_mutex_destroy(&mutex);
-}
-//-----------------------------------------------------------------------------
-int TraffCounterImpl::Start()
-{
-STG_LOCKER lock(&mutex);
-
-if (!stopped)
-    return 0;
-
-if (ReadRules())
-    {
-    printfd(__FILE__, "TraffCounterImpl::Start() - Cannot read rules\n");
-    WriteServLog("TraffCounter: Cannot read rules.");
-    return -1;
-    }
-
-printfd(__FILE__, "TraffCounter::Start()\n");
-int h = users->OpenSearch();
-assert(h && "USERS::OpenSearch is always correct");
-UserImpl * u;
-
-while (users->SearchNext(h, &u) == 0)
-    SetUserNotifiers(u);
-users->CloseSearch(h);
-
-running = true;
-if (pthread_create(&thread, NULL, Run, this))
-    {
-    printfd(__FILE__, "TraffCounterImpl::Start() - Cannot start thread\n");
-    WriteServLog("TraffCounter: Error: Cannot start thread.");
-    return -1;
-    }
-return 0;
-}
-//-----------------------------------------------------------------------------
-int TraffCounterImpl::Stop()
-{
-if (stopped)
-    return 0;
-
-running = false;
-
-int h = users->OpenSearch();
-assert(h && "USERS::OpenSearch is always correct");
-
-UserImpl * u;
-while (users->SearchNext(h, &u) == 0)
-    UnSetUserNotifiers(u);
-users->CloseSearch(h);
-
-//5 seconds to thread stops itself
-struct timespec ts = {0, 200000000};
-for (int i = 0; i < 25 && !stopped; i++)
-    {
-    nanosleep(&ts, NULL);
-    }
-
-if (!stopped)
-    return -1;
-
-printfd(__FILE__, "TraffCounter::Stop()\n");
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-void * TraffCounterImpl::Run(void * data)
-{
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-TraffCounterImpl * tc = static_cast<TraffCounterImpl *>(data);
-tc->stopped = false;
-int c = 0;
-
-time_t touchTime = stgTime - MONITOR_TIME_DELAY_SEC;
-struct timespec ts = {0, 500000000};
-while (tc->running)
-    {
-    nanosleep(&ts, 0);
-    if (!tc->running)
-        {
-        tc->FlushAndRemove();
-        break;
-        }
-
-    if (tc->monitoring && (touchTime + MONITOR_TIME_DELAY_SEC <= stgTime))
-        {
-        std::string monFile(tc->monitorDir + "/traffcounter_r");
-        printfd(__FILE__, "Monitor=%d file TraffCounter %s\n", tc->monitoring, monFile.c_str());
-        touchTime = stgTime;
-        TouchFile(monFile);
-        }
-
-    if (++c % FLUSH_TIME == 0)
-        tc->FlushAndRemove();
-    }
-
-tc->stopped = true;
-return NULL;
-}
-//-----------------------------------------------------------------------------
-void TraffCounterImpl::process(const RawPacket & rawPacket)
-{
-if (!running)
-    return;
-
-if (monitoring && (touchTimeP + MONITOR_TIME_DELAY_SEC <= stgTime))
-    {
-    std::string monFile = monitorDir + "/traffcounter_p";
-    printfd(__FILE__, "Monitor=%d file TraffCounter %s\n", monitoring, monFile.c_str());
-    touchTimeP = stgTime;
-    TouchFile(monFile);
-    }
-
-STG_LOCKER lock(&mutex);
-
-//printfd(__FILE__, "TraffCounter::Process()\n");
-//TODO replace find with lower_bound.
-
-// Searching a new packet in a tree.
-pp_iter pi = packets.find(rawPacket);
-
-// Packet found - update length and time
-if (pi != packets.end())
-    {
-    pi->second.lenU += rawPacket.GetLen();
-    pi->second.lenD += rawPacket.GetLen();
-    pi->second.updateTime = stgTime;
-    /*printfd(__FILE__, "=============================\n");
-    printfd(__FILE__, "Packet found!\n");
-    printfd(__FILE__, "Version=%d\n", rawPacket.GetIPVersion());
-    printfd(__FILE__, "HeaderLen=%d\n", rawPacket.GetHeaderLen());
-    printfd(__FILE__, "PacketLen=%d\n", rawPacket.GetLen());
-    printfd(__FILE__, "SIP=%s\n", inet_ntostring(rawPacket.GetSrcIP()).c_str());
-    printfd(__FILE__, "DIP=%s\n", inet_ntostring(rawPacket.GetDstIP()).c_str());
-    printfd(__FILE__, "src port=%d\n", rawPacket.GetSrcPort());
-    printfd(__FILE__, "pst port=%d\n", rawPacket.GetDstPort());
-    printfd(__FILE__, "len=%d\n", rawPacket.GetLen());
-    printfd(__FILE__, "proto=%d\n", rawPacket.GetProto());
-    printfd(__FILE__, "PacketDirU=%d\n", pi->second.dirU);
-    printfd(__FILE__, "PacketDirD=%d\n", pi->second.dirD);
-    printfd(__FILE__, "=============================\n");*/
-    return;
-    }
-
-PacketExtraData ed;
-
-// Packet not found - add new packet
-
-ed.updateTime = stgTime;
-ed.flushTime = stgTime;
-
-/*
- userU is that whose user_ip == packet_ip_src
- userD is that whose user_ip == packet_ip_dst
- */
-
-uint32_t ipU = rawPacket.GetSrcIP();
-uint32_t ipD = rawPacket.GetDstIP();
-
-// Searching users with such IP
-if (users->FindByIPIdx(ipU, &ed.userU) == 0)
-    {
-    ed.userUPresent = true;
-    }
-
-if (users->FindByIPIdx(ipD, &ed.userD) == 0)
-    {
-    ed.userDPresent = true;
-    }
-
-if (ed.userUPresent ||
-    ed.userDPresent)
-    {
-    DeterminateDir(rawPacket, &ed.dirU, &ed.dirD);
-
-    ed.lenD = ed.lenU = rawPacket.GetLen();
-
-    //TODO use result of lower_bound to inserting new record
-
-    // Adding packet to a tree.
-    std::pair<pp_iter, bool> insertResult = packets.insert(std::make_pair(rawPacket, ed));
-    pp_iter newPacket = insertResult.first;
-
-    // Adding packet reference to an IP index.
-    ip2packets.insert(std::make_pair(ipU, newPacket));
-    ip2packets.insert(std::make_pair(ipD, newPacket));
-    }
-}
-//-----------------------------------------------------------------------------
-void TraffCounterImpl::FlushAndRemove()
-{
-STG_LOCKER lock(&mutex);
-
-Packets::size_type oldPacketsSize = packets.size();
-Index::size_type oldIp2packetsSize = ip2packets.size();
-
-pp_iter pi;
-pi = packets.begin();
-Packets newPackets;
-ip2packets.erase(ip2packets.begin(), ip2packets.end());
-while (pi != packets.end())
-    {
-    //Flushing
-    if (stgTime - pi->second.flushTime > FLUSH_TIME)
-        {
-        if (pi->second.userUPresent)
-            {
-            //printfd(__FILE__, "+++ Flushing U user %s (%s:%d) of length %d\n", pi->second.userU->GetLogin().c_str(), inet_ntostring(pi->first.GetSrcIP()).c_str(), pi->first.GetSrcPort(), pi->second.lenU);
-
-            // Add stat
-            if (pi->second.dirU < DIR_NUM)
-                {
-                #ifdef TRAFF_STAT_WITH_PORTS
-                pi->second.userU->AddTraffStatU(pi->second.dirU,
-                                                pi->first.GetDstIP(),
-                                                pi->first.GetDstPort(),
-                                                pi->second.lenU);
-                #else
-                pi->second.userU->AddTraffStatU(pi->second.dirU,
-                                                pi->first.GetDstIP(),
-                                                pi->second.lenU);
-                #endif
-                }
-
-            pi->second.lenU = 0;
-            pi->second.flushTime = stgTime;
-            }
-
-        if (pi->second.userDPresent)
-            {
-            //printfd(__FILE__, "+++ Flushing D user %s (%s:%d) of length %d\n", pi->second.userD->GetLogin().c_str(), inet_ntostring(pi->first.GetDstIP()).c_str(), pi->first.GetDstPort(), pi->second.lenD);
-
-            // Add stat
-            if (pi->second.dirD < DIR_NUM)
-                {
-                #ifdef TRAFF_STAT_WITH_PORTS
-                pi->second.userD->AddTraffStatD(pi->second.dirD,
-                                                pi->first.GetSrcIP(),
-                                                pi->first.GetSrcPort(),
-                                                pi->second.lenD);
-                #else
-                pi->second.userD->AddTraffStatD(pi->second.dirD,
-                                                pi->first.GetSrcIP(),
-                                                pi->second.lenD);
-                #endif
-                }
-
-            pi->second.lenD = 0;
-            pi->second.flushTime = stgTime;
-            }
-        }
-
-    if (stgTime - pi->second.updateTime < REMOVE_TIME)
-        {
-        std::pair<pp_iter, bool> res = newPackets.insert(*pi);
-        if (res.second)
-            {
-            ip2packets.insert(std::make_pair(pi->first.GetSrcIP(), res.first));
-            ip2packets.insert(std::make_pair(pi->first.GetDstIP(), res.first));
-            }
-        }
-    ++pi;
-    }
-swap(packets, newPackets);
-printfd(__FILE__, "FlushAndRemove() packets: %d(rem %d) ip2packets: %d(rem %d)\n",
-        packets.size(),
-        oldPacketsSize - packets.size(),
-        ip2packets.size(),
-        oldIp2packetsSize - ip2packets.size());
-
-}
-//-----------------------------------------------------------------------------
-void TraffCounterImpl::AddUser(UserImpl * user)
-{
-printfd(__FILE__, "AddUser: %s\n", user->GetLogin().c_str());
-uint32_t uip = user->GetCurrIP();
-std::pair<ip2p_iter, ip2p_iter> pi;
-
-STG_LOCKER lock(&mutex);
-// Find all packets with IP belongs to this user
-pi = ip2packets.equal_range(uip);
-
-while (pi.first != pi.second)
-    {
-    if (pi.first->second->first.GetSrcIP() == uip)
-        {
-        assert((!pi.first->second->second.userUPresent ||
-                 pi.first->second->second.userU == user) &&
-               "U user present but it's not current user");
-
-        pi.first->second->second.lenU = 0;
-        pi.first->second->second.userU = user;
-        pi.first->second->second.userUPresent = true;
-        }
-
-    if (pi.first->second->first.GetDstIP() == uip)
-        {
-        assert((!pi.first->second->second.userDPresent ||
-                 pi.first->second->second.userD == user) &&
-               "D user present but it's not current user");
-
-        pi.first->second->second.lenD = 0;
-        pi.first->second->second.userD = user;
-        pi.first->second->second.userDPresent = true;
-        }
-
-    ++pi.first;
-    }
-}
-//-----------------------------------------------------------------------------
-void TraffCounterImpl::DelUser(uint32_t uip)
-{
-printfd(__FILE__, "DelUser: %s \n", inet_ntostring(uip).c_str());
-std::pair<ip2p_iter, ip2p_iter> pi;
-
-STG_LOCKER lock(&mutex);
-pi = ip2packets.equal_range(uip);
-
-while (pi.first != pi.second)
-    {
-    if (pi.first->second->first.GetSrcIP() == uip)
-        {
-        if (pi.first->second->second.dirU < DIR_NUM && pi.first->second->second.userUPresent)
-            {
-            #ifdef TRAFF_STAT_WITH_PORTS
-            pi.first->second->second.userU->AddTraffStatU(pi.first->second->second.dirU,
-                                                          pi.first->second->first.GetDstIP(),
-                                                          pi.first->second->first.GetDstPort(),
-                                                          pi.first->second->second.lenU);
-            #else
-            pi.first->second->second.userU->AddTraffStatU(pi.first->second->second.dirU,
-                                                          pi.first->second->first.GetDstIP(),
-                                                          pi.first->second->second.lenU);
-            #endif
-            }
-        pi.first->second->second.userUPresent = false;
-        }
-
-    if (pi.first->second->first.GetDstIP() == uip)
-        {
-        if (pi.first->second->second.dirD < DIR_NUM && pi.first->second->second.userDPresent)
-            {
-            #ifdef TRAFF_STAT_WITH_PORTS
-            pi.first->second->second.userD->AddTraffStatD(pi.first->second->second.dirD,
-                                                          pi.first->second->first.GetSrcIP(),
-                                                          pi.first->second->first.GetSrcPort(),
-                                                          pi.first->second->second.lenD);
-            #else
-            pi.first->second->second.userD->AddTraffStatD(pi.first->second->second.dirD,
-                                                          pi.first->second->first.GetSrcIP(),
-                                                          pi.first->second->second.lenD);
-            #endif
-            }
-
-        pi.first->second->second.userDPresent = false;
-        }
-
-    ++pi.first;
-    }
-
-ip2packets.erase(pi.first, pi.second);
-}
-//-----------------------------------------------------------------------------
-void TraffCounterImpl::SetUserNotifiers(UserImpl * user)
-{
-// Adding user. Adding notifiers to user.
-TRF_IP_BEFORE ipBNotifier(*this, user);
-ipBeforeNotifiers.push_front(ipBNotifier);
-user->AddCurrIPBeforeNotifier(&(*ipBeforeNotifiers.begin()));
-
-TRF_IP_AFTER ipANotifier(*this, user);
-ipAfterNotifiers.push_front(ipANotifier);
-user->AddCurrIPAfterNotifier(&(*ipAfterNotifiers.begin()));
-}
-//-----------------------------------------------------------------------------
-void TraffCounterImpl::UnSetUserNotifiers(UserImpl * user)
-{
-// Removing user. Removing notifiers from user.
-std::list<TRF_IP_BEFORE>::iterator bi;
-std::list<TRF_IP_AFTER>::iterator ai;
-
-bi = ipBeforeNotifiers.begin();
-while (bi != ipBeforeNotifiers.end())
-    {
-    if (user->GetLogin() == bi->GetUser()->GetLogin())
-        {
-        user->DelCurrIPBeforeNotifier(&(*bi));
-        ipBeforeNotifiers.erase(bi);
-        break;
-        }
-    ++bi;
-    }
-
-ai = ipAfterNotifiers.begin();
-while (ai != ipAfterNotifiers.end())
-    {
-    if (user->GetLogin() == ai->GetUser()->GetLogin())
-        {
-        user->DelCurrIPAfterNotifier(&(*ai));
-        ipAfterNotifiers.erase(ai);
-        break;
-        }
-    ++ai;
-    }
-}
-//-----------------------------------------------------------------------------
-void TraffCounterImpl::DeterminateDir(const RawPacket & packet,
-                                       int * dirU, // Direction for incoming packet
-                                       int * dirD) const // Direction for outgoing packet
-{
-bool addrMatchU = false;
-bool portMatchU = false;
-bool addrMatchD = false;
-bool portMatchD = false;
-bool foundU = false; // Was rule for U found ?
-bool foundD = false; // Was rule for D found ?
-//printfd(__FILE__, "foundU=%d, foundD=%d\n", foundU, foundD);
-
-enum { ICMP_RPOTO = 1, TCP_PROTO = 6, UDP_PROTO = 17 };
-
-std::list<Rule>::const_iterator ln;
-ln = rules.begin();
-
-while (ln != rules.end())
-    {
-    if (!foundU)
-        {
-        portMatchU = false;
-
-        switch (ln->proto)
-            {
-            case all:
-                portMatchU = true;
-                break;
-
-            case icmp:
-                portMatchU = (packet.GetProto() == ICMP_RPOTO);
-                break;
-
-            case tcp_udp:
-                if (packet.GetProto() == TCP_PROTO || packet.GetProto() == UDP_PROTO)
-                    portMatchU = (packet.GetDstPort() >= ln->port1) && (packet.GetDstPort() <= ln->port2);
-                break;
-
-            case tcp:
-                if (packet.GetProto() == TCP_PROTO)
-                    portMatchU = (packet.GetDstPort() >= ln->port1) && (packet.GetDstPort() <= ln->port2);
-                break;
-
-            case udp:
-                if (packet.GetProto() == UDP_PROTO)
-                    portMatchU = (packet.GetDstPort() >= ln->port1) && (packet.GetDstPort() <= ln->port2);
-                break;
-
-            default:
-                printfd(__FILE__, "Error! Incorrect rule!\n");
-                break;
-            }
-
-        addrMatchU = (packet.GetDstIP() & ln->mask) == ln->ip;
-
-        if (!foundU && addrMatchU && portMatchU)
-            {
-            foundU = true;
-            *dirU = ln->dir;
-            //printfd(__FILE__, "Up rule ok! %d\n", ln->dir);
-            }
-
-        } //if (!foundU)
-
-    if (!foundD)
-        {
-        portMatchD = false;
-
-        switch (ln->proto)
-            {
-            case all:
-                portMatchD = true;
-                break;
-
-            case icmp:
-                portMatchD = (packet.GetProto() == ICMP_RPOTO);
-                break;
-
-            case tcp_udp:
-                if (packet.GetProto() == TCP_PROTO || packet.GetProto() == UDP_PROTO)
-                    portMatchD = (packet.GetSrcPort() >= ln->port1) && (packet.GetSrcPort() <= ln->port2);
-                break;
-
-            case tcp:
-                if (packet.GetProto() == TCP_PROTO)
-                    portMatchD = (packet.GetSrcPort() >= ln->port1) && (packet.GetSrcPort() <= ln->port2);
-                break;
-
-            case udp:
-                if (packet.GetProto() == UDP_PROTO)
-                    portMatchD = (packet.GetSrcPort() >= ln->port1) && (packet.GetSrcPort() <= ln->port2);
-                break;
-
-            default:
-                printfd(__FILE__, "Error! Incorrect rule!\n");
-                break;
-            }
-
-        addrMatchD = (packet.GetSrcIP() & ln->mask) == ln->ip;
-
-        if (!foundD && addrMatchD && portMatchD)
-            {
-            foundD = true;
-            *dirD = ln->dir;
-            //printfd(__FILE__, "Down rule ok! %d\n", ln->dir);
-            }
-        } //if (!foundD)
-
-    ++ln;
-    }   //while (ln != rules.end())
-
-if (!foundU)
-    *dirU = DIR_NUM;
-
-if (!foundD)
-    *dirD = DIR_NUM;
-}
-//-----------------------------------------------------------------------------
-bool TraffCounterImpl::ReadRules(bool test)
-{
-//printfd(__FILE__, "TraffCounter::ReadRules()\n");
-
-Rule rul;
-FILE * f;
-char str[1024];
-char tp[100];   // protocol
-char ta[100];   // address
-char td[100];   // target direction
-int r;
-int lineNumber = 0;
-f = fopen(rulesFileName.c_str(), "rt");
-
-if (!f)
-    {
-    printfd(__FILE__, "TraffCounterImpl::ReadRules() - File '%s' cannot be opened.\n", rulesFileName.c_str());
-    WriteServLog("File '%s' cannot be oppened.", rulesFileName.c_str());
-    return true;
-    }
-
-while (fgets(str, 1023, f))
-    {
-    lineNumber++;
-    if (str[strspn(str," \t")] == '#' || str[strspn(str," \t")] == '\n')
-        {
-        continue;
-        }
-
-    r = sscanf(str,"%99s %99s %99s", tp, ta, td);
-    if (r != 3)
-        {
-        printfd(__FILE__, "TraffCounterImpl::ReadRules() - Error in file '%s' at line %d. There must be 3 parameters.\n", rulesFileName.c_str(), lineNumber);
-        WriteServLog("Error in file '%s' at line %d. There must be 3 parameters.", rulesFileName.c_str(), lineNumber);
-        fclose(f);
-        return true;
-        }
-
-    rul.proto = 0xff;
-    rul.dir = 0xff;
-
-    for (uint8_t i = 0; i < PROTOMAX; i++)
-        {
-        if (strcasecmp(tp, protoName[i]) == 0)
-            rul.proto = i;
-        }
-
-    for (uint32_t i = 0; i < DIR_NUM + 1; i++)
-        {
-        if (td == dirName[i])
-            rul.dir = i;
-        }
-
-    if (rul.dir == 0xff || rul.proto == 0xff)
-        {
-        printfd(__FILE__, "TraffCounterImpl::ReadRules() - Error in file '%s' at line %d.\n", rulesFileName.c_str(), lineNumber);
-        WriteServLog("Error in file %s. Line %d.",
-                     rulesFileName.c_str(), lineNumber);
-        fclose(f);
-        return true;
-        }
-
-    if (ParseAddress(ta, &rul) != 0)
-        {
-        printfd(__FILE__, "TraffCounterImpl::ReadRules() - Error in file '%s' at line %d. Error in adress.\n", rulesFileName.c_str(), lineNumber);
-        WriteServLog("Error in file %s. Error in adress. Line %d.",
-                     rulesFileName.c_str(), lineNumber);
-        fclose(f);
-        return true;
-        }
-    if (!test)
-        rules.push_back(rul);
-    }
-
-fclose(f);
-
-// Adding lastest rule: ALL 0.0.0.0/0 NULL
-rul.dir = DIR_NUM; //NULL
-rul.ip = 0;  //0.0.0.0
-rul.mask = 0;
-rul.port1 = 0;
-rul.port2 = 65535;
-rul.proto = all;
-
-if (!test)
-    rules.push_back(rul);
-
-return false;
-}
-//-----------------------------------------------------------------------------
-int TraffCounterImpl::Reload()
-{
-STG_LOCKER lock(&mutex);
-
-if (ReadRules(true))
-    {
-    printfd(__FILE__, "TraffCounterImpl::Reload() - Failed to reload rules.\n");
-    WriteServLog("TraffCounter: Cannot reload rules. Errors found.");
-    return -1;
-    }
-
-FreeRules();
-ReadRules();
-printfd(__FILE__, "TraffCounterImpl::Reload() -  Reloaded rules successfully.\n");
-WriteServLog("TraffCounter: Reloaded rules successfully.");
-return 0;
-}
-//-----------------------------------------------------------------------------
-bool TraffCounterImpl::ParseAddress(const char * ta, Rule * rule) const
-{
-char addr[50], mask[20], port1[20], port2[20], ports[40];
-
-size_t len = strlen(ta);
-char n = 0;
-size_t i, p;
-memset(addr, 0, sizeof(addr));
-for (i = 0; i < len; i++)
-    {
-    if (ta[i] == '/' || ta[i] == ':')
-        {
-        addr[i] = 0;
-        n = ta[i];
-        break;
-        }
-    addr[i] = ta[i];
-    n = 0;
-    }
-addr[i + 1] = 0;
-p = i + 1;
-
-if (n == '/')
-    {
-    // mask
-    for (; i < len; i++)
-        {
-        if (ta[i] == ':')
-            {
-            mask[i - p] = 0;
-            n = ':';
-            break;
-            }
-        mask[i - p] = ta[i];
-        }
-    mask[i - p] = 0;
-    }
-else
-    {
-    strcpy(mask, "32");
-    }
-
-p = i + 1;
-i++;
-
-if (n == ':')
-    {
-    // port
-    if (!(rule->proto == tcp || rule->proto == udp || rule->proto == tcp_udp))
-        {
-        printfd(__FILE__, "TraffCounterImpl::ParseAddress() - No ports specified for this protocol.\n");
-        WriteServLog("No ports specified for this protocol.");
-        return true;
-        }
-
-    for (; i < len; i++)
-        ports[i - p] = ta[i];
-
-    ports[i - p] = 0;
-    }
-else
-    {
-    strcpy(ports, "0-65535");
-    }
-
-char *sss;
-char pts[100];
-strcpy(pts, ports);
-
-if ((sss = strchr(ports, '-')) != NULL)
-    {
-    strncpy(port1, ports, int(sss-ports));
-    port1[int(sss - ports)] = 0;
-    strcpy(port2, sss + 1);
-    }
-else
-    {
-    strcpy(port1, ports);
-    strcpy(port2, ports);
-    }
-
-// Convert strings to mask, ports and IP
-uint16_t prt1, prt2, msk;
-struct in_addr ipaddr;
-char *res;
-
-msk = static_cast<uint16_t>(strtol(mask, &res, 10));
-if (*res != 0)
-    return true;
-
-prt1 = static_cast<uint16_t>(strtol(port1, &res, 10));
-if (*res != 0)
-    return true;
-
-prt2 = static_cast<uint16_t>(strtol(port2, &res, 10));
-if (*res != 0)
-    return true;
-
-int r = inet_aton(addr, &ipaddr);
-if (r == 0)
-    return true;
-
-rule->ip = ipaddr.s_addr;
-rule->mask = CalcMask(msk);
-
-if ((ipaddr.s_addr & rule->mask) != ipaddr.s_addr)
-    {
-    printfd(__FILE__, "TraffCounterImpl::ParseAddress() - Address does'n match mask.\n");
-    WriteServLog("Address does'n match mask.");
-    return true;
-    }
-
-rule->port1 = prt1;
-rule->port2 = prt2;
-
-return false;
-}
-//-----------------------------------------------------------------------------
-uint32_t TraffCounterImpl::CalcMask(uint32_t msk) const
-{
-if (msk >= 32) return 0xFFffFFff;
-if (msk == 0) return 0;
-return htonl(0xFFffFFff << (32 - msk));
-}
-//---------------------------------------------------------------------------
-void TraffCounterImpl::FreeRules()
-{
-rules.clear();
-}
-//-----------------------------------------------------------------------------
-void TraffCounterImpl::SetMonitorDir(const std::string & dir)
-{
-monitorDir = dir;
-monitoring = !monitorDir.empty();
-}
-//-----------------------------------------------------------------------------
diff --git a/stargazer/traffcounter_impl.h b/stargazer/traffcounter_impl.h
deleted file mode 100644 (file)
index 78027cb..0000000
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- */
-
-#pragma once
-
-#include "stg/traffcounter.h"
-#include "stg/logger.h"
-#include "stg/raw_ip_packet.h"
-#include "stg/noncopyable.h"
-#include "stg/notifer.h"
-#include "actions.h"
-#include "eventloop.h"
-#include "user_impl.h"
-
-#include <ctime>
-#include <list>
-#include <map>
-#include <string>
-#include <cstdint>
-
-#include <pthread.h>
-
-#define PROTOMAX    (5)
-
-namespace STG
-{
-
-class UsersImpl;
-
-//-----------------------------------------------------------------------------
-struct Rule {
-uint32_t    ip;             // IP
-uint32_t    mask;           // Network mask
-uint16_t    port1;          // Min port
-uint16_t    port2;          // Max port
-uint8_t     proto;          // Protocol
-uint32_t    dir;            // Direction
-};
-//-----------------------------------------------------------------------------
-struct PacketExtraData {
-    PacketExtraData()
-        : flushTime(0),
-          updateTime(0),
-          userU(NULL),
-          userUPresent(false),
-          userD(NULL),
-          userDPresent(false),
-          dirU(DIR_NUM),
-          dirD(DIR_NUM),
-          lenU(0),
-          lenD(0)
-    {}
-
-    time_t      flushTime;          // Last flush time
-    time_t      updateTime;         // Last update time
-    UserImpl * userU;              // Uploader
-    bool        userUPresent;       // Uploader is registered user
-    UserImpl * userD;              // Downloader
-    bool        userDPresent;       // Downloader is registered user
-    int         dirU;               // Upload direction
-    int         dirD;               // Download direction
-    uint32_t    lenU;               // Upload length
-    uint32_t    lenD;               // Download length
-};
-//-----------------------------------------------------------------------------
-class TraffCounterImpl;
-//-----------------------------------------------------------------------------
-class TRF_IP_BEFORE: public PropertyNotifierBase<uint32_t> {
-public:
-                TRF_IP_BEFORE(TraffCounterImpl & t, UserImpl * u)
-                    : PropertyNotifierBase<uint32_t>(),
-                      traffCnt(t),
-                      user(u)
-                {}
-                TRF_IP_BEFORE(const TRF_IP_BEFORE & rvalue)
-                    : PropertyNotifierBase<uint32_t>(),
-                      traffCnt(rvalue.traffCnt),
-                      user(rvalue.user)
-                {}
-    void        Notify(const uint32_t & oldValue, const uint32_t & newValue);
-    void        SetUser(UserImpl * u) { user = u; }
-    UserImpl * GetUser() const { return user; }
-
-private:
-    TRF_IP_BEFORE & operator=(const TRF_IP_BEFORE & rvalue);
-
-    TraffCounterImpl & traffCnt;
-    UserImpl * user;
-};
-//-----------------------------------------------------------------------------
-class TRF_IP_AFTER: public PropertyNotifierBase<uint32_t> {
-public:
-                TRF_IP_AFTER(TraffCounterImpl & t, UserImpl * u)
-                    : PropertyNotifierBase<uint32_t>(),
-                      traffCnt(t),
-                      user(u)
-                {}
-                TRF_IP_AFTER(const TRF_IP_AFTER & rvalue)
-                    : PropertyNotifierBase<uint32_t>(),
-                      traffCnt(rvalue.traffCnt),
-                      user(rvalue.user)
-                {}
-    void        Notify(const uint32_t & oldValue, const uint32_t & newValue);
-    void        SetUser(UserImpl * u) { user = u; }
-    UserImpl * GetUser() const { return user; }
-private:
-    TRF_IP_AFTER & operator=(const TRF_IP_AFTER & rvalue);
-
-    TraffCounterImpl & traffCnt;
-    UserImpl * user;
-};
-
-using UserImplPtr = UserImpl*;
-//-----------------------------------------------------------------------------
-class ADD_USER_NONIFIER: public NotifierBase<UserImplPtr> {
-public:
-            explicit ADD_USER_NONIFIER(TraffCounterImpl & t) :
-                NotifierBase<UserImplPtr>(),
-                traffCnt(t)
-            {}
-    virtual ~ADD_USER_NONIFIER() {}
-    void    Notify(const UserImplPtr & user);
-
-private:
-    ADD_USER_NONIFIER(const ADD_USER_NONIFIER & rvalue);
-    ADD_USER_NONIFIER & operator=(const ADD_USER_NONIFIER & rvalue);
-
-    TraffCounterImpl & traffCnt;
-};
-//-----------------------------------------------------------------------------
-class DEL_USER_NONIFIER: public NotifierBase<UserImplPtr> {
-public:
-            explicit DEL_USER_NONIFIER(TraffCounterImpl & t) :
-                NotifierBase<UserImplPtr>(),
-                traffCnt(t)
-            {}
-    virtual ~DEL_USER_NONIFIER() {}
-    void    Notify(const UserImplPtr & user);
-
-private:
-    DEL_USER_NONIFIER(const DEL_USER_NONIFIER & rvalue);
-    DEL_USER_NONIFIER & operator=(const DEL_USER_NONIFIER & rvalue);
-
-    TraffCounterImpl & traffCnt;
-};
-//-----------------------------------------------------------------------------
-class TraffCounterImpl : public TraffCounter {
-    friend class ADD_USER_NONIFIER;
-    friend class DEL_USER_NONIFIER;
-    friend class TRF_IP_BEFORE;
-    friend class TRF_IP_AFTER;
-    public:
-        TraffCounterImpl(UsersImpl * users, const std::string & rulesFileName);
-        ~TraffCounterImpl();
-
-        int         Reload();
-        int         Start();
-        int         Stop();
-
-        void        process(const RawPacket & rawPacket) override;
-        void        SetMonitorDir(const std::string & monitorDir);
-
-        size_t      rulesCount() const override { return rules.size(); }
-
-    private:
-        bool        ParseAddress(const char * ta, Rule * rule) const;
-        uint32_t    CalcMask(uint32_t msk) const;
-        void        FreeRules();
-        bool        ReadRules(bool test = false);
-
-        static void * Run(void * data);
-
-        void        DeterminateDir(const RawPacket & packet,
-                                   int * dirU, // Direction for upload
-                                   int * dirD) const; // Direction for download
-
-        void        FlushAndRemove();
-
-        void        AddUser(UserImpl * user);
-        void        DelUser(uint32_t uip);
-        void        SetUserNotifiers(UserImpl * user);
-        void        UnSetUserNotifiers(UserImpl * user);
-
-        typedef std::list<Rule>::iterator rule_iter;
-
-        std::list<Rule>          rules;
-
-        typedef std::map<RawPacket, PacketExtraData> Packets;
-        typedef Packets::iterator pp_iter;
-        typedef std::multimap<uint32_t, pp_iter> Index;
-        typedef Index::iterator ip2p_iter;
-        typedef Index::const_iterator ip2p_citer;
-
-        Packets packets; // Packets tree
-
-        Index ip2packets; // IP-to-Packet index
-
-        std::string              dirName[DIR_NUM + 1];
-
-        Logger &             WriteServLog;
-        std::string              rulesFileName;
-
-        std::string              monitorDir;
-        bool                     monitoring;
-        time_t                   touchTimeP;
-
-        UsersImpl *             users;
-
-        bool                     running;
-        bool                     stopped;
-        pthread_mutex_t          mutex;
-        pthread_t                thread;
-
-        std::list<TRF_IP_BEFORE> ipBeforeNotifiers;
-        std::list<TRF_IP_AFTER>  ipAfterNotifiers;
-
-        ADD_USER_NONIFIER        addUserNotifier;
-        DEL_USER_NONIFIER        delUserNotifier;
-};
-//-----------------------------------------------------------------------------
-inline
-void TRF_IP_BEFORE::Notify(const uint32_t & oldValue, const uint32_t &)
-{
-// User changes his address. Remove old IP
-if (!oldValue)
-    return;
-
-EVENT_LOOP_SINGLETON::GetInstance().Enqueue(traffCnt, &TraffCounterImpl::DelUser, oldValue);
-}
-//-----------------------------------------------------------------------------
-inline
-void TRF_IP_AFTER::Notify(const uint32_t &, const uint32_t & newValue)
-{
-// User changes his address. Add new IP
-if (!newValue)
-    return;
-
-EVENT_LOOP_SINGLETON::GetInstance().Enqueue(traffCnt, &TraffCounterImpl::AddUser, user);
-}
-//-----------------------------------------------------------------------------
-inline
-void ADD_USER_NONIFIER::Notify(const UserImplPtr & user)
-{
-EVENT_LOOP_SINGLETON::GetInstance().Enqueue(traffCnt, &TraffCounterImpl::SetUserNotifiers, user);
-}
-//-----------------------------------------------------------------------------
-inline
-void DEL_USER_NONIFIER::Notify(const UserImplPtr & user)
-{
-EVENT_LOOP_SINGLETON::GetInstance().Enqueue(traffCnt, &TraffCounterImpl::UnSetUserNotifiers, user);
-EVENT_LOOP_SINGLETON::GetInstance().Enqueue(traffCnt, &TraffCounterImpl::DelUser, user->GetCurrIP());
-}
-//-----------------------------------------------------------------------------
-}
diff --git a/stargazer/user_impl.cpp b/stargazer/user_impl.cpp
deleted file mode 100644 (file)
index 2b7cc3a..0000000
+++ /dev/null
@@ -1,1543 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Date: 27.10.2002
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- */
-
-/*
- $Revision: 1.101 $
- $Date: 2010/11/03 10:50:03 $
- $Author: faust $
- */
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#include "user_impl.h"
-#include "settings_impl.h"
-#include "stg_timer.h"
-
-#include "stg/users.h"
-#include "stg/common.h"
-#include "stg/scriptexecuter.h"
-#include "stg/tariff.h"
-#include "stg/tariffs.h"
-#include "stg/services.h"
-#include "stg/service_conf.h"
-#include "stg/admin.h"
-
-#include <algorithm>
-#include <functional>
-
-#include <cassert>
-#include <cstdlib>
-#include <cmath>
-
-#include <pthread.h>
-#include <unistd.h> // access
-
-using STG::UserImpl;
-
-namespace
-{
-
-std::string dirsToString(const bool * dirs)
-{
-std::string res;
-for (size_t i = 0; i < DIR_NUM; i++)
-    res += dirs[i] ? '1' : '0';
-return res;
-}
-
-void dirsFromBits(bool * dirs, uint32_t bits)
-{
-for (size_t i = 0; i < DIR_NUM; i++)
-    dirs[i] = bits & (1 << i);
-}
-
-}
-
-UserImpl::UserImpl(const Settings * s,
-           const Store * st,
-           const Tariffs * t,
-           const Admin * a,
-           const Users * u,
-           const Services & svcs)
-    : users(u),
-      properties(*s),
-      WriteServLog(Logger::get()),
-      lastScanMessages(0),
-      id(0),
-      __connected(0),
-      connected(__connected),
-      __currIP(0),
-      currIP(__currIP),
-      lastIPForDisconnect(0),
-      pingTime(0),
-      sysAdmin(a),
-      store(st),
-      tariffs(t),
-      tariff(NULL),
-      m_services(svcs),
-      settings(s),
-      authorizedModificationTime(0),
-      deleted(false),
-      lastWriteStat(0),
-      lastWriteDetailedStat(0),
-      cash(properties.cash),
-      up(properties.up),
-      down(properties.down),
-      lastCashAdd(properties.lastCashAdd),
-      passiveTime(properties.passiveTime),
-      lastCashAddTime(properties.lastCashAddTime),
-      freeMb(properties.freeMb),
-      lastActivityTime(properties.lastActivityTime),
-      password(properties.password),
-      passive(properties.passive),
-      disabled(properties.disabled),
-      disabledDetailStat(properties.disabledDetailStat),
-      alwaysOnline(properties.alwaysOnline),
-      tariffName(properties.tariffName),
-      nextTariff(properties.nextTariff),
-      address(properties.address),
-      note(properties.note),
-      group(properties.group),
-      email(properties.email),
-      phone(properties.phone),
-      realName(properties.realName),
-      credit(properties.credit),
-      creditExpire(properties.creditExpire),
-      ips(properties.ips),
-      userdata0(properties.userdata0),
-      userdata1(properties.userdata1),
-      userdata2(properties.userdata2),
-      userdata3(properties.userdata3),
-      userdata4(properties.userdata4),
-      userdata5(properties.userdata5),
-      userdata6(properties.userdata6),
-      userdata7(properties.userdata7),
-      userdata8(properties.userdata8),
-      userdata9(properties.userdata9),
-      sessionUploadModTime(stgTime),
-      sessionDownloadModTime(stgTime),
-      passiveNotifier(this),
-      disabledNotifier(this),
-      tariffNotifier(this),
-      cashNotifier(this),
-      ipNotifier(this)
-{
-Init();
-}
-//-----------------------------------------------------------------------------
-void UserImpl::Init()
-{
-password = "*_EMPTY_PASSWORD_*";
-tariffName = NO_TARIFF_NAME;
-tariff = tariffs->FindByName(tariffName);
-ips = UserIPs::parse("*");
-lastWriteStat = stgTime + random() % settings->GetStatWritePeriod();
-lastWriteDetailedStat = stgTime;
-
-properties.tariffName.AddBeforeNotifier(&tariffNotifier);
-properties.passive.AddBeforeNotifier(&passiveNotifier);
-properties.disabled.AddAfterNotifier(&disabledNotifier);
-properties.cash.AddBeforeNotifier(&cashNotifier);
-ips.AddAfterNotifier(&ipNotifier);
-
-pthread_mutexattr_t attr;
-pthread_mutexattr_init(&attr);
-pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
-pthread_mutex_init(&mutex, &attr);
-}
-//-----------------------------------------------------------------------------
-UserImpl::UserImpl(const UserImpl & u)
-    : users(u.users),
-      properties(*u.settings),
-      WriteServLog(Logger::get()),
-      lastScanMessages(0),
-      login(u.login),
-      id(u.id),
-      __connected(0),
-      connected(__connected),
-      __currIP(u.__currIP),
-      currIP(__currIP),
-      lastIPForDisconnect(0),
-      pingTime(u.pingTime),
-      sysAdmin(u.sysAdmin),
-      store(u.store),
-      tariffs(u.tariffs),
-      tariff(u.tariff),
-      m_services(u.m_services),
-      traffStat(u.traffStat),
-      traffStatSaved(u.traffStatSaved),
-      settings(u.settings),
-      authorizedModificationTime(u.authorizedModificationTime),
-      messages(u.messages),
-      deleted(u.deleted),
-      lastWriteStat(u.lastWriteStat),
-      lastWriteDetailedStat(u.lastWriteDetailedStat),
-      cash(properties.cash),
-      up(properties.up),
-      down(properties.down),
-      lastCashAdd(properties.lastCashAdd),
-      passiveTime(properties.passiveTime),
-      lastCashAddTime(properties.lastCashAddTime),
-      freeMb(properties.freeMb),
-      lastActivityTime(properties.lastActivityTime),
-      password(properties.password),
-      passive(properties.passive),
-      disabled(properties.disabled),
-      disabledDetailStat(properties.disabledDetailStat),
-      alwaysOnline(properties.alwaysOnline),
-      tariffName(properties.tariffName),
-      nextTariff(properties.nextTariff),
-      address(properties.address),
-      note(properties.note),
-      group(properties.group),
-      email(properties.email),
-      phone(properties.phone),
-      realName(properties.realName),
-      credit(properties.credit),
-      creditExpire(properties.creditExpire),
-      ips(properties.ips),
-      userdata0(properties.userdata0),
-      userdata1(properties.userdata1),
-      userdata2(properties.userdata2),
-      userdata3(properties.userdata3),
-      userdata4(properties.userdata4),
-      userdata5(properties.userdata5),
-      userdata6(properties.userdata6),
-      userdata7(properties.userdata7),
-      userdata8(properties.userdata8),
-      userdata9(properties.userdata9),
-      sessionUpload(),
-      sessionDownload(),
-      sessionUploadModTime(stgTime),
-      sessionDownloadModTime(stgTime),
-      passiveNotifier(this),
-      disabledNotifier(this),
-      tariffNotifier(this),
-      cashNotifier(this),
-      ipNotifier(this)
-{
-if (&u == this)
-    return;
-
-properties.tariffName.AddBeforeNotifier(&tariffNotifier);
-properties.passive.AddBeforeNotifier(&passiveNotifier);
-properties.disabled.AddAfterNotifier(&disabledNotifier);
-properties.cash.AddBeforeNotifier(&cashNotifier);
-ips.AddAfterNotifier(&ipNotifier);
-
-properties.SetProperties(u.properties);
-
-pthread_mutexattr_t attr;
-pthread_mutexattr_init(&attr);
-pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
-pthread_mutex_init(&mutex, &attr);
-}
-//-----------------------------------------------------------------------------
-UserImpl::~UserImpl()
-{
-properties.tariffName.DelBeforeNotifier(&tariffNotifier);
-properties.passive.DelBeforeNotifier(&passiveNotifier);
-properties.disabled.DelAfterNotifier(&disabledNotifier);
-properties.cash.DelBeforeNotifier(&cashNotifier);
-pthread_mutex_destroy(&mutex);
-}
-//-----------------------------------------------------------------------------
-void UserImpl::SetLogin(const std::string & l)
-{
-STG_LOCKER lock(&mutex);
-static int idGen = 0;
-assert(login.empty() && "Login is already set");
-login = l;
-id = idGen++;
-}
-//-----------------------------------------------------------------------------
-int UserImpl::ReadConf()
-{
-STG_LOCKER lock(&mutex);
-UserConf conf;
-
-if (store->RestoreUserConf(&conf, login))
-    {
-    WriteServLog("Cannot read conf for user %s.", login.c_str());
-    WriteServLog("%s", store->GetStrError().c_str());
-    printfd(__FILE__, "Cannot read conf for user %s.\n", login.c_str());
-    printfd(__FILE__, "%s\n", store->GetStrError().c_str());
-    return -1;
-    }
-
-properties.SetConf(conf);
-
-tariff = tariffs->FindByName(tariffName);
-if (tariff == NULL)
-    {
-    WriteServLog("Cannot read user %s. Tariff %s not exist.",
-                 login.c_str(), properties.tariffName.Get().c_str());
-    return -1;
-    }
-
-std::vector<Message::Header> hdrsList;
-
-if (store->GetMessageHdrs(&hdrsList, login))
-    {
-    printfd(__FILE__, "Error GetMessageHdrs %s\n", store->GetStrError().c_str());
-    WriteServLog("Cannot read user %s. Error reading message headers: %s.",
-                 login.c_str(),
-                 store->GetStrError().c_str());
-    return -1;
-    }
-
-std::vector<Message::Header>::const_iterator it;
-for (it = hdrsList.begin(); it != hdrsList.end(); ++it)
-    {
-    Message msg;
-    if (store->GetMessage(it->id, &msg, login) == 0)
-        {
-        messages.push_back(msg);
-        }
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int UserImpl::ReadStat()
-{
-STG_LOCKER lock(&mutex);
-UserStat stat;
-
-if (store->RestoreUserStat(&stat, login))
-    {
-    WriteServLog("Cannot read stat for user %s.", login.c_str());
-    WriteServLog("%s", store->GetStrError().c_str());
-    printfd(__FILE__, "Cannot read stat for user %s.\n", login.c_str());
-    printfd(__FILE__, "%s\n", store->GetStrError().c_str());
-    return -1;
-    }
-
-properties.SetStat(stat);
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int UserImpl::WriteConf()
-{
-STG_LOCKER lock(&mutex);
-UserConf conf(properties.GetConf());
-
-printfd(__FILE__, "UserImpl::WriteConf()\n");
-
-if (store->SaveUserConf(conf, login))
-    {
-    WriteServLog("Cannot write conf for user %s.", login.c_str());
-    WriteServLog("%s", store->GetStrError().c_str());
-    printfd(__FILE__, "Cannot write conf for user %s.\n", login.c_str());
-    printfd(__FILE__, "%s\n", store->GetStrError().c_str());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int UserImpl::WriteStat()
-{
-STG_LOCKER lock(&mutex);
-UserStat stat(properties.GetStat());
-
-if (store->SaveUserStat(stat, login))
-    {
-    WriteServLog("Cannot write stat for user %s.", login.c_str());
-    WriteServLog("%s", store->GetStrError().c_str());
-    printfd(__FILE__, "Cannot write stat for user %s.\n", login.c_str());
-    printfd(__FILE__, "%s\n", store->GetStrError().c_str());
-    return -1;
-    }
-
-lastWriteStat = stgTime;
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int UserImpl::WriteMonthStat()
-{
-STG_LOCKER lock(&mutex);
-time_t tt = stgTime - 3600;
-struct tm t1;
-localtime_r(&tt, &t1);
-
-UserStat stat(properties.GetStat());
-if (store->SaveMonthStat(stat, t1.tm_mon, t1.tm_year, login))
-    {
-    WriteServLog("Cannot write month stat for user %s.", login.c_str());
-    WriteServLog("%s", store->GetStrError().c_str());
-    printfd(__FILE__, "Cannot write month stat for user %s.\n", login.c_str());
-    printfd(__FILE__, "%s\n", store->GetStrError().c_str());
-    return -1;
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int UserImpl::Authorize(uint32_t ip, uint32_t dirs, const Auth * auth)
-{
-STG_LOCKER lock(&mutex);
-/*
- *  Authorize user. It only means that user will be authorized. Nothing more.
- *  User can be connected or disconnected while authorized.
- *  Example: user is authorized but disconnected due to 0 money or blocking
- */
-
-/*
- * TODO: in fact "authorization" means allowing access to a service. What we
- * call "authorization" here, int STG, is "authentication". So this should be
- * fixed in future.
- */
-
-/*
- * Prevent double authorization by identical authorizers
- */
-if (authorizedBy.find(auth) != authorizedBy.end())
-    return 0;
-
-if (!ip)
-    return -1;
-
-dirsFromBits(enabledDirs, dirs);
-
-if (!authorizedBy.empty())
-    {
-    if (currIP != ip)
-        {
-        // We are already authorized, but with different IP address
-        errorStr = "User " + login + " already authorized with IP address " + inet_ntostring(ip);
-        return -1;
-        }
-
-    User * u = NULL;
-    if (!users->FindByIPIdx(ip, &u))
-        {
-        // Address presents in IP-index.
-        // If it's not our IP - report it.
-        if (u != this)
-            {
-            errorStr = "IP address " + inet_ntostring(ip) + " is already in use";
-            return -1;
-            }
-        }
-    }
-else
-    {
-    if (users->IsIPInIndex(ip))
-        {
-        // Address is already present in IP-index.
-        errorStr = "IP address " + inet_ntostring(ip) + " is already in use";
-        return -1;
-        }
-
-    if (ips.ConstData().find(ip))
-        {
-        currIP = ip;
-        lastIPForDisconnect = currIP;
-        }
-    else
-        {
-        printfd(__FILE__, " user %s: ips = %s\n", login.c_str(), ips.ConstData().toString().c_str());
-        errorStr = "IP address " + inet_ntostring(ip) + " does not belong to user " + login;
-        return -1;
-        }
-    }
-
-if (authorizedBy.empty())
-    authorizedModificationTime = stgTime;
-authorizedBy.insert(auth);
-
-ScanMessage();
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-void UserImpl::Unauthorize(const Auth * auth, const std::string & reason)
-{
-STG_LOCKER lock(&mutex);
-/*
- *  Authorizer tries to unauthorize user, that was not authorized by it
- */
-if (!authorizedBy.erase(auth))
-    return;
-
-authorizedModificationTime = stgTime;
-
-if (authorizedBy.empty())
-    {
-    lastDisconnectReason = reason;
-    lastIPForDisconnect = currIP;
-    currIP = 0; // DelUser in traffcounter
-    if (connected)
-        Disconnect(false, "not authorized");
-    return;
-    }
-}
-//-----------------------------------------------------------------------------
-bool UserImpl::IsAuthorizedBy(const Auth * auth) const
-{
-STG_LOCKER lock(&mutex);
-// Is this user authorized by specified authorizer?
-return authorizedBy.find(auth) != authorizedBy.end();
-}
-//-----------------------------------------------------------------------------
-std::vector<std::string> UserImpl::GetAuthorizers() const
-{
-    STG_LOCKER lock(&mutex);
-    std::vector<std::string> list;
-    std::transform(authorizedBy.begin(), authorizedBy.end(), std::back_inserter(list), [](const auto auth){ return auth->GetVersion(); });
-    return list;
-}
-//-----------------------------------------------------------------------------
-void UserImpl::Connect(bool fakeConnect)
-{
-/*
- * Connect user to Internet. This function is differ from Authorize() !!!
- */
-
-STG_LOCKER lock(&mutex);
-
-if (!fakeConnect)
-    {
-    std::string scriptOnConnect = settings->GetScriptsDir() + "/OnConnect";
-
-    if (access(scriptOnConnect.c_str(), X_OK) == 0)
-        {
-        std::string dirs = dirsToString(enabledDirs);
-
-        std::string scriptOnConnectParams;
-        strprintf(&scriptOnConnectParams,
-                  "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
-                  scriptOnConnect.c_str(),
-                  login.c_str(),
-                  inet_ntostring(currIP).c_str(),
-                  cash.ConstData(),
-                  id,
-                  dirs.c_str());
-
-        std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
-        while (it != settings->GetScriptParams().end())
-            {
-            scriptOnConnectParams += " \"" + GetParamValue(it->c_str()) + "\"";
-            ++it;
-            }
-
-        ScriptExec(scriptOnConnectParams.c_str());
-        }
-    else
-        {
-        WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str());
-        }
-
-    connected = true;
-    }
-
-if (!settings->GetDisableSessionLog() && store->WriteUserConnect(login, currIP))
-    {
-    WriteServLog("Cannot write connect for user %s.", login.c_str());
-    WriteServLog("%s", store->GetStrError().c_str());
-    }
-
-if (!fakeConnect)
-    lastIPForDisconnect = currIP;
-}
-//-----------------------------------------------------------------------------
-void UserImpl::Disconnect(bool fakeDisconnect, const std::string & reason)
-{
-/*
- *  Disconnect user from Internet. This function is differ from UnAuthorize() !!!
- */
-
-STG_LOCKER lock(&mutex);
-
-if (!lastIPForDisconnect)
-    {
-    printfd(__FILE__, "lastIPForDisconnect\n");
-    return;
-    }
-
-if (!fakeDisconnect)
-    {
-    lastDisconnectReason = reason;
-    std::string scriptOnDisonnect = settings->GetScriptsDir() + "/OnDisconnect";
-
-    if (access(scriptOnDisonnect.c_str(), X_OK) == 0)
-        {
-        std::string dirs = dirsToString(enabledDirs);
-
-        std::string scriptOnDisonnectParams;
-        strprintf(&scriptOnDisonnectParams,
-                "%s \"%s\" \"%s\" \"%f\" \"%d\" \"%s\"",
-                scriptOnDisonnect.c_str(),
-                login.c_str(),
-                inet_ntostring(lastIPForDisconnect).c_str(),
-                cash.ConstData(),
-                id,
-                dirs.c_str());
-
-        std::vector<std::string>::const_iterator it(settings->GetScriptParams().begin());
-        while (it != settings->GetScriptParams().end())
-            {
-            scriptOnDisonnectParams += " \"" + GetParamValue(it->c_str()) + "\"";
-            ++it;
-            }
-
-        ScriptExec(scriptOnDisonnectParams.c_str());
-        }
-    else
-        {
-        WriteServLog("Script OnDisconnect cannot be executed. File not found.");
-        }
-
-    connected = false;
-    }
-
-std::string reasonMessage(reason);
-if (!lastDisconnectReason.empty())
-    reasonMessage += ": " + lastDisconnectReason;
-
-if (!settings->GetDisableSessionLog() && store->WriteUserDisconnect(login, up, down, sessionUpload, sessionDownload,
-                                                                    cash, freeMb, reasonMessage))
-    {
-    WriteServLog("Cannot write disconnect for user %s.", login.c_str());
-    WriteServLog("%s", store->GetStrError().c_str());
-    }
-
-if (!fakeDisconnect)
-    lastIPForDisconnect = 0;
-
-sessionUpload.reset();
-sessionDownload.reset();
-sessionUploadModTime = stgTime;
-sessionDownloadModTime = stgTime;
-}
-//-----------------------------------------------------------------------------
-void UserImpl::Run()
-{
-STG_LOCKER lock(&mutex);
-
-if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
-    {
-    printfd(__FILE__, "UserImpl::WriteStat user=%s\n", GetLogin().c_str());
-    WriteStat();
-    }
-if (creditExpire.ConstData() && creditExpire.ConstData() < stgTime)
-    {
-    WriteServLog("User: %s. Credit expired.", login.c_str());
-    credit = 0;
-    creditExpire = 0;
-    WriteConf();
-    }
-
-if (passive.ConstData()
-    && (stgTime % 30 == 0)
-    && (passiveTime.ModificationTime() != stgTime))
-    {
-    passiveTime = passiveTime + (stgTime - passiveTime.ModificationTime());
-    printfd(__FILE__, "===== %s: passiveTime=%d =====\n", login.c_str(), passiveTime.ConstData());
-    }
-
-if (!authorizedBy.empty())
-    {
-    if (connected)
-        properties.Stat().lastActivityTime = stgTime;
-
-    if (!connected && IsInetable())
-        Connect();
-
-    if (connected && !IsInetable())
-        {
-        if (disabled)
-            Disconnect(false, "disabled");
-        else if (passive)
-            Disconnect(false, "passive");
-        else
-            Disconnect(false, "no cash");
-        }
-
-    if (stgTime - lastScanMessages > 10)
-        {
-        ScanMessage();
-        lastScanMessages = stgTime;
-        }
-    }
-else
-    {
-    if (connected)
-        Disconnect(false, "not authorized");
-    }
-
-}
-//-----------------------------------------------------------------------------
-void UserImpl::UpdatePingTime(time_t t)
-{
-STG_LOCKER lock(&mutex);
-if (t)
-    pingTime = t;
-else
-    pingTime = stgTime;
-}
-//-----------------------------------------------------------------------------
-bool UserImpl::IsInetable()
-{
-if (disabled || passive)
-    return false;
-
-if (settings->GetFreeMbAllowInet())
-    {
-    if (freeMb >= 0)
-        return true;
-    }
-
-if (settings->GetShowFeeInCash() || tariff == NULL)
-    return (cash >= -credit);
-
-return (cash - tariff->GetFee() >= -credit);
-}
-//-----------------------------------------------------------------------------
-std::string UserImpl::GetEnabledDirs() const
-{
-return dirsToString(enabledDirs);
-}
-//-----------------------------------------------------------------------------
-#ifdef TRAFF_STAT_WITH_PORTS
-void UserImpl::AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len)
-#else
-void UserImpl::AddTraffStatU(int dir, uint32_t ip, uint32_t len)
-#endif
-{
-STG_LOCKER lock(&mutex);
-
-if (!connected || tariff == NULL)
-    return;
-
-double cost = 0;
-DirTraff dt(up);
-
-int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
-int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
-
-dt[dir] += len;
-
-int tt = tariff->GetTraffType();
-if (tt == Tariff::TRAFF_UP ||
-    tt == Tariff::TRAFF_UP_DOWN ||
-    // Check NEW traff data
-    (tt == Tariff::TRAFF_MAX && dt[dir] > down.ConstData()[dir]))
-    {
-    double dc = 0;
-    if (traff < threshold &&
-        traff + len >= threshold)
-        {
-        // cash = partBeforeThreshold * priceBeforeThreshold +
-        //        partAfterThreshold * priceAfterThreshold
-        int64_t before = threshold - traff; // Chunk part before threshold
-        int64_t after = len - before; // Chunk part after threshold
-        dc = tariff->GetPriceWithTraffType(up.ConstData()[dir], // Traff before chunk
-                                           down.ConstData()[dir],
-                                           dir,
-                                           stgTime) * before +
-             tariff->GetPriceWithTraffType(dt[dir], // Traff after chunk
-                                           down.ConstData()[dir],
-                                           dir,
-                                           stgTime) * after;
-        }
-    else
-        {
-        dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
-                                           down.ConstData()[dir],
-                                           dir,
-                                           stgTime) * len;
-        }
-
-    if (freeMb.ConstData() <= 0) // FreeMb is exhausted
-        cost = dc;
-    else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
-        cost = dc - freeMb.ConstData();
-
-    // Direct access to internal data structures via friend-specifier
-    properties.Stat().freeMb -= dc;
-    properties.Stat().cash -= cost;
-    cash.ModifyTime();
-    freeMb.ModifyTime();
-    }
-
-up = dt;
-sessionUpload[dir] += len;
-sessionUploadModTime = stgTime;
-
-//Add detailed stat
-
-if (!settings->GetWriteFreeMbTraffCost() &&
-     freeMb.ConstData() >= 0)
-    cost = 0;
-
-#ifdef TRAFF_STAT_WITH_PORTS
-IPDirPair idp(ip, dir, port);
-#else
-IPDirPair idp(ip, dir);
-#endif
-
-std::map<IPDirPair, StatNode>::iterator lb;
-lb = traffStat.lower_bound(idp);
-if (lb == traffStat.end() || lb->first != idp)
-    {
-    traffStat.insert(lb,
-                     std::make_pair(idp,
-                                    StatNode(len, 0, cost)));
-    }
-else
-    {
-    lb->second.cash += cost;
-    lb->second.up += len;
-    }
-}
-//-----------------------------------------------------------------------------
-#ifdef TRAFF_STAT_WITH_PORTS
-void UserImpl::AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len)
-#else
-void UserImpl::AddTraffStatD(int dir, uint32_t ip, uint32_t len)
-#endif
-{
-STG_LOCKER lock(&mutex);
-
-if (!connected || tariff == NULL)
-    return;
-
-double cost = 0;
-DirTraff dt(down);
-
-int64_t traff = tariff->GetTraffByType(up.ConstData()[dir], down.ConstData()[dir]);
-int64_t threshold = tariff->GetThreshold(dir) * 1024 * 1024;
-
-dt[dir] += len;
-
-int tt = tariff->GetTraffType();
-if (tt == Tariff::TRAFF_DOWN ||
-    tt == Tariff::TRAFF_UP_DOWN ||
-    // Check NEW traff data
-    (tt == Tariff::TRAFF_MAX && up.ConstData()[dir] <= dt[dir]))
-    {
-    double dc = 0;
-    if (traff < threshold &&
-        traff + len >= threshold)
-        {
-        // cash = partBeforeThreshold * priceBeforeThreshold +
-        //        partAfterThreshold * priceAfterThreshold
-        int64_t before = threshold - traff; // Chunk part before threshold
-        int64_t after = len - before; // Chunk part after threshold
-        dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
-                                           down.ConstData()[dir], // Traff before chunk
-                                           dir,
-                                           stgTime) * before +
-             tariff->GetPriceWithTraffType(up.ConstData()[dir],
-                                           dt[dir], // Traff after chunk
-                                           dir,
-                                           stgTime) * after;
-        }
-    else
-        {
-        dc = tariff->GetPriceWithTraffType(up.ConstData()[dir],
-                                           down.ConstData()[dir],
-                                           dir,
-                                           stgTime) * len;
-        }
-
-    if (freeMb.ConstData() <= 0) // FreeMb is exhausted
-        cost = dc;
-    else if (freeMb.ConstData() < dc) // FreeMb is partially exhausted
-        cost = dc - freeMb.ConstData();
-
-    properties.Stat().freeMb -= dc;
-    properties.Stat().cash -= cost;
-    cash.ModifyTime();
-    freeMb.ModifyTime();
-    }
-
-down = dt;
-sessionDownload[dir] += len;
-sessionDownloadModTime = stgTime;
-
-//Add detailed stat
-
-if (!settings->GetWriteFreeMbTraffCost() &&
-     freeMb.ConstData() >= 0)
-    cost = 0;
-
-#ifdef TRAFF_STAT_WITH_PORTS
-IPDirPair idp(ip, dir, port);
-#else
-IPDirPair idp(ip, dir);
-#endif
-
-std::map<IPDirPair, StatNode>::iterator lb;
-lb = traffStat.lower_bound(idp);
-if (lb == traffStat.end() || lb->first != idp)
-    {
-    traffStat.insert(lb,
-                     std::make_pair(idp,
-                                    StatNode(0, len, cost)));
-    }
-else
-    {
-    lb->second.cash += cost;
-    lb->second.down += len;
-    }
-}
-//-----------------------------------------------------------------------------
-void UserImpl::AddCurrIPBeforeNotifier(CURR_IP_NOTIFIER * notifier)
-{
-STG_LOCKER lock(&mutex);
-currIP.AddBeforeNotifier(notifier);
-}
-//-----------------------------------------------------------------------------
-void UserImpl::DelCurrIPBeforeNotifier(const CURR_IP_NOTIFIER * notifier)
-{
-STG_LOCKER lock(&mutex);
-currIP.DelBeforeNotifier(notifier);
-}
-//-----------------------------------------------------------------------------
-void UserImpl::AddCurrIPAfterNotifier(CURR_IP_NOTIFIER * notifier)
-{
-STG_LOCKER lock(&mutex);
-currIP.AddAfterNotifier(notifier);
-}
-//-----------------------------------------------------------------------------
-void UserImpl::DelCurrIPAfterNotifier(const CURR_IP_NOTIFIER * notifier)
-{
-STG_LOCKER lock(&mutex);
-currIP.DelAfterNotifier(notifier);
-}
-//-----------------------------------------------------------------------------
-void UserImpl::AddConnectedBeforeNotifier(CONNECTED_NOTIFIER * notifier)
-{
-STG_LOCKER lock(&mutex);
-connected.AddBeforeNotifier(notifier);
-}
-//-----------------------------------------------------------------------------
-void UserImpl::DelConnectedBeforeNotifier(const CONNECTED_NOTIFIER * notifier)
-{
-STG_LOCKER lock(&mutex);
-connected.DelBeforeNotifier(notifier);
-}
-//-----------------------------------------------------------------------------
-void UserImpl::AddConnectedAfterNotifier(CONNECTED_NOTIFIER * notifier)
-{
-STG_LOCKER lock(&mutex);
-connected.AddAfterNotifier(notifier);
-}
-//-----------------------------------------------------------------------------
-void UserImpl::DelConnectedAfterNotifier(const CONNECTED_NOTIFIER * notifier)
-{
-STG_LOCKER lock(&mutex);
-connected.DelAfterNotifier(notifier);
-}
-//-----------------------------------------------------------------------------
-void UserImpl::OnAdd()
-{
-STG_LOCKER lock(&mutex);
-
-std::string scriptOnAdd = settings->GetScriptsDir() + "/OnUserAdd";
-
-if (access(scriptOnAdd.c_str(), X_OK) == 0)
-    {
-    std::string scriptOnAddParams = scriptOnAdd + " \"" + login + "\"";
-
-    ScriptExec(scriptOnAddParams.c_str());
-    }
-else
-    {
-    WriteServLog("Script %s cannot be executed. File not found.", scriptOnAdd.c_str());
-    }
-}
-//-----------------------------------------------------------------------------
-void UserImpl::OnDelete()
-{
-STG_LOCKER lock(&mutex);
-
-std::string scriptOnDel = settings->GetScriptsDir() + "/OnUserDel";
-
-if (access(scriptOnDel.c_str(), X_OK) == 0)
-    {
-    std::string scriptOnDelParams = scriptOnDel + " \"" + login + "\"";
-
-    ScriptExec(scriptOnDelParams.c_str());
-    }
-else
-    {
-    WriteServLog("Script %s cannot be executed. File not found.", scriptOnDel.c_str());
-    }
-
-Run();
-}
-//-----------------------------------------------------------------------------
-int UserImpl::WriteDetailStat(bool hard)
-{
-printfd(__FILE__, "UserImpl::WriteDetailedStat() - saved size = %d\n", traffStatSaved.second.size());
-
-if (!traffStatSaved.second.empty())
-    {
-    if (store->WriteDetailedStat(traffStatSaved.second, traffStatSaved.first, login))
-        {
-        printfd(__FILE__, "UserImpl::WriteDetailStat() - failed to write detail stat from queue\n");
-        WriteServLog("Cannot write detail stat from queue (of size %d recs) for user %s.", traffStatSaved.second.size(), login.c_str());
-        WriteServLog("%s", store->GetStrError().c_str());
-        return -1;
-        }
-    traffStatSaved.second.erase(traffStatSaved.second.begin(), traffStatSaved.second.end());
-    }
-
-TraffStat ts;
-
-    {
-    STG_LOCKER lock(&mutex);
-    ts.swap(traffStat);
-    }
-
-printfd(__FILE__, "UserImpl::WriteDetailedStat() - size = %d\n", ts.size());
-
-if (ts.size() && !disabledDetailStat)
-    {
-    if (store->WriteDetailedStat(ts, lastWriteDetailedStat, login))
-        {
-        printfd(__FILE__, "UserImpl::WriteDetailStat() - failed to write current detail stat\n");
-        WriteServLog("Cannot write detail stat for user %s.", login.c_str());
-        WriteServLog("%s", store->GetStrError().c_str());
-        if (!hard)
-            {
-            printfd(__FILE__, "UserImpl::WriteDetailStat() - pushing detail stat to queue\n");
-            STG_LOCKER lock(&mutex);
-            traffStatSaved.second.swap(ts);
-            traffStatSaved.first = lastWriteDetailedStat;
-            }
-        return -1;
-        }
-    }
-lastWriteDetailedStat = stgTime;
-return 0;
-}
-//-----------------------------------------------------------------------------
-double UserImpl::GetPassiveTimePart() const
-{
-STG_LOCKER lock(&mutex);
-
-static int daysInMonth[12] =
-{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-
-struct tm tms;
-time_t t = stgTime;
-localtime_r(&t, &tms);
-
-time_t secMonth = daysInMonth[(tms.tm_mon + 11) % 12] * 24 * 3600; // Previous month
-
-if (tms.tm_year % 4 == 0 && tms.tm_mon == 1)
-    {
-    // Leap year
-    secMonth += 24 * 3600;
-    }
-
-time_t dt = secMonth - passiveTime;
-
-if (dt < 0)
-    dt = 0;
-
-return static_cast<double>(dt) / secMonth;
-}
-//-----------------------------------------------------------------------------
-void UserImpl::SetPassiveTimeAsNewUser()
-{
-STG_LOCKER lock(&mutex);
-
-time_t t = stgTime;
-struct tm tm;
-localtime_r(&t, &tm);
-int daysCurrMon = DaysInCurrentMonth();
-double pt = tm.tm_mday - 1;
-pt /= daysCurrMon;
-
-passiveTime = static_cast<time_t>(pt * 24 * 3600 * daysCurrMon);
-}
-//-----------------------------------------------------------------------------
-void UserImpl::MidnightResetSessionStat()
-{
-STG_LOCKER lock(&mutex);
-
-if (connected)
-    {
-    Disconnect(true, "fake");
-    Connect(true);
-    }
-}
-//-----------------------------------------------------------------------------
-void UserImpl::ProcessNewMonth()
-{
-STG_LOCKER lock(&mutex);
-//  Reset traff
-if (connected)
-    Disconnect(true, "fake");
-
-WriteMonthStat();
-
-properties.Stat().monthUp.reset();
-properties.Stat().monthDown.reset();
-
-if (connected)
-    Connect(true);
-
-//  Set new tariff
-if (nextTariff.ConstData() != "")
-    {
-    const Tariff * nt = tariffs->FindByName(nextTariff);
-    if (nt == NULL)
-        {
-        WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.",
-                     login.c_str(), properties.tariffName.Get().c_str());
-        }
-    else
-        {
-        std::string message = tariff->TariffChangeIsAllowed(*nt, stgTime);
-        if (message.empty())
-            {
-            properties.tariffName.Set(nextTariff, *sysAdmin, login, *store);
-            }
-        else
-            {
-            WriteServLog("Tariff change is prohibited for user %s. %s",
-                         login.c_str(),
-                         message.c_str());
-            }
-        }
-    ResetNextTariff();
-    WriteConf();
-    }
-}
-//-----------------------------------------------------------------------------
-void UserImpl::ProcessDayFeeSpread()
-{
-STG_LOCKER lock(&mutex);
-
-if (passive.ConstData() || tariff == NULL)
-    return;
-
-if (tariff->GetPeriod() != Tariff::MONTH)
-    return;
-
-double fee = tariff->GetFee() / DaysInCurrentMonth();
-
-if (std::fabs(fee) < 1.0e-3)
-    return;
-
-double c = cash;
-switch (settings->GetFeeChargeType())
-    {
-    case 0:
-        properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
-        break;
-    case 1:
-        if (c + credit >= 0)
-            properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
-        break;
-    case 2:
-        if (c + credit >= fee)
-            properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
-        break;
-    case 3:
-        if (c >= 0)
-            properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
-        break;
-    }
-ResetPassiveTime();
-}
-//-----------------------------------------------------------------------------
-void UserImpl::ProcessDayFee()
-{
-STG_LOCKER lock(&mutex);
-
-if (tariff == NULL)
-    return;
-
-if (tariff->GetPeriod() != Tariff::MONTH)
-    return;
-
-double passiveTimePart = 1.0;
-if (!settings->GetFullFee())
-    {
-    passiveTimePart = GetPassiveTimePart();
-    }
-else
-    {
-    if (passive.ConstData())
-        {
-        printfd(__FILE__, "Don't charge fee `cause we are passive\n");
-        return;
-        }
-    }
-double fee = tariff->GetFee() * passiveTimePart;
-
-ResetPassiveTime();
-
-if (std::fabs(fee) < 1.0e-3)
-    {
-    SetPrepaidTraff();
-    return;
-    }
-
-double c = cash;
-printfd(__FILE__, "login: %8s Cash=%f Credit=%f  Fee=%f PassiveTimePart=%f fee=%f\n",
-        login.c_str(),
-        cash.ConstData(),
-        credit.ConstData(),
-        tariff->GetFee(),
-        passiveTimePart,
-        fee);
-switch (settings->GetFeeChargeType())
-    {
-    case 0:
-        properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
-        SetPrepaidTraff();
-        break;
-    case 1:
-        if (c + credit >= 0)
-            {
-            properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
-            SetPrepaidTraff();
-            }
-        break;
-    case 2:
-        if (c + credit >= fee)
-            {
-            properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
-            SetPrepaidTraff();
-            }
-        break;
-    case 3:
-        if (c >= 0)
-            {
-            properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
-            SetPrepaidTraff();
-            }
-        break;
-    }
-}
-//-----------------------------------------------------------------------------
-void UserImpl::ProcessDailyFee()
-{
-STG_LOCKER lock(&mutex);
-
-if (passive.ConstData() || tariff == NULL)
-    return;
-
-if (tariff->GetPeriod() != Tariff::DAY)
-    return;
-
-double fee = tariff->GetFee();
-
-if (fee == 0.0)
-    return;
-
-double c = cash;
-switch (settings->GetFeeChargeType())
-    {
-    case 0:
-        properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
-        break;
-    case 1:
-        if (c + credit >= 0)
-            properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
-        break;
-    case 2:
-        if (c + credit >= fee)
-            properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
-        break;
-    }
-ResetPassiveTime();
-}
-//-----------------------------------------------------------------------------
-void UserImpl::ProcessServices()
-{
-struct tm tms;
-time_t t = stgTime;
-localtime_r(&t, &tms);
-
-double passiveTimePart = 1.0;
-if (!settings->GetFullFee())
-    {
-    passiveTimePart = GetPassiveTimePart();
-    }
-else
-    {
-    if (passive.ConstData())
-        {
-        printfd(__FILE__, "Don't charge fee `cause we are passive\n");
-        return;
-        }
-    }
-
-for (size_t i = 0; i < properties.Conf().services.size(); ++i)
-    {
-    ServiceConf conf;
-    if (m_services.Find(properties.Conf().services[i], &conf))
-        continue;
-    if (conf.payDay == tms.tm_mday ||
-        (conf.payDay == 0 && tms.tm_mday == DaysInCurrentMonth()))
-        {
-        double c = cash;
-        double fee = conf.cost * passiveTimePart;
-        printfd(__FILE__, "Service fee. login: %8s Cash=%f Credit=%f  Fee=%f PassiveTimePart=%f fee=%f\n",
-                login.c_str(),
-                cash.ConstData(),
-                credit.ConstData(),
-                tariff->GetFee(),
-                passiveTimePart,
-                fee);
-        switch (settings->GetFeeChargeType())
-            {
-            case 0:
-                properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
-                SetPrepaidTraff();
-                break;
-            case 1:
-                if (c + credit >= 0)
-                    {
-                    properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
-                    SetPrepaidTraff();
-                    }
-                break;
-            case 2:
-                if (c + credit >= fee)
-                    {
-                    properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
-                    SetPrepaidTraff();
-                    }
-                break;
-            case 3:
-                if (c >= 0)
-                    {
-                    properties.cash.Set(c - fee, *sysAdmin, login, *store, "Subscriber fee charge");
-                    SetPrepaidTraff();
-                    }
-                break;
-            }
-        }
-    }
-}
-//-----------------------------------------------------------------------------
-void UserImpl::SetPrepaidTraff()
-{
-if (tariff != NULL)
-    properties.freeMb.Set(tariff->GetFree(), *sysAdmin, login, *store, "Prepaid traffic");
-}
-//-----------------------------------------------------------------------------
-int UserImpl::AddMessage(Message * msg)
-{
-STG_LOCKER lock(&mutex);
-
-if (SendMessage(*msg))
-    {
-    if (store->AddMessage(msg, login))
-        {
-        errorStr = store->GetStrError();
-        WriteServLog("Error adding message: '%s'", errorStr.c_str());
-        printfd(__FILE__, "Error adding message: '%s'\n", errorStr.c_str());
-        return -1;
-        }
-    messages.push_back(*msg);
-    }
-else
-    {
-    if (msg->header.repeat > 0)
-        {
-        msg->header.repeat--;
-        #ifndef DEBUG
-        //TODO: gcc v. 4.x generate ICE on x86_64
-        msg->header.lastSendTime = static_cast<int>(time(NULL));
-        #else
-        msg->header.lastSendTime = static_cast<int>(stgTime);
-        #endif
-        if (store->AddMessage(msg, login))
-            {
-            errorStr = store->GetStrError();
-            WriteServLog("Error adding repeatable message: '%s'", errorStr.c_str());
-            printfd(__FILE__, "Error adding repeatable message: '%s'\n", errorStr.c_str());
-            return -1;
-            }
-        messages.push_back(*msg);
-        }
-    }
-return 0;
-}
-//-----------------------------------------------------------------------------
-int UserImpl::SendMessage(Message & msg) const
-{
-// No lock `cause we are already locked from caller
-int ret = -1;
-std::set<const Auth*>::iterator it(authorizedBy.begin());
-while (it != authorizedBy.end())
-    {
-    if (!(*it++)->SendMessage(msg, currIP))
-        ret = 0;
-    }
-if (!ret)
-    {
-#ifndef DEBUG
-    //TODO: gcc v. 4.x generate ICE on x86_64
-    msg.header.lastSendTime = static_cast<int>(time(NULL));
-#else
-    msg.header.lastSendTime = static_cast<int>(stgTime);
-#endif
-    msg.header.repeat--;
-    }
-return ret;
-}
-//-----------------------------------------------------------------------------
-void UserImpl::ScanMessage()
-{
-// No lock `cause we are already locked from caller
-// We need not check for the authorizedBy `cause it has already checked by caller
-
-auto it = messages.begin();
-while (it != messages.end())
-    {
-    if (settings->GetMessageTimeout() > 0 &&
-        difftime(stgTime, it->header.creationTime) > settings->GetMessageTimeout())
-        {
-        // Timeout exceeded
-        if (store->DelMessage(it->header.id, login))
-            {
-            WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
-            printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
-            }
-        messages.erase(it++);
-        continue;
-        }
-    if (it->GetNextSendTime() <= stgTime)
-        {
-        if (SendMessage(*it))
-            {
-            // We need to check all messages in queue for timeout
-            ++it;
-            continue;
-            }
-        if (it->header.repeat < 0)
-            {
-            if (store->DelMessage(it->header.id, login))
-                {
-                WriteServLog("Error deleting message: '%s'", store->GetStrError().c_str());
-                printfd(__FILE__, "Error deleting message: '%s'\n", store->GetStrError().c_str());
-                }
-            messages.erase(it++);
-            }
-        else
-            {
-            if (store->EditMessage(*it, login))
-                {
-                WriteServLog("Error modifying message: '%s'", store->GetStrError().c_str());
-                printfd(__FILE__, "Error modifying message: '%s'\n", store->GetStrError().c_str());
-                }
-            ++it;
-            }
-        }
-    else
-        {
-        ++it;
-        }
-    }
-}
-//-----------------------------------------------------------------------------
-std::string UserImpl::GetParamValue(const std::string & name) const
-{
-    std::string lowerName = ToLower(name);
-    if (lowerName == "id")
-        {
-        std::ostringstream stream;
-        stream << id;
-        return stream.str();
-        }
-    if (lowerName == "login")       return login;
-    if (lowerName == "currip")      return currIP.ToString();
-    if (lowerName == "enableddirs") return GetEnabledDirs();
-    if (lowerName == "tariff")      return properties.tariffName;
-    if (properties.Exists(lowerName))
-        return properties.GetPropertyValue(lowerName);
-    else
-        {
-        WriteServLog("User’s parameter '%s' does not exist.", name.c_str());
-        return "";
-        }
-}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-void STG::CHG_PASSIVE_NOTIFIER::Notify(const int & oldPassive, const int & newPassive)
-{
-if (newPassive && !oldPassive && user->tariff != NULL)
-    user->properties.cash.Set(user->cash - user->tariff->GetPassiveCost(),
-                            *user->sysAdmin,
-                            user->login,
-                            *user->store,
-                            "Freeze");
-}
-//-----------------------------------------------------------------------------
-void STG::CHG_DISABLED_NOTIFIER::Notify(const int & oldValue, const int & newValue)
-{
-if (oldValue && !newValue && user->GetConnected())
-    user->Disconnect(false, "disabled");
-else if (!oldValue && newValue && user->IsInetable())
-    user->Connect(false);
-}
-//-----------------------------------------------------------------------------
-void STG::CHG_TARIFF_NOTIFIER::Notify(const std::string &, const std::string & newTariff)
-{
-STG_LOCKER lock(&user->mutex);
-if (user->settings->GetReconnectOnTariffChange() && user->connected)
-    user->Disconnect(false, "Change tariff");
-user->tariff = user->tariffs->FindByName(newTariff);
-if (user->settings->GetReconnectOnTariffChange() &&
-    !user->authorizedBy.empty() &&
-    user->IsInetable())
-    {
-    // This notifier gets called *before* changing the tariff, and in Connect we want to see new tariff name.
-    user->properties.Conf().tariffName = newTariff;
-    user->Connect(false);
-    }
-}
-//-----------------------------------------------------------------------------
-void STG::CHG_CASH_NOTIFIER::Notify(const double & oldCash, const double & newCash)
-{
-user->lastCashAddTime = *const_cast<time_t *>(&stgTime);
-user->lastCashAdd = newCash - oldCash;
-}
-//-----------------------------------------------------------------------------
-void STG::CHG_IPS_NOTIFIER::Notify(const UserIPs & from, const UserIPs & to)
-{
-printfd(__FILE__, "Change IP from '%s' to '%s'\n", from.toString().c_str(), to.toString().c_str());
-if (user->connected)
-    user->Disconnect(false, "Change IP");
-if (!user->authorizedBy.empty() && user->IsInetable())
-    user->Connect(false);
-}
diff --git a/stargazer/user_impl.h b/stargazer/user_impl.h
deleted file mode 100644 (file)
index 2e254d6..0000000
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- */
-
-#pragma once
-
-#include "stg/user.h"
-#include "stg/user_stat.h"
-#include "stg/user_conf.h"
-#include "stg/user_ips.h"
-#include "stg/user_property.h"
-#include "stg/auth.h"
-#include "stg/message.h"
-#include "stg/noncopyable.h"
-#include "stg/const.h"
-
-#include <vector>
-#include <string>
-#include <set>
-
-#include <ctime>
-#include <cstdint>
-
-namespace STG
-{
-
-//-----------------------------------------------------------------------------
-struct Tariff;
-struct Tariffs;
-struct Admin;
-class UserImpl;
-#ifdef USE_ABSTRACT_SETTINGS
-struct Settings;
-#else
-class SettingsImpl;
-#endif
-//-----------------------------------------------------------------------------
-class CHG_PASSIVE_NOTIFIER : public PropertyNotifierBase<int> {
-    public:
-        explicit CHG_PASSIVE_NOTIFIER(UserImpl * u) : user(u) {}
-        void Notify(const int & oldPassive, const int & newPassive);
-
-    private:
-        UserImpl * user;
-};
-//-----------------------------------------------------------------------------
-class CHG_DISABLED_NOTIFIER : public PropertyNotifierBase<int> {
-public:
-    explicit CHG_DISABLED_NOTIFIER(UserImpl * u) : user(u) {}
-    void Notify(const int & oldValue, const int & newValue);
-
-private:
-    UserImpl * user;
-};
-//-----------------------------------------------------------------------------
-class CHG_TARIFF_NOTIFIER : public PropertyNotifierBase<std::string> {
-public:
-    explicit CHG_TARIFF_NOTIFIER(UserImpl * u) : user(u) {}
-    void Notify(const std::string & oldTariff, const std::string & newTariff);
-
-private:
-    UserImpl * user;
-};
-//-----------------------------------------------------------------------------
-class CHG_CASH_NOTIFIER : public PropertyNotifierBase<double> {
-public:
-    explicit CHG_CASH_NOTIFIER(UserImpl * u) : user(u) {}
-    void Notify(const double & oldCash, const double & newCash);
-
-private:
-    UserImpl * user;
-};
-//-----------------------------------------------------------------------------
-class CHG_IPS_NOTIFIER : public PropertyNotifierBase<UserIPs> {
-public:
-    explicit CHG_IPS_NOTIFIER(UserImpl * u) : user(u) {}
-    void Notify(const UserIPs & oldIPs, const UserIPs & newIPs);
-
-private:
-    UserImpl * user;
-};
-//-----------------------------------------------------------------------------
-class UserImpl : public User {
-    friend class CHG_PASSIVE_NOTIFIER;
-    friend class CHG_DISABLED_NOTIFIER;
-    friend class CHG_TARIFF_NOTIFIER;
-    friend class CHG_CASH_NOTIFIER;
-    friend class CHG_IPS_NOTIFIER;
-    public:
-#ifdef USE_ABSTRACT_SETTINGS
-        using Settings = STG::Settings;
-#else
-        using Settings = STG::SettingsImpl;
-#endif
-        UserImpl(const Settings * settings,
-                  const Store * store,
-                  const Tariffs * tariffs,
-                  const Admin * sysAdmin,
-                  const Users * u,
-                  const Services & svcs);
-        UserImpl(const UserImpl & u);
-        virtual ~UserImpl();
-
-        int             ReadConf();
-        int             ReadStat();
-        int             WriteConf() override;
-        int             WriteStat() override;
-        int             WriteMonthStat();
-
-        const std::string & GetLogin() const override { return login; }
-        void            SetLogin(std::string const & l);
-
-        uint32_t        GetCurrIP() const override{ return currIP; }
-        time_t          GetCurrIPModificationTime() const override { return currIP.ModificationTime(); }
-
-        void            AddCurrIPBeforeNotifier(CURR_IP_NOTIFIER * notifier) override;
-        void            DelCurrIPBeforeNotifier(const CURR_IP_NOTIFIER * notifier) override;
-
-        void            AddCurrIPAfterNotifier(CURR_IP_NOTIFIER * notifier) override;
-        void            DelCurrIPAfterNotifier(const CURR_IP_NOTIFIER * notifier) override;
-
-        void            AddConnectedBeforeNotifier(CONNECTED_NOTIFIER * notifier) override;
-        void            DelConnectedBeforeNotifier(const CONNECTED_NOTIFIER * notifier) override;
-
-        void            AddConnectedAfterNotifier(CONNECTED_NOTIFIER * notifier) override;
-        void            DelConnectedAfterNotifier(const CONNECTED_NOTIFIER * notifier) override;
-
-        int             GetID() const override { return id; }
-
-        double          GetPassiveTimePart() const override;
-        void            ResetPassiveTime() { passiveTime = 0; }
-        void            SetPassiveTimeAsNewUser();
-
-        int             WriteDetailStat(bool hard = false);
-
-        const Tariff *  GetTariff() const override { return tariff; }
-        void            ResetNextTariff() override { nextTariff = ""; }
-
-        #ifdef TRAFF_STAT_WITH_PORTS
-        void            AddTraffStatU(int dir, uint32_t ip, uint16_t port, uint32_t len);
-        void            AddTraffStatD(int dir, uint32_t ip, uint16_t port, uint32_t len);
-        #else
-        void            AddTraffStatU(int dir, uint32_t ip, uint32_t len);
-        void            AddTraffStatD(int dir, uint32_t ip, uint32_t len);
-        #endif
-
-        const DirTraff & GetSessionUpload() const override { return sessionUpload; }
-        const DirTraff & GetSessionDownload() const override { return sessionDownload; }
-        time_t GetSessionUploadModificationTime() const override { return sessionUploadModTime; }
-        time_t GetSessionDownloadModificationTime() const override { return sessionDownloadModTime; }
-
-        bool            GetConnected() const override { return connected; }
-        time_t          GetConnectedModificationTime() const override { return connected.ModificationTime(); }
-        const std::string & GetLastDisconnectReason() const override { return lastDisconnectReason; }
-        int             GetAuthorized() const override { return static_cast<int>(authorizedBy.size()); }
-        time_t          GetAuthorizedModificationTime() const override { return authorizedModificationTime; }
-        int             Authorize(uint32_t ip, uint32_t enabledDirs, const Auth * auth);
-        void            Unauthorize(const Auth * auth,
-                                    const std::string & reason = std::string());
-        bool            IsAuthorizedBy(const Auth * auth) const override;
-        std::vector<std::string> GetAuthorizers() const override;
-
-        int             AddMessage(Message * msg) override;
-
-        void            UpdatePingTime(time_t t = 0) override;
-        time_t          GetPingTime() const override { return pingTime; }
-
-        void            Run() override;
-
-        const std::string & GetStrError() const override { return errorStr; }
-
-        UserProperties & GetProperties() override { return properties; }
-        const UserProperties & GetProperties() const override { return properties; }
-
-        void            SetDeleted() override { deleted = true; }
-        bool            GetDeleted() const override { return deleted; }
-
-        time_t          GetLastWriteStatTime() const override { return lastWriteStat; }
-
-        void            MidnightResetSessionStat();
-        void            ProcessDayFee();
-        void            ProcessDayFeeSpread();
-        void            ProcessNewMonth();
-        void            ProcessDailyFee();
-        void            ProcessServices();
-
-        bool            IsInetable() override;
-        std::string     GetEnabledDirs() const override;
-
-        void            OnAdd() override;
-        void            OnDelete() override;
-
-        virtual std::string GetParamValue(const std::string & name) const override;
-
-    private:
-        UserImpl & operator=(const UserImpl & rvalue);
-
-        void            Init();
-
-        const Users*   users;
-        UserProperties properties;
-        STG::Logger&   WriteServLog;
-
-        void            Connect(bool fakeConnect = false);
-        void            Disconnect(bool fakeDisconnect, const std::string & reason);
-        int             SaveMonthStat(int month, int year);
-
-        void            SetPrepaidTraff();
-
-        int             SendMessage(Message & msg) const;
-        void            ScanMessage();
-
-        time_t          lastScanMessages;
-
-        std::string     login;
-        int             id;
-        bool            __connected;
-        UserProperty<bool> connected;
-
-        bool            enabledDirs[DIR_NUM];
-
-        uint32_t        __currIP; // Current user's ip
-        UserProperty<uint32_t> currIP;
-
-        uint32_t        lastIPForDisconnect; // User's ip after unauth but before disconnect
-        std::string     lastDisconnectReason;
-
-        time_t          pingTime;
-
-        const Admin *   sysAdmin;
-        const Store *   store;
-
-        const Tariffs * tariffs;
-        const Tariff *  tariff;
-
-        const Services & m_services;
-
-        TraffStat      traffStat;
-        std::pair<time_t, TraffStat> traffStatSaved;
-
-        const Settings * settings;
-
-        std::set<const Auth *> authorizedBy;
-        time_t          authorizedModificationTime;
-
-        std::vector<Message> messages;
-
-        bool            deleted;
-
-        time_t          lastWriteStat;
-        time_t          lastWriteDetailedStat;
-
-        // Properties
-        UserProperty<double>         & cash;
-        UserProperty<DirTraff>      & up;
-        UserProperty<DirTraff>      & down;
-        UserProperty<double>         & lastCashAdd;
-        UserProperty<time_t>         & passiveTime;
-        UserProperty<time_t>         & lastCashAddTime;
-        UserProperty<double>         & freeMb;
-        UserProperty<time_t>         & lastActivityTime;
-        UserProperty<std::string>    & password;
-        UserProperty<int>            & passive;
-        UserProperty<int>            & disabled;
-        UserProperty<int>            & disabledDetailStat;
-        UserProperty<int>            & alwaysOnline;
-        UserProperty<std::string>    & tariffName;
-        UserProperty<std::string>    & nextTariff;
-        UserProperty<std::string>    & address;
-        UserProperty<std::string>    & note;
-        UserProperty<std::string>    & group;
-        UserProperty<std::string>    & email;
-        UserProperty<std::string>    & phone;
-        UserProperty<std::string>    & realName;
-        UserProperty<double>         & credit;
-        UserProperty<time_t>         & creditExpire;
-        UserProperty<UserIPs>       & ips;
-        UserProperty<std::string>    & userdata0;
-        UserProperty<std::string>    & userdata1;
-        UserProperty<std::string>    & userdata2;
-        UserProperty<std::string>    & userdata3;
-        UserProperty<std::string>    & userdata4;
-        UserProperty<std::string>    & userdata5;
-        UserProperty<std::string>    & userdata6;
-        UserProperty<std::string>    & userdata7;
-        UserProperty<std::string>    & userdata8;
-        UserProperty<std::string>    & userdata9;
-
-        // End properties
-
-        DirTraff                sessionUpload;
-        DirTraff                sessionDownload;
-        time_t                   sessionUploadModTime;
-        time_t                   sessionDownloadModTime;
-
-        CHG_PASSIVE_NOTIFIER     passiveNotifier;
-        CHG_DISABLED_NOTIFIER    disabledNotifier;
-        CHG_TARIFF_NOTIFIER      tariffNotifier;
-        CHG_CASH_NOTIFIER        cashNotifier;
-        CHG_IPS_NOTIFIER         ipNotifier;
-
-        mutable pthread_mutex_t  mutex;
-
-        std::string              errorStr;
-};
-//-----------------------------------------------------------------------------
-
-}
diff --git a/stargazer/user_property.cpp b/stargazer/user_property.cpp
deleted file mode 100644 (file)
index e2213a6..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-#include "stg/user_property.h"
-
-STG::UserProperties::UserProperties(const Settings& s)
-    : cash            (stat.cash,             "cash",             false, true, s, properties),
-      up              (stat.monthUp,          "upload",           false, true, s, properties),
-      down            (stat.monthDown,        "download",         false, true, s, properties),
-      lastCashAdd     (stat.lastCashAdd,      "lastCashAdd",      false, true, s, properties),
-      passiveTime     (stat.passiveTime,      "passiveTime",      false, true, s, properties),
-      lastCashAddTime (stat.lastCashAddTime,  "lastCashAddTime",  false, true, s, properties),
-      freeMb          (stat.freeMb,           "freeMb",           false, true, s, properties),
-      lastActivityTime(stat.lastActivityTime, "lastActivityTime", false, true, s, properties),
-
-      password    (conf.password,     "password",     true,  false, s, properties),
-      passive     (conf.passive,      "passive",      false, false, s, properties),
-      disabled    (conf.disabled,     "disabled",     false, false, s, properties),
-      disabledDetailStat(conf.disabledDetailStat, "DisabledDetailStat", false, false, s, properties),
-      alwaysOnline(conf.alwaysOnline, "alwaysOnline", false, false, s, properties),
-      tariffName  (conf.tariffName,   "tariffName",   false, false, s, properties),
-      nextTariff  (conf.nextTariff,   "nextTariff",   false, false, s, properties),
-      address     (conf.address,      "address",      false, false, s, properties),
-      note        (conf.note,         "note",         false, false, s, properties),
-      group       (conf.group,        "group",        false, false, s, properties),
-      email       (conf.email,        "email",        false, false, s, properties),
-      phone       (conf.phone,        "phone",        false, false, s, properties),
-      realName    (conf.realName,     "realName",     false, false, s, properties),
-      credit      (conf.credit,       "credit",       false, false, s, properties),
-      creditExpire(conf.creditExpire, "creditExpire", false, false, s, properties),
-      ips         (conf.ips,          "ips",          false, false, s, properties),
-      userdata0   (conf.userdata[0],  "userdata0",    false, false, s, properties),
-      userdata1   (conf.userdata[1],  "userdata1",    false, false, s, properties),
-      userdata2   (conf.userdata[2],  "userdata2",    false, false, s, properties),
-      userdata3   (conf.userdata[3],  "userdata3",    false, false, s, properties),
-      userdata4   (conf.userdata[4],  "userdata4",    false, false, s, properties),
-      userdata5   (conf.userdata[5],  "userdata5",    false, false, s, properties),
-      userdata6   (conf.userdata[6],  "userdata6",    false, false, s, properties),
-      userdata7   (conf.userdata[7],  "userdata7",    false, false, s, properties),
-      userdata8   (conf.userdata[8],  "userdata8",    false, false, s, properties),
-      userdata9   (conf.userdata[9],  "userdata9",    false, false, s, properties)
-{}
diff --git a/stargazer/users_impl.cpp b/stargazer/users_impl.cpp
deleted file mode 100644 (file)
index ca8f681..0000000
+++ /dev/null
@@ -1,853 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Date: 27.10.2002
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- */
-
-#include <pthread.h>
-
-#include <csignal>
-#include <cassert>
-#include <algorithm>
-#include <utility>
-#include <string>
-#include <vector>
-
-#include "stg/settings.h"
-#include "stg/common.h"
-
-#include "users_impl.h"
-#include "stg_timer.h"
-
-extern volatile time_t stgTime;
-
-using STG::UsersImpl;
-
-//-----------------------------------------------------------------------------
-UsersImpl::UsersImpl(SettingsImpl * s, Store * st,
-                    Tariffs * t, Services & svcs,
-                    const Admin& sa)
-    : settings(s),
-      tariffs(t),
-      m_services(svcs),
-      store(st),
-      sysAdmin(sa),
-      WriteServLog(Logger::get()),
-      nonstop(false),
-      isRunning(false),
-      handle(0)
-{
-pthread_mutexattr_t attr;
-pthread_mutexattr_init(&attr);
-pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
-pthread_mutex_init(&mutex, &attr);
-}
-//-----------------------------------------------------------------------------
-UsersImpl::~UsersImpl()
-{
-pthread_mutex_destroy(&mutex);
-}
-//-----------------------------------------------------------------------------
-int UsersImpl::FindByNameNonLock(const std::string & login, user_iter * user)
-{
-const std::map<std::string, user_iter>::const_iterator iter(loginIndex.find(login));
-if (iter == loginIndex.end())
-    return -1;
-if (user)
-    *user = iter->second;
-return 0;
-}
-//-----------------------------------------------------------------------------
-int UsersImpl::FindByNameNonLock(const std::string & login, const_user_iter * user) const
-{
-const std::map<std::string, user_iter>::const_iterator iter(loginIndex.find(login));
-if (iter == loginIndex.end())
-    return -1;
-if (user)
-    *user = iter->second;
-return 0;
-}
-//-----------------------------------------------------------------------------
-int UsersImpl::FindByName(const std::string & login, UserPtr * user)
-{
-STG_LOCKER lock(&mutex);
-user_iter u;
-if (FindByNameNonLock(login, &u))
-    return -1;
-*user = &(*u);
-return 0;
-}
-//-----------------------------------------------------------------------------
-int UsersImpl::FindByName(const std::string & login, ConstUserPtr * user) const
-{
-STG_LOCKER lock(&mutex);
-const_user_iter u;
-if (FindByNameNonLock(login, &u))
-    return -1;
-*user = &(*u);
-return 0;
-}
-//-----------------------------------------------------------------------------
-bool UsersImpl::Exists(const std::string & login) const
-{
-STG_LOCKER lock(&mutex);
-const std::map<std::string, user_iter>::const_iterator iter(loginIndex.find(login));
-return iter != loginIndex.end();
-}
-//-----------------------------------------------------------------------------
-bool UsersImpl::TariffInUse(const std::string & tariffName) const
-{
-STG_LOCKER lock(&mutex);
-std::list<UserImpl>::const_iterator iter;
-iter = users.begin();
-while (iter != users.end())
-    {
-    if (iter->GetProperties().tariffName.Get() == tariffName)
-        return true;
-    ++iter;
-    }
-return false;
-}
-//-----------------------------------------------------------------------------
-int UsersImpl::Add(const std::string & login, const Admin * admin)
-{
-STG_LOCKER lock(&mutex);
-const auto& priv = admin->priv();
-
-if (!priv.userAddDel)
-    {
-    WriteServLog("%s tried to add user \'%s\'. Access denied.",
-                 admin->logStr().c_str(), login.c_str());
-    return -1;
-    }
-
-if (store->AddUser(login))
-    return -1;
-
-UserImpl u(settings, store, tariffs, &sysAdmin, this, m_services);
-
-u.SetLogin(login);
-
-u.SetPassiveTimeAsNewUser();
-
-u.WriteConf();
-u.WriteStat();
-
-WriteServLog("%s User \'%s\' added.",
-             admin->logStr().c_str(), login.c_str());
-
-u.OnAdd();
-
-users.push_front(u);
-
-AddUserIntoIndexes(users.begin());
-
-    {
-    // Fire all "on add" notifiers
-    std::set<NotifierBase<UserPtr> *>::iterator ni = onAddNotifiers.begin();
-    while (ni != onAddNotifiers.end())
-        {
-        (*ni)->Notify(&users.front());
-        ++ni;
-        }
-    }
-
-    {
-    // Fire all "on add" implementation notifiers
-    std::set<NotifierBase<UserImplPtr> *>::iterator ni = onAddNotifiersImpl.begin();
-    while (ni != onAddNotifiersImpl.end())
-        {
-        (*ni)->Notify(&users.front());
-        ++ni;
-        }
-    }
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-void UsersImpl::Del(const std::string & login, const Admin * admin)
-{
-const auto& priv = admin->priv();
-user_iter u;
-
-if (!priv.userAddDel)
-    {
-    WriteServLog("%s tried to remove user \'%s\'. Access denied.",
-                 admin->logStr().c_str(), login.c_str());
-    return;
-    }
-
-
-    {
-    STG_LOCKER lock(&mutex);
-
-    if (FindByNameNonLock(login, &u))
-        {
-        WriteServLog("%s tried to delete user \'%s\': not found.",
-                     admin->logStr().c_str(),
-                     login.c_str());
-        return;
-        }
-
-    u->SetDeleted();
-    }
-
-    {
-    std::set<NotifierBase<UserPtr> *>::iterator ni = onDelNotifiers.begin();
-    while (ni != onDelNotifiers.end())
-        {
-        (*ni)->Notify(&(*u));
-        ++ni;
-        }
-    }
-
-    {
-    std::set<NotifierBase<UserImplPtr> *>::iterator ni = onDelNotifiersImpl.begin();
-    while (ni != onDelNotifiersImpl.end())
-        {
-        (*ni)->Notify(&(*u));
-        ++ni;
-        }
-    }
-
-    {
-    STG_LOCKER lock(&mutex);
-
-    u->OnDelete();
-
-    USER_TO_DEL utd;
-    utd.iter = u;
-    utd.delTime = stgTime;
-    usersToDelete.push_back(utd);
-
-    DelUserFromIndexes(u);
-
-    WriteServLog("%s User \'%s\' deleted.",
-                 admin->logStr().c_str(), login.c_str());
-
-    }
-}
-//-----------------------------------------------------------------------------
-bool UsersImpl::Authorize(const std::string & login, uint32_t ip,
-                           uint32_t enabledDirs, const Auth * auth)
-{
-user_iter iter;
-STG_LOCKER lock(&mutex);
-if (FindByNameNonLock(login, &iter))
-    {
-    WriteServLog("Attempt to authorize non-existant user '%s'", login.c_str());
-    return false;
-    }
-
-if (FindByIPIdx(ip, iter))
-    {
-    if (iter->GetLogin() != login)
-        {
-        WriteServLog("Attempt to authorize user '%s' from ip %s which already occupied by '%s'",
-                     login.c_str(), inet_ntostring(ip).c_str(),
-                     iter->GetLogin().c_str());
-        return false;
-        }
-    if (iter->Authorize(ip, enabledDirs, auth))
-        return false;
-    return true;
-    }
-
-if (iter->Authorize(ip, enabledDirs, auth))
-    return false;
-
-AddToIPIdx(iter);
-return true;
-}
-//-----------------------------------------------------------------------------
-bool UsersImpl::Unauthorize(const std::string & login,
-                             const Auth * auth,
-                             const std::string & reason)
-{
-user_iter iter;
-STG_LOCKER lock(&mutex);
-if (FindByNameNonLock(login, &iter))
-    {
-    WriteServLog("Attempt to unauthorize non-existant user '%s'", login.c_str());
-    printfd(__FILE__, "Attempt to unauthorize non-existant user '%s'", login.c_str());
-    return false;
-    }
-
-uint32_t ip = iter->GetCurrIP();
-
-iter->Unauthorize(auth, reason);
-
-if (!iter->GetAuthorized())
-    DelFromIPIdx(ip);
-
-return true;
-}
-//-----------------------------------------------------------------------------
-int UsersImpl::ReadUsers()
-{
-std::vector<std::string> usersList;
-usersList.clear();
-if (store->GetUsersList(&usersList) < 0)
-    {
-    WriteServLog(store->GetStrError().c_str());
-    return -1;
-    }
-
-user_iter ui;
-
-unsigned errors = 0;
-for (unsigned int i = 0; i < usersList.size(); i++)
-    {
-    UserImpl u(settings, store, tariffs, &sysAdmin, this, m_services);
-
-    u.SetLogin(usersList[i]);
-    users.push_front(u);
-    ui = users.begin();
-
-    AddUserIntoIndexes(ui);
-
-    if (settings->GetStopOnError())
-        {
-        if (ui->ReadConf() < 0)
-            return -1;
-
-        if (ui->ReadStat() < 0)
-            return -1;
-        }
-    else
-        {
-        if (ui->ReadConf() < 0)
-            errors++;
-
-        if (ui->ReadStat() < 0)
-            errors++;
-        }
-    }
-
-if (errors > 0)
-    return -1;
-return 0;
-}
-//-----------------------------------------------------------------------------
-void * UsersImpl::Run(void * d)
-{
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-printfd(__FILE__, "=====================| pid: %d |===================== \n", getpid());
-UsersImpl * us = static_cast<UsersImpl *>(d);
-
-struct tm t;
-time_t tt = stgTime;
-localtime_r(&tt, &t);
-
-int min = t.tm_min;
-int day = t.tm_mday;
-
-printfd(__FILE__,"Day = %d Min = %d\n", day, min);
-
-time_t touchTime = stgTime - MONITOR_TIME_DELAY_SEC;
-std::string monFile = us->settings->GetMonitorDir() + "/users_r";
-printfd(__FILE__, "Monitor=%d file USERS %s\n", us->settings->GetMonitoring(), monFile.c_str());
-
-us->isRunning = true;
-while (us->nonstop)
-    {
-    //printfd(__FILE__,"New Minute. old = %02d current = %02d\n", min, t->tm_min);
-    //printfd(__FILE__,"New Day.    old = %2d current = %2d\n", day, t->tm_mday);
-
-    for_each(us->users.begin(), us->users.end(), [](auto& user){ user.Run(); });
-
-    tt = stgTime;
-    localtime_r(&tt, &t);
-
-    if (min != t.tm_min)
-        {
-        printfd(__FILE__,"Sec = %d\n", stgTime);
-        printfd(__FILE__,"New Minute. old = %d current = %d\n", min, t.tm_min);
-        min = t.tm_min;
-
-        us->NewMinute(t);
-        }
-
-    if (day != t.tm_mday)
-        {
-        printfd(__FILE__,"Sec = %d\n", stgTime);
-        printfd(__FILE__,"New Day. old = %d current = %d\n", day, t.tm_mday);
-        day = t.tm_mday;
-        us->NewDay(t);
-        }
-
-    if (us->settings->GetMonitoring() && (touchTime + MONITOR_TIME_DELAY_SEC <= stgTime))
-        {
-        //printfd(__FILE__, "Monitor=%d file TRAFFCOUNTER %s\n", tc->monitoring, monFile.c_str());
-        touchTime = stgTime;
-        TouchFile(monFile);
-        }
-
-    stgUsleep(100000);
-    } //while (us->nonstop)
-
-std::list<USER_TO_DEL>::iterator iter(us->usersToDelete.begin());
-while (iter != us->usersToDelete.end())
-    {
-    iter->delTime -= 2 * userDeleteDelayTime;
-    ++iter;
-    }
-us->RealDelUser();
-
-us->isRunning = false;
-
-return NULL;
-}
-//-----------------------------------------------------------------------------
-void UsersImpl::NewMinute(const struct tm & t)
-{
-//Write traff, reset session traff. Fake disconnect-connect
-if (t.tm_hour == 23 && t.tm_min == 59)
-    {
-    printfd(__FILE__,"MidnightResetSessionStat\n");
-    for_each(users.begin(), users.end(), [](auto& user){ user.MidnightResetSessionStat(); });
-    }
-
-if (TimeToWriteDetailStat(t))
-    {
-    //printfd(__FILE__, "USER::WriteInetStat\n");
-    int usersCnt = 0;
-
-    // ðÉÛÅÍ ÀÚÅÒÏ× ÞÁÓÔÑÍÉ. ÷ ÐÅÒÅÒÙ×ÁÈ ×ÙÚÙ×ÁÅÍ USER::Run
-    std::list<UserImpl>::iterator usr = users.begin();
-    while (usr != users.end())
-        {
-        usersCnt++;
-        usr->WriteDetailStat();
-        ++usr;
-        if (usersCnt % 10 == 0)
-            for_each(users.begin(), users.end(), [](auto& user){ user.Run(); });
-        }
-    }
-
-RealDelUser();
-}
-//-----------------------------------------------------------------------------
-void UsersImpl::NewDay(const struct tm & t)
-{
-struct tm t1;
-time_t tt = stgTime;
-localtime_r(&tt, &t1);
-int dayFee = settings->GetDayFee();
-
-if (dayFee == 0)
-    dayFee = DaysInCurrentMonth();
-
-printfd(__FILE__, "DayFee = %d\n", dayFee);
-printfd(__FILE__, "Today = %d DayResetTraff = %d\n", t1.tm_mday, settings->GetDayResetTraff());
-printfd(__FILE__, "DayFeeIsLastDay = %d\n", settings->GetDayFeeIsLastDay());
-
-if (!settings->GetDayFeeIsLastDay())
-    {
-    printfd(__FILE__, "DayResetTraff - 1 -\n");
-    DayResetTraff(t1);
-    //printfd(__FILE__, "DayResetTraff - 1 - 1 -\n");
-    }
-
-if (settings->GetSpreadFee())
-    {
-    printfd(__FILE__, "Spread DayFee\n");
-    for_each(users.begin(), users.end(), [](auto& user){ user.ProcessDayFeeSpread(); });
-    }
-else
-    {
-    if (t.tm_mday == dayFee)
-        {
-        printfd(__FILE__, "DayFee\n");
-        for_each(users.begin(), users.end(), [](auto& user){ user.ProcessDayFee(); });
-        }
-    }
-
-std::for_each(users.begin(), users.end(), [](auto& user){ user.ProcessDailyFee(); });
-std::for_each(users.begin(), users.end(), [](auto& user){ user.ProcessServices(); });
-
-if (settings->GetDayFeeIsLastDay())
-    {
-    printfd(__FILE__, "DayResetTraff - 2 -\n");
-    DayResetTraff(t1);
-    }
-}
-//-----------------------------------------------------------------------------
-void UsersImpl::DayResetTraff(const struct tm & t1)
-{
-int dayResetTraff = settings->GetDayResetTraff();
-if (dayResetTraff == 0)
-    dayResetTraff = DaysInCurrentMonth();
-if (t1.tm_mday == dayResetTraff)
-    {
-    printfd(__FILE__, "ResetTraff\n");
-    for_each(users.begin(), users.end(), [](auto& user){ user.ProcessNewMonth(); });
-    //for_each(users.begin(), users.end(), mem_fun_ref(&UserImpl::SetPrepaidTraff));
-    }
-}
-//-----------------------------------------------------------------------------
-int UsersImpl::Start()
-{
-if (ReadUsers())
-    {
-    WriteServLog("USERS: Error: Cannot read users!");
-    return -1;
-    }
-
-nonstop = true;
-if (pthread_create(&thread, NULL, Run, this))
-    {
-    WriteServLog("USERS: Error: Cannot start thread!");
-    return -1;
-    }
-return 0;
-}
-//-----------------------------------------------------------------------------
-int UsersImpl::Stop()
-{
-printfd(__FILE__, "USERS::Stop()\n");
-
-if (!isRunning)
-    {
-    //printfd(__FILE__, "Alredy stopped\n");
-    return 0;
-    }
-
-nonstop = false;
-
-//5 seconds to thread stops itself
-struct timespec ts = {0, 200000000};
-for (size_t i = 0; i < 25 * (users.size() / 50 + 1); i++)
-    {
-    if (!isRunning)
-        break;
-
-    nanosleep(&ts, NULL);
-    }
-
-//after 5 seconds waiting thread still running. now kill it
-if (isRunning)
-    {
-    printfd(__FILE__, "kill USERS thread.\n");
-    //TODO pthread_cancel()
-    if (pthread_kill(thread, SIGINT))
-        {
-        //errorStr = "Cannot kill USERS thread.";
-        //printfd(__FILE__, "Cannot kill USERS thread.\n");
-        //return 0;
-        }
-    printfd(__FILE__, "USERS killed\n");
-    }
-
-printfd(__FILE__, "Before USERS::Run()\n");
-for_each(users.begin(), users.end(), [](auto& user){ user.Run(); });
-
-// 'cause bind2st accepts only constant first param
-for (std::list<UserImpl>::iterator it = users.begin();
-     it != users.end();
-     ++it)
-    it->WriteDetailStat(true);
-
-for_each(users.begin(), users.end(), [](auto& user){ user.WriteStat(); });
-//for_each(users.begin(), users.end(), mem_fun_ref(&UserImpl::WriteConf));
-
-printfd(__FILE__, "USERS::Stop()\n");
-return 0;
-}
-//-----------------------------------------------------------------------------
-void UsersImpl::RealDelUser()
-{
-STG_LOCKER lock(&mutex);
-
-printfd(__FILE__, "RealDelUser() users to del: %d\n", usersToDelete.size());
-
-std::list<USER_TO_DEL>::iterator iter;
-iter = usersToDelete.begin();
-while (iter != usersToDelete.end())
-    {
-    printfd(__FILE__, "RealDelUser() user=%s\n", iter->iter->GetLogin().c_str());
-    if (iter->delTime + userDeleteDelayTime < stgTime)
-        {
-        printfd(__FILE__, "RealDelUser() user=%s removed from DB\n", iter->iter->GetLogin().c_str());
-        if (store->DelUser(iter->iter->GetLogin()))
-            {
-            WriteServLog("Error removing user \'%s\' from database.", iter->iter->GetLogin().c_str());
-            }
-        users.erase(iter->iter);
-        usersToDelete.erase(iter++);
-        }
-    else
-        {
-        ++iter;
-        }
-    }
-return;
-}
-//-----------------------------------------------------------------------------
-void UsersImpl::AddToIPIdx(user_iter user)
-{
-printfd(__FILE__, "USERS: Add IP Idx\n");
-uint32_t ip = user->GetCurrIP();
-//assert(ip && "User has non-null ip");
-if (!ip)
-    return; // User has disconnected
-
-STG_LOCKER lock(&mutex);
-
-const std::map<uint32_t, user_iter>::iterator it(
-        ipIndex.lower_bound(ip)
-);
-
-assert((it == ipIndex.end() || it->first != ip) && "User is not in index");
-
-ipIndex.insert(it, std::make_pair(ip, user));
-}
-//-----------------------------------------------------------------------------
-void UsersImpl::DelFromIPIdx(uint32_t ip)
-{
-printfd(__FILE__, "USERS: Del IP Idx\n");
-assert(ip && "User has non-null ip");
-
-STG_LOCKER lock(&mutex);
-
-const std::map<uint32_t, user_iter>::iterator it(
-        ipIndex.find(ip)
-);
-
-if (it == ipIndex.end())
-    return;
-
-ipIndex.erase(it);
-}
-//-----------------------------------------------------------------------------
-bool UsersImpl::FindByIPIdx(uint32_t ip, user_iter & iter) const
-{
-std::map<uint32_t, user_iter>::const_iterator it(ipIndex.find(ip));
-if (it == ipIndex.end())
-    return false;
-iter = it->second;
-return true;
-}
-//-----------------------------------------------------------------------------
-int UsersImpl::FindByIPIdx(uint32_t ip, UserPtr * usr) const
-{
-STG_LOCKER lock(&mutex);
-
-user_iter iter;
-if (FindByIPIdx(ip, iter))
-    {
-    *usr = &(*iter);
-    return 0;
-    }
-
-return -1;
-}
-//-----------------------------------------------------------------------------
-int UsersImpl::FindByIPIdx(uint32_t ip, UserImpl ** usr) const
-{
-STG_LOCKER lock(&mutex);
-
-user_iter iter;
-if (FindByIPIdx(ip, iter))
-    {
-    *usr = &(*iter);
-    return 0;
-    }
-
-return -1;
-}
-//-----------------------------------------------------------------------------
-bool UsersImpl::IsIPInIndex(uint32_t ip) const
-{
-STG_LOCKER lock(&mutex);
-
-std::map<uint32_t, user_iter>::const_iterator it(ipIndex.find(ip));
-
-return it != ipIndex.end();
-}
-//-----------------------------------------------------------------------------
-bool UsersImpl::IsIPInUse(uint32_t ip, const std::string & login, ConstUserPtr * user) const
-{
-STG_LOCKER lock(&mutex);
-std::list<UserImpl>::const_iterator iter;
-iter = users.begin();
-while (iter != users.end())
-    {
-    if (iter->GetLogin() != login &&
-        !iter->GetProperties().ips.Get().isAnyIP() &&
-        iter->GetProperties().ips.Get().find(ip))
-        {
-        if (user != NULL)
-            *user = &(*iter);
-        return true;
-        }
-    ++iter;
-    }
-return false;
-}
-//-----------------------------------------------------------------------------
-void UsersImpl::AddNotifierUserAdd(NotifierBase<UserPtr> * n)
-{
-STG_LOCKER lock(&mutex);
-onAddNotifiers.insert(n);
-}
-//-----------------------------------------------------------------------------
-void UsersImpl::DelNotifierUserAdd(NotifierBase<UserPtr> * n)
-{
-STG_LOCKER lock(&mutex);
-onAddNotifiers.erase(n);
-}
-//-----------------------------------------------------------------------------
-void UsersImpl::AddNotifierUserDel(NotifierBase<UserPtr> * n)
-{
-STG_LOCKER lock(&mutex);
-onDelNotifiers.insert(n);
-}
-//-----------------------------------------------------------------------------
-void UsersImpl::DelNotifierUserDel(NotifierBase<UserPtr> * n)
-{
-STG_LOCKER lock(&mutex);
-onDelNotifiers.erase(n);
-}
-//-----------------------------------------------------------------------------
-void UsersImpl::AddNotifierUserAdd(NotifierBase<UserImplPtr> * n)
-{
-STG_LOCKER lock(&mutex);
-onAddNotifiersImpl.insert(n);
-}
-//-----------------------------------------------------------------------------
-void UsersImpl::DelNotifierUserAdd(NotifierBase<UserImplPtr> * n)
-{
-STG_LOCKER lock(&mutex);
-onAddNotifiersImpl.erase(n);
-}
-//-----------------------------------------------------------------------------
-void UsersImpl::AddNotifierUserDel(NotifierBase<UserImplPtr> * n)
-{
-STG_LOCKER lock(&mutex);
-onDelNotifiersImpl.insert(n);
-}
-//-----------------------------------------------------------------------------
-void UsersImpl::DelNotifierUserDel(NotifierBase<UserImplPtr> * n)
-{
-STG_LOCKER lock(&mutex);
-onDelNotifiersImpl.erase(n);
-}
-//-----------------------------------------------------------------------------
-int UsersImpl::OpenSearch()
-{
-STG_LOCKER lock(&mutex);
-handle++;
-searchDescriptors[handle] = users.begin();
-return handle;
-}
-//-----------------------------------------------------------------------------
-int UsersImpl::SearchNext(int h, UserPtr * user)
-{
-    UserImpl * ptr = NULL;
-    if (SearchNext(h, &ptr))
-        return -1;
-    *user = ptr;
-    return 0;
-}
-//-----------------------------------------------------------------------------
-int UsersImpl::SearchNext(int h, UserImpl ** user)
-{
-STG_LOCKER lock(&mutex);
-
-if (searchDescriptors.find(h) == searchDescriptors.end())
-    {
-    WriteServLog("USERS. Incorrect search handle.");
-    return -1;
-    }
-
-if (searchDescriptors[h] == users.end())
-    return -1;
-
-while (searchDescriptors[h]->GetDeleted())
-    {
-    ++searchDescriptors[h];
-    if (searchDescriptors[h] == users.end())
-        {
-        return -1;
-        }
-    }
-
-*user = &(*searchDescriptors[h]);
-
-++searchDescriptors[h];
-
-return 0;
-}
-//-----------------------------------------------------------------------------
-int UsersImpl::CloseSearch(int h)
-{
-STG_LOCKER lock(&mutex);
-if (searchDescriptors.find(h) != searchDescriptors.end())
-    {
-    searchDescriptors.erase(searchDescriptors.find(h));
-    return 0;
-    }
-
-WriteServLog("USERS. Incorrect search handle.");
-return -1;
-}
-//-----------------------------------------------------------------------------
-void UsersImpl::AddUserIntoIndexes(user_iter user)
-{
-STG_LOCKER lock(&mutex);
-loginIndex.insert(make_pair(user->GetLogin(), user));
-}
-//-----------------------------------------------------------------------------
-void UsersImpl::DelUserFromIndexes(user_iter user)
-{
-STG_LOCKER lock(&mutex);
-loginIndex.erase(user->GetLogin());
-}
-//-----------------------------------------------------------------------------
-bool UsersImpl::TimeToWriteDetailStat(const struct tm & t)
-{
-int statTime = settings->GetDetailStatWritePeriod();
-
-switch (statTime)
-    {
-    case dsPeriod_1:
-        if (t.tm_min == 0)
-            return true;
-        break;
-    case dsPeriod_1_2:
-        if (t.tm_min % 30 == 0)
-            return true;
-        break;
-    case dsPeriod_1_4:
-        if (t.tm_min % 15 == 0)
-            return true;
-        break;
-    case dsPeriod_1_6:
-        if (t.tm_min % 10 == 0)
-            return true;
-        break;
-    }
-return false;
-}
diff --git a/stargazer/users_impl.h b/stargazer/users_impl.h
deleted file mode 100644 (file)
index ef5ee0e..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
- */
-
-#pragma once
-
-#include <pthread.h>
-
-#include <string>
-#include <map>
-#include <list>
-#include <set>
-#include <ctime>
-#include <cstdint>
-
-#include "stg/store.h"
-#include "stg/users.h"
-#include "stg/user.h"
-#include "stg/tariffs.h"
-#include "stg/logger.h"
-#include "stg/notifer.h"
-#include "stg/noncopyable.h"
-#include "actions.h"
-#include "eventloop.h"
-#include "settings_impl.h"
-#include "user_impl.h"
-
-namespace STG
-{
-
-const int userDeleteDelayTime = 120;
-
-typedef std::list<UserImpl>::iterator user_iter;
-typedef std::list<UserImpl>::const_iterator const_user_iter;
-
-class UsersImpl;
-//-----------------------------------------------------------------------------
-struct USER_TO_DEL {
-USER_TO_DEL()
-    : iter(),
-      delTime(0)
-{}
-
-std::list<UserImpl>::iterator iter;
-time_t  delTime;
-};
-//-----------------------------------------------------------------------------
-class UsersImpl : public Users {
-    friend class PROPERTY_NOTIFER_IP_BEFORE;
-    friend class PROPERTY_NOTIFER_IP_AFTER;
-
-public:
-    using UserImplPtr = UserImpl*;
-
-    UsersImpl(SettingsImpl * s, Store * store,
-              Tariffs * tariffs, Services & svcs,
-              const Admin& sysAdmin);
-    virtual ~UsersImpl();
-
-    int             FindByName(const std::string & login, UserPtr * user) override;
-    int             FindByName(const std::string & login, ConstUserPtr * user) const override;
-    bool            Exists(const std::string & login) const override;
-
-    bool            TariffInUse(const std::string & tariffName) const override;
-
-    void            AddNotifierUserAdd(NotifierBase<UserPtr> *) override;
-    void            DelNotifierUserAdd(NotifierBase<UserPtr> *) override;
-
-    void            AddNotifierUserDel(NotifierBase<UserPtr> *) override;
-    void            DelNotifierUserDel(NotifierBase<UserPtr> *) override;
-
-    void            AddNotifierUserAdd(NotifierBase<UserImplPtr> *);
-    void            DelNotifierUserAdd(NotifierBase<UserImplPtr> *);
-
-    void            AddNotifierUserDel(NotifierBase<UserImplPtr> *);
-    void            DelNotifierUserDel(NotifierBase<UserImplPtr> *);
-
-    int             Add(const std::string & login, const Admin * admin) override;
-    void            Del(const std::string & login, const Admin * admin) override;
-
-    bool            Authorize(const std::string & login, uint32_t ip,
-                              uint32_t enabledDirs, const Auth * auth) override;
-    bool            Unauthorize(const std::string & login,
-                                const Auth * auth,
-                                const std::string & reason) override;
-
-    int             ReadUsers() override;
-    size_t          Count() const override { return users.size(); }
-
-    int             FindByIPIdx(uint32_t ip, UserPtr * user) const override;
-    int             FindByIPIdx(uint32_t ip, UserImpl ** user) const;
-    bool            IsIPInIndex(uint32_t ip) const override;
-    bool            IsIPInUse(uint32_t ip, const std::string & login, ConstUserPtr * user) const override;
-
-    int             OpenSearch() override;
-    int             SearchNext(int handler, UserPtr * user) override;
-    int             SearchNext(int handler, UserImpl ** user);
-    int             CloseSearch(int handler) override;
-
-    int             Start() override;
-    int             Stop() override;
-
-private:
-    UsersImpl(const UsersImpl & rvalue);
-    UsersImpl & operator=(const UsersImpl & rvalue);
-
-    void            AddToIPIdx(user_iter user);
-    void            DelFromIPIdx(uint32_t ip);
-    bool            FindByIPIdx(uint32_t ip, user_iter & iter) const;
-
-    int             FindByNameNonLock(const std::string & login, user_iter * user);
-    int             FindByNameNonLock(const std::string & login, const_user_iter * user) const;
-
-    void            RealDelUser();
-    void            ProcessActions();
-
-    void            AddUserIntoIndexes(user_iter user);
-    void            DelUserFromIndexes(user_iter user);
-
-    static void *   Run(void *);
-    void            NewMinute(const struct tm & t);
-    void            NewDay(const struct tm & t);
-    void            DayResetTraff(const struct tm & t);
-
-    bool            TimeToWriteDetailStat(const struct tm & t);
-
-    std::list<UserImpl>                  users;
-    std::list<USER_TO_DEL>                usersToDelete;
-
-    std::map<uint32_t, user_iter>         ipIndex;
-    std::map<std::string, user_iter>      loginIndex;
-
-    SettingsImpl *     settings;
-    Tariffs *           tariffs;
-    Services &          m_services;
-    Store *             store;
-    const Admin&       sysAdmin;
-    Logger &        WriteServLog;
-
-    bool                nonstop;
-    bool                isRunning;
-
-    mutable pthread_mutex_t mutex;
-    pthread_t               thread;
-    mutable unsigned int    handle;
-
-    mutable std::map<int, user_iter>  searchDescriptors;
-
-    std::set<NotifierBase<UserPtr>*> onAddNotifiers;
-    std::set<NotifierBase<UserPtr>*> onDelNotifiers;
-    std::set<NotifierBase<UserImplPtr>*> onAddNotifiersImpl;
-    std::set<NotifierBase<UserImplPtr>*> onDelNotifiersImpl;
-};
-
-}
index 30286d2e717c522adafaba7752808f2d6b95ad17..226b9b22d0296869bdf0c4a2ef2bd5be963431f2 100644 (file)
@@ -9,9 +9,9 @@ set ( CPP_FILES main.cpp
                 test_filter_params_log.cpp
                 test_crypto.cpp
                 test_bfstream.cpp
-                ../stargazer/tariff_impl.cpp
-                ../stargazer/user_impl.cpp
-                ../stargazer/user_property.cpp )
+                ../projects/stargazer/tariff_impl.cpp
+                ../projects/stargazer/user_impl.cpp
+                ../projects/stargazer/user_property.cpp )
 
 set ( THREADS_PREFER_PTHREAD_FLAG ON )
 find_package ( Threads REQUIRED )
@@ -22,4 +22,4 @@ add_executable ( tests ${CPP_FILES} )
 
 target_link_libraries ( tests conffiles crypto logger scriptexecuter common Threads::Threads )
 
-target_include_directories ( tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ../stargazer )
+target_include_directories ( tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ../projects/stargazer )