Password and account security updates

security updates:

various commands that change or create account passwords now disallow
the user name, display name or email from being contained in it. this
will force users to not use public information inside the password,
hardening password security a little.

the root user name is now changeable and required to be changed on
initial login. this harden security a little by giving host admins the
option to not have a well known user name attached to a high privileged
account.

users can no longer re-use the old password and/or user name when
required to change. however, this does not actually implement full
password history because the user can then later change the password
back to the old password after the required change.

the host can longer block by ip addresses and the auto block threshold
setting has been removed. something like this is best left up to
firewalls, routers, switches or any other networking infrastructure. in
the future i can consider adding event triggering that run certain
admin defined external or internal commands when the host detects
certain event thresholds.

minor changes/bug fixes:

all commands that change or create user names now no longer accept
user names that looks like an mail address. this works out better for
clients when differentiating logging in via user name or email address.

the recover_acct command now also have cancel on blank text options
making it more consistent with all other commands that take text input.

resetting the root user's account password via command line now also
unlocks it if locked.

the -help and -about command line options no longer display the
default password. a new -default_pw option was added for this purpose.

the -status -addr or -stop command line options require super user
privileges to run properly depending on how the host is installed.
an error message like "permission denied" was addded on failure to
make this requirement clear to the end user.

fs_copy and fs_move now does implicit skip on error instead of stop on
error.

the IDLE frame type id now carry an integer return code that can be
interpreted by clients to determine the result of the command that was
sent to the host.

house keeping:

all documentation was updated to reflect the changes made in this commit.
the module tester example is no longer relevant to this project so it
was deleted.
This commit is contained in:
Maurice ONeal 2020-01-29 12:29:01 -05:00
parent 8c1c02efa8
commit 4c1d13f8f8
51 changed files with 1114 additions and 1503 deletions

3
.gitignore vendored
View File

@ -47,3 +47,6 @@ compile_commands.json
# QtCreator local machine specific files for imported projects # QtCreator local machine specific files for imported projects
*creator.user* *creator.user*
# VSCode
/.vscode

View File

@ -60,7 +60,6 @@ SOURCES += src/main.cpp \
src/commands/mods.cpp \ src/commands/mods.cpp \
src/commands/info.cpp \ src/commands/info.cpp \
src/commands/cast.cpp \ src/commands/cast.cpp \
src/commands/bans.cpp \
src/commands/admin.cpp \ src/commands/admin.cpp \
src/commands/auth.cpp \ src/commands/auth.cpp \
src/commands/acct_recovery.cpp \ src/commands/acct_recovery.cpp \
@ -88,7 +87,6 @@ HEADERS += \
src/commands/mods.h \ src/commands/mods.h \
src/commands/info.h \ src/commands/info.h \
src/commands/cast.h \ src/commands/cast.h \
src/commands/bans.h \
src/commands/admin.h \ src/commands/admin.h \
src/commands/auth.h \ src/commands/auth.h \
src/commands/acct_recovery.h \ src/commands/acct_recovery.h \

View File

@ -2,7 +2,6 @@
<qresource prefix="/"> <qresource prefix="/">
<file>docs/intern_commands/accept_ch.md</file> <file>docs/intern_commands/accept_ch.md</file>
<file>docs/intern_commands/add_acct.md</file> <file>docs/intern_commands/add_acct.md</file>
<file>docs/intern_commands/add_ban.md</file>
<file>docs/intern_commands/add_cert.md</file> <file>docs/intern_commands/add_cert.md</file>
<file>docs/intern_commands/add_ch.md</file> <file>docs/intern_commands/add_ch.md</file>
<file>docs/intern_commands/add_mod.md</file> <file>docs/intern_commands/add_mod.md</file>
@ -34,7 +33,6 @@
<file>docs/intern_commands/lock_acct.md</file> <file>docs/intern_commands/lock_acct.md</file>
<file>docs/intern_commands/ls_act_log.md</file> <file>docs/intern_commands/ls_act_log.md</file>
<file>docs/intern_commands/ls_auth_log.md</file> <file>docs/intern_commands/ls_auth_log.md</file>
<file>docs/intern_commands/ls_bans.md</file>
<file>docs/intern_commands/ls_certs.md</file> <file>docs/intern_commands/ls_certs.md</file>
<file>docs/intern_commands/ls_ch_members.md</file> <file>docs/intern_commands/ls_ch_members.md</file>
<file>docs/intern_commands/ls_chs.md</file> <file>docs/intern_commands/ls_chs.md</file>
@ -62,7 +60,6 @@
<file>docs/intern_commands/request_pw_reset.md</file> <file>docs/intern_commands/request_pw_reset.md</file>
<file>docs/intern_commands/restart_host.md</file> <file>docs/intern_commands/restart_host.md</file>
<file>docs/intern_commands/rm_acct.md</file> <file>docs/intern_commands/rm_acct.md</file>
<file>docs/intern_commands/rm_ban.md</file>
<file>docs/intern_commands/rm_cert.md</file> <file>docs/intern_commands/rm_cert.md</file>
<file>docs/intern_commands/rm_ch.md</file> <file>docs/intern_commands/rm_ch.md</file>
<file>docs/intern_commands/rm_mod.md</file> <file>docs/intern_commands/rm_mod.md</file>

View File

@ -16,6 +16,7 @@ Usage: mrci <argument>
-status : display status information about the host instance if it is currently running. -status : display status information about the host instance if it is currently running.
-reset_root : reset the root account password to the default password. -reset_root : reset the root account password to the default password.
-host : start a new host instance. (this blocks). -host : start a new host instance. (this blocks).
-default_pw : show the default password.
-public_cmds : run the internal module to list it's public commands. for internal use only. -public_cmds : run the internal module to list it's public commands. for internal use only.
-exempt_cmds : run the internal module to list it's rank exempt commands. for internal use only. -exempt_cmds : run the internal module to list it's rank exempt commands. for internal use only.
-user_cmds : run the internal module to list it's user commands. for internal use only. -user_cmds : run the internal module to list it's user commands. for internal use only.
@ -30,7 +31,7 @@ Internal module | -public_cmds, -user_cmds, -exempt_cmds, -run_cmd |:
The host can only be managed via a connected client that supports text input/output so the host application is always listening for clients while running entirely in the background. By default the host listen for clients on address 0.0.0.0 and port 35516, effectively making it reachable on any network interface of the host platform via that specific port. The host can only be managed via a connected client that supports text input/output so the host application is always listening for clients while running entirely in the background. By default the host listen for clients on address 0.0.0.0 and port 35516, effectively making it reachable on any network interface of the host platform via that specific port.
Just like any linux based OS, the host will have an administrative user called root. This account can be used to modify anything on the host without restriction. The default password is randomized and set on the root user account upon running the host for the first time. To find out what the default password is, run -help or -about. When logging in as root with the default password, the host will require you to change the password before continuing. Any one user account registered with the host can be given root privileges which basically gives this user unrestricted access to anything in the host for administrative purposes. When a host instance is created for the first time, it will create a new user account called 'root' with a randomized default password. To find out what the default password is, run -default_pw. When logging in for the fist time, the host will require you to change the user name and password before continuing.
### More Than Just a Command Interpreter ### ### More Than Just a Command Interpreter ###

View File

@ -2,7 +2,7 @@
An async command is a virtual command that the host can use to send data to the client at any time while connected to the host. As the name implies, the occurance of a client receiving data from an async command is not always the result of running a regular command in the current session. This can occur for example when information in your account is changed by another client connected to the host; your client would not know about this change until an async command is sent notify it of the change. These commands can be called directly or indirectly by a module and are considered "virtual" commands because there is no defined objects attached to them. Instead, async commands are best identified by command id values 1-255. An async command is a virtual command that the host can use to send data to the client at any time while connected to the host. As the name implies, the occurance of a client receiving data from an async command is not always the result of running a regular command in the current session. This can occur for example when information in your account is changed by another client connected to the host; your client would not know about this change until an async command is sent notify it of the change. These commands can be called directly or indirectly by a module and are considered "virtual" commands because there is no defined objects attached to them. Instead, async commands are best identified by command id values 1-255.
Async commands are not only used to send data to the client but also used internally within the host to help objects operating in different processes to communicate with each other. Some async commands in fact are considered internal only because the client should never see any data come from them at anytime. There is also data flow contriants for aysnc commands, meaning some gets blocked if sent from the module or has no effect if sent with the unexpected [IPC](type_ids.md) type id. The list below shows the various data flow contriants each of these async commands have. Async commands are not only used to send data to the client but also used internally within the host to help objects operating in different processes to communicate with each other. Some async commands in fact are considered internal only because the client should never see any data come from them at anytime. There is also data flow contriants for async commands, meaning some gets blocked if sent from the module or has no effect if sent with the unexpected [IPC](type_ids.md) type id. The list below shows the various data flow contriants each of these async commands have.
Here is a describtion of what the keywords in the list mean: Here is a describtion of what the keywords in the list mean:
``` ```
@ -74,7 +74,6 @@ enum AsyncCommands : quint16
ASYNC_PING_PEERS = 38, // internal | private ASYNC_PING_PEERS = 38, // internal | private
ASYNC_OPEN_SUBCH = 39, // internal | private ASYNC_OPEN_SUBCH = 39, // internal | private
ASYNC_CLOSE_SUBCH = 40, // internal | private ASYNC_CLOSE_SUBCH = 40, // internal | private
ASYNC_UPDATE_BANS = 41, // internal | private
ASYNC_KEEP_ALIVE = 42, // internal | private ASYNC_KEEP_ALIVE = 42, // internal | private
ASYNC_SET_DIR = 43, // internal | private ASYNC_SET_DIR = 43, // internal | private
ASYNC_DEBUG_TEXT = 44 // internal | private ASYNC_DEBUG_TEXT = 44 // internal | private
@ -289,9 +288,6 @@ format: [8bytes(64bit_ch_id)][1byte(8bit_sub_ch_id)]
```ASYNC_CLOSE_SUBCH (40)``` ```ASYNC_CLOSE_SUBCH (40)```
This is the other half to ASYNC_OPEN_SUBCH that tells the session to close the requested sub-channel. This is the other half to ASYNC_OPEN_SUBCH that tells the session to close the requested sub-channel.
```ASYNC_UPDATE_BANS (41)```
This internal only async command doesn't carry any data. It can be use by modules to tell the TCPServer object to update it's ip ban list cache from the database. This generally only needs to be used if the ip ban list in the database has changed in anyway.
```ASYNC_KEEP_ALIVE (42)``` ```ASYNC_KEEP_ALIVE (42)```
This internal only async command doesn't carry any data. The session object normally sends a [KILL_CMD](type_ids.md) to the module when it detects that the module process has not sent an IPC frame in 2 minutes to terminate the module process. If desired, the module can send this async command in regular intervals to reset this 2 minute idle timer to prevent auto termination. This internal only async command doesn't carry any data. The session object normally sends a [KILL_CMD](type_ids.md) to the module when it detects that the module process has not sent an IPC frame in 2 minutes to terminate the module process. If desired, the module can send this async command in regular intervals to reset this 2 minute idle timer to prevent auto termination.

View File

@ -6,8 +6,6 @@ The host is extendable via 3rd party modules but the host itself is an internal
* [add_acct](intern_commands/add_acct.md) - create a new host user account. * [add_acct](intern_commands/add_acct.md) - create a new host user account.
* [add_ban](intern_commands/add_ban.md) - add an ip address to the host ban list.
* [add_cert](intern_commands/add_cert.md) - install a new SSL/TLS cert into the host. * [add_cert](intern_commands/add_cert.md) - install a new SSL/TLS cert into the host.
* [add_ch](intern_commands/add_ch.md) - create a new channel. * [add_ch](intern_commands/add_ch.md) - create a new channel.
@ -72,8 +70,6 @@ The host is extendable via 3rd party modules but the host itself is an internal
* [ls_auth_log](intern_commands/ls_auth_log.md) - display the host authorization activity log. * [ls_auth_log](intern_commands/ls_auth_log.md) - display the host authorization activity log.
* [ls_bans](intern_commands/ls_bans.md) - display or manage the host ip address ban table.
* [ls_certs](intern_commands/ls_certs.md) - display a list of all SSL/TLS certificates installed in the host database. * [ls_certs](intern_commands/ls_certs.md) - display a list of all SSL/TLS certificates installed in the host database.
* [ls_ch_members](intern_commands/ls_ch_members.md) - list all members in a channel. * [ls_ch_members](intern_commands/ls_ch_members.md) - list all members in a channel.
@ -128,8 +124,6 @@ The host is extendable via 3rd party modules but the host itself is an internal
* [rm_acct](intern_commands/rm_acct.md) - delete a user account from the host database. * [rm_acct](intern_commands/rm_acct.md) - delete a user account from the host database.
* [rm_ban](intern_commands/rm_ban.md) - remove an ip address from the ban list.
* [rm_cert](intern_commands/rm_cert.md) - remove the SSL/TLS cert associated with the given common name. * [rm_cert](intern_commands/rm_cert.md) - remove the SSL/TLS cert associated with the given common name.
* [rm_ch](intern_commands/rm_ch.md) - permanently remove a channel and all of it's sub-shannels from the host. * [rm_ch](intern_commands/rm_ch.md) - permanently remove a channel and all of it's sub-shannels from the host.

View File

@ -8,4 +8,8 @@ create a new host user account.
### Description ### ### Description ###
this creates a new user account with the user name given in -name and an email address used for account recovery in -email. the command will fail if the user name or email address already exists. you can pass the optional -disp to set the display name for the new user account. the display name can be used by clients to present the user account to other clients without showing the true user name or make it easier for users to identify each other since the display name is not restricted by uniqueness. the display name can be anything; it's only restricted to 32 chars or less but it cannot contain new lines or lines breaks. this creates a new user account with the user name given in -name and an email address used for account recovery in -email. the command will fail if the user name or email address already exists. you can pass the optional -disp to set the display name for the new user account.
the command will ask for a new password during execution. avoid using a password that contains the user name, email address or display name; the command will actively block this. also aviod using a user name that is formatted like a email address since this would cause undesired behaviour in 3rd party client applications. setting the user name as 'root' is forbidden.
the display name can be used by clients to present the user account to other clients without showing the true user name or make it easier for users to identify each other since the display name is not restricted by uniqueness. the display name can be anything; it's only restricted to 32 chars or less but it cannot contain new lines or lines breaks.

View File

@ -1,11 +0,0 @@
### Summary ###
add an ip address to the host ban list.
### IO ###
```[-ip (text)]/[text]```
### Description ###
add an ip address or its integer representative given in -ip to the host ban list that will prevent any client from connecting to the host with that ip address.

View File

@ -8,4 +8,4 @@ login to the host using a registered user account name or email address.
### Description ### ### Description ###
login into a user account name given in -user or email address given in -email. this command will ask for the password during execution to complete the authentication. login into a user account name given in -user or email address given in -email. this command will ask for the password during execution to complete the authentication. this command will also honor any request to change the password or user name before completing the authentication.

View File

@ -1,16 +0,0 @@
### Summary ###
display or manage the host ip address ban table.
### IO ###
```[{search_terms} {-delete}]/[text]```
### Description ###
by default, all entries in the table are displayed in 50 entries per page. you can pass the column names as -column_name (text) to refine your search to specific entries. this command can handle the following columns:
-time_stamp
-ip_address
you can also pass -delete that will cause the command to delete the entries instead of displaying them. note: passing no search terms with this option will delete all entries in the table. keep in mind, the host use this table to enforce the ban-by-ip option. deleting entries in this table will un-ban the ip's affected by the deletion.

View File

@ -1,11 +0,0 @@
### Summary ###
remove an ip address from the ban list.
### IO ###
```[-ip (text)]/[text]```
### Description ###
this removes an ip address from the host ban list. nothing happens if the ip does not exists in the list.

View File

@ -8,4 +8,4 @@ update your account password.
### Description ### ### Description ###
this changes the password on your own account. during execution, this command will ask for a new password to be entered. this changes the password on your own account. the command will ask for a new password during execution. avoid using a password that contains the user name, email address or display name; the command will actively block this.

View File

@ -2,7 +2,15 @@
Modules in this project are independent applications that communicate with the host application's session objects via named pipes and/or shared memory segments. The host will call multiple instances of these modules if needed using the command line options described in section 2.3 depending on session activity. The format for data transport between the session and module via the named pipe is a modified version of the MRCI frame described in section 2.2 called the IPC frame. Modules in this project are independent applications that communicate with the host application's session objects via named pipes and/or shared memory segments. The host will call multiple instances of these modules if needed using the command line options described in section 2.3 depending on session activity. The format for data transport between the session and module via the named pipe is a modified version of the MRCI frame described in section 2.2 called the IPC frame.
Basically the module's main job is to input and output IPC frames with the session object with the option to read session data from shared memory. Basically the module's main job is to input and output IPC frames with the session object with the option to read session data from shared memory. The MRCI host have internal commands that are loaded using the module interface so the MRCI host project itself is a good example of a module. See the following classes and source files to understand how the internal module works and to understand how to make an external module based on it.
```
int main() - main.cpp
class Module - module.h, module.cpp
class MemShare - mem_share.h, mem_share.cpp
class CmdObject - cmd_object.h, cmd_object.cpp
class IPCWorker - cmd_object.h, cmd_object.cpp
```
### 2.2 IPC Frame ### ### 2.2 IPC Frame ###

View File

@ -77,7 +77,27 @@ This id can be treated exactly like TEXT except this should tell the client to h
Also formatted exactly like TEXT but this indicates to the client that this is a large body of text that is recommended to be word wrapped when displaying to the user. It can contain line breaks so clients are also recommended to honor those line breaks. Also formatted exactly like TEXT but this indicates to the client that this is a large body of text that is recommended to be word wrapped when displaying to the user. It can contain line breaks so clients are also recommended to honor those line breaks.
```IDLE``` ```IDLE```
This doesn't carry any actual data, instead this indicates that the command id and branch id that sent it has finished it's task. Modules that send this doesn't need to terminate it's process. All commands started during the session returns this type id when it has finished it's task. by default, it carries a 16bit unsigned integer indicating the result of the task that the command was running.
```
enum RetCode : quint16
{
NO_ERRORS = 1, // task execution completed without any issues.
ABORTED = 2, // the task aborted via user or host intervention.
INVALID_PARAMS = 3, // invalid/missing parameters prevented the task from executing.
CRASH = 4, // the command process has crashed.
FAILED_TO_START = 5, // the command process could not start.
EXECUTION_FAIL = 6, // command specific error prevented execution of the task.
CUSTOM = 7 // indicates a custom return code.
};
notes:
1. the custom return code can be additional data added to the end of the 16bit
integer that can carry additional data about the result of the task. it can
be any format that the module itself decides it should be. nothing is
stopping modules from defining return codes beyond the value of 7 but it is
advised not to because this enum might be expanded in the future.
```
```KILL_CMD``` ```KILL_CMD```
This doesn't carry any actual data, instead can be sent by the client or session object to tell the command-branch id sent in the frame to terminate the module process. Modules that receive this need to send a IDLE frame if a command is still running and then terminate itself. The module will have 3 seconds to do this before it is force killed by the session. This doesn't carry any actual data, instead can be sent by the client or session object to tell the command-branch id sent in the frame to terminate the module process. Modules that receive this need to send a IDLE frame if a command is still running and then terminate itself. The module will have 3 seconds to do this before it is force killed by the session.

View File

@ -5,7 +5,7 @@ installer_file="$2"
src_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" src_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
bin_name="mrci" bin_name="mrci"
app_version="2.1.3" app_version="2.2.3"
app_name="MRCI" app_name="MRCI"
install_dir="/opt/$bin_name" install_dir="/opt/$bin_name"
var_dir="/var/opt/$bin_name" var_dir="/var/opt/$bin_name"

View File

@ -1,36 +0,0 @@
#-------------------------------------------------
#
# Project created by QtCreator 2017-06-26T15:36:12
#
# This file is part of MRCI.
#
# MRCI 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 3 of the License, or
# (at your option) any later version.
#
# MRCI 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 MRCI under the LICENSE.md file. If not, see
# <http://www.gnu.org/licenses/>.
#
#-------------------------------------------------
QT -= gui
TARGET = ModTester
TEMPLATE = lib
DEFINES += MOD_TESTER
SOURCES += \
command.cpp \
main.cpp
HEADERS += \
command.h \
main.h

View File

@ -1,70 +0,0 @@
#include "command.h"
// This file is part of MRCI.
// MRCI 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 3 of the License, or
// (at your option) any later version.
// MRCI 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 MRCI under the LICENSE.md file. If not, see
// <http://www.gnu.org/licenses/>.
SharedObjs::SharedObjs(QObject *parent) : QObject(parent)
{
p2pAccepted = nullptr;
p2pPending = nullptr;
chIds = nullptr;
wrAbleChIds = nullptr;
chList = nullptr;
activeUpdate = nullptr;
chOwnerOverride = nullptr;
sessionAddr = nullptr;
userName = nullptr;
groupName = nullptr;
displayName = nullptr;
appName = nullptr;
clientMajor = nullptr;
clientMinor = nullptr;
clientPatch = nullptr;
sessionId = nullptr;
userId = nullptr;
moreInputCmds = nullptr;
activeLoopCmds = nullptr;
pausedCmds = nullptr;
hostRank = nullptr;
cmdNames = nullptr;
}
bool ExternCommand::errState()
{
return errSent;
}
void ExternCommand::mainTxt(const QString &txt)
{
emit dataToClient(QTextCodec::codecForName(TXT_CODEC)->fromUnicode(txt).mid(2), TEXT);
}
void ExternCommand::errTxt(const QString &txt)
{
errSent = true;
emit dataToClient(QTextCodec::codecForName(TXT_CODEC)->fromUnicode(txt).mid(2), ERR);
}
void ExternCommand::privTxt(const QString &txt)
{
emit dataToClient(QTextCodec::codecForName(TXT_CODEC)->fromUnicode(txt).mid(2), PRIV_TEXT);
}
void ExternCommand::bigTxt(const QString &txt)
{
emit dataToClient(QTextCodec::codecForName(TXT_CODEC)->fromUnicode(txt).mid(2), BIG_TEXT);
}

View File

@ -1,170 +0,0 @@
#ifndef EXTERN_COMMAND_H
#define EXTERN_COMMAND_H
// This file is part of MRCI.
// MRCI 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 3 of the License, or
// (at your option) any later version.
// MRCI 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 MRCI under the LICENSE.md file. If not, see
// <http://www.gnu.org/licenses/>.
#define TXT_CODEC "UTF-16LE"
#define TXT_CODEC_BITS 16
#define MOD_LOADER_IID "MCRI.host.module"
#include <QObject>
#include <QTextCodec>
#include <QCoreApplication>
#include <QHash>
#include <QPluginLoader>
enum TypeID
{
GEN_FILE = 30,
TEXT = 31,
ERR = 32,
PRIV_TEXT = 33,
IDLE = 34,
HOST_CERT = 35,
FILE_INFO = 36,
PEER_INFO = 37,
MY_INFO = 38,
PEER_STAT = 39,
P2P_REQUEST = 40,
P2P_CLOSE = 41,
P2P_OPEN = 42,
BYTES = 43,
SESSION_ID = 44,
NEW_CMD = 45,
CMD_ID = 46,
BIG_TEXT = 47
};
enum ChannelMemberLevel
{
OWNER = 1,
ADMIN = 2,
OFFICER = 3,
REGULAR = 4,
PUBLIC = 5
};
class ExternCommand;
class SharedObjs : public QObject
{
Q_OBJECT
public:
const QHash<quint16, QString> *cmdNames;
const QList<QString> *chList;
const QList<QByteArray> *p2pAccepted;
const QList<QByteArray> *p2pPending;
const QList<quint16> *moreInputCmds;
const QList<quint16> *activeLoopCmds;
const QList<quint16> *pausedCmds;
const QString *sessionAddr;
const QString *userName;
const QString *groupName;
const QString *displayName;
const QString *appName;
const ushort *clientMajor;
const ushort *clientMinor;
const ushort *clientPatch;
const QByteArray *chIds;
const QByteArray *wrAbleChIds;
const QByteArray *sessionId;
const QByteArray *userId;
const bool *activeUpdate;
const bool *chOwnerOverride;
const uint *hostRank;
explicit SharedObjs(QObject *parent = nullptr);
};
class ExternCommand : public QObject
{
Q_OBJECT
protected:
void mainTxt(const QString &txt);
void errTxt(const QString &txt);
void privTxt(const QString &txt);
void bigTxt(const QString &txt);
public:
explicit ExternCommand(QObject *parent = nullptr) : QObject(parent) {}
virtual ~ExternCommand() {}
virtual void procBin(const SharedObjs *, const QByteArray &, uchar) {}
virtual void aboutToDelete() {}
virtual void term() {}
virtual bool handlesGenfile() {return false;}
virtual bool errState();
virtual QString shortText() {return "";}
virtual QString ioText() {return "";}
virtual QString longText() {return "";}
virtual QString libText() {return "";}
virtual QStringList internRequest() {return QStringList();}
QHash<QString, ExternCommand*> internCommands;
quint16 cmdId;
bool errSent;
bool inLoopMode;
bool inMoreInputMode;
signals:
void dataToClient(const QByteArray &data, uchar typeId = TEXT);
void castToPeers(const QByteArray &data, uchar typeId = TEXT);
void toPeer(const QByteArray &dst, const QByteArray &data, uchar typeId = TEXT);
void closeChByName(const QString &ch, const QString &sub);
void closeChById(quint64 id, uchar subId);
void openChByName(const QString &ch, const QString &sub);
void openChById(quint64 id, uchar subId);
void enableLoop(bool state);
void enableMoreInput(bool state);
void closeSession();
void cmdFinished();
void logout();
};
class CommandLoader : public QObject
{
Q_OBJECT
public:
explicit CommandLoader(QObject *parent = nullptr) : QObject(parent) {}
virtual ~CommandLoader() {}
virtual void modPath(const QString &) {}
virtual void aboutToDelete() {}
virtual bool hostRevOk(quint64, quint16, quint16, quint16) {return false;}
virtual QString lastError() {return "";}
virtual quint64 rev() {return 0;}
virtual QStringList pubCmdList() {return QStringList();}
virtual QStringList cmdList() {return QStringList();}
virtual QStringList rankExemptList() {return QStringList();}
virtual ExternCommand *cmdObj(const QString &) {return nullptr;}
};
QT_BEGIN_NAMESPACE
Q_DECLARE_INTERFACE(CommandLoader, MOD_LOADER_IID)
QT_END_NAMESPACE
#endif // EXTERN_COMMAND_H

View File

@ -1,255 +0,0 @@
#include "main.h"
// This file is part of MRCI.
// MRCI 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 3 of the License, or
// (at your option) any later version.
// MRCI 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 MRCI under the LICENSE.md file. If not, see
// <http://www.gnu.org/licenses/>.
CommandLoader *hostImport()
{
return new Loader();
}
QString libName()
{
return QString(LIB_NAME) + "_" + QString(LIB_VERSION);
}
Loader::Loader(QObject *parent) : CommandLoader(parent)
{
}
bool Loader::hostRevOk(quint64 minRev, quint16 vMajor, quint16 vMinor, quint16 vPatch)
{
Q_UNUSED(vPatch)
bool ret = false;
if (minRev < IMPORT_REV)
{
err = "This module requires the host to supprt minimum import rev " + QString::number(IMPORT_REV) + " or higher.";
}
else if (vMajor != 1)
{
err = "Host major " + QString::number(vMajor) + " not supported. expected 1.";
}
else if (vMinor < 1)
{
err = "Host minor " + QString::number(vMinor) + " not supported. expected 1 or higher.";
}
else
{
ret = true;
}
return ret;
}
quint64 Loader::rev()
{
return IMPORT_REV;
}
QStringList Loader::cmdList()
{
return QStringList() << "test_text" << "test_input" << "test_loop" << "test_inherit";
}
QString Loader::lastError()
{
return err;
}
ExternCommand *Loader::cmdObj(const QString &name)
{
ExternCommand *ret = nullptr;
if (name == "test_text") ret = new ModText(this);
else if (name == "test_input") ret = new ModInput(this);
else if (name == "test_loop") ret = new ModLoop(this);
else if (name == "test_inherit") ret = new ModInherit(this);
else
{
err = "Command name '" + name + "' does not exists in this module. (" + QString(LIB_NAME) + ")";
}
return ret;
}
ModText::ModText(QObject *parent) : ExternCommand(parent) {}
QString ModText::shortText() {return "test module text output.";}
QString ModText::ioText() {return "[none]/[text]";}
QString ModText::longText() {return "this test the module interface text output. input data is ignored.";}
QString ModText::libText() {return libName();}
ModInput::ModInput(QObject *parent) : ExternCommand(parent) {}
QString ModInput::shortText() {return "test module input hook.";}
QString ModInput::ioText() {return "[text]/[text]";}
QString ModInput::longText() {return "this command will ask you to enter Yes or No and will not release until a valid response is entered. this demonstrates how to impliment a confirmation question using the more input mode.";}
QString ModInput::libText() {return libName();}
ModLoop::ModLoop(QObject *parent) : ExternCommand(parent) {index = 0;}
QString ModLoop::shortText() {return "test module looping command.";}
QString ModLoop::ioText() {return "[none]/[text]";}
QString ModLoop::longText() {return "this command will display 'loop' along with the loop number 10 times to demonstrate looping.";}
QString ModLoop::libText() {return libName();}
ModInherit::ModInherit(QObject *parent) : ExternCommand(parent) {}
QString ModInherit::shortText() {return "module internal command inheritance test.";}
QString ModInherit::ioText() {return "[text]/[text]";}
QString ModInherit::longText() {return "this command will run the output of the known internal command 'my_info' to demonstrate internal command inheritance.";}
QString ModInherit::libText() {return libName();}
void ModText::procBin(const SharedObjs *sharedObjs, const QByteArray &data, uchar dType)
{
Q_UNUSED(data)
Q_UNUSED(dType)
Q_UNUSED(sharedObjs)
// mainTxt() is convenience function that sends a TEXT frame to the CmdExecutor
// object to be processed by the host. it's basically a short hand for the emit
// call:
// emit dataToClient(toTEXT("some text\n"), TEXT);
// errTxt() does the same thing but indicates to the client that it is a error
// message so it can be displayed in a different color, size, logged etc..
// depending on the client.
// emit dataToClient(toTEXT("some error\n"), ERR);
// privTxt() this also does that same thing except it indicates to the client
// that the command is asking for private data like a password, SSN, pin number
// etc.. clients that get this indicator should not echo or display the next
// data frame to be sent back to the host.
// emit dataToClient(toTEXT("enter your password: "), PRIV);
mainTxt("Main text out from module: " + QString(LIB_NAME) + "\n");
errTxt("Error text out from module: " + QString(LIB_NAME) + "\n");
}
void ModInput::procBin(const SharedObjs *sharedObjs, const QByteArray &data, uchar dType)
{
Q_UNUSED(sharedObjs)
if (dType == TEXT)
{
QString text = QTextCodec::codecForName(TXT_CODEC)->toUnicode(data);
if (inMoreInputMode)
{
if (text.isEmpty())
{
errTxt("err: You entered nothing.\n");
}
else
{
if ((text.toLower() == "yes") || (text.toLower() == "no"))
{
// setting moreInput false tells the host that the command
// is no longer asking for more input from the client so the
// host will consider the command finished at this point.
emit enableMoreInput(false);
mainTxt("You entered: '" + text + "' Good bye.\n");
}
else
{
errTxt("err: Invalid response.\n");
}
}
}
else
{
// setting moreInput true tells the host that the command is not
// finished and is awaiting more input from the client. you don't
// need to reimplement term() if all it takes for the command to
// finish its task is to set moreInput and/or loop false; the
// host will do that externally.
emit enableMoreInput(true);
mainTxt("Please enter Yes or No: ");
}
}
}
void ModLoop::term()
{
// this function is called by the host to terminate the command if
// termination is requested and only if the more input or loop modes
// are active.
// this command has a variable called 'index' that the host is not aware
// of and does not have access to it so in this case, index needs reset
// to 0 when the command is requested to terminate.
index = 0;
}
void ModLoop::procBin(const SharedObjs *sharedObjs, const QByteArray &data, uchar dType)
{
Q_UNUSED(data)
Q_UNUSED(dType)
Q_UNUSED(sharedObjs)
// the host will constantly call this function for as long as loop
// mode remains true or if requested to terminate. keep in mind that
// in all subsequent calls after the initial call, the input data will
// always be empty and dType will always default to TEXT.
if (inLoopMode)
{
mainTxt("Loop: " + QString::number(index++) + "\n");
if (index == 10)
{
emit enableLoop(false);
index = 0;
}
}
else
{
emit enableLoop(true);
}
}
QStringList ModInherit::internRequest()
{
return QStringList() << "my_info";
}
void ModInherit::procBin(const SharedObjs *sharedObjs, const QByteArray &data, uchar dType)
{
Q_UNUSED(data)
Q_UNUSED(dType)
if (!internCommands.contains("my_info"))
{
errTxt("err: This command object did not successfully inherit 'my_info' unable to continue.\n");
}
else
{
mainTxt("If inherited correctly, the output of 'my_info' should show below:\n\n");
internCommands["my_info"]->procBin(sharedObjs, QByteArray(), TEXT);
}
}

View File

@ -1,142 +0,0 @@
#ifndef MOD_TESTER_H
#define MOD_TESTER_H
// This file is part of MRCI.
// MRCI 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 3 of the License, or
// (at your option) any later version.
// MRCI 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 MRCI under the LICENSE.md file. If not, see
// <http://www.gnu.org/licenses/>.
#include <QPluginLoader>
#include <QtPlugin>
#include <QObject>
#include "command.h"
#define IMPORT_REV 3
// the import revision is a module compatibility version number
// used by the host to determine if it can successfully load and
// run this library or not. as of right now, the host supports rev1
// and up.
#define LIB_VERSION "1.0.1"
#define LIB_NAME "MRCITestMod"
// the versioning system for the library itself can be completely
// different from the host import revision.
#if defined(MOD_TESTER)
# define MOD_TESTER_EXPORT Q_DECL_EXPORT
#else
# define MOD_TESTER_EXPORT Q_DECL_IMPORT
#endif
extern "C" MOD_TESTER_EXPORT CommandLoader *hostImport();
QString libName();
class Loader : public CommandLoader
{
Q_OBJECT
private:
QString err;
public:
bool hostRevOk(quint64 minRev, quint16 vMajor, quint16 vMinor, quint16 vPatch);
quint64 rev();
ExternCommand *cmdObj(const QString &name);
QStringList cmdList();
QString lastError();
explicit Loader(QObject *parent = nullptr);
};
//-----------------
class ModText : public ExternCommand
{
Q_OBJECT
public:
explicit ModText(QObject *parent = nullptr);
void procBin(const SharedObjs *sharedObjs, const QByteArray &data, uchar dType);
QString shortText();
QString ioText();
QString longText();
QString libText();
};
//--------------------
class ModInput : public ExternCommand
{
Q_OBJECT
public:
explicit ModInput(QObject *parent = nullptr);
void procBin(const SharedObjs *sharedObjs, const QByteArray &data, uchar dType);
QString shortText();
QString ioText();
QString longText();
QString libText();
};
//-----------------------
class ModLoop : public ExternCommand
{
Q_OBJECT
private:
int index;
public:
explicit ModLoop(QObject *parent = nullptr);
void term();
void procBin(const SharedObjs *sharedObjs, const QByteArray &data, uchar dType);
QString shortText();
QString ioText();
QString longText();
QString libText();
};
//--------------------------
class ModInherit : public ExternCommand
{
Q_OBJECT
public:
explicit ModInherit(QObject *parent = nullptr);
void procBin(const SharedObjs *sharedObjs, const QByteArray &data, uchar dType);
QString shortText();
QString ioText();
QString longText();
QString libText();
QStringList internRequest();
};
#endif // MOD_TESTER_H

View File

@ -70,12 +70,13 @@ void IPCWorker::connectIPC()
CmdObject::CmdObject(QObject *parent) : MemShare(parent) CmdObject::CmdObject(QObject *parent) : MemShare(parent)
{ {
flags = 0; flags = 0;
retCode = NO_ERRORS;
QStringList args = QCoreApplication::instance()->arguments(); auto args = QCoreApplication::instance()->arguments();
QString pipe = getParam("-pipe_name", args); auto pipe = getParam("-pipe_name", args);
QString sMemKey = getParam("-mem_ses", args); auto sMemKey = getParam("-mem_ses", args);
QString hMemKey = getParam("-mem_host", args); auto hMemKey = getParam("-mem_host", args);
if (attachSharedMem(sMemKey, hMemKey)) if (attachSharedMem(sMemKey, hMemKey))
{ {
@ -114,7 +115,8 @@ void CmdObject::term()
{ {
if (flags & (MORE_INPUT | HALT_STATE | LOOPING)) if (flags & (MORE_INPUT | HALT_STATE | LOOPING))
{ {
flags = 0; flags = 0;
retCode = ABORTED;
onTerminate(); onTerminate();
postProc(); postProc();
@ -180,7 +182,9 @@ void CmdObject::postProc()
{ {
keepAliveTimer->stop(); keepAliveTimer->stop();
emit procOut(QByteArray(), IDLE); emit procOut(wrInt(retCode, 16), IDLE);
retCode = NO_ERRORS;
} }
} }

View File

@ -67,6 +67,7 @@ protected:
QTimer *keepAliveTimer; QTimer *keepAliveTimer;
IPCWorker *ipcWorker; IPCWorker *ipcWorker;
quint32 flags; quint32 flags;
quint16 retCode;
void mainTxt(const QString &txt); void mainTxt(const QString &txt);
void errTxt(const QString &txt); void errTxt(const QString &txt);

View File

@ -428,7 +428,7 @@ void CmdProcess::onReady()
void CmdProcess::onFailToStart() void CmdProcess::onFailToStart()
{ {
emit dataToClient(cmdId, toTEXT("err: The command failed to start. error details were logged for admin review.\n"), ERR); emit dataToClient(cmdId, toTEXT("err: The command failed to start. error details were logged for admin review.\n"), ERR);
emit dataToClient(cmdId, QByteArray(), IDLE); emit dataToClient(cmdId, wrInt(FAILED_TO_START, 16), IDLE);
} }
void CmdProcess::onFinished(int exitCode, QProcess::ExitStatus exitStatus) void CmdProcess::onFinished(int exitCode, QProcess::ExitStatus exitStatus)
@ -436,7 +436,7 @@ void CmdProcess::onFinished(int exitCode, QProcess::ExitStatus exitStatus)
if (!cmdIdle) if (!cmdIdle)
{ {
emit dataToClient(cmdId, toTEXT("err: The command has stopped unexpectedly or it has failed to send an IDLE frame before exiting.\n"), ERR); emit dataToClient(cmdId, toTEXT("err: The command has stopped unexpectedly or it has failed to send an IDLE frame before exiting.\n"), ERR);
emit dataToClient(cmdId, QByteArray(), IDLE); emit dataToClient(cmdId, wrInt(CRASH, 16), IDLE);
} }
emit cmdProcFinished(cmdId); emit cmdProcFinished(cmdId);
@ -648,9 +648,20 @@ void CmdProcess::onDataFromProc(quint8 typeId, const QByteArray &data)
if (typeId == IDLE) if (typeId == IDLE)
{ {
cmdIdle = true; cmdIdle = true;
}
emit dataToClient(cmdId, data, typeId); if (data.isEmpty())
{
emit dataToClient(cmdId, wrInt(NO_ERRORS, 16), typeId);
}
else
{
emit dataToClient(cmdId, data, typeId);
}
}
else
{
emit dataToClient(cmdId, data, typeId);
}
} }
} }

View File

@ -48,7 +48,7 @@ void delRecoverPw(const QByteArray &uId)
bool expired(const QByteArray &uId) bool expired(const QByteArray &uId)
{ {
bool ret = true; auto ret = true;
Query db; Query db;
@ -57,7 +57,7 @@ bool expired(const QByteArray &uId)
db.addCondition(COLUMN_USER_ID, uId); db.addCondition(COLUMN_USER_ID, uId);
db.exec(); db.exec();
QDateTime expiry = db.getData(COLUMN_TIME).toDateTime().addSecs(3600); // pw datetime + 1hour; auto expiry = db.getData(COLUMN_TIME).toDateTime().addSecs(3600); // pw datetime + 1hour;
if (expiry > QDateTime::currentDateTime().toUTC()) if (expiry > QDateTime::currentDateTime().toUTC())
{ {
@ -88,7 +88,7 @@ void RecoverAcct::addToThreshold()
db.addColumn(COLUMN_LOCK_LIMIT); db.addColumn(COLUMN_LOCK_LIMIT);
db.exec(); db.exec();
quint32 maxAttempts = db.getData(COLUMN_LOCK_LIMIT).toUInt(); auto maxAttempts = db.getData(COLUMN_LOCK_LIMIT).toUInt();
db.setType(Query::PULL, TABLE_AUTH_LOG); db.setType(Query::PULL, TABLE_AUTH_LOG);
db.addColumn(COLUMN_IPADDR); db.addColumn(COLUMN_IPADDR);
@ -107,7 +107,7 @@ void RecoverAcct::addToThreshold()
else else
{ {
errTxt("err: Access denied.\n"); errTxt("err: Access denied.\n");
privTxt("Enter the temporary password: "); privTxt("Enter the temporary password (leave blank to cancel): ");
} }
} }
@ -115,14 +115,21 @@ void RecoverAcct::procIn(const QByteArray &binIn, quint8 dType)
{ {
if ((flags & MORE_INPUT) && (dType == TEXT)) if ((flags & MORE_INPUT) && (dType == TEXT))
{ {
QString pw = fromTEXT(binIn); auto pw = fromTEXT(binIn);
if (inputOk) if (inputOk)
{ {
if (!validPassword(pw)) QString errMsg;
if (pw.isEmpty())
{ {
errTxt("err: Invalid password. it must be 8-200 chars long containing numbers, mixed case letters and special chars.\n"); retCode = ABORTED;
privTxt("Enter a new password: "); flags &= ~MORE_INPUT;
}
else if (!acceptablePw(pw, uId, &errMsg))
{
errTxt(errMsg + "\n");
privTxt("Enter a new password (leave blank to cancel): ");
} }
else else
{ {
@ -136,7 +143,8 @@ void RecoverAcct::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (pw.isEmpty()) if (pw.isEmpty())
{ {
flags &= ~MORE_INPUT; retCode = ABORTED;
flags &= ~MORE_INPUT;
} }
else if (!validPassword(pw)) else if (!validPassword(pw))
{ {
@ -148,7 +156,7 @@ void RecoverAcct::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
privTxt("Enter a new password: "); privTxt("Enter a new password (leave blank to cancel): ");
inputOk = true; inputOk = true;
} }
@ -156,15 +164,17 @@ void RecoverAcct::procIn(const QByteArray &binIn, quint8 dType)
} }
else if (dType == TEXT) else if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 2); auto args = parseArgs(binIn, 2);
QString email = getParam("-email", args); auto email = getParam("-email", args);
QString name = getParam("-user", args); auto name = getParam("-user", args);
if (!email.isEmpty() && validEmailAddr(email)) if (!email.isEmpty() && validEmailAddr(email))
{ {
name = getUserNameForEmail(email); name = getUserNameForEmail(email);
} }
retCode = INVALID_PARAMS;
if (name.isEmpty() || !validUserName(name)) if (name.isEmpty() || !validUserName(name))
{ {
errTxt("err: The -user or -email argument is empty, not found or invalid.\n"); errTxt("err: The -user or -email argument is empty, not found or invalid.\n");
@ -186,6 +196,7 @@ void RecoverAcct::procIn(const QByteArray &binIn, quint8 dType)
privTxt("Enter the temporary password (leave blank to cancel): "); privTxt("Enter the temporary password (leave blank to cancel): ");
inputOk = false; inputOk = false;
retCode = NO_ERRORS;
flags |= MORE_INPUT; flags |= MORE_INPUT;
} }
} }
@ -195,16 +206,19 @@ void ResetPwRequest::procIn(const QByteArray &binIn, uchar dType)
{ {
if (dType == TEXT) if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 2); auto args = parseArgs(binIn, 2);
QString email = getParam("-email", args); auto email = getParam("-email", args);
QString name = getParam("-user", args); auto name = getParam("-user", args);
QByteArray uId;
QByteArray uId;
if (!email.isEmpty() && validEmailAddr(email)) if (!email.isEmpty() && validEmailAddr(email))
{ {
name = getUserNameForEmail(email); name = getUserNameForEmail(email);
} }
retCode = INVALID_PARAMS;
if (name.isEmpty() || !validUserName(name)) if (name.isEmpty() || !validUserName(name))
{ {
errTxt("err: The -user or -email argument is empty, not found or invalid.\n"); errTxt("err: The -user or -email argument is empty, not found or invalid.\n");
@ -215,9 +229,10 @@ void ResetPwRequest::procIn(const QByteArray &binIn, uchar dType)
} }
else else
{ {
QString pw = genPw(); retCode = NO_ERRORS;
QString date = QDateTime::currentDateTimeUtc().toString("YYYY-MM-DD HH:MM:SS");
auto pw = genPw();
if (recoverPWExists(uId)) if (recoverPWExists(uId))
{ {
updatePassword(uId, pw, TABLE_PW_RECOVERY); updatePassword(uId, pw, TABLE_PW_RECOVERY);
@ -236,10 +251,11 @@ void ResetPwRequest::procIn(const QByteArray &binIn, uchar dType)
db.addColumn(COLUMN_MAIL_SEND); db.addColumn(COLUMN_MAIL_SEND);
db.exec(); db.exec();
QString subject = db.getData(COLUMN_TEMP_PW_SUBJECT).toString(); auto date = QDateTime::currentDateTimeUtc().toString("YYYY-MM-DD HH:MM:SS");
QString body = db.getData(COLUMN_TEMP_PW_MSG).toString(); auto subject = db.getData(COLUMN_TEMP_PW_SUBJECT).toString();
QString app = db.getData(COLUMN_MAILERBIN).toString(); auto body = db.getData(COLUMN_TEMP_PW_MSG).toString();
QString cmdLine = db.getData(COLUMN_MAIL_SEND).toString(); auto app = db.getData(COLUMN_MAILERBIN).toString();
auto cmdLine = db.getData(COLUMN_MAIL_SEND).toString();
body.replace(DATE_SUB, date); body.replace(DATE_SUB, date);
body.replace(USERNAME_SUB, name); body.replace(USERNAME_SUB, name);
@ -260,11 +276,12 @@ void VerifyEmail::procIn(const QByteArray &binIn, quint8 dType)
{ {
if ((flags & MORE_INPUT) && (dType == TEXT)) if ((flags & MORE_INPUT) && (dType == TEXT))
{ {
QString txt = fromTEXT(binIn); auto txt = fromTEXT(binIn);
if (txt.isEmpty()) if (txt.isEmpty())
{ {
flags &= ~MORE_INPUT; retCode = ABORTED;
flags &= ~MORE_INPUT;
} }
else if (txt == code) else if (txt == code)
{ {
@ -289,10 +306,12 @@ void VerifyEmail::procIn(const QByteArray &binIn, quint8 dType)
{ {
uId = rdFromBlock(userId, BLKSIZE_USER_ID); uId = rdFromBlock(userId, BLKSIZE_USER_ID);
QString email = getEmailForUser(uId); auto email = getEmailForUser(uId);
if (email.isEmpty()) if (email.isEmpty())
{ {
retCode = INVALID_PARAMS;
errTxt("err: Your account currently has no email address, please update it.\n"); errTxt("err: Your account currently has no email address, please update it.\n");
} }
else else
@ -309,12 +328,12 @@ void VerifyEmail::procIn(const QByteArray &binIn, quint8 dType)
db.addColumn(COLUMN_MAIL_SEND); db.addColumn(COLUMN_MAIL_SEND);
db.exec(); db.exec();
QString uName = rdStringFromBlock(userName, BLKSIZE_USER_NAME); auto uName = rdStringFromBlock(userName, BLKSIZE_USER_NAME);
QString date = QDateTime::currentDateTimeUtc().toString("yyyy-MM-dd HH:mm:ss"); auto date = QDateTime::currentDateTimeUtc().toString("yyyy-MM-dd HH:mm:ss");
QString subject = db.getData(COLUMN_CONFIRM_SUBJECT).toString(); auto subject = db.getData(COLUMN_CONFIRM_SUBJECT).toString();
QString body = db.getData(COLUMN_CONFIRM_MSG).toString(); auto body = db.getData(COLUMN_CONFIRM_MSG).toString();
QString app = db.getData(COLUMN_MAILERBIN).toString(); auto app = db.getData(COLUMN_MAILERBIN).toString();
QString cmdLine = db.getData(COLUMN_MAIL_SEND).toString(); auto cmdLine = db.getData(COLUMN_MAIL_SEND).toString();
body.replace(DATE_SUB, date); body.replace(DATE_SUB, date);
body.replace(USERNAME_SUB, uName); body.replace(USERNAME_SUB, uName);
@ -337,7 +356,7 @@ void IsEmailVerified::procIn(const QByteArray &binIn, quint8 dType)
if (dType == TEXT) if (dType == TEXT)
{ {
QByteArray uId = rdFromBlock(userId, BLKSIZE_USER_ID); auto uId = rdFromBlock(userId, BLKSIZE_USER_ID);
Query db(this); Query db(this);
@ -368,7 +387,7 @@ void SetEmailTemplate::procIn(const QByteArray &binIn, quint8 dType)
} }
else if ((dType == GEN_FILE) || (dType == TEXT)) else if ((dType == GEN_FILE) || (dType == TEXT))
{ {
QStringList args = parseArgs(binIn, 9); auto args = parseArgs(binIn, 9);
dataSent = 0; dataSent = 0;
textFromFile = argExists("-client_file", args); textFromFile = argExists("-client_file", args);
@ -389,6 +408,8 @@ void SetEmailTemplate::procIn(const QByteArray &binIn, quint8 dType)
eType = NONE; eType = NONE;
} }
retCode = INVALID_PARAMS;
if (eType == NONE) if (eType == NONE)
{ {
errTxt("err: Which template do you want to change? -reset_template or -confirm_template not found.\n"); errTxt("err: Which template do you want to change? -reset_template or -confirm_template not found.\n");
@ -407,6 +428,8 @@ void SetEmailTemplate::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
retCode = NO_ERRORS;
if (argExists("-subject", args) && subject.isEmpty()) if (argExists("-subject", args) && subject.isEmpty())
{ {
if (eType == CONFIRM_EMAIL) subject = DEFAULT_CONFIRM_SUBJECT; if (eType == CONFIRM_EMAIL) subject = DEFAULT_CONFIRM_SUBJECT;
@ -442,6 +465,8 @@ void SetEmailTemplate::proc()
{ {
if (bodyText.isEmpty() && subject.isEmpty()) if (bodyText.isEmpty() && subject.isEmpty())
{ {
retCode = INVALID_PARAMS;
errTxt("err: The email body and subject text are empty, nothing will be changed.\n"); errTxt("err: The email body and subject text are empty, nothing will be changed.\n");
} }
else else
@ -453,7 +478,8 @@ void SetEmailTemplate::proc()
QString codeSub; QString codeSub;
QString bodyColumn; QString bodyColumn;
QString subjectColumn; QString subjectColumn;
bool execQuery = false;
auto execQuery = false;
if (eType == PW_RESET) if (eType == PW_RESET)
{ {
@ -470,6 +496,8 @@ void SetEmailTemplate::proc()
if (!bodyText.isEmpty()) if (!bodyText.isEmpty())
{ {
retCode = INVALID_PARAMS;
if (!bodyText.contains(DATE_SUB, Qt::CaseInsensitive)) if (!bodyText.contains(DATE_SUB, Qt::CaseInsensitive))
{ {
errTxt("err: The email body does not contain: " + QString(DATE_SUB) + "\n"); errTxt("err: The email body does not contain: " + QString(DATE_SUB) + "\n");
@ -493,11 +521,14 @@ void SetEmailTemplate::proc()
db.addColumn(bodyColumn, bodyText); db.addColumn(bodyColumn, bodyText);
execQuery = true; execQuery = true;
retCode = NO_ERRORS;
} }
} }
if (!subject.isEmpty()) if (!subject.isEmpty())
{ {
retCode = INVALID_PARAMS;
if (subject.size() > 120) if (subject.size() > 120)
{ {
errTxt("err: The subject is too large. it cannot exceed 120 chars.\n"); errTxt("err: The subject is too large. it cannot exceed 120 chars.\n");
@ -509,6 +540,7 @@ void SetEmailTemplate::proc()
db.addColumn(subjectColumn, subject); db.addColumn(subjectColumn, subject);
execQuery = true; execQuery = true;
retCode = NO_ERRORS;
} }
} }
@ -522,14 +554,16 @@ void PreviewEmail::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (dType == TEXT) if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 4); auto args = parseArgs(binIn, 4);
TemplateType eType = NONE; auto eType = NONE;
if (argExists("-reset_email", args)) eType = PW_RESET; if (argExists("-reset_email", args)) eType = PW_RESET;
else if (argExists("-confirm_email", args)) eType = CONFIRM_EMAIL; else if (argExists("-confirm_email", args)) eType = CONFIRM_EMAIL;
if (eType == NONE) if (eType == NONE)
{ {
retCode = INVALID_PARAMS;
errTxt("err: which template do you want to preview? -reset_email or -confirm_email not found.\n"); errTxt("err: which template do you want to preview? -reset_email or -confirm_email not found.\n");
} }
else else
@ -538,7 +572,8 @@ void PreviewEmail::procIn(const QByteArray &binIn, quint8 dType)
QString code; QString code;
QString bodyColumn; QString bodyColumn;
QString subjectColumn; QString subjectColumn;
QString date = QDateTime::currentDateTimeUtc().toString("yyyy-MM-dd HH:mm:ss");
auto date = QDateTime::currentDateTimeUtc().toString("yyyy-MM-dd HH:mm:ss");
if (eType == PW_RESET) if (eType == PW_RESET)
{ {
@ -562,9 +597,9 @@ void PreviewEmail::procIn(const QByteArray &binIn, quint8 dType)
db.addColumn(subjectColumn); db.addColumn(subjectColumn);
db.exec(); db.exec();
QString uName = rdStringFromBlock(userName, BLKSIZE_USER_NAME); auto uName = rdStringFromBlock(userName, BLKSIZE_USER_NAME);
QString subject = db.getData(subjectColumn).toString(); auto subject = db.getData(subjectColumn).toString();
QString body = db.getData(bodyColumn).toString(); auto body = db.getData(bodyColumn).toString();
body.replace(DATE_SUB, date); body.replace(DATE_SUB, date);
body.replace(USERNAME_SUB, uName); body.replace(USERNAME_SUB, uName);

View File

@ -30,7 +30,7 @@ void CloseHost::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (flags & MORE_INPUT) if (flags & MORE_INPUT)
{ {
QString input = fromTEXT(binIn); auto input = fromTEXT(binIn);
if (input == "CLOSE") if (input == "CLOSE")
{ {
@ -40,7 +40,8 @@ void CloseHost::procIn(const QByteArray &binIn, quint8 dType)
} }
else if (input.isEmpty()) else if (input.isEmpty())
{ {
flags &= ~MORE_INPUT; retCode = ABORTED;
flags &= ~MORE_INPUT;
} }
else else
{ {
@ -63,7 +64,7 @@ void RestartHost::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (flags & MORE_INPUT) if (flags & MORE_INPUT)
{ {
QString input = fromTEXT(binIn); auto input = fromTEXT(binIn);
if (input == "RESTART") if (input == "RESTART")
{ {
@ -73,7 +74,8 @@ void RestartHost::procIn(const QByteArray &binIn, quint8 dType)
} }
else if (input.isEmpty()) else if (input.isEmpty())
{ {
flags &= ~MORE_INPUT; retCode = ABORTED;
flags &= ~MORE_INPUT;
} }
else if (!input.isEmpty()) else if (!input.isEmpty())
{ {
@ -96,7 +98,6 @@ void ServSettings::printSettings()
db.setType(Query::PULL, TABLE_SERV_SETTINGS); db.setType(Query::PULL, TABLE_SERV_SETTINGS);
db.addColumn(COLUMN_PUB_USERS); db.addColumn(COLUMN_PUB_USERS);
db.addColumn(COLUMN_BAN_LIMIT);
db.addColumn(COLUMN_LOCK_LIMIT); db.addColumn(COLUMN_LOCK_LIMIT);
db.addColumn(COLUMN_MAXSESSIONS); db.addColumn(COLUMN_MAXSESSIONS);
db.addColumn(COLUMN_INITRANK); db.addColumn(COLUMN_INITRANK);
@ -108,26 +109,26 @@ void ServSettings::printSettings()
db.addColumn(COLUMN_MAX_SUB_CH); db.addColumn(COLUMN_MAX_SUB_CH);
db.exec(); db.exec();
QString pubBool = boolStr(db.getData(COLUMN_PUB_USERS).toBool()); auto pubBool = boolStr(db.getData(COLUMN_PUB_USERS).toBool());
QString resBool = boolStr(db.getData(COLUMN_ENABLE_PW_RESET).toBool()); auto resBool = boolStr(db.getData(COLUMN_ENABLE_PW_RESET).toBool());
QString conBool = boolStr(db.getData(COLUMN_ENABLE_CONFIRM).toBool()); auto conBool = boolStr(db.getData(COLUMN_ENABLE_CONFIRM).toBool());
QString actBool = boolStr(db.getData(COLUMN_ACTIVE_UPDATE).toBool()); auto actBool = boolStr(db.getData(COLUMN_ACTIVE_UPDATE).toBool());
QString txt; QString txt;
QTextStream txtOut(&txt); QTextStream txtOut(&txt);
txtOut << "All Sub-Channels Active Update: " << actBool << endl; txtOut << "All Sub-Channels Active Update: " << actBool << endl;
txtOut << "Public Registration: " << pubBool << endl; txtOut << "Public Registration: " << pubBool << endl;
txtOut << "Automated Password Resets: " << resBool << endl; txtOut << "Automated Password Resets: " << resBool << endl;
txtOut << "Automated Email Verify: " << conBool << endl; txtOut << "Automated Email Verify: " << conBool << endl;
txtOut << "Maximum Sessions: " << db.getData(COLUMN_MAXSESSIONS).toUInt() << endl; txtOut << "Maximum Sessions: " << db.getData(COLUMN_MAXSESSIONS).toUInt() << endl;
txtOut << "Autoban Threshold: " << db.getData(COLUMN_BAN_LIMIT).toUInt() << endl; txtOut << "Autolock Threshold: " << db.getData(COLUMN_LOCK_LIMIT).toUInt() << endl;
txtOut << "Autolock Threshold: " << db.getData(COLUMN_LOCK_LIMIT).toUInt() << endl; txtOut << "Maximum Sub-Channels: " << db.getData(COLUMN_MAX_SUB_CH).toUInt() << endl;
txtOut << "Maximum Sub-Channels: " << db.getData(COLUMN_MAX_SUB_CH).toUInt() << endl; txtOut << "Initial Host Rank: " << db.getData(COLUMN_INITRANK).toUInt() << endl;
txtOut << "Initial Host Rank: " << db.getData(COLUMN_INITRANK).toUInt() << endl; txtOut << "Root User: " << getUserName(rootUserId()) << endl;
txtOut << "Database Path: " << sqlDataPath() << endl; txtOut << "Database Path: " << sqlDataPath() << endl;
txtOut << "Mailer Executable: " << db.getData(COLUMN_MAILERBIN).toString() << endl; txtOut << "Mailer Executable: " << db.getData(COLUMN_MAILERBIN).toString() << endl;
txtOut << "Mailer Command: " << db.getData(COLUMN_MAIL_SEND).toString() << endl << endl; txtOut << "Mailer Command: " << db.getData(COLUMN_MAIL_SEND).toString() << endl << endl;
mainTxt(txt); mainTxt(txt);
} }
@ -139,12 +140,12 @@ void ServSettings::printOptions()
QString txt; QString txt;
QTextStream txtOut(&txt); QTextStream txtOut(&txt);
txtOut << "[01] Autoban Threshold [02] Autolock Threshold" << endl; txtOut << "[01] Autolock Threshold [02] Max Sessions" << endl;
txtOut << "[03] Max Sessions [04] Public Registration" << endl; txtOut << "[03] Public Registration [04] Initial Rank" << endl;
txtOut << "[05] Initial Rank [06] Mailer Exe" << endl; txtOut << "[05] Mailer Exe [06] Mailer Command" << endl;
txtOut << "[07] Mailer Command [08] Password Resets" << endl; txtOut << "[07] Password Resets [08] Email Verify" << endl;
txtOut << "[09] Email Verify [10] Active Update" << endl; txtOut << "[09] Active Update [10] Max Sub-Channels" << endl;
txtOut << "[11] Max Sub-Channels [00] Exit" << endl << endl; txtOut << "[11] Set Root User [00] Exit" << endl << endl;
txtOut << "Select an option: "; txtOut << "Select an option: ";
level = 1; level = 1;
@ -174,33 +175,21 @@ void ServSettings::procIn(const QByteArray &binIn, quint8 dType)
QString txt; QString txt;
QTextStream txtOut(&txt); QTextStream txtOut(&txt);
bool ok = false; auto ok = false;
select = fromTEXT(binIn).toInt(&ok); select = fromTEXT(binIn).toInt(&ok);
if ((select == 1) && ok) if ((select == 1) && ok)
{ {
txtOut << "" << endl; txtOut << "" << endl;
txtOut << "The autoban threshold is an integar value that determines how many" << endl; txtOut << "The autolock threshold is an integer value that determines how many" << endl;
txtOut << "failed login attempts can be made to the " << ROOT_USER << " user before the" << endl; txtOut << "failed login attempts can be made before the user account is locked" << endl;
txtOut << "offending ip address is blocked by the host." << endl << endl; txtOut << "by the host." << endl << endl;
txtOut << "Enter a new value (leave blank to cancel): "; txtOut << "Enter a new value (leave blank to cancel): ";
level = 2; level = 2;
} }
else if ((select == 2) && ok) else if ((select == 2) && ok)
{
txtOut << "" << endl;
txtOut << "The autolock threshold is an integer value that determines how many" << endl;
txtOut << "failed login attempts can be made before the user account is locked" << endl;
txtOut << "by the host." << endl << endl;
txtOut << "note: the " << ROOT_USER << " user never gets locked. instead, the offenders are blocked" << endl;
txtOut << " by ip address according to the autoban threshold." << endl << endl;
txtOut << "Enter a new value (leave blank to cancel): ";
level = 2;
}
else if ((select == 3) && ok)
{ {
txtOut << "" << endl; txtOut << "" << endl;
txtOut << "Max sessions is an integar value that determines how many simultaneous" << endl; txtOut << "Max sessions is an integar value that determines how many simultaneous" << endl;
@ -209,11 +198,11 @@ void ServSettings::procIn(const QByteArray &binIn, quint8 dType)
level = 2; level = 2;
} }
else if ((select == 4) && ok) else if ((select == 3) && ok)
{ {
txtOut << "" << endl; txtOut << "" << endl;
txtOut << "Public registration basically allows un-logged in clients to run the" << endl; txtOut << "Public registration basically allows un-logged in clients to run the" << endl;
txtOut << "new_user command. doing this allows un-registered users to become" << endl; txtOut << "add_acct command. doing this allows un-registered users to become" << endl;
txtOut << "registered users without the need to contact an admin." << endl << endl; txtOut << "registered users without the need to contact an admin." << endl << endl;
txtOut << "[0] Disable" << endl; txtOut << "[0] Disable" << endl;
txtOut << "[1] Enable" << endl << endl; txtOut << "[1] Enable" << endl << endl;
@ -221,7 +210,7 @@ void ServSettings::procIn(const QByteArray &binIn, quint8 dType)
level = 2; level = 2;
} }
else if ((select == 5) && ok) else if ((select == 4) && ok)
{ {
txtOut << "" << endl; txtOut << "" << endl;
txtOut << "The initial host rank is the rank all new user accounts are registered" << endl; txtOut << "The initial host rank is the rank all new user accounts are registered" << endl;
@ -231,7 +220,7 @@ void ServSettings::procIn(const QByteArray &binIn, quint8 dType)
level = 2; level = 2;
} }
else if ((select == 6) && ok) else if ((select == 5) && ok)
{ {
txtOut << "" << endl; txtOut << "" << endl;
txtOut << "This is the path to the command line email client executable" << endl; txtOut << "This is the path to the command line email client executable" << endl;
@ -242,7 +231,7 @@ void ServSettings::procIn(const QByteArray &binIn, quint8 dType)
level = 2; level = 2;
} }
else if ((select == 7) && ok) else if ((select == 6) && ok)
{ {
txtOut << "" << endl; txtOut << "" << endl;
txtOut << "This is the command line that will be used with the email client" << endl; txtOut << "This is the command line that will be used with the email client" << endl;
@ -254,31 +243,32 @@ void ServSettings::procIn(const QByteArray &binIn, quint8 dType)
level = 2; level = 2;
} }
else if ((select == 8) && ok) else if ((select == 7) && ok)
{ {
txtOut << "" << endl; txtOut << "" << endl;
txtOut << "This enables automated password resets via email so users can" << endl; txtOut << "This enables automated password resets via email so users can" << endl;
txtOut << "reset their account passwords without the need to contact an" << endl; txtOut << "reset their account passwords without the need to contact an" << endl;
txtOut << "admin. this basically tells the host if it is allowed to load" << endl; txtOut << "admin. this basically tells the host if it is allowed to load" << endl;
txtOut << "the request_pw_reset and recover_account commands or not." << endl << endl; txtOut << "the request_pw_reset and recover_acct commands or not." << endl << endl;
txtOut << "[0] Disable" << endl; txtOut << "[0] Disable" << endl;
txtOut << "[1] Enable" << endl << endl; txtOut << "[1] Enable" << endl << endl;
txtOut << "Select an option (leave blank to cancel): "; txtOut << "Select an option (leave blank to cancel): ";
level = 2; level = 2;
} }
else if ((select == 9) && ok) else if ((select == 8) && ok)
{ {
txtOut << "" << endl; txtOut << "" << endl;
txtOut << "This enables automated email confirmations. this tells the" << endl; txtOut << "This enables/disables automated email confirmations. this" << endl;
txtOut << "host if it is allowed to load the confirm_email command." << endl << endl; txtOut << "tells the host if it is allowed to load the verify_email " << endl;
txtOut << "[0] Disable" << endl; txtOut << "command for any user, regardless of rank." << endl << endl;
txtOut << "[1] Enable" << endl << endl; txtOut << "[0] Disable" << endl;
txtOut << "[1] Enable" << endl << endl;
txtOut << "Select an option (leave blank to cancel): "; txtOut << "Select an option (leave blank to cancel): ";
level = 2; level = 2;
} }
else if ((select == 10) && ok) else if ((select == 9) && ok)
{ {
txtOut << "" << endl; txtOut << "" << endl;
txtOut << "This option tells the host if all sub-channels should be considered" << endl; txtOut << "This option tells the host if all sub-channels should be considered" << endl;
@ -293,7 +283,7 @@ void ServSettings::procIn(const QByteArray &binIn, quint8 dType)
level = 2; level = 2;
} }
else if ((select == 11) && ok) else if ((select == 10) && ok)
{ {
txtOut << "" << endl; txtOut << "" << endl;
txtOut << "This option sets the maximum amount of sub-channels each channel can" << endl; txtOut << "This option sets the maximum amount of sub-channels each channel can" << endl;
@ -302,6 +292,27 @@ void ServSettings::procIn(const QByteArray &binIn, quint8 dType)
level = 2; level = 2;
} }
else if ((select == 11) && ok)
{
txtOut << "" << endl;
txtOut << "Set the root user of the host by the given user name. the root user" << endl;
txtOut << "is an unrestricted user that can do anything on the host. this user" << endl;
txtOut << "however is unable to change rank (1) and cannot get deleted. only" << endl;
txtOut << "the current root user can use this option to appoint an existing" << endl;
txtOut << "user as the new root." << endl << endl;
if (rdFromBlock(userId, BLKSIZE_USER_ID) != rootUserId())
{
txtOut << "Enter a new user name (leave blank to cancel): ";
}
else
{
txtOut << "You are not the current root user so this option is blocked." << endl;
txtOut << "Press enter to return to the main menu.";
}
level = 2;
}
else if ((select == 0) && ok) else if ((select == 0) && ok)
{ {
flags &= ~MORE_INPUT; flags &= ~MORE_INPUT;
@ -315,7 +326,7 @@ void ServSettings::procIn(const QByteArray &binIn, quint8 dType)
} }
else if (level == 2) else if (level == 2)
{ {
QString value = fromTEXT(binIn); auto value = fromTEXT(binIn);
if (value.isEmpty()) if (value.isEmpty())
{ {
@ -324,7 +335,7 @@ void ServSettings::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
if ((select == 1) || (select == 2) || (select == 3) || (select == 5)) if ((select == 1) || (select == 2) || (select == 4))
{ {
bool ok; bool ok;
quint32 num = value.toUInt(&ok, 10); quint32 num = value.toUInt(&ok, 10);
@ -345,14 +356,13 @@ void ServSettings::procIn(const QByteArray &binIn, quint8 dType)
db.setType(Query::UPDATE, TABLE_SERV_SETTINGS); db.setType(Query::UPDATE, TABLE_SERV_SETTINGS);
if (select == 1) db.addColumn(COLUMN_BAN_LIMIT, num); if (select == 1) db.addColumn(COLUMN_LOCK_LIMIT, num);
else if (select == 2) db.addColumn(COLUMN_LOCK_LIMIT, num); else if (select == 2) db.addColumn(COLUMN_MAXSESSIONS, num);
else if (select == 3) db.addColumn(COLUMN_MAXSESSIONS, num);
else db.addColumn(COLUMN_INITRANK, num); else db.addColumn(COLUMN_INITRANK, num);
db.exec(); db.exec();
if (select == 3) if (select == 2)
{ {
async(ASYNC_MAXSES, PRIV_IPC, wrInt(num, BLKSIZE_HOST_LOAD * 8)); async(ASYNC_MAXSES, PRIV_IPC, wrInt(num, BLKSIZE_HOST_LOAD * 8));
} }
@ -360,7 +370,7 @@ void ServSettings::procIn(const QByteArray &binIn, quint8 dType)
returnToStart(); returnToStart();
} }
} }
else if ((select == 4) || (select == 8) || (select == 9) || (select == 10)) else if ((select == 3) || (select == 7) || (select == 8) || (select == 9))
{ {
if (!isBool(value)) if (!isBool(value))
{ {
@ -371,9 +381,9 @@ void ServSettings::procIn(const QByteArray &binIn, quint8 dType)
{ {
QString column; QString column;
if (select == 4) column = COLUMN_PUB_USERS; if (select == 3) column = COLUMN_PUB_USERS;
else if (select == 8) column = COLUMN_ENABLE_PW_RESET; else if (select == 7) column = COLUMN_ENABLE_PW_RESET;
else if (select == 9) column = COLUMN_ENABLE_CONFIRM; else if (select == 8) column = COLUMN_ENABLE_CONFIRM;
else column = COLUMN_ACTIVE_UPDATE; else column = COLUMN_ACTIVE_UPDATE;
Query db(this); Query db(this);
@ -385,7 +395,7 @@ void ServSettings::procIn(const QByteArray &binIn, quint8 dType)
returnToStart(); returnToStart();
} }
} }
else if (select == 6) else if (select == 5)
{ {
if (!QFile::exists(expandEnvVariables(value))) if (!QFile::exists(expandEnvVariables(value)))
{ {
@ -403,7 +413,7 @@ void ServSettings::procIn(const QByteArray &binIn, quint8 dType)
returnToStart(); returnToStart();
} }
} }
else if (select == 7) else if (select == 6)
{ {
if (!value.contains(SUBJECT_SUB, Qt::CaseInsensitive)) if (!value.contains(SUBJECT_SUB, Qt::CaseInsensitive))
{ {
@ -431,7 +441,7 @@ void ServSettings::procIn(const QByteArray &binIn, quint8 dType)
returnToStart(); returnToStart();
} }
} }
else if (select == 11) else if (select == 10)
{ {
if (!isInt(value)) if (!isInt(value))
{ {
@ -451,6 +461,35 @@ void ServSettings::procIn(const QByteArray &binIn, quint8 dType)
db.addColumn(COLUMN_MAX_SUB_CH, value.toInt()); db.addColumn(COLUMN_MAX_SUB_CH, value.toInt());
db.exec(); db.exec();
returnToStart();
}
}
else if (select == 11)
{
QByteArray uId;
if (rdFromBlock(userId, BLKSIZE_USER_ID) != rootUserId())
{
returnToStart();
}
else if (!validUserName(value))
{
errTxt("err: Invalid user name. it must be 2-24 chars long and contain no spaces.\n");
mainTxt("Enter a new user name (leave blank to cancel): ");
}
else if (!userExists(value, &uId))
{
errTxt("err: The requested user name does not exists.\n");
mainTxt("Enter a new user name (leave blank to cancel): ");
}
else
{
Query db(this);
db.setType(Query::UPDATE, TABLE_SERV_SETTINGS);
db.addColumn(COLUMN_ROOT_USER, value);
db.exec();
returnToStart(); returnToStart();
} }
} }

View File

@ -48,26 +48,10 @@ void Auth::addToThreshold()
db.exec(); db.exec();
db.setType(Query::PULL, TABLE_SERV_SETTINGS); db.setType(Query::PULL, TABLE_SERV_SETTINGS);
db.addColumn(COLUMN_LOCK_LIMIT);
db.exec();
quint32 maxAttempts = 0; auto maxAttempts = db.getData(COLUMN_LOCK_LIMIT).toUInt();
bool isRoot = false;
if (noCaseMatch(ROOT_USER, uName))
{
isRoot = true;
db.addColumn(COLUMN_BAN_LIMIT);
db.exec();
maxAttempts = db.getData(COLUMN_BAN_LIMIT).toUInt();
}
else
{
db.addColumn(COLUMN_LOCK_LIMIT);
db.exec();
maxAttempts = db.getData(COLUMN_LOCK_LIMIT).toUInt();
}
db.setType(Query::PULL, TABLE_AUTH_LOG); db.setType(Query::PULL, TABLE_AUTH_LOG);
db.addColumn(COLUMN_IPADDR); db.addColumn(COLUMN_IPADDR);
@ -75,32 +59,14 @@ void Auth::addToThreshold()
db.addCondition(COLUMN_AUTH_ATTEMPT, true); db.addCondition(COLUMN_AUTH_ATTEMPT, true);
db.addCondition(COLUMN_COUNT, true); db.addCondition(COLUMN_COUNT, true);
db.addCondition(COLUMN_ACCEPTED, false); db.addCondition(COLUMN_ACCEPTED, false);
if (isRoot) db.addCondition(COLUMN_IPADDR, ip);
db.exec(); db.exec();
if (static_cast<quint32>(db.rows()) > maxAttempts) if (static_cast<quint32>(db.rows()) > maxAttempts)
{ {
if (isRoot) db.setType(Query::UPDATE, TABLE_USERS);
{ db.addColumn(COLUMN_LOCKED, true);
if (!QHostAddress(ip).isLoopback()) db.addCondition(COLUMN_USER_ID, uId);
{ db.exec();
db.setType(Query::PUSH, TABLE_IPBANS);
db.addColumn(COLUMN_IPADDR, ip);
db.exec();
async(ASYNC_UPDATE_BANS, PRIV_IPC);
async(ASYNC_END_SESSION, PRIV_IPC);
}
}
else
{
db.setType(Query::UPDATE, TABLE_USERS);
db.addColumn(COLUMN_LOCKED, true);
db.addCondition(COLUMN_USER_ID, uId);
db.exec();
}
flags &= ~MORE_INPUT; flags &= ~MORE_INPUT;
} }
@ -121,7 +87,7 @@ void Auth::confirmAuth()
db.addCondition(COLUMN_USER_ID, uId); db.addCondition(COLUMN_USER_ID, uId);
db.addCondition(COLUMN_AUTH_ATTEMPT, true); db.addCondition(COLUMN_AUTH_ATTEMPT, true);
if (noCaseMatch(ROOT_USER, uName)) if (rootUserId() == uId)
{ {
db.addCondition(COLUMN_IPADDR, ip); db.addCondition(COLUMN_IPADDR, ip);
} }
@ -155,15 +121,18 @@ void Auth::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (newPassword) if (newPassword)
{ {
QString errMsg;
if (text.isEmpty()) if (text.isEmpty())
{ {
mainTxt("\n"); mainTxt("\n");
flags &= ~MORE_INPUT; flags &= ~MORE_INPUT;
retCode = ABORTED;
} }
else if (!validPassword(text)) else if (!acceptablePw(text, uId, &errMsg))
{ {
errTxt("err: Invalid password. it must be 8-200 chars long containing numbers, mixed case letters and special chars.\n\n"); errTxt(errMsg + "\n");
privTxt("Enter a new password (leave blank to cancel): "); privTxt("Enter a new password (leave blank to cancel): ");
} }
else else
@ -195,16 +164,32 @@ void Auth::procIn(const QByteArray &binIn, quint8 dType)
{ {
mainTxt("\n"); mainTxt("\n");
flags &= ~MORE_INPUT; flags &= ~MORE_INPUT;
retCode = ABORTED;
}
else if (noCaseMatch(DEFAULT_ROOT_USER, text))
{
errTxt("err: '" + QString(DEFAULT_ROOT_USER) + "' is a reserved keyword. invalid for use as a user name.\n");
mainTxt("Enter a new user name (leave blank to cancel): ");
}
else if (validEmailAddr(text))
{
errTxt("err: Invaild use rname. it looks like an email address.\n");
mainTxt("Enter a new user name (leave blank to cancel): ");
} }
else if (!validUserName(text)) else if (!validUserName(text))
{ {
errTxt("err: Invalid username. it must be 2-24 chars long and contain no spaces.\n\n"); errTxt("err: Invalid user name. it must be 2-24 chars long and contain no spaces.\n\n");
mainTxt("Enter a new user name (leave blank to cancel): "); mainTxt("Enter a new user name (leave blank to cancel): ");
} }
else if (!userExists(text)) else if (noCaseMatch(text, uName))
{ {
errTxt("err: The requested User name already exists.\n\n"); errTxt("err: You cannot re-apply your old user name.\n\n");
mainTxt("Enter a new user name (leave blank to cancel): ");
}
else if (userExists(text))
{
errTxt("err: The requested user name already exists.\n\n");
mainTxt("Enter a new user name (leave blank to cancel): "); mainTxt("Enter a new user name (leave blank to cancel): ");
} }
else else
@ -230,7 +215,8 @@ void Auth::procIn(const QByteArray &binIn, quint8 dType)
{ {
mainTxt("\n"); mainTxt("\n");
flags &= ~MORE_INPUT; flags &= ~MORE_INPUT;
retCode = ABORTED;
} }
else if (!validPassword(text)) else if (!validPassword(text))
{ {
@ -260,15 +246,17 @@ void Auth::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
QStringList args = parseArgs(binIn, 2); auto args = parseArgs(binIn, 2);
QString email = getParam("-email", args); auto email = getParam("-email", args);
QString name = getParam("-user", args); auto name = getParam("-user", args);
if (!email.isEmpty() && validEmailAddr(email)) if (!email.isEmpty() && validEmailAddr(email))
{ {
name = getUserNameForEmail(email); name = getUserNameForEmail(email);
} }
retCode = INVALID_PARAMS;
if (name.isEmpty() || !validUserName(name)) if (name.isEmpty() || !validUserName(name))
{ {
errTxt("err: The -user or -email argument is empty, not found or invalid.\n"); errTxt("err: The -user or -email argument is empty, not found or invalid.\n");
@ -294,6 +282,7 @@ void Auth::procIn(const QByteArray &binIn, quint8 dType)
loginOk = false; loginOk = false;
uName = name; uName = name;
retCode = NO_ERRORS;
flags |= MORE_INPUT; flags |= MORE_INPUT;
ip = rdStringFromBlock(clientIp, BLKSIZE_CLIENT_IP); ip = rdStringFromBlock(clientIp, BLKSIZE_CLIENT_IP);
newPassword = db.getData(COLUMN_NEED_PASS).toBool(); newPassword = db.getData(COLUMN_NEED_PASS).toBool();

View File

@ -1,96 +0,0 @@
#include "bans.h"
// This file is part of MRCI.
// MRCI 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 3 of the License, or
// (at your option) any later version.
// MRCI 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 MRCI under the LICENSE.md file. If not, see
// <http://www.gnu.org/licenses/>.
ListBans::ListBans(QObject *parent) : TableViewer(parent)
{
setParams(TABLE_IPBANS, true);
addTableColumn(TABLE_IPBANS, COLUMN_TIME);
addTableColumn(TABLE_IPBANS, COLUMN_IPADDR);
}
BanIP::BanIP(QObject *parent) : CmdObject(parent) {}
UnBanIP::UnBanIP(QObject *parent) : CmdObject(parent) {}
QString ListBans::cmdName() {return "ls_bans";}
QString BanIP::cmdName() {return "add_ban";}
QString UnBanIP::cmdName() {return "rm_ban";}
void ListBans::onDel()
{
async(ASYNC_UPDATE_BANS, PRIV_IPC);
}
void BanIP::procIn(const QByteArray &binIn, quint8 dType)
{
if (dType == TEXT)
{
QStringList args = parseArgs(binIn, 2);
QString ip = getParam("-ip", args);
if (ip.isEmpty())
{
errTxt("err: The ip address argument (-ip) was not found or is empty.\n");
}
else if (!QHostAddress().setAddress(ip))
{
errTxt("err: '" + ip + "' is not a valid ip address.\n");
}
else
{
QHostAddress addr(ip);
Query db(this);
db.setType(Query::PUSH, TABLE_IPBANS);
db.addColumn(COLUMN_IPADDR, addr.toString());
db.exec();
async(ASYNC_UPDATE_BANS, PRIV_IPC);
}
}
}
void UnBanIP::procIn(const QByteArray &binIn, quint8 dType)
{
if (dType == TEXT)
{
QStringList args = parseArgs(binIn, 2);
QString ip = getParam("-ip", args);
if (ip.isEmpty())
{
errTxt("err: The ip address argument (-ip) was not found or is empty.\n");
}
else if (!QHostAddress().setAddress(ip))
{
errTxt("err: '" + ip + "' is not a valid ip address.\n");
}
else
{
QHostAddress addr(ip);
Query db;
db.setType(Query::DEL, TABLE_IPBANS);
db.addCondition(COLUMN_IPADDR, addr.toString());
db.exec();
async(ASYNC_UPDATE_BANS, PRIV_IPC);
}
}
}

View File

@ -1,69 +0,0 @@
#ifndef BAN_CMDS_H
#define BAN_CMDS_H
// This file is part of MRCI.
// MRCI 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 3 of the License, or
// (at your option) any later version.
// MRCI 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 MRCI under the LICENSE.md file. If not, see
// <http://www.gnu.org/licenses/>.
#include "../common.h"
#include "../cmd_object.h"
#include "table_viewer.h"
class ListBans : public TableViewer
{
Q_OBJECT
private:
void onDel();
public:
static QString cmdName();
explicit ListBans(QObject *parent = nullptr);
};
//---------------------------------
class BanIP : public CmdObject
{
Q_OBJECT
public:
static QString cmdName();
void procIn(const QByteArray &binIn, quint8 dType);
explicit BanIP(QObject *parent = nullptr);
};
//--------------------------------
class UnBanIP : public CmdObject
{
Q_OBJECT
public:
static QString cmdName();
void procIn(const QByteArray &binIn, quint8 dType);
explicit UnBanIP(QObject *parent = nullptr);
};
#endif // BAN_CMDS_H

View File

@ -45,15 +45,15 @@ QString ListRDonlyFlags::cmdName() {return "ls_rdonly_flags";}
bool canOpenSubChannel(const QByteArray &uId, const char *override, quint64 chId, quint8 subId) bool canOpenSubChannel(const QByteArray &uId, const char *override, quint64 chId, quint8 subId)
{ {
int uLevel = channelAccessLevel(uId, override, chId); auto uLevel = channelAccessLevel(uId, override, chId);
int sLevel = lowestAcessLevel(chId, subId); auto sLevel = lowestAcessLevel(chId, subId);
return uLevel <= sLevel; return uLevel <= sLevel;
} }
int lowestAcessLevel(quint64 chId, quint8 subId) int lowestAcessLevel(quint64 chId, quint8 subId)
{ {
int ret = 5000; auto ret = 5000;
Query db; Query db;
@ -80,11 +80,14 @@ void OpenSubChannel::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (dType == TEXT) if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 4); auto args = parseArgs(binIn, 4);
QString ch = getParam("-ch_name", args); auto ch = getParam("-ch_name", args);
QString sub = getParam("-sub_name", args); auto sub = getParam("-sub_name", args);
quint64 chId;
quint8 subId; quint64 chId;
quint8 subId;
retCode = INVALID_PARAMS;
if (ch.isEmpty()) if (ch.isEmpty())
{ {
@ -108,6 +111,8 @@ void OpenSubChannel::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
retCode = NO_ERRORS;
async(ASYNC_OPEN_SUBCH, PRIV_IPC, wrInt(chId, 64) + wrInt(subId, 8)); async(ASYNC_OPEN_SUBCH, PRIV_IPC, wrInt(chId, 64) + wrInt(subId, 8));
} }
} }
@ -117,11 +122,14 @@ void CloseSubChannel::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (dType == TEXT) if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 4); auto args = parseArgs(binIn, 4);
QString ch = getParam("-ch_name", args); auto ch = getParam("-ch_name", args);
QString sub = getParam("-sub_name", args); auto sub = getParam("-sub_name", args);
quint64 chId;
quint8 subId; quint64 chId;
quint8 subId;
retCode = INVALID_PARAMS;
if (ch.isEmpty()) if (ch.isEmpty())
{ {
@ -141,6 +149,8 @@ void CloseSubChannel::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
retCode = NO_ERRORS;
async(ASYNC_CLOSE_SUBCH, PRIV_IPC, wrInt(chId, 64) + wrInt(subId, 8)); async(ASYNC_CLOSE_SUBCH, PRIV_IPC, wrInt(chId, 64) + wrInt(subId, 8));
} }
} }
@ -168,8 +178,8 @@ void LsOpenChannels::procIn(const QByteArray &binIn, quint8 dType)
for (int i = 0; i < MAX_OPEN_SUB_CHANNELS; i += BLKSIZE_SUB_CHANNEL) for (int i = 0; i < MAX_OPEN_SUB_CHANNELS; i += BLKSIZE_SUB_CHANNEL)
{ {
quint64 chId = rd64BitFromBlock(openSubChs + i); auto chId = rd64BitFromBlock(openSubChs + i);
quint8 subId = rd8BitFromBlock(openSubChs + (i + 8)); auto subId = rd8BitFromBlock(openSubChs + (i + 8));
if (chId) if (chId)
{ {
@ -183,8 +193,9 @@ void LsOpenChannels::procIn(const QByteArray &binIn, quint8 dType)
db.addCondition(COLUMN_SUB_CH_ID, subId); db.addCondition(COLUMN_SUB_CH_ID, subId);
db.exec(); db.exec();
QString chName = db.getData(COLUMN_CHANNEL_NAME).toString(); auto chName = db.getData(COLUMN_CHANNEL_NAME).toString();
QString subName = db.getData(COLUMN_SUB_CH_NAME).toString(); auto subName = db.getData(COLUMN_SUB_CH_NAME).toString();
QString rdOnly; QString rdOnly;
if (posOfBlock(openSubChs + i, openWritableSubChs, MAX_OPEN_SUB_CHANNELS, BLKSIZE_SUB_CHANNEL) == -1) if (posOfBlock(openSubChs + i, openWritableSubChs, MAX_OPEN_SUB_CHANNELS, BLKSIZE_SUB_CHANNEL) == -1)
@ -233,6 +244,8 @@ void PingPeers::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (rd8BitFromBlock(activeUpdate) == 0) if (rd8BitFromBlock(activeUpdate) == 0)
{ {
retCode = INVALID_PARAMS;
errTxt("err: You don't currently have any active update sub-channels open. sending a ping request is pointless because peers won't be able to respond.\n"); errTxt("err: You don't currently have any active update sub-channels open. sending a ping request is pointless because peers won't be able to respond.\n");
} }
else else
@ -246,11 +259,14 @@ void AddRDOnlyFlag::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (dType == TEXT) if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 6); auto args = parseArgs(binIn, 6);
QString chName = getParam("-ch_name", args); auto chName = getParam("-ch_name", args);
QString subId = getParam("-sub_id", args); auto subId = getParam("-sub_id", args);
QString level = getParam("-level", args); auto level = getParam("-level", args);
quint64 chId;
quint64 chId;
retCode = INVALID_PARAMS;
if (chName.isEmpty()) if (chName.isEmpty())
{ {
@ -290,7 +306,9 @@ void AddRDOnlyFlag::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
QByteArray frame = wrInt(chId, 64) + wrInt(subId.toUInt(), 8) + wrInt(level.toUInt(), 8); retCode = NO_ERRORS;
auto frame = wrInt(chId, 64) + wrInt(subId.toUInt(), 8) + wrInt(level.toUInt(), 8);
Query db(this); Query db(this);
@ -309,11 +327,14 @@ void RemoveRDOnlyFlag::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (dType == TEXT) if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 6); auto args = parseArgs(binIn, 6);
QString chName = getParam("-ch_name", args); auto chName = getParam("-ch_name", args);
QString subId = getParam("-sub_id", args); auto subId = getParam("-sub_id", args);
QString level = getParam("-level", args); auto level = getParam("-level", args);
quint64 chId;
quint64 chId;
retCode = INVALID_PARAMS;
if (chName.isEmpty()) if (chName.isEmpty())
{ {
@ -353,7 +374,9 @@ void RemoveRDOnlyFlag::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
QByteArray frame = wrInt(chId, 64) + wrInt(subId.toUInt(), 8) + wrInt(level.toUInt(), 8); retCode = NO_ERRORS;
auto frame = wrInt(chId, 64) + wrInt(subId.toUInt(), 8) + wrInt(level.toUInt(), 8);
Query db(this); Query db(this);
@ -378,9 +401,12 @@ void ListRDonlyFlags::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
QStringList args = parseArgs(binIn, 2); auto args = parseArgs(binIn, 2);
QString chName = getParam("-ch_name", args); auto chName = getParam("-ch_name", args);
quint64 chId;
quint64 chId;
retCode = INVALID_PARAMS;
if (chName.isEmpty()) if (chName.isEmpty())
{ {
@ -396,6 +422,8 @@ void ListRDonlyFlags::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
retCode = NO_ERRORS;
if (channelAccessLevel(rdFromBlock(userId, BLKSIZE_USER_ID), chOwnerOverride, chId) > REGULAR) if (channelAccessLevel(rdFromBlock(userId, BLKSIZE_USER_ID), chOwnerOverride, chId) > REGULAR)
{ {
TableViewer::procIn(toTEXT("-" + QString(COLUMN_CHANNEL_NAME) + " " + chName + " -" + QString(COLUMN_LOWEST_LEVEL) + " " + QString::number(PUBLIC)), dType); TableViewer::procIn(toTEXT("-" + QString(COLUMN_CHANNEL_NAME) + " " + chName + " -" + QString(COLUMN_LOWEST_LEVEL) + " " + QString::number(PUBLIC)), dType);

View File

@ -35,8 +35,10 @@ void CertInfo::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (dType == TEXT) if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 2); auto args = parseArgs(binIn, 2);
QString coName = getParam("-name", args); auto coName = getParam("-name", args);
retCode = INVALID_PARAMS;
if (coName.isEmpty()) if (coName.isEmpty())
{ {
@ -52,6 +54,8 @@ void CertInfo::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
retCode = NO_ERRORS;
QString txt; QString txt;
QTextStream txtOut(&txt); QTextStream txtOut(&txt);
@ -62,7 +66,7 @@ void CertInfo::procIn(const QByteArray &binIn, quint8 dType)
db.addCondition(COLUMN_COMMON_NAME, coName); db.addCondition(COLUMN_COMMON_NAME, coName);
db.exec(); db.exec();
QSslCertificate cert = toSSLCert(db.getData(COLUMN_CERT).toByteArray()); auto cert = toSSLCert(db.getData(COLUMN_CERT).toByteArray());
txtOut << "Self Signed: " << boolStr(cert.isSelfSigned()) << endl; txtOut << "Self Signed: " << boolStr(cert.isSelfSigned()) << endl;
txtOut << "Black Listed: " << boolStr(cert.isBlacklisted()) << endl; txtOut << "Black Listed: " << boolStr(cert.isBlacklisted()) << endl;
@ -98,11 +102,12 @@ void AddCert::procIn(const QByteArray &binIn, quint8 dType)
{ {
if ((dType == TEXT) && (flags & MORE_INPUT)) if ((dType == TEXT) && (flags & MORE_INPUT))
{ {
QString ans = fromTEXT(binIn); auto ans = fromTEXT(binIn);
if (noCaseMatch("n", ans)) if (noCaseMatch("n", ans))
{ {
flags &= ~MORE_INPUT; retCode = ABORTED;
flags &= ~MORE_INPUT;
} }
else if (noCaseMatch("y", ans)) else if (noCaseMatch("y", ans))
{ {
@ -115,12 +120,13 @@ void AddCert::procIn(const QByteArray &binIn, quint8 dType)
} }
else if (dType == TEXT) else if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 7); auto args = parseArgs(binIn, 7);
QString cert = getParam("-cert", args); auto cert = getParam("-cert", args);
QString priv = getParam("-priv", args); auto priv = getParam("-priv", args);
bool force = argExists("-force", args); auto force = argExists("-force", args);
coName = getParam("-name", args); coName = getParam("-name", args);
retCode = INVALID_PARAMS;
QFile certFile(cert, this); QFile certFile(cert, this);
QFile privFile(priv, this); QFile privFile(priv, this);
@ -167,8 +173,9 @@ void AddCert::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
certBa = certFile.readAll(); retCode = NO_ERRORS;
privBa = privFile.readAll(); certBa = certFile.readAll();
privBa = privFile.readAll();
if (certExists(coName)) if (certExists(coName))
{ {
@ -216,7 +223,8 @@ void RemoveCert::procIn(const QByteArray &binIn, quint8 dType)
if (noCaseMatch("n", ans)) if (noCaseMatch("n", ans))
{ {
flags &= ~MORE_INPUT; retCode = ABORTED;
flags &= ~MORE_INPUT;
} }
else if (noCaseMatch("y", ans)) else if (noCaseMatch("y", ans))
{ {
@ -229,9 +237,11 @@ void RemoveCert::procIn(const QByteArray &binIn, quint8 dType)
} }
else if (dType == TEXT) else if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, -1); auto args = parseArgs(binIn, -1);
QString name = getParam("-name", args); auto name = getParam("-name", args);
bool force = argExists("-force", args); auto force = argExists("-force", args);
retCode = INVALID_PARAMS;
if (name.isEmpty()) if (name.isEmpty())
{ {
@ -247,7 +257,8 @@ void RemoveCert::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
coName = name; retCode = NO_ERRORS;
coName = name;
if (force) run(); if (force) run();
else ask(); else ask();

View File

@ -130,9 +130,12 @@ void ListSubCh::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (dType == TEXT) if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 2); auto args = parseArgs(binIn, 2);
QString chName = getParam("-ch_name", args); auto chName = getParam("-ch_name", args);
quint64 chId;
quint64 chId;
retCode = INVALID_PARAMS;
if (chName.isEmpty()) if (chName.isEmpty())
{ {
@ -148,6 +151,8 @@ void ListSubCh::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
retCode = NO_ERRORS;
if (channelAccessLevel(rdFromBlock(userId, BLKSIZE_USER_ID), chOwnerOverride, chId) > REGULAR) if (channelAccessLevel(rdFromBlock(userId, BLKSIZE_USER_ID), chOwnerOverride, chId) > REGULAR)
{ {
TableViewer::procIn(toTEXT("-" + QString(COLUMN_CHANNEL_NAME) + " " + chName + " -" + QString(COLUMN_LOWEST_LEVEL) + " " + QString::number(PUBLIC)), dType); TableViewer::procIn(toTEXT("-" + QString(COLUMN_CHANNEL_NAME) + " " + chName + " -" + QString(COLUMN_LOWEST_LEVEL) + " " + QString::number(PUBLIC)), dType);
@ -170,9 +175,11 @@ void SearchChannels::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
QStringList args = parseArgs(binIn, 4); auto args = parseArgs(binIn, 4);
QString name = getParam("-name", args); auto name = getParam("-name", args);
QString chId = getParam("-id", args); auto chId = getParam("-id", args);
retCode = INVALID_PARAMS;
if (!name.isEmpty() && !validChName(name)) if (!name.isEmpty() && !validChName(name))
{ {
@ -184,14 +191,20 @@ void SearchChannels::procIn(const QByteArray &binIn, quint8 dType)
} }
else if (!name.isEmpty()) else if (!name.isEmpty())
{ {
retCode = NO_ERRORS;
TableViewer::procIn(toTEXT("-" + QString(COLUMN_CHANNEL_NAME) + " " + name), dType); TableViewer::procIn(toTEXT("-" + QString(COLUMN_CHANNEL_NAME) + " " + name), dType);
} }
else if (!chId.isEmpty()) else if (!chId.isEmpty())
{ {
retCode = NO_ERRORS;
TableViewer::procIn(toTEXT("-" + QString(COLUMN_CHANNEL_ID) + " " + chId), dType); TableViewer::procIn(toTEXT("-" + QString(COLUMN_CHANNEL_ID) + " " + chId), dType);
} }
else else
{ {
retCode = NO_ERRORS;
TableViewer::procIn(QByteArray(), dType); TableViewer::procIn(QByteArray(), dType);
} }
} }
@ -208,11 +221,14 @@ void ListMembers::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
QStringList args = parseArgs(binIn, 6); auto args = parseArgs(binIn, 6);
QString chName = getParam("-ch_name", args); auto chName = getParam("-ch_name", args);
QString userFind = getParam("-user_name", args); auto userFind = getParam("-user_name", args);
QString dispFind = getParam("-disp_name", args); auto dispFind = getParam("-disp_name", args);
quint64 chId;
quint64 chId;
retCode = INVALID_PARAMS;
if (chName.isEmpty()) if (chName.isEmpty())
{ {
@ -232,7 +248,9 @@ void ListMembers::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
QByteArray argsBa = toTEXT("-" + QString(COLUMN_CHANNEL_NAME) + " " + chName); retCode = NO_ERRORS;
auto argsBa = toTEXT("-" + QString(COLUMN_CHANNEL_NAME) + " " + chName);
if (!userFind.isEmpty()) if (!userFind.isEmpty())
{ {
@ -254,9 +272,12 @@ void CreateChannel::procIn(const QByteArray &binIn, uchar dType)
{ {
if (dType == TEXT) if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 2); auto args = parseArgs(binIn, 2);
QString chName = getParam("-ch_name", args); auto chName = getParam("-ch_name", args);
quint64 chId;
quint64 chId;
retCode = INVALID_PARAMS;
if (chName.isEmpty()) if (chName.isEmpty())
{ {
@ -272,15 +293,17 @@ void CreateChannel::procIn(const QByteArray &binIn, uchar dType)
} }
else else
{ {
retCode = NO_ERRORS;
Query db(this); Query db(this);
db.setType(Query::PUSH, TABLE_CHANNELS); db.setType(Query::PUSH, TABLE_CHANNELS);
db.addColumn(COLUMN_CHANNEL_NAME, chName); db.addColumn(COLUMN_CHANNEL_NAME, chName);
db.exec(); db.exec();
QByteArray uId = rdFromBlock(userId, BLKSIZE_USER_ID); auto uId = rdFromBlock(userId, BLKSIZE_USER_ID);
QString uName = rdStringFromBlock(userName, BLKSIZE_USER_NAME); auto uName = rdStringFromBlock(userName, BLKSIZE_USER_NAME);
QString dName = rdStringFromBlock(displayName, BLKSIZE_DISP_NAME); auto dName = rdStringFromBlock(displayName, BLKSIZE_DISP_NAME);
db.setType(Query::PUSH, TABLE_CH_MEMBERS); db.setType(Query::PUSH, TABLE_CH_MEMBERS);
db.addColumn(COLUMN_CHANNEL_ID, chId); db.addColumn(COLUMN_CHANNEL_ID, chId);
@ -289,7 +312,7 @@ void CreateChannel::procIn(const QByteArray &binIn, uchar dType)
db.addColumn(COLUMN_PENDING_INVITE, false); db.addColumn(COLUMN_PENDING_INVITE, false);
db.exec(); db.exec();
QByteArray frame = createChMemberAsyncFrame(chId, uId, false, OWNER, uName, dName, chName); auto frame = createChMemberAsyncFrame(chId, uId, false, OWNER, uName, dName, chName);
async(ASYNC_NEW_CH_MEMBER, PUB_IPC_WITH_FEEDBACK, frame); async(ASYNC_NEW_CH_MEMBER, PUB_IPC_WITH_FEEDBACK, frame);
} }
@ -300,9 +323,12 @@ void RemoveChannel::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (dType == TEXT) if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 2); auto args = parseArgs(binIn, 2);
QString chName = getParam("-ch_name", args); auto chName = getParam("-ch_name", args);
quint64 chId;
quint64 chId;
retCode = INVALID_PARAMS;
if (chName.isEmpty()) if (chName.isEmpty())
{ {
@ -322,6 +348,8 @@ void RemoveChannel::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
retCode = NO_ERRORS;
Query db(this); Query db(this);
db.setType(Query::DEL, TABLE_CHANNELS); db.setType(Query::DEL, TABLE_CHANNELS);
@ -337,10 +365,13 @@ void RenameChannel::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (dType == TEXT) if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 4); auto args = parseArgs(binIn, 4);
QString chName = getParam("-ch_name", args); auto chName = getParam("-ch_name", args);
QString newName = getParam("-new_name", args); auto newName = getParam("-new_name", args);
quint64 chId;
quint64 chId;
retCode = INVALID_PARAMS;
if (chName.isEmpty()) if (chName.isEmpty())
{ {
@ -372,6 +403,8 @@ void RenameChannel::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
retCode = NO_ERRORS;
Query db(this); Query db(this);
db.setType(Query::UPDATE, TABLE_CHANNELS); db.setType(Query::UPDATE, TABLE_CHANNELS);
@ -390,12 +423,15 @@ void SetActiveState::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (dType == TEXT) if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 6); auto args = parseArgs(binIn, 6);
QString chName = getParam("-ch_name", args); auto chName = getParam("-ch_name", args);
QString subName = getParam("-sub_name", args); auto subName = getParam("-sub_name", args);
QString state = getParam("-state", args); auto state = getParam("-state", args);
quint64 chId;
quint8 subId; quint64 chId;
quint8 subId;
retCode = INVALID_PARAMS;
if (chName.isEmpty()) if (chName.isEmpty())
{ {
@ -435,6 +471,8 @@ void SetActiveState::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
retCode = NO_ERRORS;
Query db(this); Query db(this);
db.setType(Query::UPDATE, TABLE_SUB_CHANNELS); db.setType(Query::UPDATE, TABLE_SUB_CHANNELS);
@ -459,11 +497,14 @@ void CreateSubCh::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (dType == TEXT) if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 4); auto args = parseArgs(binIn, 4);
QString chName = getParam("-ch_name", args); auto chName = getParam("-ch_name", args);
QString subName = getParam("-sub_name", args); auto subName = getParam("-sub_name", args);
quint64 chId;
quint8 subId; quint64 chId;
quint8 subId;
retCode = INVALID_PARAMS;
if (chName.isEmpty()) if (chName.isEmpty())
{ {
@ -499,6 +540,8 @@ void CreateSubCh::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
retCode = NO_ERRORS;
Query db(this); Query db(this);
db.setType(Query::PUSH, TABLE_SUB_CHANNELS); db.setType(Query::PUSH, TABLE_SUB_CHANNELS);
@ -509,7 +552,7 @@ void CreateSubCh::procIn(const QByteArray &binIn, quint8 dType)
db.addColumn(COLUMN_ACTIVE_UPDATE, false); db.addColumn(COLUMN_ACTIVE_UPDATE, false);
db.exec(); db.exec();
QByteArray frame = wrInt(chId, 64) + wrInt(subId, 8) + wrInt(REGULAR, 8) + wrInt(0, 8) + nullTermTEXT(subName); auto frame = wrInt(chId, 64) + wrInt(subId, 8) + wrInt(REGULAR, 8) + wrInt(0, 8) + nullTermTEXT(subName);
async(ASYNC_NEW_SUB_CH, PUB_IPC_WITH_FEEDBACK, frame); async(ASYNC_NEW_SUB_CH, PUB_IPC_WITH_FEEDBACK, frame);
} }
@ -520,11 +563,14 @@ void RemoveSubCh::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (dType == TEXT) if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 4); auto args = parseArgs(binIn, 4);
QString chName = getParam("-ch_name", args); auto chName = getParam("-ch_name", args);
QString subName = getParam("-sub_name", args); auto subName = getParam("-sub_name", args);
quint64 chId;
quint8 subId; quint64 chId;
quint8 subId;
retCode = INVALID_PARAMS;
if (chName.isEmpty()) if (chName.isEmpty())
{ {
@ -556,6 +602,8 @@ void RemoveSubCh::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
retCode = NO_ERRORS;
Query db(this); Query db(this);
db.setType(Query::DEL, TABLE_SUB_CHANNELS); db.setType(Query::DEL, TABLE_SUB_CHANNELS);
@ -572,12 +620,15 @@ void RenameSubCh::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (dType == TEXT) if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 6); auto args = parseArgs(binIn, 6);
QString chName = getParam("-ch_name", args); auto chName = getParam("-ch_name", args);
QString subName = getParam("-sub_name", args); auto subName = getParam("-sub_name", args);
QString newName = getParam("-new_name", args); auto newName = getParam("-new_name", args);
quint64 chId;
quint8 subId; quint64 chId;
quint8 subId;
retCode = INVALID_PARAMS;
if (chName.isEmpty()) if (chName.isEmpty())
{ {
@ -617,6 +668,8 @@ void RenameSubCh::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
retCode = NO_ERRORS;
Query db(this); Query db(this);
db.setType(Query::UPDATE, TABLE_SUB_CHANNELS); db.setType(Query::UPDATE, TABLE_SUB_CHANNELS);
@ -625,7 +678,7 @@ void RenameSubCh::procIn(const QByteArray &binIn, quint8 dType)
db.addCondition(COLUMN_SUB_CH_ID, subId); db.addCondition(COLUMN_SUB_CH_ID, subId);
db.exec(); db.exec();
QByteArray frame = wrInt(chId, 64) + wrInt(subId, 8) + nullTermTEXT(newName); auto frame = wrInt(chId, 64) + wrInt(subId, 8) + nullTermTEXT(newName);
async(ASYNC_RENAME_SUB_CH, PUB_IPC_WITH_FEEDBACK, frame); async(ASYNC_RENAME_SUB_CH, PUB_IPC_WITH_FEEDBACK, frame);
} }
@ -636,11 +689,14 @@ void InviteToCh::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (dType == TEXT) if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 4); auto args = parseArgs(binIn, 4);
QString chName = getParam("-ch_name", args); auto chName = getParam("-ch_name", args);
QString uName = getParam("-user", args); auto uName = getParam("-user", args);
QByteArray uId;
quint64 chId; QByteArray uId;
quint64 chId;
retCode = INVALID_PARAMS;
if (chName.isEmpty()) if (chName.isEmpty())
{ {
@ -680,6 +736,8 @@ void InviteToCh::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
retCode = NO_ERRORS;
Query db(this); Query db(this);
db.setType(Query::PUSH, TABLE_CH_MEMBERS); db.setType(Query::PUSH, TABLE_CH_MEMBERS);
@ -689,7 +747,7 @@ void InviteToCh::procIn(const QByteArray &binIn, quint8 dType)
db.addColumn(COLUMN_ACCESS_LEVEL, REGULAR); db.addColumn(COLUMN_ACCESS_LEVEL, REGULAR);
db.exec(); db.exec();
QByteArray frame = createChMemberAsyncFrame(chId, uId, true, REGULAR, uName, getDispName(uId), chName); auto frame = createChMemberAsyncFrame(chId, uId, true, REGULAR, uName, getDispName(uId), chName);
async(ASYNC_INVITED_TO_CH, PUB_IPC_WITH_FEEDBACK, frame); async(ASYNC_INVITED_TO_CH, PUB_IPC_WITH_FEEDBACK, frame);
} }
@ -700,9 +758,12 @@ void DeclineChInvite::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (dType == TEXT) if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 2); auto args = parseArgs(binIn, 2);
QString chName = getParam("-ch_name", args); auto chName = getParam("-ch_name", args);
quint64 chId;
quint64 chId;
retCode = INVALID_PARAMS;
if (chName.isEmpty()) if (chName.isEmpty())
{ {
@ -718,6 +779,8 @@ void DeclineChInvite::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
retCode = NO_ERRORS;
Query db(this); Query db(this);
db.setType(Query::DEL, TABLE_CH_MEMBERS); db.setType(Query::DEL, TABLE_CH_MEMBERS);
@ -734,9 +797,12 @@ void AcceptChInvite::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (dType == TEXT) if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 2); auto args = parseArgs(binIn, 2);
QString chName = getParam("-ch_name", args); auto chName = getParam("-ch_name", args);
quint64 chId;
quint64 chId;
retCode = INVALID_PARAMS;
if (chName.isEmpty()) if (chName.isEmpty())
{ {
@ -752,6 +818,8 @@ void AcceptChInvite::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
retCode = NO_ERRORS;
Query db(this); Query db(this);
db.setType(Query::UPDATE, TABLE_CH_MEMBERS); db.setType(Query::UPDATE, TABLE_CH_MEMBERS);
@ -767,11 +835,11 @@ void AcceptChInvite::procIn(const QByteArray &binIn, quint8 dType)
bool RemoveChMember::allowMemberDel(const QByteArray &uId, quint64 chId) bool RemoveChMember::allowMemberDel(const QByteArray &uId, quint64 chId)
{ {
QByteArray myId = rdFromBlock(userId, BLKSIZE_USER_ID); auto myId = rdFromBlock(userId, BLKSIZE_USER_ID);
bool ret = false; auto ret = false;
bool leaving = (uId == myId); auto leaving = (uId == myId);
int targetLevel = channelAccessLevel(uId, chId); auto targetLevel = channelAccessLevel(uId, chId);
int myLevel = channelAccessLevel(myId, chOwnerOverride, BLKSIZE_USER_ID); auto myLevel = channelAccessLevel(myId, chOwnerOverride, BLKSIZE_USER_ID);
if (leaving && (myLevel == OWNER)) if (leaving && (myLevel == OWNER))
{ {
@ -797,11 +865,14 @@ void RemoveChMember::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (dType == TEXT) if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 4); auto args = parseArgs(binIn, 4);
QString chName = getParam("-ch_name", args); auto chName = getParam("-ch_name", args);
QString uName = getParam("-user", args); auto uName = getParam("-user", args);
QByteArray uId;
quint64 chId; QByteArray uId;
quint64 chId;
retCode = INVALID_PARAMS;
if (chName.isEmpty()) if (chName.isEmpty())
{ {
@ -833,6 +904,8 @@ void RemoveChMember::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
retCode = NO_ERRORS;
Query db(this); Query db(this);
db.setType(Query::DEL, TABLE_CH_MEMBERS); db.setType(Query::DEL, TABLE_CH_MEMBERS);
@ -847,8 +920,8 @@ void RemoveChMember::procIn(const QByteArray &binIn, quint8 dType)
bool SetMemberLevel::allowLevelChange(const QByteArray &uId, int newLevel, quint64 chId) bool SetMemberLevel::allowLevelChange(const QByteArray &uId, int newLevel, quint64 chId)
{ {
int targetLevel = channelAccessLevel(uId, chId); auto targetLevel = channelAccessLevel(uId, chId);
int myLevel = channelAccessLevel(rdFromBlock(userId, BLKSIZE_USER_ID), chOwnerOverride, BLKSIZE_USER_ID); auto myLevel = channelAccessLevel(rdFromBlock(userId, BLKSIZE_USER_ID), chOwnerOverride, BLKSIZE_USER_ID);
return (newLevel >= myLevel) && (targetLevel > myLevel); return (newLevel >= myLevel) && (targetLevel > myLevel);
} }
@ -857,12 +930,15 @@ void SetMemberLevel::procIn(const QByteArray &binIn, uchar dType)
{ {
if (dType == TEXT) if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 6); auto args = parseArgs(binIn, 6);
QString chName = getParam("-ch_name", args); auto chName = getParam("-ch_name", args);
QString uName = getParam("-user", args); auto uName = getParam("-user", args);
QString level = getParam("-level", args); auto level = getParam("-level", args);
quint64 chId;
QByteArray uId; quint64 chId;
QByteArray uId;
retCode = INVALID_PARAMS;
if (chName.isEmpty()) if (chName.isEmpty())
{ {
@ -902,6 +978,8 @@ void SetMemberLevel::procIn(const QByteArray &binIn, uchar dType)
} }
else else
{ {
retCode = NO_ERRORS;
Query db(this); Query db(this);
db.setType(Query::PULL, TABLE_CH_MEMBERS); db.setType(Query::PULL, TABLE_CH_MEMBERS);
@ -910,8 +988,8 @@ void SetMemberLevel::procIn(const QByteArray &binIn, uchar dType)
db.addCondition(COLUMN_CHANNEL_ID, chId); db.addCondition(COLUMN_CHANNEL_ID, chId);
db.exec(); db.exec();
int newLevel = level.toInt(); auto newLevel = level.toInt();
QByteArray owner = db.getData(COLUMN_USER_ID).toByteArray(); auto owner = db.getData(COLUMN_USER_ID).toByteArray();
db.setType(Query::UPDATE, TABLE_CH_MEMBERS); db.setType(Query::UPDATE, TABLE_CH_MEMBERS);
db.addColumn(COLUMN_ACCESS_LEVEL, newLevel); db.addColumn(COLUMN_ACCESS_LEVEL, newLevel);
@ -939,12 +1017,15 @@ void SetSubAcessLevel::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (dType == TEXT) if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 6); auto args = parseArgs(binIn, 6);
QString chName = getParam("-ch_name", args); auto chName = getParam("-ch_name", args);
QString subName = getParam("-sub_name", args); auto subName = getParam("-sub_name", args);
QString level = getParam("-level", args); auto level = getParam("-level", args);
quint64 chId;
quint8 subId; quint64 chId;
quint8 subId;
retCode = INVALID_PARAMS;
if (chName.isEmpty()) if (chName.isEmpty())
{ {
@ -984,6 +1065,8 @@ void SetSubAcessLevel::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
retCode = NO_ERRORS;
Query db(this); Query db(this);
db.setType(Query::UPDATE, TABLE_SUB_CHANNELS); db.setType(Query::UPDATE, TABLE_SUB_CHANNELS);
@ -1001,8 +1084,10 @@ void OwnerOverride::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (dType == TEXT) if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 2); auto args = parseArgs(binIn, 2);
QString state = getParam("-state", args); auto state = getParam("-state", args);
retCode = INVALID_PARAMS;
if (state.isEmpty()) if (state.isEmpty())
{ {
@ -1014,6 +1099,8 @@ void OwnerOverride::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
retCode = NO_ERRORS;
wr8BitToBlock(static_cast<quint8>(state.toUInt()), chOwnerOverride); wr8BitToBlock(static_cast<quint8>(state.toUInt()), chOwnerOverride);
} }
} }

View File

@ -49,10 +49,12 @@ void AssignCmdRank::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (dType == TEXT) if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 6); auto args = parseArgs(binIn, 6);
QString cmdName = getParam("-command", args); auto cmdName = getParam("-command", args);
QString mod = getParam("-mod", args); auto mod = getParam("-mod", args);
QString rank = getParam("-rank", args); auto rank = getParam("-rank", args);
retCode = INVALID_PARAMS;
if (cmdName.isEmpty()) if (cmdName.isEmpty())
{ {
@ -84,6 +86,8 @@ void AssignCmdRank::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
retCode = NO_ERRORS;
Query db(this); Query db(this);
db.setType(Query::PUSH, TABLE_CMD_RANKS); db.setType(Query::PUSH, TABLE_CMD_RANKS);
@ -101,9 +105,11 @@ void RemoveCmdRank::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (dType == TEXT) if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 4); auto args = parseArgs(binIn, 4);
QString cmdName = getParam("-command", args); auto cmdName = getParam("-command", args);
QString mod = getParam("-mod", args); auto mod = getParam("-mod", args);
retCode = INVALID_PARAMS;
if (cmdName.isEmpty()) if (cmdName.isEmpty())
{ {
@ -127,6 +133,8 @@ void RemoveCmdRank::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
retCode = NO_ERRORS;
Query db(this); Query db(this);
db.setType(Query::DEL, TABLE_CMD_RANKS); db.setType(Query::DEL, TABLE_CMD_RANKS);

View File

@ -30,7 +30,7 @@ QByteArray toFILE_INFO(const QFileInfo &info)
// note: the integer data found in flags, modTime, createTime and fileSize // note: the integer data found in flags, modTime, createTime and fileSize
// are formatted in little endian byte order (unsigned). // are formatted in little endian byte order (unsigned).
char flags = 0; auto flags = 0x00;
if (info.isFile()) flags |= IS_FILE; if (info.isFile()) flags |= IS_FILE;
if (info.isDir()) flags |= IS_DIR; if (info.isDir()) flags |= IS_DIR;
@ -98,18 +98,28 @@ void DownloadFile::onTerminate()
void DownloadFile::sendChunk() void DownloadFile::sendChunk()
{ {
QByteArray data = file->read(LOCAL_BUFFSIZE); auto data = file->read(LOCAL_BUFFSIZE);
dataSent += data.size(); if (file->error() != QFile::NoError)
emit procOut(data, GEN_FILE);
mainTxt(QString::number(dataSent) + " / " + QString::number(len) + "\n");
if ((dataSent >= len) || file->atEnd())
{ {
retCode = EXECUTION_FAIL;
errTxt("err: File IO failure: " + file->errorString() + ".\n");
onTerminate(); onTerminate();
} }
else
{
dataSent += data.size();
emit procOut(data, GEN_FILE);
mainTxt(QString::number(dataSent) + " / " + QString::number(len) + "\n");
if ((dataSent >= len) || file->atEnd())
{
onTerminate();
}
}
} }
void DownloadFile::procIn(const QByteArray &binIn, quint8 dType) void DownloadFile::procIn(const QByteArray &binIn, quint8 dType)
@ -126,10 +136,12 @@ void DownloadFile::procIn(const QByteArray &binIn, quint8 dType)
} }
else if (dType == GEN_FILE) else if (dType == GEN_FILE)
{ {
QStringList args = parseArgs(binIn, 11); auto args = parseArgs(binIn, 11);
QString path = getParam("-remote_file", args); auto path = getParam("-remote_file", args);
QString offStr = getParam("-offset", args); auto offStr = getParam("-offset", args);
QString lenStr = getParam("-len", args); auto lenStr = getParam("-len", args);
retCode = INVALID_PARAMS;
file->setFileName(path); file->setFileName(path);
@ -155,6 +167,8 @@ void DownloadFile::procIn(const QByteArray &binIn, quint8 dType)
} }
else if (!file->open(QFile::ReadOnly)) else if (!file->open(QFile::ReadOnly))
{ {
retCode = EXECUTION_FAIL;
errTxt("err: Unable to open the remote file for reading. reason: " + file->errorString() + "\n"); errTxt("err: Unable to open the remote file for reading. reason: " + file->errorString() + "\n");
} }
else else
@ -162,6 +176,7 @@ void DownloadFile::procIn(const QByteArray &binIn, quint8 dType)
len = lenStr.toLongLong(); len = lenStr.toLongLong();
ssMode = argExists("-single_step", args); ssMode = argExists("-single_step", args);
paramsSet = true; paramsSet = true;
retCode = NO_ERRORS;
flags |= MORE_INPUT; flags |= MORE_INPUT;
if ((len == 0) || (len > file->size())) if ((len == 0) || (len > file->size()))
@ -192,19 +207,29 @@ void UploadFile::onTerminate()
void UploadFile::wrToFile(const QByteArray &data) void UploadFile::wrToFile(const QByteArray &data)
{ {
dataReceived += data.size(); auto written = file->write(data);
file->write(data); if (written == -1)
mainTxt(QString::number(dataReceived) + " / " + QString::number(len) + "\n");
if (dataReceived >= len)
{ {
retCode = EXECUTION_FAIL;
errTxt("err: File IO failure: " + file->errorString() + ".\n");
onTerminate(); onTerminate();
} }
else if (ssMode) else
{ {
emit procOut(QByteArray(), GEN_FILE); dataReceived += written;
mainTxt(QString::number(dataReceived) + " / " + QString::number(len) + "\n");
if (dataReceived >= len)
{
onTerminate();
}
else if (ssMode)
{
emit procOut(QByteArray(), GEN_FILE);
}
} }
} }
@ -225,6 +250,8 @@ void UploadFile::run()
} }
else else
{ {
retCode = EXECUTION_FAIL;
errTxt("err: Unable to open the remote file for writing. reason: " + file->errorString() + "\n"); errTxt("err: Unable to open the remote file for writing. reason: " + file->errorString() + "\n");
onTerminate(); onTerminate();
} }
@ -234,7 +261,7 @@ void UploadFile::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (((dType == GEN_FILE) || (dType == TEXT)) && confirm) if (((dType == GEN_FILE) || (dType == TEXT)) && confirm)
{ {
QString ans = fromTEXT(binIn); auto ans = fromTEXT(binIn);
if (noCaseMatch("y", ans)) if (noCaseMatch("y", ans))
{ {
@ -244,6 +271,8 @@ void UploadFile::procIn(const QByteArray &binIn, quint8 dType)
} }
else if (noCaseMatch("n", ans)) else if (noCaseMatch("n", ans))
{ {
retCode = ABORTED;
onTerminate(); onTerminate();
} }
else else
@ -257,10 +286,12 @@ void UploadFile::procIn(const QByteArray &binIn, quint8 dType)
} }
else if (dType == GEN_FILE) else if (dType == GEN_FILE)
{ {
QStringList args = parseArgs(binIn, 11); auto args = parseArgs(binIn, 11);
QString lenStr = getParam("-len", args); auto lenStr = getParam("-len", args);
QString offStr = getParam("-offset", args); auto offStr = getParam("-offset", args);
QString dst = getParam("-remote_file", args); auto dst = getParam("-remote_file", args);
retCode = INVALID_PARAMS;
if (dst.isEmpty()) if (dst.isEmpty())
{ {
@ -289,11 +320,12 @@ void UploadFile::procIn(const QByteArray &binIn, quint8 dType)
mode = QFile::ReadWrite; mode = QFile::ReadWrite;
} }
force = argExists("-force", args); force = argExists("-force", args);
ssMode = argExists("-single_step", args); ssMode = argExists("-single_step", args);
len = lenStr.toLongLong(); len = lenStr.toLongLong();
offs = offStr.toLongLong(); offs = offStr.toLongLong();
flags |= MORE_INPUT; retCode = NO_ERRORS;
flags |= MORE_INPUT;
file->setFileName(dst); file->setFileName(dst);
@ -333,6 +365,11 @@ void Delete::run()
ok = QDir(path).removeRecursively(); ok = QDir(path).removeRecursively();
} }
if (!ok)
{
retCode = EXECUTION_FAIL;
}
if (!ok && !info.exists()) if (!ok && !info.exists())
{ {
errTxt("err: '" + path + "' already does not exists.\n"); errTxt("err: '" + path + "' already does not exists.\n");
@ -351,7 +388,7 @@ void Delete::procIn(const QByteArray &binIn, uchar dType)
{ {
if ((flags & MORE_INPUT) && (dType == TEXT)) if ((flags & MORE_INPUT) && (dType == TEXT))
{ {
QString ans = fromTEXT(binIn); auto ans = fromTEXT(binIn);
if (noCaseMatch("y", ans)) if (noCaseMatch("y", ans))
{ {
@ -361,7 +398,8 @@ void Delete::procIn(const QByteArray &binIn, uchar dType)
} }
else if (noCaseMatch("n", ans)) else if (noCaseMatch("n", ans))
{ {
flags &= ~MORE_INPUT; retCode = ABORTED;
flags &= ~MORE_INPUT;
} }
else else
{ {
@ -370,9 +408,10 @@ void Delete::procIn(const QByteArray &binIn, uchar dType)
} }
else if (dType == TEXT) else if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 3); auto args = parseArgs(binIn, 3);
path = getParam("-path", args); path = getParam("-path", args);
retCode = INVALID_PARAMS;
if (path.isEmpty()) if (path.isEmpty())
{ {
@ -430,7 +469,7 @@ bool Copy::matchingVolumeMatters()
bool Copy::permissionsOk(bool dstExists) bool Copy::permissionsOk(bool dstExists)
{ {
bool ret = true; auto ret = true;
if (!QFileInfo(srcPath).isReadable()) if (!QFileInfo(srcPath).isReadable())
{ {
@ -445,6 +484,15 @@ bool Copy::permissionsOk(bool dstExists)
ret = false; ret = false;
} }
if (ret)
{
retCode = NO_ERRORS;
}
else
{
retCode = EXECUTION_FAIL;
}
return ret; return ret;
} }
@ -471,7 +519,11 @@ void Copy::run()
else else
{ {
errTxt("err: Unable to re-create the source symlink at the destination path. writing to the path is not possible/denied.\n"); errTxt("err: Unable to re-create the source symlink at the destination path. writing to the path is not possible/denied.\n");
onTerminate();
if (queue.isEmpty())
{
onTerminate();
}
} }
} }
else if (QFileInfo(srcPath).isDir()) else if (QFileInfo(srcPath).isDir())
@ -486,12 +538,20 @@ void Copy::run()
if (!dst->open(QFile::WriteOnly | QFile::Truncate)) if (!dst->open(QFile::WriteOnly | QFile::Truncate))
{ {
errTxt("err: Unable to open the destination file '" + dstPath + "' for writing. reason: " + dst->errorString() + "\n"); errTxt("err: Unable to open the destination file '" + dstPath + "' for writing. reason: " + dst->errorString() + "\n");
onTerminate();
if (queue.isEmpty())
{
onTerminate();
}
} }
else if (!src->open(QFile::ReadOnly)) else if (!src->open(QFile::ReadOnly))
{ {
errTxt("err: Unable to open the source file '" + srcPath + "' for reading. reason: " + src->errorString() + "\n"); errTxt("err: Unable to open the source file '" + srcPath + "' for reading. reason: " + src->errorString() + "\n");
onTerminate();
if (queue.isEmpty())
{
onTerminate();
}
} }
else else
{ {
@ -526,7 +586,7 @@ void Copy::procIn(const QByteArray &binIn, uchar dType)
} }
else if (!queue.isEmpty()) else if (!queue.isEmpty())
{ {
QPair<QString,QString> srcToDst = queue.takeFirst(); auto srcToDst = queue.takeFirst();
srcPath = srcToDst.first; srcPath = srcToDst.first;
dstPath = srcToDst.second; dstPath = srcToDst.second;
@ -535,7 +595,7 @@ void Copy::procIn(const QByteArray &binIn, uchar dType)
src->setFileName(srcPath); src->setFileName(srcPath);
dst->setFileName(dstPath); dst->setFileName(dstPath);
bool exists = QFileInfo(dstPath).exists(); auto exists = QFileInfo(dstPath).exists();
if (exists && !yToAll && !nToAll) if (exists && !yToAll && !nToAll)
{ {
@ -556,7 +616,7 @@ void Copy::procIn(const QByteArray &binIn, uchar dType)
} }
else if ((dType == TEXT) && (flags & MORE_INPUT)) else if ((dType == TEXT) && (flags & MORE_INPUT))
{ {
QString ans = fromTEXT(binIn); auto ans = fromTEXT(binIn);
if (noCaseMatch("y", ans)) if (noCaseMatch("y", ans))
{ {
@ -611,14 +671,15 @@ void Copy::procIn(const QByteArray &binIn, uchar dType)
{ {
onTerminate(); onTerminate();
QStringList args = parseArgs(binIn, 5); auto args = parseArgs(binIn, 5);
bool force = argExists("-force", args); auto force = argExists("-force", args);
srcPath = getParam("-src", args); srcPath = getParam("-src", args);
dstPath = getParam("-dst", args); dstPath = getParam("-dst", args);
oriSrcPath = srcPath; oriSrcPath = srcPath;
retCode = INVALID_PARAMS;
bool dstExists = QFileInfo(dstPath).exists(); auto dstExists = QFileInfo(dstPath).exists();
src->setFileName(srcPath); src->setFileName(srcPath);
dst->setFileName(dstPath); dst->setFileName(dstPath);
@ -665,6 +726,8 @@ void Move::runOnMatchingVolume()
if (!QFile::rename(srcPath, dstPath)) if (!QFile::rename(srcPath, dstPath))
{ {
retCode = EXECUTION_FAIL;
errTxt("err: Unable to do move operation. it's likely the command failed to remove the existing destination object or writing to the path is not possible/denied.\n"); errTxt("err: Unable to do move operation. it's likely the command failed to remove the existing destination object or writing to the path is not possible/denied.\n");
onTerminate(); onTerminate();
} }
@ -685,7 +748,7 @@ void Move::preFinish()
bool Move::permissionsOk(bool dstExists) bool Move::permissionsOk(bool dstExists)
{ {
bool ret = true; auto ret = true;
if (!QFileInfo(srcPath).isReadable() || !QFileInfo(srcPath).isWritable()) if (!QFileInfo(srcPath).isReadable() || !QFileInfo(srcPath).isWritable())
{ {
@ -700,6 +763,15 @@ bool Move::permissionsOk(bool dstExists)
ret = false; ret = false;
} }
if (ret)
{
retCode = NO_ERRORS;
}
else
{
retCode = EXECUTION_FAIL;
}
return ret; return ret;
} }
@ -707,11 +779,13 @@ void MakePath::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (dType == TEXT) if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 2); auto args = parseArgs(binIn, 2);
QString path = getParam("-path", args); auto path = getParam("-path", args);
if (path.isEmpty()) if (path.isEmpty())
{ {
retCode = INVALID_PARAMS;
errTxt("err: The path argument (-path) was not found or is empty.\n"); errTxt("err: The path argument (-path) was not found or is empty.\n");
} }
else else
@ -725,10 +799,10 @@ void ListFiles::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (dType == TEXT) if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 4); auto args = parseArgs(binIn, 4);
QString path = getParam("-path", args); auto path = getParam("-path", args);
bool infoFrame = argExists("-info_frame", args); auto infoFrame = argExists("-info_frame", args);
bool noHidden = argExists("-no_hidden", args); auto noHidden = argExists("-no_hidden", args);
if (path.isEmpty()) if (path.isEmpty())
{ {
@ -737,6 +811,8 @@ void ListFiles::procIn(const QByteArray &binIn, quint8 dType)
QFileInfo pathInfo(path); QFileInfo pathInfo(path);
retCode = INVALID_PARAMS;
if (!pathInfo.exists()) if (!pathInfo.exists())
{ {
errTxt("err: '" + path + "' does not exists.\n"); errTxt("err: '" + path + "' does not exists.\n");
@ -751,6 +827,8 @@ void ListFiles::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
retCode = NO_ERRORS;
QDir dir(path); QDir dir(path);
if (noHidden) if (noHidden)
@ -789,12 +867,14 @@ void FileInfo::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (dType == TEXT) if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 3); auto args = parseArgs(binIn, 3);
QString path = getParam("-path", args); auto path = getParam("-path", args);
bool infoFrame = argExists("-info_frame", args); auto infoFrame = argExists("-info_frame", args);
QFileInfo info(path); QFileInfo info(path);
retCode = INVALID_PARAMS;
if (path.isEmpty()) if (path.isEmpty())
{ {
errTxt("err: The path argument (-path) was not found or is empty.\n"); errTxt("err: The path argument (-path) was not found or is empty.\n");
@ -805,6 +885,8 @@ void FileInfo::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
retCode = NO_ERRORS;
if (infoFrame) if (infoFrame)
{ {
emit procOut(toFILE_INFO(info), FILE_INFO); emit procOut(toFILE_INFO(info), FILE_INFO);
@ -841,8 +923,10 @@ void ChangeDir::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (dType == TEXT) if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 3); auto args = parseArgs(binIn, 3);
QString path = getParam("-path", args); auto path = getParam("-path", args);
retCode = INVALID_PARAMS;
if (path.isEmpty()) if (path.isEmpty())
{ {
@ -858,6 +942,8 @@ void ChangeDir::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
retCode = NO_ERRORS;
QDir::setCurrent(path); QDir::setCurrent(path);
mainTxt(QDir::currentPath() + "\n"); mainTxt(QDir::currentPath() + "\n");
@ -931,11 +1017,12 @@ void Tree::procIn(const QByteArray &binIn, quint8 dType)
} }
else if (dType == TEXT) else if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 4); auto args = parseArgs(binIn, 4);
QString path = getParam("-path", args); auto path = getParam("-path", args);
infoFrames = argExists("-info_frame", args); infoFrames = argExists("-info_frame", args);
noHidden = argExists("-no_hidden", args); noHidden = argExists("-no_hidden", args);
retCode = INVALID_PARAMS;
if (path.isEmpty()) if (path.isEmpty())
{ {
@ -958,6 +1045,8 @@ void Tree::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
retCode = NO_ERRORS;
printList(path); printList(path);
} }
} }

View File

@ -65,8 +65,7 @@ void ListCommands::onIPCConnected()
{ {
for (auto&& cmdName : list) for (auto&& cmdName : list)
{ {
QByteArray frame; auto genType = QByteArray(1, 0x00);
QByteArray genType = QByteArray(1, 0x00);
if (cmdName == DownloadFile::cmdName()) if (cmdName == DownloadFile::cmdName())
{ {
@ -81,6 +80,8 @@ void ListCommands::onIPCConnected()
genType = QByteArray(1, GEN_UPLOAD); genType = QByteArray(1, GEN_UPLOAD);
} }
QByteArray frame;
frame.append(QByteArray(2, 0x00)); frame.append(QByteArray(2, 0x00));
frame.append(genType); frame.append(genType);
frame.append(fixedToTEXT(cmdName, BLKSIZE_CMD_NAME)); frame.append(fixedToTEXT(cmdName, BLKSIZE_CMD_NAME));

View File

@ -22,26 +22,28 @@ ListMods::ListMods(QObject *parent) : TableViewer(parent)
addTableColumn(TABLE_MODULES, COLUMN_MOD_MAIN); addTableColumn(TABLE_MODULES, COLUMN_MOD_MAIN);
} }
UploadMod::UploadMod(QObject *parent) : CmdObject(parent) {} AddMod::AddMod(QObject *parent) : CmdObject(parent) {}
DelMod::DelMod(QObject *parent) : CmdObject(parent) {} DelMod::DelMod(QObject *parent) : CmdObject(parent) {}
QString ListMods::cmdName() {return "ls_mods";} QString ListMods::cmdName() {return "ls_mods";}
QString DelMod::cmdName() {return "rm_mod";} QString DelMod::cmdName() {return "rm_mod";}
QString UploadMod::cmdName() {return "add_mod";} QString AddMod::cmdName() {return "add_mod";}
bool UploadMod::isExecutable(const QString &path) bool AddMod::isExecutable(const QString &path)
{ {
QFileInfo info(expandEnvVariables(path)); QFileInfo info(expandEnvVariables(path));
return info.exists() && info.isExecutable(); return info.exists() && info.isExecutable();
} }
void UploadMod::procIn(const QByteArray &binIn, quint8 dType) void AddMod::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (dType == TEXT) if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 2); auto args = parseArgs(binIn, 2);
QString path = getParam("-mod_path", args); auto path = getParam("-mod_path", args);
retCode = INVALID_PARAMS;
if (path.isEmpty()) if (path.isEmpty())
{ {
@ -61,6 +63,8 @@ void UploadMod::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
retCode = NO_ERRORS;
Query db(this); Query db(this);
db.setType(Query::PUSH, TABLE_MODULES); db.setType(Query::PUSH, TABLE_MODULES);
@ -76,8 +80,10 @@ void DelMod::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (dType == TEXT) if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 2); auto args = parseArgs(binIn, 2);
QString path = getParam("-mod_path", args); auto path = getParam("-mod_path", args);
retCode = INVALID_PARAMS;
if (path.isEmpty()) if (path.isEmpty())
{ {
@ -93,6 +99,8 @@ void DelMod::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
retCode = NO_ERRORS;
Query db(this); Query db(this);
db.setType(Query::DEL, TABLE_MODULES); db.setType(Query::DEL, TABLE_MODULES);

View File

@ -24,7 +24,7 @@
QString rmFileSuffix(const QString &filePath); QString rmFileSuffix(const QString &filePath);
bool validFileOnlyName(const QString &fileName); bool validFileOnlyName(const QString &fileName);
class UploadMod : public CmdObject class AddMod : public CmdObject
{ {
Q_OBJECT Q_OBJECT
@ -38,7 +38,7 @@ public:
void procIn(const QByteArray &binIn, quint8 dType); void procIn(const QByteArray &binIn, quint8 dType);
explicit UploadMod(QObject *parent = nullptr); explicit AddMod(QObject *parent = nullptr);
}; };
//------------------------------- //-------------------------------

View File

@ -30,6 +30,8 @@ QString LsP2P::cmdName() {return "ls_p2p";}
void ToPeer::procIn(const QByteArray &binIn, quint8 dType) void ToPeer::procIn(const QByteArray &binIn, quint8 dType)
{ {
retCode = INVALID_PARAMS;
if (binIn.size() >= BLKSIZE_SESSION_ID) if (binIn.size() >= BLKSIZE_SESSION_ID)
{ {
errTxt("err: The p2p data does not contain a session id header.\n"); errTxt("err: The p2p data does not contain a session id header.\n");
@ -40,11 +42,13 @@ void ToPeer::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
quint32 len = static_cast<quint32>(binIn.size()); retCode = NO_ERRORS;
QByteArray dst = rdFromBlock(binIn.data(), BLKSIZE_SESSION_ID);
QByteArray src = rdFromBlock(sessionId, BLKSIZE_SESSION_ID); auto len = static_cast<quint32>(binIn.size());
QByteArray data = rdFromBlock(binIn.data() + BLKSIZE_SESSION_ID, len - BLKSIZE_SESSION_ID); auto dst = rdFromBlock(binIn.data(), BLKSIZE_SESSION_ID);
QByteArray typeBa = wrInt(dType, 8); auto src = rdFromBlock(sessionId, BLKSIZE_SESSION_ID);
auto data = rdFromBlock(binIn.data() + BLKSIZE_SESSION_ID, len - BLKSIZE_SESSION_ID);
auto typeBa = wrInt(dType, 8);
async(ASYNC_P2P, PUB_IPC, dst + src + typeBa + data); async(ASYNC_P2P, PUB_IPC, dst + src + typeBa + data);
} }
@ -54,6 +58,8 @@ void P2PRequest::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (dType == SESSION_ID) if (dType == SESSION_ID)
{ {
retCode = INVALID_PARAMS;
if (binIn.size() != BLKSIZE_SESSION_ID) if (binIn.size() != BLKSIZE_SESSION_ID)
{ {
errTxt("err: The given client session id does not equal " + QString::number(BLKSIZE_SESSION_ID) + " bytes.\n"); errTxt("err: The given client session id does not equal " + QString::number(BLKSIZE_SESSION_ID) + " bytes.\n");
@ -68,9 +74,11 @@ void P2PRequest::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
QByteArray dst = rdFromBlock(binIn.data(), BLKSIZE_SESSION_ID); retCode = NO_ERRORS;
QByteArray src = rdFromBlock(sessionId, BLKSIZE_SESSION_ID);
QByteArray typeBa = wrInt(P2P_REQUEST, 8); auto dst = rdFromBlock(binIn.data(), BLKSIZE_SESSION_ID);
auto src = rdFromBlock(sessionId, BLKSIZE_SESSION_ID);
auto typeBa = wrInt(P2P_REQUEST, 8);
async(ASYNC_P2P, PUB_IPC, dst + src + typeBa + createPeerInfoFrame()); async(ASYNC_P2P, PUB_IPC, dst + src + typeBa + createPeerInfoFrame());
} }
@ -81,6 +89,8 @@ void P2POpen::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (dType == SESSION_ID) if (dType == SESSION_ID)
{ {
retCode = INVALID_PARAMS;
if (binIn.size() != BLKSIZE_SESSION_ID) if (binIn.size() != BLKSIZE_SESSION_ID)
{ {
errTxt("err: The given client session id does not equal " + QString::number(BLKSIZE_SESSION_ID) + " bytes.\n"); errTxt("err: The given client session id does not equal " + QString::number(BLKSIZE_SESSION_ID) + " bytes.\n");
@ -95,9 +105,11 @@ void P2POpen::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
QByteArray dst = rdFromBlock(binIn.data(), BLKSIZE_SESSION_ID); retCode = NO_ERRORS;
QByteArray src = rdFromBlock(sessionId, BLKSIZE_SESSION_ID);
QByteArray typeBa = wrInt(P2P_OPEN, 8); auto dst = rdFromBlock(binIn.data(), BLKSIZE_SESSION_ID);
auto src = rdFromBlock(sessionId, BLKSIZE_SESSION_ID);
auto typeBa = wrInt(P2P_OPEN, 8);
async(ASYNC_P2P, PUB_IPC, dst + src + typeBa + dst); async(ASYNC_P2P, PUB_IPC, dst + src + typeBa + dst);
} }
@ -108,6 +120,8 @@ void P2PClose::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (dType == SESSION_ID) if (dType == SESSION_ID)
{ {
retCode = INVALID_PARAMS;
if (binIn.size() != BLKSIZE_SESSION_ID) if (binIn.size() != BLKSIZE_SESSION_ID)
{ {
errTxt("err: The given client session id does not equal " + QString::number(BLKSIZE_SESSION_ID) + " bytes.\n"); errTxt("err: The given client session id does not equal " + QString::number(BLKSIZE_SESSION_ID) + " bytes.\n");
@ -119,9 +133,11 @@ void P2PClose::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
QByteArray dst = rdFromBlock(binIn.data(), BLKSIZE_SESSION_ID); retCode = NO_ERRORS;
QByteArray src = rdFromBlock(sessionId, BLKSIZE_SESSION_ID);
QByteArray typeBa = wrInt(P2P_CLOSE, 8); auto dst = rdFromBlock(binIn.data(), BLKSIZE_SESSION_ID);
auto src = rdFromBlock(sessionId, BLKSIZE_SESSION_ID);
auto typeBa = wrInt(P2P_CLOSE, 8);
async(P2P_CLOSE, PUB_IPC, dst + src + typeBa + dst); async(P2P_CLOSE, PUB_IPC, dst + src + typeBa + dst);
} }
@ -153,8 +169,9 @@ void LsP2P::procIn(const QByteArray &binIn, quint8 dType)
if (dType == TEXT) if (dType == TEXT)
{ {
QList<QByteArray> peerIds = lsBlocks(p2pAccepted, MAX_P2P_LINKS, BLKSIZE_SESSION_ID) + auto peerIds = lsBlocks(p2pAccepted, MAX_P2P_LINKS, BLKSIZE_SESSION_ID) +
lsBlocks(p2pPending, MAX_P2P_LINKS, BLKSIZE_SESSION_ID); lsBlocks(p2pPending, MAX_P2P_LINKS, BLKSIZE_SESSION_ID);
QList<QStringList> tableData; QList<QStringList> tableData;
QStringList separators; QStringList separators;
QList<int> justLens; QList<int> justLens;
@ -170,7 +187,8 @@ void LsP2P::procIn(const QByteArray &binIn, quint8 dType)
for (auto&& peerId: peerIds) for (auto&& peerId: peerIds)
{ {
QString pending = "0"; auto pending = "0";
QStringList columnData; QStringList columnData;
if (posOfBlock(peerId.data(), p2pPending, MAX_P2P_LINKS, BLKSIZE_SESSION_ID) != -1) if (posOfBlock(peerId.data(), p2pPending, MAX_P2P_LINKS, BLKSIZE_SESSION_ID) != -1)

View File

@ -96,7 +96,7 @@ void TableViewer::addWhereConds(const QStringList &userArgs)
for (int i = 0; i < columns.size(); ++i) for (int i = 0; i < columns.size(); ++i)
{ {
QString value = getParam("-" + columns[i], userArgs); auto value = getParam("-" + columns[i], userArgs);
if (!value.isEmpty()) if (!value.isEmpty())
{ {
@ -190,8 +190,8 @@ QList<int> TableViewer::getColumnLens(const QList<QStringList> &data)
void TableViewer::dispData() void TableViewer::dispData()
{ {
QList<QStringList> tableRows = toStrings(rdQuery.allData()); auto tableRows = toStrings(rdQuery.allData());
QList<int> lens = getColumnLens(columnRows + tableRows); auto lens = getColumnLens(columnRows + tableRows);
for (auto&& row: columnRows + tableRows) for (auto&& row: columnRows + tableRows)
{ {
@ -210,7 +210,7 @@ void TableViewer::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (flags & MORE_INPUT) if (flags & MORE_INPUT)
{ {
QString text = fromTEXT(binIn).toLower(); auto text = fromTEXT(binIn).toLower();
if (text == "y") if (text == "y")
{ {

View File

@ -73,10 +73,13 @@ void LockUser::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (dType == TEXT) if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 4); auto args = parseArgs(binIn, 4);
QString uName = getParam("-user", args); auto uName = getParam("-user", args);
QString state = getParam("-state", args); auto state = getParam("-state", args);
QByteArray uId;
QByteArray uId;
retCode = INVALID_PARAMS;
if (uName.isEmpty()) if (uName.isEmpty())
{ {
@ -104,6 +107,8 @@ void LockUser::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
retCode = NO_ERRORS;
Query db(this); Query db(this);
db.setType(Query::UPDATE, TABLE_USERS); db.setType(Query::UPDATE, TABLE_USERS);
@ -128,19 +133,25 @@ void CreateUser::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (flags & MORE_INPUT) if (flags & MORE_INPUT)
{ {
QString password = fromTEXT(binIn); auto password = fromTEXT(binIn);
QString errMsg;
if (password.isEmpty()) if (password.isEmpty())
{ {
retCode = ABORTED;
clear(); clear();
} }
else if (!validPassword(password)) else if (!acceptablePw(password, newName, dispName, email, &errMsg))
{ {
errTxt("err: Invalid password. it must be 8-200 chars long containing numbers, mixed case letters and special chars.\n\n"); errTxt(errMsg + "\n");
privTxt("Enter a new password (leave blank to cancel): "); privTxt("Enter a new password (leave blank to cancel): ");
} }
else if (!createUser(newName, email, dispName, password)) else if (!createUser(newName, email, dispName, password))
{ {
retCode = INVALID_PARAMS;
errTxt("err: The requested User name already exists.\n"); errTxt("err: The requested User name already exists.\n");
clear(); clear();
} }
@ -151,11 +162,12 @@ void CreateUser::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
QStringList args = parseArgs(binIn, 6); auto args = parseArgs(binIn, 6);
dispName = getParam("-disp", args); dispName = getParam("-disp", args);
newName = getParam("-name", args); newName = getParam("-name", args);
email = getParam("-email", args); email = getParam("-email", args);
retCode = INVALID_PARAMS;
if (newName.isEmpty()) if (newName.isEmpty())
{ {
@ -169,6 +181,14 @@ void CreateUser::procIn(const QByteArray &binIn, quint8 dType)
{ {
errTxt("err: Invalid username. it must be 2-24 chars long and contain no spaces.\n"); errTxt("err: Invalid username. it must be 2-24 chars long and contain no spaces.\n");
} }
else if (noCaseMatch(DEFAULT_ROOT_USER, newName))
{
errTxt("err: '" + QString(DEFAULT_ROOT_USER) + "' is a reserved keyword. invalid for use as a username.\n");
}
else if (validEmailAddr(newName))
{
errTxt("err: Invaild username. it looks like an email address.\n");
}
else if (!validEmailAddr(email)) else if (!validEmailAddr(email))
{ {
errTxt("err: Invalid email address. it must contain a '@' symbol along with a vaild host address and user name that contain no spaces. it must also be less than 64 chars long.\n"); errTxt("err: Invalid email address. it must contain a '@' symbol along with a vaild host address and user name that contain no spaces. it must also be less than 64 chars long.\n");
@ -187,7 +207,8 @@ void CreateUser::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
flags |= MORE_INPUT; retCode = NO_ERRORS;
flags |= MORE_INPUT;
privTxt("Enter a new password (leave blank to cancel): "); privTxt("Enter a new password (leave blank to cancel): ");
} }
@ -221,7 +242,7 @@ void RemoveUser::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (flags & MORE_INPUT) if (flags & MORE_INPUT)
{ {
QString ans = fromTEXT(binIn); auto ans = fromTEXT(binIn);
if (noCaseMatch("y", ans)) if (noCaseMatch("y", ans))
{ {
@ -229,7 +250,8 @@ void RemoveUser::procIn(const QByteArray &binIn, quint8 dType)
} }
else if (noCaseMatch("n", ans)) else if (noCaseMatch("n", ans))
{ {
flags &= ~MORE_INPUT; retCode = ABORTED;
flags &= ~MORE_INPUT;
} }
else else
{ {
@ -238,17 +260,15 @@ void RemoveUser::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
QStringList args = parseArgs(binIn, 2); auto args = parseArgs(binIn, 2);
QString uName = getParam("-name", args); auto uName = getParam("-name", args);
retCode = INVALID_PARAMS;
if (uName.isEmpty()) if (uName.isEmpty())
{ {
errTxt("err: User name argument (-name) not found or is empty.\n"); errTxt("err: User name argument (-name) not found or is empty.\n");
} }
else if (noCaseMatch(ROOT_USER, uName))
{
errTxt("err: Unable to delete protected user: '" + QString(ROOT_USER) + "'\n");
}
else if (!validUserName(uName)) else if (!validUserName(uName))
{ {
errTxt("err: Invalid username.\n"); errTxt("err: Invalid username.\n");
@ -257,6 +277,10 @@ void RemoveUser::procIn(const QByteArray &binIn, quint8 dType)
{ {
errTxt("err: The requested user name does not exists.\n"); errTxt("err: The requested user name does not exists.\n");
} }
else if (rootUserId() == uId)
{
errTxt("err: Unable to delete root user: '" + uName + "'\n");
}
else if (isChOwner(uId)) else if (isChOwner(uId))
{ {
errTxt("err: The requested user name is the owner of one or more channels. assign new owners for these channels before attempting to delete this account.\n"); errTxt("err: The requested user name is the owner of one or more channels. assign new owners for these channels before attempting to delete this account.\n");
@ -267,6 +291,8 @@ void RemoveUser::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
retCode = NO_ERRORS;
if (argExists("-force", args)) if (argExists("-force", args))
{ {
rm(); rm();
@ -284,10 +310,13 @@ void ChangeUserRank::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (dType == TEXT) if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 4); auto args = parseArgs(binIn, 4);
QString uName = getParam("-user", args); auto uName = getParam("-user", args);
QString rank = getParam("-rank", args); auto rank = getParam("-rank", args);
QByteArray uId;
QByteArray uId;
retCode = INVALID_PARAMS;
if (uName.isEmpty()) if (uName.isEmpty())
{ {
@ -297,10 +326,6 @@ void ChangeUserRank::procIn(const QByteArray &binIn, quint8 dType)
{ {
errTxt("err: New rank argument (-rank) not found or is empty.\n"); errTxt("err: New rank argument (-rank) not found or is empty.\n");
} }
else if (noCaseMatch(ROOT_USER, uName))
{
errTxt("err: You are not allowed to change the rank of protected user: '" + QString(ROOT_USER) + "'\n");
}
else if (!validUserName(uName)) else if (!validUserName(uName))
{ {
errTxt("err: Invalid username.\n"); errTxt("err: Invalid username.\n");
@ -321,12 +346,18 @@ void ChangeUserRank::procIn(const QByteArray &binIn, quint8 dType)
{ {
errTxt("err: The requested user account does not exists.\n"); errTxt("err: The requested user account does not exists.\n");
} }
else if (rootUserId() == uId)
{
errTxt("err: You are not allowed to change the rank of root user: '" + uName + "'\n");
}
else if (!canModifyUser(uId, rd32BitFromBlock(hostRank), false)) else if (!canModifyUser(uId, rd32BitFromBlock(hostRank), false))
{ {
errTxt("err: The target user out ranks you or is equal to your own rank. access denied.\n"); errTxt("err: The target user out ranks you or is equal to your own rank. access denied.\n");
} }
else else
{ {
retCode = NO_ERRORS;
Query db(this); Query db(this);
db.setType(Query::UPDATE, TABLE_USERS); db.setType(Query::UPDATE, TABLE_USERS);
@ -345,15 +376,18 @@ void ChangePassword::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (flags & MORE_INPUT) if (flags & MORE_INPUT)
{ {
QString password = fromTEXT(binIn); auto password = fromTEXT(binIn);
QString errMsg;
if (password.isEmpty()) if (password.isEmpty())
{ {
flags &= ~MORE_INPUT; retCode = ABORTED;
flags &= ~MORE_INPUT;
} }
else if (!validPassword(password)) else if (!acceptablePw(password, rdFromBlock(userId, BLKSIZE_USER_ID), &errMsg))
{ {
errTxt("err: Invalid password. it must be 8-200 chars long containing numbers, mixed case letters and special chars.\n\n"); errTxt(errMsg + "\n");
privTxt("Enter a new password (leave blank to cancel): "); privTxt("Enter a new password (leave blank to cancel): ");
} }
else else
@ -376,8 +410,10 @@ void ChangeUsername::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (dType == TEXT) if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 2); auto args = parseArgs(binIn, 2);
QString newName = getParam("-new_name", args); auto newName = getParam("-new_name", args);
retCode = INVALID_PARAMS;
if (newName.isEmpty()) if (newName.isEmpty())
{ {
@ -387,14 +423,24 @@ void ChangeUsername::procIn(const QByteArray &binIn, quint8 dType)
{ {
errTxt("err: Invalid username. it must be 2-24 chars long and contain no spaces.\n"); errTxt("err: Invalid username. it must be 2-24 chars long and contain no spaces.\n");
} }
else if (noCaseMatch(DEFAULT_ROOT_USER, newName))
{
errTxt("err: '" + QString(DEFAULT_ROOT_USER) + "' is a reserved keyword. invalid for use as a username.\n");
}
else if (validEmailAddr(newName))
{
errTxt("err: Invaild username. it looks like an email address.\n");
}
else if (userExists(newName)) else if (userExists(newName))
{ {
errTxt("err: The requested user name already exists.\n"); errTxt("err: The requested user name already exists.\n");
} }
else else
{ {
QByteArray uId = rdFromBlock(userId, BLKSIZE_USER_ID); retCode = NO_ERRORS;
QByteArray newNameBa = fixedToTEXT(newName, BLKSIZE_USER_NAME);
auto uId = rdFromBlock(userId, BLKSIZE_USER_ID);
auto newNameBa = fixedToTEXT(newName, BLKSIZE_USER_NAME);
Query db(this); Query db(this);
@ -412,8 +458,10 @@ void ChangeDispName::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (dType == TEXT) if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 2); auto args = parseArgs(binIn, 2);
QString name = getParam("-new_name", args).trimmed(); auto name = getParam("-new_name", args).trimmed();
retCode = INVALID_PARAMS;
if (argExists("-new_name", args)) if (argExists("-new_name", args))
{ {
@ -425,10 +473,12 @@ void ChangeDispName::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
retCode = NO_ERRORS;
Query db(this); Query db(this);
QByteArray uId = rdFromBlock(userId, BLKSIZE_USER_ID); auto uId = rdFromBlock(userId, BLKSIZE_USER_ID);
QByteArray newNameBa = fixedToTEXT(name, BLKSIZE_DISP_NAME); auto newNameBa = fixedToTEXT(name, BLKSIZE_DISP_NAME);
db.setType(Query::UPDATE, TABLE_USERS); db.setType(Query::UPDATE, TABLE_USERS);
db.addColumn(COLUMN_DISPLAY_NAME, name); db.addColumn(COLUMN_DISPLAY_NAME, name);
@ -444,6 +494,8 @@ void OverWriteEmail::procArgs(const QString &uName, const QString &newEmail, boo
{ {
QByteArray uId; QByteArray uId;
retCode = INVALID_PARAMS;
if (newEmail.isEmpty()) if (newEmail.isEmpty())
{ {
errTxt("err: New email address (-new_email) argument was not found or is empty.\n"); errTxt("err: New email address (-new_email) argument was not found or is empty.\n");
@ -474,6 +526,8 @@ void OverWriteEmail::procArgs(const QString &uName, const QString &newEmail, boo
} }
else else
{ {
retCode = NO_ERRORS;
Query db(this); Query db(this);
db.setType(Query::UPDATE, TABLE_USERS); db.setType(Query::UPDATE, TABLE_USERS);
@ -490,9 +544,9 @@ void OverWriteEmail::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (dType == TEXT) if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 4); auto args = parseArgs(binIn, 4);
QString uName = getParam("-user", args); auto uName = getParam("-user", args);
QString newEmail = getParam("-new_email", args); auto newEmail = getParam("-new_email", args);
procArgs(uName, newEmail, false); procArgs(uName, newEmail, false);
} }
@ -502,8 +556,8 @@ void ChangeEmail::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (dType == TEXT) if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 2); auto args = parseArgs(binIn, 2);
QString newEmail = getParam("-new_email", args); auto newEmail = getParam("-new_email", args);
procArgs(rdStringFromBlock(userName, BLKSIZE_USER_NAME), newEmail, true); procArgs(rdStringFromBlock(userName, BLKSIZE_USER_NAME), newEmail, true);
} }
@ -523,10 +577,13 @@ void PasswordChangeRequest::procIn(const QByteArray &binIn, quint8 dType)
{ {
if (dType == TEXT) if (dType == TEXT)
{ {
QStringList args = parseArgs(binIn, 4); auto args = parseArgs(binIn, 4);
QString uName = getParam("-user", args); auto uName = getParam("-user", args);
QString req = getParam("-req", args); auto req = getParam("-req", args);
QByteArray uId;
QByteArray uId;
retCode = INVALID_PARAMS;
if (uName.isEmpty()) if (uName.isEmpty())
{ {
@ -554,6 +611,8 @@ void PasswordChangeRequest::procIn(const QByteArray &binIn, quint8 dType)
} }
else else
{ {
retCode = NO_ERRORS;
exec(uId, static_cast<bool>(req.toUInt())); exec(uId, static_cast<bool>(req.toUInt()));
} }
} }

View File

@ -226,6 +226,69 @@ bool validModPath(const QString &modPath)
return ret; return ret;
} }
bool acceptablePw(const QString &pw, const QString &uName, const QString &dispName, const QString &email, QString *errMsg)
{
auto ret = validPassword(pw);
if (!ret)
{
*errMsg = "err: Invalid password. it must be between 8-200 chars long containing numbers, mixed case letters and special chars.\n";
}
else if (ret && !email.isEmpty())
{
if (pw.contains(email, Qt::CaseInsensitive))
{
*errMsg = "err: Invalid password. it contains your email address.\n"; ret = false;
}
}
else if (ret && !uName.isEmpty())
{
if (pw.contains(uName, Qt::CaseInsensitive))
{
*errMsg = "err: Invalid password. it contains your user name.\n"; ret = false;
}
}
else if (ret && !dispName.isEmpty())
{
if (pw.contains(dispName, Qt::CaseInsensitive))
{
*errMsg = "err: Invalid password. it contains your display name.\n"; ret = false;
}
}
return ret;
}
bool acceptablePw(const QString &pw, const QByteArray &uId, QString *errMsg)
{
auto ret = false;
if (auth(uId, pw, TABLE_USERS))
{
*errMsg = "err: Invaild password. you cannot re-use your old password.\n";
}
else
{
Query db;
db.setType(Query::PULL, TABLE_USERS);
db.addColumn(COLUMN_EMAIL);
db.addColumn(COLUMN_USERNAME);
db.addColumn(COLUMN_DISPLAY_NAME);
db.addCondition(COLUMN_USER_ID, uId);
db.exec();
auto email = db.getData(COLUMN_EMAIL).toString();
auto uName = db.getData(COLUMN_USERNAME).toString();
auto dName = db.getData(COLUMN_DISPLAY_NAME).toString();
ret = acceptablePw(pw, uName, dName, email, errMsg);
}
return ret;
}
bool validPassword(const QString &pw) bool validPassword(const QString &pw)
{ {
bool ret = false; bool ret = false;
@ -656,6 +719,18 @@ QString getDispName(const QByteArray &uId)
return db.getData(COLUMN_DISPLAY_NAME).toString(); return db.getData(COLUMN_DISPLAY_NAME).toString();
} }
QString getUserName(const QByteArray &uId)
{
Query db;
db.setType(Query::PULL, TABLE_USERS);
db.addColumn(COLUMN_USERNAME);
db.addCondition(COLUMN_USER_ID, uId);
db.exec();
return db.getData(COLUMN_USERNAME).toString();
}
QString getEmailForUser(const QByteArray &uId) QString getEmailForUser(const QByteArray &uId)
{ {
Query db; Query db;
@ -866,7 +941,14 @@ bool ShellIPC::connectToHost()
if (!waitForConnected()) if (!waitForConnected())
{ {
QTextStream(stdout) << "" << endl << "Host instance not running." << endl << endl; if (QFileInfo(QDir::tempPath() + "/" + HOST_CONTROL_PIPE).exists())
{
QTextStream(stdout) << "" << endl << "Permission denied." << endl << endl;
}
else
{
QTextStream(stdout) << "" << endl << "Host instance not running." << endl << endl;
}
} }
return state() == QLocalSocket::ConnectedState; return state() == QLocalSocket::ConnectedState;

View File

@ -130,7 +130,6 @@ enum AsyncCommands : quint16
ASYNC_PING_PEERS = 38, // internal | private ASYNC_PING_PEERS = 38, // internal | private
ASYNC_OPEN_SUBCH = 39, // internal | private ASYNC_OPEN_SUBCH = 39, // internal | private
ASYNC_CLOSE_SUBCH = 40, // internal | private ASYNC_CLOSE_SUBCH = 40, // internal | private
ASYNC_UPDATE_BANS = 41, // internal | private
ASYNC_KEEP_ALIVE = 42, // internal | private ASYNC_KEEP_ALIVE = 42, // internal | private
ASYNC_SET_DIR = 43, // internal | private ASYNC_SET_DIR = 43, // internal | private
ASYNC_DEBUG_TEXT = 44 // internal | private ASYNC_DEBUG_TEXT = 44 // internal | private
@ -201,6 +200,17 @@ enum TypeID : quint8
RESUME_CMD = 29 RESUME_CMD = 29
}; };
enum RetCode : quint16
{
NO_ERRORS = 1, // task execution completed without any issues.
ABORTED = 2, // the task aborted via user or host intervention.
INVALID_PARAMS = 3, // invalid/missing parameters prevented the task from executing.
CRASH = 4, // the command process has crashed.
FAILED_TO_START = 5, // the command process could not start.
EXECUTION_FAIL = 6, // command specific error prevented execution of the task.
CUSTOM = 7 // indicates a custom return code.
};
enum GenFileType : quint8 enum GenFileType : quint8
{ {
GEN_UPLOAD = 2, GEN_UPLOAD = 2,
@ -227,6 +237,8 @@ void serializeThread(QThread *thr);
void mkPath(const QString &path); void mkPath(const QString &path);
void listDir(QList<QPair<QString,QString> > &list, const QString &srcPath, const QString &dstPath); void listDir(QList<QPair<QString,QString> > &list, const QString &srcPath, const QString &dstPath);
void containsActiveCh(const char *subChs, char *actBlock); void containsActiveCh(const char *subChs, char *actBlock);
bool acceptablePw(const QString &pw, const QByteArray &uId, QString *errMsg);
bool acceptablePw(const QString &pw, const QString &uName, const QString &dispName, const QString &email, QString *errMsg);
bool containsNewLine(const QString &str); bool containsNewLine(const QString &str);
bool validModPath(const QString &modPath); bool validModPath(const QString &modPath);
bool validUserName(const QString &uName); bool validUserName(const QString &uName);
@ -264,6 +276,7 @@ QString fromTEXT(const QByteArray &txt);
QString getUserNameForEmail(const QString &email); QString getUserNameForEmail(const QString &email);
QString getEmailForUser(const QByteArray &uId); QString getEmailForUser(const QByteArray &uId);
QString getDispName(const QByteArray &uId); QString getDispName(const QByteArray &uId);
QString getUserName(const QByteArray &uId);
QString boolStr(bool state); QString boolStr(bool state);
QString getParam(const QString &key, const QStringList &args); QString getParam(const QString &key, const QStringList &args);
QString escapeChars(const QString &str, const QChar &escapeChr, const QChar &chr); QString escapeChars(const QString &str, const QChar &escapeChr, const QChar &chr);

View File

@ -222,6 +222,29 @@ QByteArray getSalt(const QByteArray &uId, const QString &table)
return db.getData(COLUMN_SALT).toByteArray(); return db.getData(COLUMN_SALT).toByteArray();
} }
QByteArray rootUserId()
{
Query db;
db.setType(Query::PULL, TABLE_SERV_SETTINGS);
db.addColumn(COLUMN_ROOT_USER);
db.exec();
QByteArray id = db.getData(COLUMN_ROOT_USER).toByteArray();
if (id.isEmpty())
{
db.setType(Query::PULL, TABLE_USERS);
db.addColumn(COLUMN_USER_ID);
db.addCondition(COLUMN_USERNAME, DEFAULT_ROOT_USER);
db.exec();
id = db.getData(COLUMN_USER_ID).toByteArray();
}
return id;
}
bool createUser(const QString &userName, const QString &email, const QString &dispName, const QString &password) bool createUser(const QString &userName, const QString &email, const QString &dispName, const QString &password)
{ {
bool ret = false; bool ret = false;
@ -237,6 +260,7 @@ bool createUser(const QString &userName, const QString &email, const QString &di
db.addColumn(COLUMN_EMAIL_VERIFIED, false); db.addColumn(COLUMN_EMAIL_VERIFIED, false);
db.addColumn(COLUMN_NEED_PASS, false); db.addColumn(COLUMN_NEED_PASS, false);
db.addColumn(COLUMN_NEED_NAME, false); db.addColumn(COLUMN_NEED_NAME, false);
db.addColumn(COLUMN_LOCKED, false);
db.addColumn(COLUMN_USER_ID, newUId); db.addColumn(COLUMN_USER_ID, newUId);
db.addRandBlob(COLUMN_SALT, 128); db.addRandBlob(COLUMN_SALT, 128);

View File

@ -37,7 +37,7 @@
#include "shell.h" #include "shell.h"
#define APP_NAME "MRCI" #define APP_NAME "MRCI"
#define APP_VER "2.1.3" #define APP_VER "2.2.3"
#define APP_TARGET "mrci" #define APP_TARGET "mrci"
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
@ -67,6 +67,7 @@
#define USERNAME_SUB "%user_name%" #define USERNAME_SUB "%user_name%"
#define DATE_SUB "%date%" #define DATE_SUB "%date%"
#define INTERN_MOD_NAME ":internal_mod" #define INTERN_MOD_NAME ":internal_mod"
#define DEFAULT_ROOT_USER "root"
#define DEFAULT_CONFIRM_SUBJECT "Email Verification" #define DEFAULT_CONFIRM_SUBJECT "Email Verification"
#define DEFAULT_TEMP_PW_SUBJECT "Password Reset" #define DEFAULT_TEMP_PW_SUBJECT "Password Reset"
#define DEFAULT_LISTEN_ADDRESS "0.0.0.0" #define DEFAULT_LISTEN_ADDRESS "0.0.0.0"
@ -93,7 +94,6 @@ Your confirmation code is as follows:\n\n\
Date requested: %date%." Date requested: %date%."
#define TABLE_IPHIST "ip_history" #define TABLE_IPHIST "ip_history"
#define TABLE_IPBANS "ban_list"
#define TABLE_USERS "users" #define TABLE_USERS "users"
#define TABLE_SERV_SETTINGS "host_settings" #define TABLE_SERV_SETTINGS "host_settings"
#define TABLE_CMD_RANKS "command_ranks" #define TABLE_CMD_RANKS "command_ranks"
@ -160,6 +160,7 @@ Date requested: %date%."
#define COLUMN_MAX_SUB_CH "max_sub_channels" #define COLUMN_MAX_SUB_CH "max_sub_channels"
#define COLUMN_APP_NAME "client_app" #define COLUMN_APP_NAME "client_app"
#define COLUMN_DEFAULT_PASS "default_password" #define COLUMN_DEFAULT_PASS "default_password"
#define COLUMN_ROOT_USER "root_user"
QString genPw(); QString genPw();
QList<int> genSequence(int min, int max, int len); QList<int> genSequence(int min, int max, int len);
@ -172,6 +173,7 @@ QString columnType(const QString &column);
quint32 initHostRank(); quint32 initHostRank();
QByteArray getSalt(const QByteArray &uId, const QString &table); QByteArray getSalt(const QByteArray &uId, const QString &table);
QByteArray genUniqueHash(); QByteArray genUniqueHash();
QByteArray rootUserId();
bool createUser(const QString &userName, const QString &email, const QString &dispName, const QString &password); bool createUser(const QString &userName, const QString &email, const QString &dispName, const QString &password);
bool createTempPw(const QByteArray &uId, const QString &password); bool createTempPw(const QByteArray &uId, const QString &password);
bool updatePassword(const QByteArray &uId, const QString &password, const QString &table, bool requireNewPass = false); bool updatePassword(const QByteArray &uId, const QString &password, const QString &table, bool requireNewPass = false);

View File

@ -56,17 +56,6 @@ bool setupDb(QString *errMsg)
ret = query.exec(); ret = query.exec();
} }
if (ret)
{
query.setType(Query::CREATE_TABLE, TABLE_IPBANS);
query.addColumn(COLUMN_IPADDR);
query.addColumn(COLUMN_TIME);
query.setPrimary(COLUMN_IPADDR);
query.addUnique(COLUMN_IPADDR);
ret = query.exec();
}
if (ret) if (ret)
{ {
query.setType(Query::CREATE_TABLE, TABLE_CMD_RANKS); query.setType(Query::CREATE_TABLE, TABLE_CMD_RANKS);
@ -136,10 +125,10 @@ bool setupDb(QString *errMsg)
QByteArray uId = genUniqueHash(); QByteArray uId = genUniqueHash();
query.setType(Query::PUSH, TABLE_USERS); query.setType(Query::PUSH, TABLE_USERS);
query.addColumn(COLUMN_USERNAME, ROOT_USER); query.addColumn(COLUMN_USERNAME, DEFAULT_ROOT_USER);
query.addColumn(COLUMN_HOST_RANK, 1); query.addColumn(COLUMN_HOST_RANK, 1);
query.addColumn(COLUMN_NEED_PASS, true); query.addColumn(COLUMN_NEED_PASS, true);
query.addColumn(COLUMN_NEED_NAME, false); query.addColumn(COLUMN_NEED_NAME, true);
query.addColumn(COLUMN_LOCKED, false); query.addColumn(COLUMN_LOCKED, false);
query.addColumn(COLUMN_EMAIL_VERIFIED, false); query.addColumn(COLUMN_EMAIL_VERIFIED, false);
query.addColumn(COLUMN_USER_ID, uId); query.addColumn(COLUMN_USER_ID, uId);
@ -153,6 +142,14 @@ bool setupDb(QString *errMsg)
ret = updatePassword(uId, randPw, TABLE_USERS, true); ret = updatePassword(uId, randPw, TABLE_USERS, true);
} }
} }
else
{
query.setType(Query::UPDATE, TABLE_USERS);
query.addColumn(COLUMN_NEED_NAME, true);
query.addCondition(COLUMN_USERNAME, DEFAULT_ROOT_USER);
ret = query.exec();
}
} }
if (ret) if (ret)
@ -240,6 +237,7 @@ bool setupDb(QString *errMsg)
query.addColumn(COLUMN_ACTIVE_UPDATE); query.addColumn(COLUMN_ACTIVE_UPDATE);
query.addColumn(COLUMN_MAX_SUB_CH); query.addColumn(COLUMN_MAX_SUB_CH);
query.addColumn(COLUMN_DEFAULT_PASS); query.addColumn(COLUMN_DEFAULT_PASS);
query.addColumn(COLUMN_ROOT_USER);
ret = query.exec(); ret = query.exec();
@ -248,6 +246,8 @@ bool setupDb(QString *errMsg)
randPw = genPw(); randPw = genPw();
} }
QByteArray rootUId = rootUserId();
if (query.createExecuted()) if (query.createExecuted())
{ {
query.setType(Query::PUSH, TABLE_SERV_SETTINGS); query.setType(Query::PUSH, TABLE_SERV_SETTINGS);
@ -269,6 +269,7 @@ bool setupDb(QString *errMsg)
query.addColumn(COLUMN_ACTIVE_UPDATE, true); query.addColumn(COLUMN_ACTIVE_UPDATE, true);
query.addColumn(COLUMN_MAX_SUB_CH, DEFAULT_MAX_SUBS); query.addColumn(COLUMN_MAX_SUB_CH, DEFAULT_MAX_SUBS);
query.addColumn(COLUMN_DEFAULT_PASS, randPw); query.addColumn(COLUMN_DEFAULT_PASS, randPw);
query.addColumn(COLUMN_ROOT_USER, rootUId);
ret = query.exec(); ret = query.exec();
} }
@ -296,6 +297,7 @@ bool setupDb(QString *errMsg)
query.addColumn(COLUMN_ACTIVE_UPDATE); query.addColumn(COLUMN_ACTIVE_UPDATE);
query.addColumn(COLUMN_MAX_SUB_CH); query.addColumn(COLUMN_MAX_SUB_CH);
query.addColumn(COLUMN_DEFAULT_PASS); query.addColumn(COLUMN_DEFAULT_PASS);
query.addColumn(COLUMN_ROOT_USER);
ret = query.exec(); ret = query.exec();
@ -321,6 +323,7 @@ bool setupDb(QString *errMsg)
if (query.getData(COLUMN_ACTIVE_UPDATE).isNull()) defaults.addColumn(COLUMN_ACTIVE_UPDATE, true); if (query.getData(COLUMN_ACTIVE_UPDATE).isNull()) defaults.addColumn(COLUMN_ACTIVE_UPDATE, true);
if (query.getData(COLUMN_MAX_SUB_CH).isNull()) defaults.addColumn(COLUMN_MAX_SUB_CH, DEFAULT_MAX_SUBS); if (query.getData(COLUMN_MAX_SUB_CH).isNull()) defaults.addColumn(COLUMN_MAX_SUB_CH, DEFAULT_MAX_SUBS);
if (query.getData(COLUMN_DEFAULT_PASS).isNull()) defaults.addColumn(COLUMN_DEFAULT_PASS, randPw); if (query.getData(COLUMN_DEFAULT_PASS).isNull()) defaults.addColumn(COLUMN_DEFAULT_PASS, randPw);
if (query.getData(COLUMN_ROOT_USER).isNull()) defaults.addColumn(COLUMN_ROOT_USER, rootUId);
if (defaults.columns()) if (defaults.columns())
{ {

View File

@ -40,18 +40,6 @@ void msgHandler(QtMsgType type, const QMessageLogContext &context, const QString
} }
} }
QByteArray rootUserId()
{
Query db;
db.setType(Query::PULL, TABLE_USERS);
db.addColumn(COLUMN_USER_ID);
db.addCondition(COLUMN_USERNAME, ROOT_USER);
db.exec();
return db.getData(COLUMN_USER_ID).toByteArray();
}
void showHelp() void showHelp()
{ {
QTextStream txtOut(stdout); QTextStream txtOut(stdout);
@ -64,8 +52,9 @@ void showHelp()
txtOut << " -about : display versioning/warranty information about this application." << endl; txtOut << " -about : display versioning/warranty information about this application." << endl;
txtOut << " -addr {ip_address:port} : set the listening address and port for TCP clients." << endl; txtOut << " -addr {ip_address:port} : set the listening address and port for TCP clients." << endl;
txtOut << " -status : display status information about the host instance if it is currently running." << endl; txtOut << " -status : display status information about the host instance if it is currently running." << endl;
txtOut << " -reset_root : reset the root account password to the default password shown below." << endl; txtOut << " -reset_root : reset the root account password to the default password." << endl;
txtOut << " -host : start a new host instance. (this blocks)" << endl; txtOut << " -host : start a new host instance. (this blocks)" << endl;
txtOut << " -default_pw : show the default password." << endl;
txtOut << " -public_cmds : run the internal module to list it's public commands. for internal use only." << endl; txtOut << " -public_cmds : run the internal module to list it's public commands. for internal use only." << endl;
txtOut << " -exempt_cmds : run the internal module to list it's rank exempt commands. for internal use only." << endl; txtOut << " -exempt_cmds : run the internal module to list it's rank exempt commands. for internal use only." << endl;
txtOut << " -user_cmds : run the internal module to list it's user commands. for internal use only." << endl; txtOut << " -user_cmds : run the internal module to list it's user commands. for internal use only." << endl;
@ -74,19 +63,19 @@ void showHelp()
txtOut << " -pipe {pipe_name/path} : the named pipe used to establish a data connection with the session." << endl; txtOut << " -pipe {pipe_name/path} : the named pipe used to establish a data connection with the session." << endl;
txtOut << " -mem_ses {key_name} : the shared memory key for the session." << endl; txtOut << " -mem_ses {key_name} : the shared memory key for the session." << endl;
txtOut << " -mem_host {key_name} : the shared memory key for the host main process." << endl << endl; txtOut << " -mem_host {key_name} : the shared memory key for the host main process." << endl << endl;
txtOut << " default password: " << defaultPw() << endl << endl;
} }
void soeDueToDbErr(int *retCode) void soeDueToDbErr(int *retCode, const QString *errMsg)
{ {
*retCode = 1; *retCode = 1;
QTextStream(stderr) << "" << endl << "err: Unable to continue due to an unclean or non-existent database structure." << endl; QTextStream(stderr) << "" << endl << "err: Stop error." << endl;
QTextStream(stderr) << " what happened: " << endl << *errMsg << endl << endl;
} }
int shellToHost(const QStringList &args, QCoreApplication &app) int shellToHost(const QStringList &args, QCoreApplication &app)
{ {
int ret = 0; auto ret = 0;
auto *ipc = new ShellIPC(args, &app); auto *ipc = new ShellIPC(args, &app);
QObject::connect(ipc, SIGNAL(closeInstance()), &app, SLOT(quit())); QObject::connect(ipc, SIGNAL(closeInstance()), &app, SLOT(quit()));
@ -109,28 +98,19 @@ int main(int argc, char *argv[])
serializeThread(app.thread()); serializeThread(app.thread());
QString workDir = expandEnvVariables(qEnvironmentVariable(ENV_WORK_DIR, DEFAULT_WORK_DIR)); auto workDir = expandEnvVariables(qEnvironmentVariable(ENV_WORK_DIR, DEFAULT_WORK_DIR));
auto args = QCoreApplication::arguments();
auto ret = 0;
QDir::setCurrent(workDir); QDir::setCurrent(workDir);
QCoreApplication::setApplicationName(APP_NAME); QCoreApplication::setApplicationName(APP_NAME);
QCoreApplication::setApplicationVersion(APP_VER); QCoreApplication::setApplicationVersion(APP_VER);
QString err; QString err;
QStringList args = QCoreApplication::arguments();
bool dbFail = false;
int ret = 0;
if (!setupDb(&err))
{
QTextStream(stderr) << "" << endl << "err: Database setup error, the host will not be able to start without a solid database structure." << endl;
QTextStream(stderr) << " what happened: " << endl << err << endl;
dbFail = true;
}
qInstallMessageHandler(msgHandler); qInstallMessageHandler(msgHandler);
//args.append("-host"); // debug //args.append("-default_pw"); // debug
if (args.contains("-help", Qt::CaseInsensitive)) if (args.contains("-help", Qt::CaseInsensitive))
{ {
@ -142,18 +122,23 @@ int main(int argc, char *argv[])
QTextStream(stdout) << "Based on QT " << QT_VERSION_STR << " " << 8 * QT_POINTER_SIZE << "bit" << endl << endl; QTextStream(stdout) << "Based on QT " << QT_VERSION_STR << " " << 8 * QT_POINTER_SIZE << "bit" << endl << endl;
QTextStream(stdout) << "The program is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE" << endl; QTextStream(stdout) << "The program is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE" << endl;
QTextStream(stdout) << "WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE." << endl << endl; QTextStream(stdout) << "WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE." << endl << endl;
QTextStream(stdout) << " default password: " << defaultPw() << endl << endl;
}
else if (args.contains("-default_pw", Qt::CaseInsensitive))
{
QTextStream(stdout) << "" << endl << " Root User : " << getUserName(rootUserId()) << endl;
QTextStream(stdout) << " Default Password: " << defaultPw() << endl << endl;
} }
else if (args.contains("-addr", Qt::CaseInsensitive)) else if (args.contains("-addr", Qt::CaseInsensitive))
{ {
QString params = getParam("-addr", args); auto params = getParam("-addr", args);
QStringList addr = params.split(':'); auto addr = params.split(':');
ret = 128; ret = 128;
if (dbFail) if (!setupDb(&err))
{ {
soeDueToDbErr(&ret); soeDueToDbErr(&ret, &err);
} }
else if (addr.size() != 2) else if (addr.size() != 2)
{ {
@ -194,9 +179,9 @@ int main(int argc, char *argv[])
args.contains("-exempt_cmds", Qt::CaseInsensitive) || args.contains("-exempt_cmds", Qt::CaseInsensitive) ||
args.contains("-user_cmds", Qt::CaseInsensitive)) args.contains("-user_cmds", Qt::CaseInsensitive))
{ {
if (dbFail) if (!setupDb(&err))
{ {
soeDueToDbErr(&ret); soeDueToDbErr(&ret, &err);
} }
else else
{ {
@ -210,9 +195,9 @@ int main(int argc, char *argv[])
} }
else if (args.contains("-host", Qt::CaseInsensitive)) else if (args.contains("-host", Qt::CaseInsensitive))
{ {
if (dbFail) if (!setupDb(&err))
{ {
soeDueToDbErr(&ret); soeDueToDbErr(&ret, &err);
} }
else else
{ {
@ -230,13 +215,22 @@ int main(int argc, char *argv[])
} }
else if (args.contains("-reset_root", Qt::CaseInsensitive)) else if (args.contains("-reset_root", Qt::CaseInsensitive))
{ {
if (dbFail) if (!setupDb(&err))
{ {
soeDueToDbErr(&ret); soeDueToDbErr(&ret, &err);
} }
else else
{ {
updatePassword(rootUserId(), defaultPw(), TABLE_USERS, true); auto uId = rootUserId();
Query db(&app);
db.setType(Query::UPDATE, TABLE_USERS);
db.addColumn(COLUMN_LOCKED, false);
db.addCondition(COLUMN_USER_ID, uId);
db.exec();
updatePassword(uId, defaultPw(), TABLE_USERS, true);
} }
} }
else else

View File

@ -46,9 +46,6 @@ QStringList Module::userCmdList()
ret << CloseHost::cmdName(); ret << CloseHost::cmdName();
ret << RestartHost::cmdName(); ret << RestartHost::cmdName();
ret << ListBans::cmdName();
ret << BanIP::cmdName();
ret << UnBanIP::cmdName();
ret << Cast::cmdName(); ret << Cast::cmdName();
ret << OpenSubChannel::cmdName(); ret << OpenSubChannel::cmdName();
ret << CloseSubChannel::cmdName(); ret << CloseSubChannel::cmdName();
@ -57,7 +54,7 @@ QStringList Module::userCmdList()
ret << IPHist::cmdName(); ret << IPHist::cmdName();
ret << ListMods::cmdName(); ret << ListMods::cmdName();
ret << DelMod::cmdName(); ret << DelMod::cmdName();
ret << UploadMod::cmdName(); ret << AddMod::cmdName();
ret << ListUsers::cmdName(); ret << ListUsers::cmdName();
ret << CreateUser::cmdName(); ret << CreateUser::cmdName();
ret << RecoverAcct::cmdName(); ret << RecoverAcct::cmdName();
@ -171,9 +168,6 @@ bool Module::runCmd(const QString &name)
if (noCaseMatch(name, CloseHost::cmdName())) new CloseHost(this); if (noCaseMatch(name, CloseHost::cmdName())) new CloseHost(this);
else if (noCaseMatch(name, RestartHost::cmdName())) new RestartHost(this); else if (noCaseMatch(name, RestartHost::cmdName())) new RestartHost(this);
else if (noCaseMatch(name, Auth::cmdName())) new Auth(this); else if (noCaseMatch(name, Auth::cmdName())) new Auth(this);
else if (noCaseMatch(name, ListBans::cmdName())) new ListBans(this);
else if (noCaseMatch(name, BanIP::cmdName())) new BanIP(this);
else if (noCaseMatch(name, UnBanIP::cmdName())) new UnBanIP(this);
else if (noCaseMatch(name, Cast::cmdName())) new Cast(this); else if (noCaseMatch(name, Cast::cmdName())) new Cast(this);
else if (noCaseMatch(name, OpenSubChannel::cmdName())) new OpenSubChannel(this); else if (noCaseMatch(name, OpenSubChannel::cmdName())) new OpenSubChannel(this);
else if (noCaseMatch(name, CloseSubChannel::cmdName())) new CloseSubChannel(this); else if (noCaseMatch(name, CloseSubChannel::cmdName())) new CloseSubChannel(this);
@ -182,7 +176,7 @@ bool Module::runCmd(const QString &name)
else if (noCaseMatch(name, IPHist::cmdName())) new IPHist(this); else if (noCaseMatch(name, IPHist::cmdName())) new IPHist(this);
else if (noCaseMatch(name, ListMods::cmdName())) new ListMods(this); else if (noCaseMatch(name, ListMods::cmdName())) new ListMods(this);
else if (noCaseMatch(name, DelMod::cmdName())) new DelMod(this); else if (noCaseMatch(name, DelMod::cmdName())) new DelMod(this);
else if (noCaseMatch(name, UploadMod::cmdName())) new UploadMod(this); else if (noCaseMatch(name, AddMod::cmdName())) new AddMod(this);
else if (noCaseMatch(name, ListUsers::cmdName())) new ListUsers(this); else if (noCaseMatch(name, ListUsers::cmdName())) new ListUsers(this);
else if (noCaseMatch(name, CreateUser::cmdName())) new CreateUser(this); else if (noCaseMatch(name, CreateUser::cmdName())) new CreateUser(this);
else if (noCaseMatch(name, RecoverAcct::cmdName())) new RecoverAcct(this); else if (noCaseMatch(name, RecoverAcct::cmdName())) new RecoverAcct(this);

View File

@ -20,7 +20,6 @@
#include "common.h" #include "common.h"
#include "cmd_object.h" #include "cmd_object.h"
#include "commands/admin.h" #include "commands/admin.h"
#include "commands/bans.h"
#include "commands/cast.h" #include "commands/cast.h"
#include "commands/info.h" #include "commands/info.h"
#include "commands/mods.h" #include "commands/mods.h"

View File

@ -18,9 +18,9 @@
QByteArray wrFrame(quint32 cmdId, const QByteArray &data, uchar dType) QByteArray wrFrame(quint32 cmdId, const QByteArray &data, uchar dType)
{ {
QByteArray typeBa = wrInt(dType, 8); auto typeBa = wrInt(dType, 8);
QByteArray cmdBa = wrInt(cmdId, 32); auto cmdBa = wrInt(cmdId, 32);
QByteArray sizeBa = wrInt(data.size(), MAX_FRAME_BITS); auto sizeBa = wrInt(data.size(), MAX_FRAME_BITS);
return typeBa + cmdBa + sizeBa + data; return typeBa + cmdBa + sizeBa + data;
} }
@ -55,8 +55,8 @@ void Session::init()
QByteArray Session::genSessionId() QByteArray Session::genSessionId()
{ {
QByteArray serial = genSerialNumber().toUtf8(); auto serial = genSerialNumber().toUtf8();
QByteArray sysId = QSysInfo::machineUniqueId(); auto sysId = QSysInfo::machineUniqueId();
QCryptographicHash hasher(QCryptographicHash::Sha3_224); QCryptographicHash hasher(QCryptographicHash::Sha3_224);
@ -106,9 +106,9 @@ void Session::addIpAction(const QString &action)
{ {
Query db(this); Query db(this);
QString ip = rdStringFromBlock(clientIp, BLKSIZE_CLIENT_IP); auto ip = rdStringFromBlock(clientIp, BLKSIZE_CLIENT_IP);
QString app = rdStringFromBlock(appName, BLKSIZE_APP_NAME); auto app = rdStringFromBlock(appName, BLKSIZE_APP_NAME);
QByteArray id = rdFromBlock(sessionId, BLKSIZE_SESSION_ID); auto id = rdFromBlock(sessionId, BLKSIZE_SESSION_ID);
db.setType(Query::PUSH, TABLE_IPHIST); db.setType(Query::PUSH, TABLE_IPHIST);
db.addColumn(COLUMN_IPADDR, ip); db.addColumn(COLUMN_IPADDR, ip);
@ -594,10 +594,6 @@ void Session::privAsyncDataIn(quint16 cmdId, const QByteArray &data)
{ {
emit setMaxSessions(static_cast<quint32>(rdInt(data))); emit setMaxSessions(static_cast<quint32>(rdInt(data)));
} }
else if (cmdId == ASYNC_UPDATE_BANS)
{
emit updateBanList();
}
else if (cmdId == ASYNC_PING_PEERS) else if (cmdId == ASYNC_PING_PEERS)
{ {
castPingForPeers(); castPingForPeers();

View File

@ -118,7 +118,6 @@ signals:
void ended(); void ended();
void closeServer(); void closeServer();
void resServer(); void resServer();
void updateBanList();
void killMods(); void killMods();
}; };

View File

@ -62,7 +62,7 @@ void TCPServer::closedPipeConnection()
bool TCPServer::createPipe() bool TCPServer::createPipe()
{ {
bool ret = controlPipe->listen(HOST_CONTROL_PIPE); auto ret = controlPipe->listen(HOST_CONTROL_PIPE);
controlPipePath = controlPipe->fullServerName(); controlPipePath = controlPipe->fullServerName();
@ -94,9 +94,9 @@ bool TCPServer::start()
maxSessions = db.getData(COLUMN_MAXSESSIONS).toUInt(); maxSessions = db.getData(COLUMN_MAXSESSIONS).toUInt();
bool ret = false; auto ret = false;
QString addr = db.getData(COLUMN_IPADDR).toString(); auto addr = db.getData(COLUMN_IPADDR).toString();
quint16 port = static_cast<quint16>(db.getData(COLUMN_PORT).toUInt()); auto port = static_cast<quint16>(db.getData(COLUMN_PORT).toUInt());
if (!createPipe()) if (!createPipe())
{ {
@ -115,8 +115,6 @@ bool TCPServer::start()
} }
else else
{ {
updateBanList();
ret = true; ret = true;
flags |= ACCEPTING; flags |= ACCEPTING;
} }
@ -200,7 +198,7 @@ bool TCPServer::servOverloaded()
void TCPServer::procPipeIn() void TCPServer::procPipeIn()
{ {
QStringList args = parseArgs(controlSocket->readAll(), -1); auto args = parseArgs(controlSocket->readAll(), -1);
if (args.contains("-stop", Qt::CaseInsensitive)) if (args.contains("-stop", Qt::CaseInsensitive))
{ {
@ -235,22 +233,6 @@ void TCPServer::procPipeIn()
} }
} }
void TCPServer::updateBanList()
{
banList.clear();
Query db(this);
db.setType(Query::PULL, TABLE_IPBANS);
db.addColumn(COLUMN_IPADDR);
db.exec();
for (int i = 0; i < db.rows(); ++i)
{
banList.append(db.getData(COLUMN_IPADDR, i).toString());
}
}
void TCPServer::setMaxSessions(quint32 value) void TCPServer::setMaxSessions(quint32 value)
{ {
Query db(this); Query db(this);
@ -278,48 +260,40 @@ void TCPServer::incomingConnection(qintptr socketDescriptor)
{ {
resumeAccepting(); resumeAccepting();
if (banList.contains(soc->peerAddress().toString(), Qt::CaseInsensitive)) auto buffSize = static_cast<uint>(qPow(2, MAX_FRAME_BITS) - 1) + (MAX_FRAME_BITS / 8) + 4;
{ // max_data_size_per_frame + size_of_size_bytes + size_of_cmd_id
soc->deleteLater();
}
else
{
auto buffSize = static_cast<uint>(qPow(2, MAX_FRAME_BITS) - 1) + (MAX_FRAME_BITS / 8) + 4;
// max_data_size_per_frame + size_of_size_bytes + size_of_cmd_id
soc->setSocketOption(QAbstractSocket::ReceiveBufferSizeSocketOption, buffSize); soc->setSocketOption(QAbstractSocket::ReceiveBufferSizeSocketOption, buffSize);
soc->setSocketOption(QAbstractSocket::SendBufferSizeSocketOption, buffSize); soc->setSocketOption(QAbstractSocket::SendBufferSizeSocketOption, buffSize);
auto *ses = new Session(hostKey, soc, nullptr); auto *ses = new Session(hostKey, soc, nullptr);
auto *thr = new QThread(nullptr); auto *thr = new QThread(nullptr);
connect(thr, &QThread::finished, soc, &QSslSocket::deleteLater); connect(thr, &QThread::finished, soc, &QSslSocket::deleteLater);
connect(thr, &QThread::finished, ses, &QSslSocket::deleteLater); connect(thr, &QThread::finished, ses, &QSslSocket::deleteLater);
connect(thr, &QThread::finished, thr, &QSslSocket::deleteLater); connect(thr, &QThread::finished, thr, &QSslSocket::deleteLater);
connect(thr, &QThread::started, ses, &Session::init); connect(thr, &QThread::started, ses, &Session::init);
connect(ses, &Session::ended, this, &TCPServer::sessionEnded); connect(ses, &Session::ended, this, &TCPServer::sessionEnded);
connect(ses, &Session::ended, thr, &QThread::quit); connect(ses, &Session::ended, thr, &QThread::quit);
connect(ses, &Session::connectPeers, this, &TCPServer::connectPeers); connect(ses, &Session::connectPeers, this, &TCPServer::connectPeers);
connect(ses, &Session::closeServer, this, &TCPServer::closeServer); connect(ses, &Session::closeServer, this, &TCPServer::closeServer);
connect(ses, &Session::resServer, this, &TCPServer::resServer); connect(ses, &Session::resServer, this, &TCPServer::resServer);
connect(ses, &Session::setMaxSessions, this, &TCPServer::setMaxSessions); connect(ses, &Session::setMaxSessions, this, &TCPServer::setMaxSessions);
connect(ses, &Session::updateBanList, this, &TCPServer::updateBanList);
connect(this, &TCPServer::connectPeers, ses, &Session::connectToPeer); connect(this, &TCPServer::connectPeers, ses, &Session::connectToPeer);
connect(this, &TCPServer::endAllSessions, ses, &Session::endSession); connect(this, &TCPServer::endAllSessions, ses, &Session::endSession);
serializeThread(thr); serializeThread(thr);
ses->moveToThread(thr); ses->moveToThread(thr);
soc->moveToThread(thr); soc->moveToThread(thr);
thr->start(); thr->start();
hostSharedMem->lock(); hostSharedMem->lock();
wr32BitToBlock((rd32BitFromBlock(hostLoad) + 1), hostLoad); wr32BitToBlock((rd32BitFromBlock(hostLoad) + 1), hostLoad);
hostSharedMem->unlock(); hostSharedMem->unlock();
}
} }
} }

View File

@ -34,7 +34,6 @@ private:
QLocalServer *controlPipe; QLocalServer *controlPipe;
QLocalSocket *controlSocket; QLocalSocket *controlSocket;
char *hostLoad; char *hostLoad;
QStringList banList;
QString controlPipePath; QString controlPipePath;
QString hostKey; QString hostKey;
quint32 maxSessions; quint32 maxSessions;
@ -50,7 +49,6 @@ private slots:
void newPipeConnection(); void newPipeConnection();
void closedPipeConnection(); void closedPipeConnection();
void sessionEnded(); void sessionEnded();
void updateBanList();
void setMaxSessions(quint32 value); void setMaxSessions(quint32 value);
public slots: public slots: