Major upgrade and module interface changes
Made some major changes to the project to facilitate a lighter code base and the must flexible module interface possible. -the mutli-process architecture now operate at the command object level so each command now operate in it's own process instead of a single process handling multiple command objects. -each module is now an independent application that will now tell the session object all of the commands it can run via named pipe. during command execution, it will run the requested command object also running io with the session object via named pipe. with this change, it is now possible for modules to be developed in different versions or QT or entirely different languages. the only requirement is the need to support named pipes. shared memory segments is also a nice to have but not needed. -clients can now run multiple instances of the same command via changes to the protocol. mrci frames will now include a branch id along with the command id. the branch id can be used by clients to differentiate the io between instances of the same command. -the command states are longer controlled by a single object. it will now be up to the command object (internal/exterenal) to send an IDLE frame to the client to notify it that the command has finished. the session object will still track if the command is in idle state or not but not directly control it. -must async commands now use binary formatted data instead of TEXT as a way to reduce overhead. -all command objects can now send async commands. it is no longer limited to just internal commands, however; the data of these async commands are verified by session in some way to prevent host crashing due to malformed data. -changed up the database structure to rely more on user ids, channel ids and removed all foreign keys pointing to user names, channel names and sub-channel names. also removed the groups table altogether. instead, the host rank is now directly attached to the user data in the users table. -changed the query object to now support the INNER JOIN SQL clause. this change was needed to support the new database structure. -version negotiation is now one-way via tcp connection or module interface. the host will make it's own verion numner known to the client connected via tcp or the module connected via named pipe. it will now be entirely up to the client or module to decide if they support the host. another change in this regard is the removal of the import rev for the modules. compatibility for modules shall now use just the host verion. -removed ls_cmds and cmd_info. the NEW_CMD frame now carries all information about the command (cmd_id, cmd_name, summery, io and full_description) so it is now possible for the clients to display the command documentation instead of the host. Documentation for the internal commands were updated to reflect the changes but all other documentation will need to be updated in the near future.
This commit is contained in:
parent
73409ca26e
commit
72d57a0b10
19
MRCI.pro
19
MRCI.pro
|
@ -40,58 +40,57 @@ win32 {
|
|||
}
|
||||
|
||||
SOURCES += src/main.cpp \
|
||||
src/async_funcs.cpp \
|
||||
src/cmd_object.cpp \
|
||||
src/cmd_proc.cpp \
|
||||
src/commands/channels.cpp \
|
||||
src/commands/cmd_ranks.cpp \
|
||||
src/commands/p2p.cpp \
|
||||
src/mem_share.cpp \
|
||||
src/module.cpp \
|
||||
src/session.cpp \
|
||||
src/db.cpp \
|
||||
src/make_cert.cpp \
|
||||
src/int_loader.cpp \
|
||||
src/tcp_server.cpp \
|
||||
src/unix_signal.cpp \
|
||||
src/cmd_executor.cpp \
|
||||
src/common.cpp \
|
||||
src/shell.cpp \
|
||||
src/db_setup.cpp \
|
||||
src/commands/users.cpp \
|
||||
src/commands/mods.cpp \
|
||||
src/commands/info.cpp \
|
||||
src/commands/groups.cpp \
|
||||
src/commands/cast.cpp \
|
||||
src/commands/bans.cpp \
|
||||
src/commands/admin.cpp \
|
||||
src/commands/auth.cpp \
|
||||
src/commands/command.cpp \
|
||||
src/commands/cmd_state.cpp \
|
||||
src/commands/acct_recovery.cpp \
|
||||
src/commands/table_viewer.cpp \
|
||||
src/commands/fs.cpp \
|
||||
src/commands/certs.cpp
|
||||
|
||||
HEADERS += \
|
||||
src/cmd_object.h \
|
||||
src/cmd_proc.h \
|
||||
src/commands/channels.h \
|
||||
src/commands/cmd_ranks.h \
|
||||
src/commands/p2p.h \
|
||||
src/mem_share.h \
|
||||
src/module.h \
|
||||
src/session.h \
|
||||
src/db.h \
|
||||
src/make_cert.h \
|
||||
src/int_loader.h \
|
||||
src/tcp_server.h \
|
||||
src/unix_signal.h \
|
||||
src/cmd_executor.h \
|
||||
src/common.h \
|
||||
src/shell.h \
|
||||
src/db_setup.h \
|
||||
src/commands/users.h \
|
||||
src/commands/mods.h \
|
||||
src/commands/info.h \
|
||||
src/commands/groups.h \
|
||||
src/commands/cast.h \
|
||||
src/commands/bans.h \
|
||||
src/commands/admin.h \
|
||||
src/commands/auth.h \
|
||||
src/commands/command.h \
|
||||
src/commands/cmd_state.h \
|
||||
src/commands/acct_recovery.h \
|
||||
src/commands/table_viewer.h \
|
||||
src/commands/fs.h \
|
||||
|
|
11
cmd_docs.qrc
11
cmd_docs.qrc
|
@ -5,7 +5,6 @@
|
|||
<file>docs/intern_commands/add_ban.md</file>
|
||||
<file>docs/intern_commands/add_cert.md</file>
|
||||
<file>docs/intern_commands/add_ch.md</file>
|
||||
<file>docs/intern_commands/add_group.md</file>
|
||||
<file>docs/intern_commands/add_mod.md</file>
|
||||
<file>docs/intern_commands/add_ranked_cmd.md</file>
|
||||
<file>docs/intern_commands/add_rdonly_flag.md</file>
|
||||
|
@ -15,7 +14,6 @@
|
|||
<file>docs/intern_commands/cert_info.md</file>
|
||||
<file>docs/intern_commands/close_host.md</file>
|
||||
<file>docs/intern_commands/close_sub_ch.md</file>
|
||||
<file>docs/intern_commands/cmd_info.md</file>
|
||||
<file>docs/intern_commands/decline_ch.md</file>
|
||||
<file>docs/intern_commands/find_ch.md</file>
|
||||
<file>docs/intern_commands/force_set_email.md</file>
|
||||
|
@ -40,9 +38,7 @@
|
|||
<file>docs/intern_commands/ls_certs.md</file>
|
||||
<file>docs/intern_commands/ls_ch_members.md</file>
|
||||
<file>docs/intern_commands/ls_chs.md</file>
|
||||
<file>docs/intern_commands/ls_cmds.md</file>
|
||||
<file>docs/intern_commands/ls_dbg.md</file>
|
||||
<file>docs/intern_commands/ls_groups.md</file>
|
||||
<file>docs/intern_commands/ls_mods.md</file>
|
||||
<file>docs/intern_commands/ls_open_chs.md</file>
|
||||
<file>docs/intern_commands/ls_p2p.md</file>
|
||||
|
@ -55,7 +51,6 @@
|
|||
<file>docs/intern_commands/p2p_close.md</file>
|
||||
<file>docs/intern_commands/p2p_open.md</file>
|
||||
<file>docs/intern_commands/p2p_request.md</file>
|
||||
<file>docs/intern_commands/pause.md</file>
|
||||
<file>docs/intern_commands/ping_peers.md</file>
|
||||
<file>docs/intern_commands/preview_email.md</file>
|
||||
<file>docs/intern_commands/recover_acct.md</file>
|
||||
|
@ -66,7 +61,6 @@
|
|||
<file>docs/intern_commands/request_new_user_name.md</file>
|
||||
<file>docs/intern_commands/request_pw_reset.md</file>
|
||||
<file>docs/intern_commands/restart_host.md</file>
|
||||
<file>docs/intern_commands/resume.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>
|
||||
|
@ -79,16 +73,13 @@
|
|||
<file>docs/intern_commands/set_disp_name.md</file>
|
||||
<file>docs/intern_commands/set_email_template.md</file>
|
||||
<file>docs/intern_commands/set_email.md</file>
|
||||
<file>docs/intern_commands/set_group_rank.md</file>
|
||||
<file>docs/intern_commands/set_group.md</file>
|
||||
<file>docs/intern_commands/set_member_level.md</file>
|
||||
<file>docs/intern_commands/set_pw.md</file>
|
||||
<file>docs/intern_commands/set_sub_ch_level.md</file>
|
||||
<file>docs/intern_commands/set_user_name.md</file>
|
||||
<file>docs/intern_commands/term.md</file>
|
||||
<file>docs/intern_commands/to_peer.md</file>
|
||||
<file>docs/intern_commands/trans_group.md</file>
|
||||
<file>docs/intern_commands/verify_email.md</file>
|
||||
<file>docs/intern_commands/ch_owner_override.md</file>
|
||||
<file>docs/intern_commands/set_user_rank.md</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
@ -3,26 +3,34 @@
|
|||
All mrci frames transferred throughout this application are usually passed into various functions using a ```uchar``` numeric value to indicate the type of data being passed with the ```QByteArray``` that are also usually passed into the functions. The type id enum values are as follows:
|
||||
|
||||
```
|
||||
enum TypeID
|
||||
enum TypeID : quint8
|
||||
{
|
||||
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
|
||||
GEN_FILE = 1,
|
||||
TEXT = 2,
|
||||
ERR = 3,
|
||||
PRIV_TEXT = 4,
|
||||
IDLE = 5,
|
||||
HOST_CERT = 6,
|
||||
FILE_INFO = 7,
|
||||
PEER_INFO = 8,
|
||||
MY_INFO = 9,
|
||||
PEER_STAT = 10,
|
||||
P2P_REQUEST = 11,
|
||||
P2P_CLOSE = 12,
|
||||
P2P_OPEN = 13,
|
||||
BYTES = 14,
|
||||
SESSION_ID = 15,
|
||||
NEW_CMD = 16,
|
||||
CMD_ID = 17,
|
||||
BIG_TEXT = 18,
|
||||
TERM_CMD = 19,
|
||||
HOST_VER = 20,
|
||||
PRIV_IPC = 21,
|
||||
PUB_IPC = 22,
|
||||
PUB_IPC_WITH_FEEDBACK = 23,
|
||||
PING_PEERS = 24,
|
||||
CH_MEMBER_INFO = 25,
|
||||
CH_ID = 26
|
||||
};
|
||||
```
|
||||
|
||||
|
@ -131,8 +139,8 @@ This contains all of the information found in ```PEER_INFO``` for the local sess
|
|||
```
|
||||
format:
|
||||
1. bytes[300-427] 128bytes - email (TEXT - padded with empty spaces)
|
||||
2. bytes[428-451] 24bytes - group name (TEXT - padded with empty spaces)
|
||||
3. bytes[452] 1byte - is email confirmed? (0x00 false, 0x01 true)
|
||||
2. bytes[428-431] 4bytes - host rank (32bit unsigned int)
|
||||
3. bytes[432] 1byte - is email confirmed? (0x00 false, 0x01 true)
|
||||
```
|
||||
|
||||
```NEW_CMD```
|
||||
|
@ -142,17 +150,19 @@ This contains information about a new command that was added to the current sess
|
|||
format:
|
||||
1. bytes[0-1] 2bytes - 16bit LE unsigned int (command id)
|
||||
2. bytes[2] 1byte - bool (0x01 or 0x00) (handles gen file)
|
||||
3. bytes[3-130] 128bytes - command name (TEXT - padded with empty spaces)
|
||||
4. bytes[131-258] 128bytes - library name (TEXT - padded with empty spaces)
|
||||
3. bytes[3-130] 128bytes - command name (TEXT - padded with 0x00)
|
||||
4. bytes[131-258] 128bytes - library name (TEXT - padded with 0x00)
|
||||
5. bytes[259-n] variable - short text (16bit null terminated)
|
||||
6. bytes[n-n] variable - io text (16bit null terminated)
|
||||
7. bytes[n-n] variable - long text (16bit null terminated)
|
||||
|
||||
notes:
|
||||
1. the handles gen file flag is a single byte 0x01 to indicate true and
|
||||
0x00 to indicate false. clients need to be aware of which command
|
||||
handles the GEN_FILE mini protocol because it requires user input at
|
||||
both ends (host and client).
|
||||
2. the library name is what ever is returned by the command object's
|
||||
ExternCommand::libText() function. this can contain the module name
|
||||
and/or extra informaion the client can use to identify the command.
|
||||
2. the library name can contain the module name and/or extra informaion
|
||||
the client can use to identify the library the command is a part of.
|
||||
```
|
||||
|
||||
```CMD_ID```
|
||||
|
@ -201,6 +211,30 @@ format: ```28bytes - session id (224bit sha3 hash)```
|
|||
```BYTES```
|
||||
This contains arbitrary binary data of any format that is not specialized for any internal objects in the host.
|
||||
|
||||
```CH_MEMBER_INFO```
|
||||
This contains public information about a channel member.
|
||||
|
||||
```
|
||||
format:
|
||||
1. bytes[0-7] 8bytes - channel id (64bit unsigned int)
|
||||
2. bytes[8-39] 32bytes - user id (256bit hash)
|
||||
3. bytes[40] 1byte - is invite? (0x00=false, 0x01=true)
|
||||
4. bytes[41] 1byte - member's channel privilege level (8bit unsigned int)
|
||||
5. bytes[42-n] variable - user name (TEXT - 16bit null terminated)
|
||||
6. bytes[n-n] variable - display name (TEXT - 16bit null terminated)
|
||||
7. bytes[n-n] variable - channel name (TEXT - 16bit null terminated)
|
||||
|
||||
notes:
|
||||
1. a 16bit null terminated TEXT formatted string ended with 2 bytes of
|
||||
(0x00) to indicate the end of the string data.
|
||||
2. the member's privilege level can be any of the values discribed in
|
||||
section [5.3](Host_Features.md).
|
||||
3. is invite? indicates if this user has received an invite to join
|
||||
that channel by has not accepted yet. if, accepted the user will
|
||||
become a full member of the channel at the level indicated by this
|
||||
data type.
|
||||
```
|
||||
|
||||
### 4.3 GEN_FILE Example ###
|
||||
|
||||
Setup:
|
||||
|
|
|
@ -8,4 +8,4 @@ create a new host user account.
|
|||
|
||||
### 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 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.
|
||||
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.
|
|
@ -1,6 +1,6 @@
|
|||
### Summary ###
|
||||
|
||||
install a new SSL/TLS cert into the host from a local cert and private key file.
|
||||
install a new SSL/TLS cert into the host.
|
||||
|
||||
### IO ###
|
||||
|
||||
|
@ -8,4 +8,4 @@ install a new SSL/TLS cert into the host from a local cert and private key file.
|
|||
|
||||
### Description ###
|
||||
|
||||
add an SSL/TLS certificate to a common name given in -name. the common name is used by clients to request certain certificate installed in the host. certificates usually come in seperate cert file and private key file pairs. -cert is the file path to the cert file and -priv is the path to the private key. the files must be formatted in Pem or Der (extension doesn't matter). once installed, the file pairs no longer need to exists for the host to use them. you can the pass the optional -force option to replace a common name if it already exists without asking a confirmation question.
|
||||
add an SSL/TLS certificate to a common name given in -name. the common name is used by clients to request a certain certificate installed in the host. certificates usually come in seperate cert file and private key file pairs. -cert is the file path to the cert file and -priv is the path to the private key. the files must be formatted in Pem or Der (extension doesn't matter). once installed, the file pairs no longer need to exists for the host to use them. you can the pass the optional -force option to replace a common name if it already exists without asking a confirmation question.
|
|
@ -8,4 +8,4 @@ create a new channel.
|
|||
|
||||
### Description ###
|
||||
|
||||
create a new channel with a unique name given in -ch_name. this command will automatically add the currently logged in user as a member and set it as the channel owner. being a channel owner prevents you from being able to delete your account at a later time. you will need to name a new owner from the channel member list or delete the entire channel to allow account deletion. the host will automatically assign a unique channel id for the new channel. channels are used for broadcast peer to peer data transfers within the host and the base channel created by this command is used to manage who has access to such data.
|
||||
create a new channel with a unique name given in -ch_name. this command will automatically add the currently logged in user as a member and set it as the channel owner. being a channel owner prevents you from being able to delete your account at a later time. you will need to name a new owner from the channel member list or delete the entire channel to allow account deletion. the host will automatically assign a unique channel id for the new channel. channels are used to broadcast peer to peer data transfers within the host and is used to manage who has access to such data.
|
|
@ -1,11 +0,0 @@
|
|||
### Summary ###
|
||||
|
||||
create a new host group.
|
||||
|
||||
### IO ###
|
||||
|
||||
```[-name (text)]/[text]```
|
||||
|
||||
### Description ###
|
||||
|
||||
this will create a new host group with the unique group name given in -name. all new groups are initialized at rank 2. this can be reconfigured at any time using various group editing commands. host groups are used to manage the access level of all users. each user registered in the host must be assigned a group and each group must be assigned a host rank. the rank is numeric integer that indicates the value of the group's rank. The lower it's numeric value, the higher the level of access the users in that group have in the host with 0 being invalid.
|
|
@ -1,15 +1,11 @@
|
|||
### Summary ###
|
||||
|
||||
upload a new module to install into the host.
|
||||
add a new module to the host.
|
||||
|
||||
### IO ###
|
||||
|
||||
```[-client_file (path) -name (text) -len (int)]/[text]```
|
||||
```[-mod_path (path)]/[text]```
|
||||
|
||||
### Description ###
|
||||
|
||||
upload a new module to the host using an archive file (.zip, .tar, .7z, etc...) or a loadable library file (.so, .dll, .a, etc...) using the GEN_FILE data type id. the module name is given in -name while GEN_FILE specific arguments like -len determine the size of the file being sent and -client_file determine the file location on the client's file system. note: the host will use -client_file argument to read the file's suffix and determine if it is an archive or library file.
|
||||
|
||||
once successfully unloaded; if it is an archive file, all of it's contents are extracted to the module installation directory. the archive file must contain a loadable library file called 'main' with any of the host platform compatible library suffixes like (.so, .dll, .a, etc...). if a library file is uploaded, it is simply copied over to the module installation directory as 'main.'
|
||||
|
||||
if successfully installed, all sessions are notified to load the new module. even after a successful install, the module can still fail to load. check the host debug log for failure details if that is the case.
|
||||
add a new module to the host in the form of a path to an executable file given in -mod_path. the path can be absolute, relative to the host working directory or can contain environmental variables. a module that gets successfully added to the database via this command does not guarantee it's commands will successfuly load. any failures during module loading will be logged in the host debug log.
|
|
@ -1,11 +1,11 @@
|
|||
### Summary ###
|
||||
|
||||
assign a rank to a command object name.
|
||||
assign a rank to a module's command name.
|
||||
|
||||
### IO ###
|
||||
|
||||
```[-command (text) -rank (int)]/[text]```
|
||||
```[-mod (text) -command (text) -rank (int)]/[text]```
|
||||
|
||||
### Description ###
|
||||
|
||||
this will assign the command rank in -rank to the command name given in -command. assigning ranks to commands give groups that have that rank or higher access to running the command. any commands that don't have an assigned rank is assumed a rank of 1. the lower the numeric value of the rank, the higher the rank (0 is invalid). some commands can claim immunity from host ranking which basically means the command is allowed to load/run regardless of the user's host rank. for internal commands, any commands that edit the user's own information like it's name, display name, password, etc including the login command and various session state commands have immunity.
|
||||
this will assign the command rank in -rank to the command name given in -command for the module executable given in -mod. assigning ranks to commands give users that have that rank or higher access to running the command. any commands that don't have an assigned rank is assumed a rank of 1. the lower the numeric value of the rank, the higher the rank (0 is invalid). some commands can claim immunity from host ranking which basically means the command is allowed to load/run regardless of the user's host rank. for internal commands, any commands that edit the user's own information like it's name, display name, password, etc including the login command have immunity. the path to the mod executable can be relative or absolute but this command doesn't check if it actually exists. for ranked command enforcement to work properly, the mod to command name relationship must match with what is actually there.
|
|
@ -8,4 +8,4 @@ add a read only flag to a certain sub-channel and privilege level.
|
|||
|
||||
### Description ###
|
||||
|
||||
this adds a read only flag to a sub-channel for users at a certain privilage level given in -level. valid privilage levels range 1-5 representing owner-level(1), admin-level(2), officer-level(3), regular-level(4) and public-level(5). the presents of a read only flag bassically tells the host that users connected to this sub-channel at this level can only receive data from this sub-channel and cannot cast data to the sub-channel. this is useful if you want to setup a channel that allow certain user(s) to broadcast data while everybody else can only listen for the data. the channel name given in -ch_name must already exists but the sub-channel id given in -sub_id doesn't need to exists (valid range 0-255) but what ever sub-channel name that takes the sub-id specified here gets the read only flag. only the channel owner-level(1) and admin-level(2) can add read only flags to sub-channels. also note that this command will cause all sessions that currently have the sub-channel open to close it. it will be up to the clients to re-open the sub-channel.
|
||||
this adds a read only flag to a sub-channel for users at a certain privilage level given in -level. valid privilage levels range 1-5 representing owner-level(1), admin-level(2), officer-level(3), regular-level(4) and public-level(5). the presents of a read only flag bassically tells the host that users connected to this sub-channel at this level can only receive data from this sub-channel and cannot cast data to the sub-channel. this is useful if you want to setup a channel that allow certain user(s) to broadcast data while everybody else can only listen for the data. the channel name given in -ch_name must already exists but the sub-channel id given in -sub_id doesn't need to exists (valid range 0-255) but what ever sub-channel name that takes the sub-id specified here gets the read only flag. only the channel owner-level(1) and admin-level(2) can add read only flags to sub-channels. also note that this command will cause all sessions that currently have the sub-channel open to close it. it will be up to the clients to re-open the sub-channel if they still have access.
|
|
@ -8,4 +8,4 @@ create a new sub-channel within a channel.
|
|||
|
||||
### Description ###
|
||||
|
||||
create a new sub-channel given in -sub_name for the channel given in -ch_name. only the channel owner-level(1) and admin-level(2) is allowed to do this. sub-channels are used to determine which clients can send/receive broadcast data. when a client broadcast data to a open sub-channel, the clients that want to receive that data will also need to have the matching sub-channel open.
|
||||
create a new sub-channel given in -sub_name for the channel given in -ch_name. only the channel owner-level(1) and admin-level(2) are allowed to do this. sub-channels are used to determine which clients can send/receive broadcast data. when a client broadcast data to a open sub-channel, the clients that want to receive that data will also need to have the matching sub-channel open.
|
|
@ -1,6 +1,6 @@
|
|||
### Summary ###
|
||||
|
||||
broadcast text/data to all sessions listening to any matching sub-channels.
|
||||
broadcast data to all sessions listening to any matching sub-channels.
|
||||
|
||||
### IO ###
|
||||
|
||||
|
|
|
@ -8,4 +8,4 @@ close the host instance.
|
|||
|
||||
### Description ###
|
||||
|
||||
this ends all sessions and closes the host main instance. be very careful with this command since it will shutdown the mrci host entirely so all clients will not be able to connect until it is started again.
|
||||
this ends all sessions and closes the host main instance. be very careful with this command since it will shutdown the mrci host application entirely so all clients will not be able to connect until it is started again.
|
|
@ -1,11 +0,0 @@
|
|||
### Summary ###
|
||||
|
||||
display detailed information about a command.
|
||||
|
||||
### IO ###
|
||||
|
||||
```[-cmd_name (text)] or [-cmd_id (int)]/[text]```
|
||||
|
||||
### Description ###
|
||||
|
||||
display more detailed information about the command name given in -cmd_name or the command id given in -cmd_id.
|
|
@ -8,4 +8,4 @@ display or change the current directory for the current session.
|
|||
|
||||
### Description ###
|
||||
|
||||
change the current directory of your current session to the directory specified in -path or display it if -path is not specified. note: the current directory is not shared among any of the peer sessions.
|
||||
change the current directory of your current session to the directory specified in -path or display it if -path is not specified. note: the current directory is not shared among any of the peer sessions and changes to it does not take effect on currently running commands until fully terminated (not IDLE but fully terminated via KILL_CMD).
|
|
@ -1,6 +1,6 @@
|
|||
### Summary ###
|
||||
|
||||
copy a file system object (file,directory,symlink) from one location to another.
|
||||
copy a file or directory in the host file system.
|
||||
|
||||
### IO ###
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
### Summary ###
|
||||
|
||||
attempt to delete a file system object (file,directory,symlink) in the host.
|
||||
delete a file or directory in the host file system.
|
||||
|
||||
### IO ###
|
||||
|
||||
|
|
|
@ -10,8 +10,8 @@ download a single file from the host.
|
|||
|
||||
this command sends GEN_FILE data of the file given in -remote_file. depending on the client, you might need to enter the destination file in -client_file.
|
||||
|
||||
-offset is the position in the file to start reading and it defaults to 0 if not given.
|
||||
-len is the amount of data to read from the file and the host will auto fill it to the file size if not given. the host also auto fill to the file size if it larger than the actual file size.
|
||||
-offset is the position in the file to start reading. it defaults to 0 if not given.
|
||||
-len is the amount of data to read from the file. the host will auto fill it to the file size if not given. the host also auto fill to the file size if it larger than the actual file size.
|
||||
-single_step enables GEN_FILE's single step mode if the client/host desires it.
|
||||
-force bypasses any overwrite confirmation question if the client does such a thing.
|
||||
-force bypasses any overwrite confirmation questions if the client does such a thing. the host does nothing with this. it's entirely up to the client to implement this option.
|
||||
-truncate tells the client if it should truncate the destination file. the host does nothing with this. it's entirely up to the client to support it.
|
|
@ -1,6 +1,6 @@
|
|||
### Summary ###
|
||||
|
||||
get detailed information about a file system object (file,directory,symlink) in the host.
|
||||
get detailed information about a file in the host file system.
|
||||
|
||||
### IO ###
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
### Summary ###
|
||||
|
||||
move/rename a file system object (file,directory,symlink) from one location to another.
|
||||
move/rename a file or directory in the host file system.
|
||||
|
||||
### IO ###
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ upload a single file to the host.
|
|||
|
||||
attempt to upload the file given in -client_file to the destination file path in the host given in -remote_file. depending on the client, you might not need to enter -len. if supported, the client will auto fill -len with what ever value is needed.
|
||||
|
||||
-offset is the position in the file to start writing and it defaults to 0 if not given.
|
||||
-offset is the position in the file to start writing. it defaults to 0 if not given.
|
||||
-single_step enables GEN_FILE's single step mode if the client/host desires it.
|
||||
-force bypasses the overwrite confirmation question if the destination file already exists.
|
||||
-truncate tells the host if it should truncate the destination file.
|
|
@ -1,6 +1,6 @@
|
|||
### Summary ###
|
||||
|
||||
lock user account.
|
||||
lock a user account.
|
||||
|
||||
### IO ###
|
||||
|
||||
|
|
|
@ -12,8 +12,8 @@ by default, all entries in the table are displayed in 50 entries per page. you c
|
|||
|
||||
-time_stamp
|
||||
-ip_address
|
||||
-client_app
|
||||
-session_id
|
||||
-client_version
|
||||
-log_entry
|
||||
|
||||
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.
|
|
@ -1,10 +1,10 @@
|
|||
### Summary ###
|
||||
|
||||
display or manage the host authorization activity log.
|
||||
display the host authorization activity log.
|
||||
|
||||
### IO ###
|
||||
|
||||
```[{search_terms} {-delete}]/[text]```
|
||||
```[{search_terms}]/[text]```
|
||||
|
||||
### Description ###
|
||||
|
||||
|
@ -18,8 +18,6 @@ by default, all entries in the table are displayed in 50 entries per page. you c
|
|||
-count_to_threshold
|
||||
-accepted
|
||||
|
||||
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.
|
||||
|
||||
the host use entries in this table to enforce maximum failed login thresholds using a combination of the values found in the -count_to_threshold, -user_name, -count_to_threshold and -accepted columns. so for example, if the host counts a maximum of 50 entries for a certain -user_name with -count_to_threshold = 1 and -accepted = 0 and the host maximum amount of failed attempts is set to 50 then the host will then auto lock the user account to protect it.
|
||||
|
||||
the -accepted column is a 1 or 0 to indicate if the user successfully logged in or not and the -count_to_threshold column is also 1 or 0 to determine if this particular entry should be counted toward the threshold or not.
|
|
@ -4,8 +4,8 @@ list all members in a channel.
|
|||
|
||||
### IO ###
|
||||
|
||||
```[-ch_name (text) {-find (text)}]/[text]```
|
||||
```[-ch_name (text) {-user_name (text)} {-disp_name (text)}]/[text]```
|
||||
|
||||
### Description ###
|
||||
|
||||
list all members currently in the channel given in -ch_name. you must be a member of the channel (any level) for this to work. this command will display 50 entries per page but you can pass the optional -find argument with a text search term to find members via the user name.
|
||||
list all members currently in the channel given in -ch_name. you must be a member of the channel (any level) for this to work. this command will display 50 entries per page but you can pass the optional -user_name argument with a text search term to find members via the user name and/or -disp_name to find members via the display name.
|
|
@ -1,11 +0,0 @@
|
|||
### Summary ###
|
||||
|
||||
list all available commands for your current session.
|
||||
|
||||
### IO ###
|
||||
|
||||
```[{-find (text)}]/[text]```
|
||||
|
||||
### Description ###
|
||||
|
||||
display all available commands in your current session in a table format. you can pass an optional -find text to narrow down the size of the list or find specific commands via the command name.
|
|
@ -1,6 +1,6 @@
|
|||
### Summary ###
|
||||
|
||||
display debug messages from the host instance and all session instances.
|
||||
display all debug log messages.
|
||||
|
||||
### IO ###
|
||||
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
### Summary ###
|
||||
|
||||
list all groups currently registered in the host.
|
||||
|
||||
### IO ###
|
||||
|
||||
```[{search_terms}]/[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:
|
||||
|
||||
-group_name
|
||||
-host_rank
|
|
@ -1,6 +1,6 @@
|
|||
### Summary ###
|
||||
|
||||
list all available modules currently installed in the host.
|
||||
list all available modules currently configured in the host.
|
||||
|
||||
### IO ###
|
||||
|
||||
|
@ -8,8 +8,4 @@ list all available modules currently installed in the host.
|
|||
|
||||
### Description ###
|
||||
|
||||
display a list of all modules currently installed in the host. any mods marked with a '1' on the locked column will prevent new sessions from attempting to load it. the presents of a lock can mean 3 things:
|
||||
|
||||
1. the module is queued for deletion.
|
||||
2. installation is in process and the module is not yet ready for loading.
|
||||
3. a session has crashed while attempting to load the module.
|
||||
display a list of all modules currently configured to run in the host. modules are independent applications so having them listed here doesn't guarantee the commands installed in them will actually be avaiable for running. any module that fails to load correctly should log debug messages.
|
|
@ -1,6 +1,6 @@
|
|||
### Summary ###
|
||||
|
||||
list all command names with assigned host ranks.
|
||||
list all module commands with assigned host ranks.
|
||||
|
||||
### IO ###
|
||||
|
||||
|
@ -10,5 +10,6 @@ list all command names with assigned host ranks.
|
|||
|
||||
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:
|
||||
|
||||
-command_obj_name
|
||||
-module_executable
|
||||
-command_name
|
||||
-host_rank
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
### Summary ###
|
||||
|
||||
list all sub-channels within a channel you currently a member of.
|
||||
list all sub-channels within a channel.
|
||||
|
||||
### IO ###
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ list all users currently registered in the host database.
|
|||
|
||||
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:
|
||||
|
||||
-DateAdded
|
||||
-UserName
|
||||
-GroupName
|
||||
-UserID
|
||||
-time_stamp
|
||||
-user_name
|
||||
-host_rank
|
||||
-user_id
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
### Summary ###
|
||||
|
||||
open a sub-channel to send/receive broadcasted data to/from other peers.
|
||||
open a sub-channel to send/receive broadcasted data to/from peers.
|
||||
|
||||
### IO ###
|
||||
|
||||
|
@ -8,4 +8,4 @@ open a sub-channel to send/receive broadcasted data to/from other peers.
|
|||
|
||||
### Description ###
|
||||
|
||||
use this command to open the channel and sub-channel name given in -ch for the main channel name and -sub for the sub-channel name. only peers with matching channel-sub combinations can send/receive data with each other when using the cast command. whether peers send/receive auto/pinged PEER_INFO or PEER_STAT frames depends if the active update flag is set on the channel itself or the host.
|
||||
use this command to open the channel and sub-channel name given in -ch for the main channel name and -sub for the sub-channel name. only peers with matching channel-sub combinations can send/receive data with each other when using the cast command. whether peers can send/receive PEER_INFO or PEER_STAT frames depends if the active update flag is set on the sub-channel itself or the host global setting.
|
|
@ -1,6 +1,6 @@
|
|||
### Summary ###
|
||||
|
||||
close the p2p connection with the client given in this command or decline a p2p request.
|
||||
close the p2p connection with the peer given in this command or decline a p2p request.
|
||||
|
||||
### IO ###
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
### Summary ###
|
||||
|
||||
accept the p2p request you may have received from another client connected to the host.
|
||||
accept the p2p request you may have received from another peer connected to the host.
|
||||
|
||||
### IO ###
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
### Summary ###
|
||||
|
||||
send out a p2p request to the client session id given in this command.
|
||||
send out a p2p request to the peer session id given in this command.
|
||||
|
||||
### IO ###
|
||||
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
### Summary ###
|
||||
|
||||
pause the current task that the command is running.
|
||||
|
||||
### IO ###
|
||||
|
||||
```[{CMD_ID}]/[text]```
|
||||
|
||||
### Description ###
|
||||
|
||||
this pauses the command given by a CMD_ID frame sent into this command. an error is returned if the requested command is not currently in the looping state. if the frame is empty, this command pauses all commands currently in the looping state.
|
|
@ -8,4 +8,4 @@ preview the confirmation or password reset emails with dummy values.
|
|||
|
||||
### Description ###
|
||||
|
||||
preview the reset password email with the -reset_email argument or preview the email confirmation with -confirm_email. this prints the subject first and then the message body with the keywords substituted the dummy values/text.
|
||||
preview the reset password email with the -reset_email argument or preview the email confirmation with -confirm_email. this prints the subject first and then the message body with the keywords substituted the dummy values/text. this command will output the preview as configured so if the messages do contain html, it will output the html as is. it will be up to the client to parse the html or not.
|
|
@ -1,6 +1,6 @@
|
|||
### Summary ###
|
||||
|
||||
reset a user account password.
|
||||
login to a user account using a temporary password.
|
||||
|
||||
### IO ###
|
||||
|
||||
|
@ -8,4 +8,4 @@ reset a user account password.
|
|||
|
||||
### Description ###
|
||||
|
||||
reset the password for the user account given in -email or -user. during execution, this command will ask for the temporary password that was sent to that email address when request_pw_reset was called.
|
||||
reset the password for the user account given in -email or -user. during execution, this command will ask for the temporary password that was sent to that email address when the password reset was requested. if successful, you will then be required to enter a new password.
|
|
@ -8,4 +8,4 @@ remove a user as a member of a channel you currently a member of or cancel an in
|
|||
|
||||
### Description ###
|
||||
|
||||
remove a user given in -user from the channel member list for the channel given in -ch_name. normally, only the channel owner-level(1), admin-level(2) of officer(3) can do this but it is unrestricted if removing your self as a member except the channel owner. another restriction is if trying to remove members with higher or equal member privileges than your self so officers can't remove admins, other officers or the owner and admins can't remove other admins or the owner. the owner can't be removed from the channel at anytime. this command can also be used to cancel an invite for a user.
|
||||
remove a user given in -user from the channel member list for the channel given in -ch_name. normally, only the channel owner-level(1), admin-level(2) of officer(3) can do this but it is unrestricted if removing your self as a member except the channel owner. another restriction is if trying to remove members with higher or equal member privileges than your self so officers can't remove admins, other officers or the owner and admins can't remove other admins or the owner. the owner can't be removed from the channel in any case. this command can also be used to cancel an invite for a user.
|
|
@ -8,4 +8,4 @@ request a password reset for a user account.
|
|||
|
||||
### Description ###
|
||||
|
||||
this will send a temporary password for the user account associated with the email adress given in -email or the username given in -user. this password can then be used with recover_account to reset the password.
|
||||
this will send a temporary password for the user account associated with the email adress given in -email or the user name given in -user. this password can then be used to login via the recovery command to reset the password.
|
|
@ -8,4 +8,4 @@ re-start the host instance.
|
|||
|
||||
### Description ###
|
||||
|
||||
this will restart the host instance, along with a database reload. be very careful with this command. it ends all current sessions and since it also reloads the database, host behaviour might also change depending on what is in the new database if the path was changed.
|
||||
this will restart the host instance. it will stop listening for new clients, close all current sessions, reload the database and then start listening for clients again. the host behaviour might also change depending on what is new in the database or if the path has changed.
|
|
@ -1,11 +0,0 @@
|
|||
### Summary ###
|
||||
|
||||
resumes the current task that the command is running.
|
||||
|
||||
### IO ###
|
||||
|
||||
```[{CMD_ID}]/[text]```
|
||||
|
||||
### Description ###
|
||||
|
||||
this resumes the looping task for the command given by a CMD_ID frame sent into this command. a failure is returned if the command is not currently in a paused state. if the frame is empty, all currently paused commands are resumed.
|
|
@ -8,4 +8,4 @@ delete a user account from the host database.
|
|||
|
||||
### Description ###
|
||||
|
||||
delete the user account given in -name. this will also automatically kill all sessions currently using this user account. be very careful with this command since it's changes cannot be undone. you can use the -force option to bypass the confirmation question.
|
||||
delete the user account given in -name. this will also automatically kill all sessions currently using this user account. be very careful with this command since it's changes cannot be undone. you can use the -force option to bypass the confirmation question. this command will fail if the user account is the owner of a channel. you must assign a new owner for that channel or delete the channel to unlock account deletion.
|
|
@ -1,11 +1,11 @@
|
|||
### Summary ###
|
||||
|
||||
uninstall a module from the host.
|
||||
remove a module from the host.
|
||||
|
||||
### IO ###
|
||||
|
||||
```[-name (text)]/[text]```
|
||||
```[-mod_path (text)]/[text]```
|
||||
|
||||
### Description ###
|
||||
|
||||
this tells all sessions in the host to unload the module given in -name and all associated commands. it will also permanently delete all files associated with the module from the host. file deletion is not done instantly; instead, a specific amount of time is allotted to allow all sessions to unload the mod/clean up before it's files are deleted. also note that all associated commands are forced to terminate when the module is unloaded.
|
||||
this tells all sessions in the host to unload the module given in -mod_path and all associated commands. all associated commands are forced to terminate when the module is unloaded. this command will not uninstall the module application, all it does is remove the path to the module application from the host database so the module's commands will no longer be executable by host users.
|
|
@ -1,11 +1,11 @@
|
|||
### Summary ###
|
||||
|
||||
remove a rank from a command object name.
|
||||
remove a rank from a module command name.
|
||||
|
||||
### IO ###
|
||||
|
||||
```[-command (text)]/[text]```
|
||||
```[-command (text) -mod (text)]/[text]```
|
||||
|
||||
### Description ###
|
||||
|
||||
this will remove the command rank from the command object given in -command. any command object without an assigned perm id is assumed a rank of 1 but some exceptions apply for commands that need to be allowed for all users regardless of rank.
|
||||
this will remove the command rank from the command name given in -command for the module given in -mod. any command name without an assigned rank is assumed a rank of 1 except for commands that claim immunity.
|
|
@ -8,4 +8,4 @@ remove a read only flag from a certain sub-channel privilege level combination.
|
|||
|
||||
### Description ###
|
||||
|
||||
remove a read only flag the sub-channel given in -sub_id for connected users at the level given in -level. the channel given in -ch_name must already exists. with, the read only flag gone users connected to the sub-channel at the specified level would be able to cast data to the sub-channel once again. also note that this command will cause all sessions that currently have the sub-channel open to close the sub-channel. it will be up to the clients to re-open the sub-channel.
|
||||
remove a read only flag the sub-channel given in -sub_id for connected users at the level given in -level. the channel given in -ch_name must already exists. with, the read only flag gone; users connected to the sub-channel at the specified level would be able to cast data to the sub-channel once again. also note that this command will cause all sessions that currently have the sub-channel open to close the sub-channel. it will be up to the clients to re-open the sub-channel if the user still has access.
|
|
@ -8,4 +8,4 @@ remove a sub-channel within a channel.
|
|||
|
||||
### Description ###
|
||||
|
||||
remove a sub-channel given in -sub_name for the channel given in -ch_name. only the channel owner-level(1) and admin-level(2) is allowed to do this. only the channel owner-level(1) and admin-level(2) is allowed to do this.
|
||||
remove a sub-channel given in -sub_name for the channel given in -ch_name. only the channel owner-level(1) and admin-level(2) is allowed to do this. all sessions that currently have this sub-channel open will be forced to close it.
|
|
@ -8,4 +8,4 @@ set or unset the active update flag of a sub-channel.
|
|||
|
||||
### Description ###
|
||||
|
||||
this sets the active update flag on the channel given in -ch_name true or false based on the value given in -state. the active update flag allow the sessions to send PEER_INFO or PEER_STAT frames to the clients when a peer connected to the channel changes information like it's user name, group name, display name, disconnect etc...this flag is ignored if the host have the global active update flag set. if that's the case, all channels will active update. the channel owner-level(1) and admin-level(2) is allowed to do this.
|
||||
this sets the active update flag on the channel given in -ch_name true or false based on the value given in -state. the active update flag allow the sessions to send PEER_INFO or PEER_STAT frames to the clients when a peer connected to the sub-channel changes information like it's user name, sub-channels, display name, disconnect etc...this flag is ignored if the host have the global active update flag set. if that's the case, all channels will active update. the channel owner-level(1) and admin-level(2) is allowed update this flag.
|
|
@ -4,8 +4,8 @@ change your account display name.
|
|||
|
||||
### IO ###
|
||||
|
||||
```[-name (text)]/[text]```
|
||||
```[-new_name (text)]/[text]```
|
||||
|
||||
### Description ###
|
||||
|
||||
this changes the display name on your own account to the name given in -name. the display name is used by some clients to present your account to other clients instead of showing your real user name. it is not restricted by uniqueness and can be any text that is less than or equal to 32 chars.
|
||||
this changes the display name on your own account to the name given in -new_name. the display name is used by some clients to present your account to other clients instead of showing your real user name. it is not restricted by uniqueness and can be any text that is less than or equal to 32 chars long. it can even contain spaces if desired but a display name of just spaces will be considered empty because this command will trim the text. the only chars that are considered invalid is new lines or line breaks of any kind.
|
|
@ -1,6 +1,6 @@
|
|||
### Summary ###
|
||||
|
||||
change the user account email address.
|
||||
set the user account email address.
|
||||
|
||||
### IO ###
|
||||
|
||||
|
|
|
@ -8,7 +8,9 @@ set the email template used by the host to send emails for user account resets a
|
|||
|
||||
### Description ###
|
||||
|
||||
this updates the email template used by the host to send emails to the users that request password resets and or email confirmations. the presents of -reset_template updates the password reset email or the presents of -confirm_template updates the confirmation email. -subject is exactly as the name implies, it tells the host what subject to use when sending the email.
|
||||
this updates the email template used by the host to send emails to the users that request password resets and or email confirmations. the presents of -reset_template updates the password reset email or the presents of -confirm_template updates the confirmation email.
|
||||
|
||||
-subject is exactly as the name implies, it tells the host what subject to use when sending the email.
|
||||
|
||||
-body sets the email message body directly from the command line or -client_file loads the body from a text file. if uploading a text file, use the -len parameter to enter the file size in bytes if your client does not auto fill that.
|
||||
|
||||
|
@ -19,4 +21,4 @@ the message body must contain the following keywords to be acceptable:
|
|||
%temp_pw% (if -reset_template)
|
||||
%confirmation_code% (if -confirm_template)
|
||||
|
||||
the host will substitute these keywords with actual values/text when contructing the email. note: if sending a text file, the host assumes it is encoded in UTF-16LE. pass an empty -subject and/or a empty -body to reset the values to host defaults. if the body or subject contains single quotes ' ' escape them with a \.
|
||||
the host will substitute these keywords with actual values/text when contructing the email. note: if sending a text file, the host assumes it is encoded in UTF-16LE. pass an empty -subject and/or a empty -body to reset the values to host defaults.
|
|
@ -1,11 +0,0 @@
|
|||
### Summary ###
|
||||
|
||||
change a user account's group.
|
||||
|
||||
### IO ###
|
||||
|
||||
```[-user (text) -group (text)]/[text]```
|
||||
|
||||
### Description ###
|
||||
|
||||
this changes the group of the user account given in -user to the target group given in -group.
|
|
@ -1,11 +0,0 @@
|
|||
### Summary ###
|
||||
|
||||
set the host rank of a group.
|
||||
|
||||
### IO ###
|
||||
|
||||
```[-name (text) -rank (int)]/[text]```
|
||||
|
||||
### Description ###
|
||||
|
||||
set the host rank for the group name given in -name to the rank given in -rank. the host rank is used throughout this application to determine how much access to the host commands each user attached to the group has. the lower the numeric value of the host rank, the higher the level of access to the host the group has (1 being the highest level of access). you cannot change the group of a group that has a higher rank than your own group.
|
|
@ -1,6 +1,6 @@
|
|||
### Summary ###
|
||||
|
||||
set the user privilege levels of a channel member. (lower the value, the higher the privilege)
|
||||
set the user privilege levels of a channel member.
|
||||
|
||||
### IO ###
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
### Summary ###
|
||||
|
||||
change your account password.
|
||||
update your account password.
|
||||
|
||||
### IO ###
|
||||
|
||||
|
@ -8,4 +8,4 @@ change your account password.
|
|||
|
||||
### Description ###
|
||||
|
||||
this changes the password on your own account. this command will instantly hook the input and await a new password to be entered.
|
||||
this changes the password on your own account. during execution, this command will ask for a new password to be entered.
|
|
@ -8,4 +8,4 @@ set the lowest privilege level that members need to be in order to open a certai
|
|||
|
||||
### Description ###
|
||||
|
||||
this command makes it possible so set minimum privilege levels to open the sub-channel given in -sub_name to the level given in -level for the channel given in -ch_name. a valid level is an integer between 1-5 representing owner-level(1), admin-level(2), officer-level(3), regular-level(4) and public-level(5). for example, you could set a sub-channel's minimum level to 4 to make it so only channel regular members and above can open/close the sub-channel or you can set it to 5 to make it so anybody can open/close the sub-channel, affectively making it a public sub-channel. only the channel owner or admin(s) are allowed to do this. also note that this command will cause all sessions that currently have the sub-channel open to close the sub-channel. it will be up to the client to re-open the sub-channel if it's user account still have access to it.
|
||||
this command makes it possible so set minimum privilege levels to open the sub-channel given in -sub_name to the level given in -level for the channel given in -ch_name. a valid level is an integer between 1-5 representing owner-level(1), admin-level(2), officer-level(3), regular-level(4) and public-level(5). for example, you could set a sub-channel's minimum level to 4 to make it so only channel regular members and above can open/close the sub-channel or you can set it to 5 to make it so anybody can open/close the sub-channel, affectively making it a public sub-channel. only the channel owner or admin(s) are allowed to update this. also note that this command will cause all sessions that currently have the sub-channel open to close the sub-channel. it will be up to the client to re-open the sub-channel if it's user account still have access to it.
|
11
docs/intern_commands/set_user_rank.md
Normal file
11
docs/intern_commands/set_user_rank.md
Normal file
|
@ -0,0 +1,11 @@
|
|||
### Summary ###
|
||||
|
||||
change a user account's host rank.
|
||||
|
||||
### IO ###
|
||||
|
||||
```[-user (text) -rank (int)]/[text]```
|
||||
|
||||
### Description ###
|
||||
|
||||
this changes the host rank of the target user account name given in -user to the rank given in -rank. the host rank itself is an integer value that determine what commands each user can or cannot run depending on how the ranked commands are configured. it is also used to determine what direct changes a user can do to another user's account. the lower the numerical value the rank is the higher level of privilege the user have on the host (zero is invalid so 1 is the highest level of privilege any user can have).
|
|
@ -1,11 +0,0 @@
|
|||
### Summary ###
|
||||
|
||||
terminate the current task that the command is running.
|
||||
|
||||
### IO ###
|
||||
|
||||
```[{CMD_ID}]/[text]```
|
||||
|
||||
### Description ###
|
||||
|
||||
this terminates the command given by a CMD_ID frame sent into this command. if the frame is empty, this command terminates all commands. this command doesn't care if the target command object itself is in looping and/or more input states.
|
|
@ -1,6 +1,6 @@
|
|||
### Summary ###
|
||||
|
||||
send/receive any data directly with a client connected to the host that has accepted your p2p request or the peer's p2p request.
|
||||
send/receive any data directly with a client connected to the host.
|
||||
|
||||
### IO ###
|
||||
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
### Summary ###
|
||||
|
||||
transfer all user accounts from one group to another.
|
||||
|
||||
### IO ###
|
||||
|
||||
```[-src (text) -dst (text)]/[text]```
|
||||
|
||||
### Description ###
|
||||
|
||||
transfer all user accounts currently attached to the group given in -src to the group given in -dst. you must have a higher rank than both groups for this to work.
|
386
src/async_funcs.cpp
Normal file
386
src/async_funcs.cpp
Normal file
|
@ -0,0 +1,386 @@
|
|||
#include "session.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/>.
|
||||
|
||||
void Session::acctDeleted(const QByteArray &data)
|
||||
{
|
||||
if (flags & LOGGED_IN)
|
||||
{
|
||||
// format: [32bytes(user_id)]
|
||||
|
||||
if (memcmp(userId, data.data(), BLKSIZE_USER_ID) == 0)
|
||||
{
|
||||
logout("", true);
|
||||
asyncToClient(ASYNC_SYS_MSG, toTEXT("\nsystem: your session was forced to logout because your account was deleted.\n"), TEXT);
|
||||
asyncToClient(ASYNC_USER_DELETED, data, TEXT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Session::acctEdited(const QByteArray &data)
|
||||
{
|
||||
if (flags & LOGGED_IN)
|
||||
{
|
||||
// format: [32bytes(user_id)]
|
||||
|
||||
if (memcmp(userId, data.data(), BLKSIZE_USER_ID) == 0)
|
||||
{
|
||||
sendLocalInfo();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Session::acctRenamed(const QByteArray &data)
|
||||
{
|
||||
if (flags & LOGGED_IN)
|
||||
{
|
||||
// format: [32bytes(user_id)][48bytes(new_user_name)]
|
||||
|
||||
if (memcmp(userId, data.data(), BLKSIZE_USER_ID) == 0)
|
||||
{
|
||||
memcpy(userName, data.data() + BLKSIZE_USER_ID, BLKSIZE_USER_NAME);
|
||||
castPeerInfo(PEER_INFO);
|
||||
sendLocalInfo();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Session::acctDispChanged(const QByteArray &data)
|
||||
{
|
||||
if (flags & LOGGED_IN)
|
||||
{
|
||||
// format: [32bytes(user_id)][64bytes(new_disp_name)]
|
||||
|
||||
if (memcmp(userId, data.data(), BLKSIZE_USER_ID) == 0)
|
||||
{
|
||||
memcpy(displayName, data.data() + BLKSIZE_USER_ID, BLKSIZE_DISP_NAME);
|
||||
castPeerInfo(PEER_INFO);
|
||||
sendLocalInfo();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Session::castCatch(const QByteArray &data)
|
||||
{
|
||||
// format: [54bytes(chIds)][1byte(typeId)][rest-of-bytes(payload)]
|
||||
|
||||
if (matchChs(openSubChs, data.data()))
|
||||
{
|
||||
int payloadOffs = (MAX_OPEN_SUB_CHANNELS * BLKSIZE_SUB_CHANNEL) + 1;
|
||||
quint8 typeId = static_cast<quint8>(data[payloadOffs - 1]);
|
||||
quint32 len = static_cast<quint32>(data.size() - payloadOffs);
|
||||
|
||||
const char *payload = data.data() + payloadOffs;
|
||||
|
||||
asyncToClient(ASYNC_CAST, rdFromBlock(payload, len), typeId);
|
||||
}
|
||||
}
|
||||
|
||||
void Session::directDataFromPeer(const QByteArray &data)
|
||||
{
|
||||
// format: [28bytes(sessionId)][1byte(typeId)][rest-of-bytes(payload)]
|
||||
|
||||
if (memcmp(sessionId, data.data(), BLKSIZE_SESSION_ID) == 0)
|
||||
{
|
||||
int payloadOffs = BLKSIZE_SESSION_ID + 1;
|
||||
quint8 typeId = static_cast<quint8>(data[payloadOffs - 1]);
|
||||
quint32 len = static_cast<quint32>(data.size() - payloadOffs);
|
||||
|
||||
const char *payload = data.data() + payloadOffs;
|
||||
|
||||
asyncToClient(ASYNC_TO_PEER, rdFromBlock(payload, len), typeId);
|
||||
}
|
||||
}
|
||||
|
||||
void Session::p2p(const QByteArray &data)
|
||||
{
|
||||
// format: [28bytes(dst_sessionId)][28bytes(src_sessionId)][1byte(typeId)][rest-of-bytes(payload)]
|
||||
|
||||
if (memcmp(sessionId, data.data(), BLKSIZE_SESSION_ID) == 0)
|
||||
{
|
||||
int payloadOffs = (BLKSIZE_SESSION_ID * 2) + 1;
|
||||
|
||||
const char *src = data.data() + BLKSIZE_SESSION_ID;
|
||||
const char *payload = data.data() + payloadOffs;
|
||||
|
||||
quint32 len = static_cast<quint32>(data.size() - payloadOffs);
|
||||
quint8 typeId = static_cast<quint8>(data[payloadOffs - 1]);
|
||||
|
||||
if (typeId == P2P_REQUEST)
|
||||
{
|
||||
if (posOfBlock(src, p2pAccepted, MAX_P2P_LINKS, BLKSIZE_SESSION_ID) == -1)
|
||||
{
|
||||
if (addBlockToBlockset(src, p2pPending, MAX_P2P_LINKS, BLKSIZE_SESSION_ID))
|
||||
{
|
||||
asyncToClient(ASYNC_P2P, rdFromBlock(payload, len), P2P_REQUEST);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (typeId == P2P_OPEN)
|
||||
{
|
||||
if (rmBlockFromBlockset(src, p2pPending, MAX_P2P_LINKS, BLKSIZE_SESSION_ID))
|
||||
{
|
||||
if (addBlockToBlockset(src, p2pAccepted, MAX_P2P_LINKS, BLKSIZE_SESSION_ID))
|
||||
{
|
||||
asyncToClient(ASYNC_P2P, rdFromBlock(payload, len), P2P_OPEN);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (typeId == P2P_CLOSE)
|
||||
{
|
||||
if (rmBlockFromBlockset(src, p2pPending, MAX_P2P_LINKS, BLKSIZE_SESSION_ID))
|
||||
{
|
||||
asyncToClient(ASYNC_P2P, rdFromBlock(payload, len), P2P_CLOSE);
|
||||
}
|
||||
else if (rmBlockFromBlockset(src, p2pAccepted, MAX_P2P_LINKS, BLKSIZE_SESSION_ID))
|
||||
{
|
||||
asyncToClient(ASYNC_P2P, rdFromBlock(payload, len), P2P_CLOSE);
|
||||
}
|
||||
}
|
||||
else if (posOfBlock(src, p2pAccepted, MAX_P2P_LINKS, BLKSIZE_SESSION_ID) != -1)
|
||||
{
|
||||
asyncToClient(ASYNC_P2P, rdFromBlock(src, BLKSIZE_SESSION_ID) + rdFromBlock(payload, len), typeId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Session::closeP2P(const QByteArray &data)
|
||||
{
|
||||
// format: [28bytes(src_sessionId)]
|
||||
|
||||
if (rmBlockFromBlockset(data.data(), p2pAccepted, MAX_P2P_LINKS, BLKSIZE_SESSION_ID) ||
|
||||
rmBlockFromBlockset(data.data(), p2pPending, MAX_P2P_LINKS, BLKSIZE_SESSION_ID))
|
||||
{
|
||||
asyncToClient(ASYNC_P2P, data, P2P_CLOSE);
|
||||
}
|
||||
}
|
||||
|
||||
void Session::limitedCastCatch(const QByteArray &data)
|
||||
{
|
||||
// format: [54bytes(chIds)][1byte(typeId)][rest-of-bytes(payload)]
|
||||
|
||||
if (rd8BitFromBlock(activeUpdate) && matchChs(openSubChs, data.data()))
|
||||
{
|
||||
int payloadOffs = (MAX_OPEN_SUB_CHANNELS * BLKSIZE_SUB_CHANNEL) + 1;
|
||||
quint32 len = static_cast<quint32>(data.size() - payloadOffs);
|
||||
quint8 typeId = static_cast<quint8>(data[payloadOffs - 1]);
|
||||
|
||||
const char *payload = data.data() + payloadOffs;
|
||||
|
||||
if (typeId == PING_PEERS)
|
||||
{
|
||||
// PING_PEERS is formatted exactly like PEER_INFO. it only tells this
|
||||
// async command to also send PEER_INFO of this session to the session
|
||||
// that requested the ping using ASYNC_TO_PEER.
|
||||
|
||||
QByteArray peerId = rdFromBlock(payload, BLKSIZE_SESSION_ID);
|
||||
QByteArray typeId = wrInt(PEER_INFO, 8);
|
||||
QByteArray info = createPeerInfoFrame();
|
||||
|
||||
emit asyncToPeers(ASYNC_TO_PEER, peerId + typeId + info);
|
||||
|
||||
asyncToClient(ASYNC_LIMITED_CAST, rdFromBlock(payload, len), PEER_INFO);
|
||||
}
|
||||
else
|
||||
{
|
||||
asyncToClient(ASYNC_LIMITED_CAST, rdFromBlock(payload, len), typeId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Session::updateRankViaUser(const QByteArray &data)
|
||||
{
|
||||
if (flags & LOGGED_IN)
|
||||
{
|
||||
// format: [32bytes(userId)][4bytes(newRank)]
|
||||
|
||||
if (memcmp(data.data(), userId, BLKSIZE_USER_ID) == 0)
|
||||
{
|
||||
wr32BitToBlock(rd32BitFromBlock(data.data() + BLKSIZE_USER_ID), hostRank);
|
||||
sendLocalInfo();
|
||||
loadCmds();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Session::userAddedToChannel(quint16 cmdId, const QByteArray &data)
|
||||
{
|
||||
// format: [8bytes(chId)][32bytes(userId)]
|
||||
|
||||
if (memcmp(data.data() + BLKSIZE_CHANNEL_ID, userId, BLKSIZE_USER_ID) == 0)
|
||||
{
|
||||
if ((cmdId == ASYNC_NEW_CH_MEMBER) || (cmdId == ASYNC_INVITE_ACCEPTED))
|
||||
{
|
||||
addBlockToBlockset(data.data(), chList, MAX_CHANNELS_PER_USER, BLKSIZE_CHANNEL_ID);
|
||||
}
|
||||
|
||||
asyncToClient(cmdId, data, CH_MEMBER_INFO);
|
||||
}
|
||||
else if (posOfBlock(data.data(), chList, MAX_CHANNELS_PER_USER, BLKSIZE_CHANNEL_ID) != -1)
|
||||
{
|
||||
asyncToClient(cmdId, data, CH_MEMBER_INFO);
|
||||
}
|
||||
}
|
||||
|
||||
void Session::userRemovedFromChannel(const QByteArray &data)
|
||||
{
|
||||
// format: [8bytes(chId)][32bytes(user_id)]
|
||||
|
||||
if (memcmp(data.data() + BLKSIZE_CHANNEL_ID, userId, BLKSIZE_USER_ID) == 0)
|
||||
{
|
||||
closeByChId(rdFromBlock(data.data(), BLKSIZE_CHANNEL_ID), true);
|
||||
rmBlockFromBlockset(data.data(), chList, MAX_CHANNELS_PER_USER, BLKSIZE_CHANNEL_ID);
|
||||
asyncToClient(ASYNC_RM_CH_MEMBER, data, BYTES);
|
||||
}
|
||||
else if (posOfBlock(data.data(), chList, MAX_CHANNELS_PER_USER, BLKSIZE_CHANNEL_ID) != -1)
|
||||
{
|
||||
asyncToClient(ASYNC_RM_CH_MEMBER, data, BYTES);
|
||||
}
|
||||
}
|
||||
|
||||
void Session::channelDeleted(const QByteArray &data)
|
||||
{
|
||||
// format: [8bytes(chId)]
|
||||
|
||||
if (rmBlockFromBlockset(data.data(), chList, MAX_CHANNELS_PER_USER, BLKSIZE_CHANNEL_ID))
|
||||
{
|
||||
closeByChId(data, false);
|
||||
asyncToClient(ASYNC_DEL_CH, data, CH_ID);
|
||||
}
|
||||
else if (rmLikeBlkFromBlkset(data, openSubChs, MAX_OPEN_SUB_CHANNELS, BLKSIZE_SUB_CHANNEL))
|
||||
{
|
||||
rmLikeBlkFromBlkset(data, openWritableSubChs, MAX_OPEN_SUB_CHANNELS, BLKSIZE_SUB_CHANNEL);
|
||||
asyncToClient(ASYNC_DEL_CH, data, CH_ID);
|
||||
}
|
||||
}
|
||||
|
||||
void Session::channelMemberLevelUpdated(const QByteArray &data)
|
||||
{
|
||||
// format: [8bytes(chId)][32bytes(user_id)]
|
||||
|
||||
if (memcmp(data.data() + BLKSIZE_CHANNEL_ID, userId, BLKSIZE_USER_ID) == 0)
|
||||
{
|
||||
closeByChId(rdFromBlock(data.data(), BLKSIZE_CHANNEL_ID), true);
|
||||
asyncToClient(ASYNC_MEM_LEVEL_CHANGED, data, BYTES);
|
||||
}
|
||||
else if (posOfBlock(data.data(), chList, MAX_CHANNELS_PER_USER, BLKSIZE_CHANNEL_ID) != -1)
|
||||
{
|
||||
asyncToClient(ASYNC_MEM_LEVEL_CHANGED, data, BYTES);
|
||||
}
|
||||
}
|
||||
|
||||
void Session::channelRenamed(const QByteArray &data)
|
||||
{
|
||||
// format: [8bytes(chId)]
|
||||
|
||||
if (posOfBlock(data.data(), chList, MAX_CHANNELS_PER_USER, BLKSIZE_CHANNEL_ID) != -1)
|
||||
{
|
||||
asyncToClient(ASYNC_RENAME_CH, data, BYTES);
|
||||
}
|
||||
}
|
||||
|
||||
void Session::channelActiveFlagUpdated(const QByteArray &data)
|
||||
{
|
||||
// format: [9bytes(72bit_sub_id)]
|
||||
|
||||
if (posOfBlock(data.data(), openSubChs, MAX_OPEN_SUB_CHANNELS, BLKSIZE_SUB_CHANNEL) != -1)
|
||||
{
|
||||
containsActiveCh(openSubChs, activeUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
void Session::subChannelAdded(quint16 cmdId, const QByteArray &data)
|
||||
{
|
||||
// format: [8bytes(64bit_ch_id)][1byte(8bit_sub_ch_id)]
|
||||
|
||||
if (posOfBlock(data.data(), chList, MAX_CHANNELS_PER_USER, BLKSIZE_CHANNEL_ID) != -1)
|
||||
{
|
||||
asyncToClient(cmdId, data, BYTES);
|
||||
}
|
||||
}
|
||||
|
||||
void Session::subChannelUpdated(quint16 cmdId, const QByteArray &data)
|
||||
{
|
||||
// format: [9bytes(72bit_sub_id)]
|
||||
|
||||
if (rmBlockFromBlockset(data.data(), openSubChs, MAX_OPEN_SUB_CHANNELS, BLKSIZE_SUB_CHANNEL))
|
||||
{
|
||||
rmBlockFromBlockset(data.data(), openWritableSubChs, MAX_OPEN_SUB_CHANNELS, BLKSIZE_SUB_CHANNEL);
|
||||
asyncToClient(cmdId, data, BYTES);
|
||||
}
|
||||
else if (posOfBlock(data.data(), chList, MAX_CHANNELS_PER_USER, BLKSIZE_CHANNEL_ID) != -1)
|
||||
{
|
||||
asyncToClient(cmdId, data, BYTES);
|
||||
}
|
||||
}
|
||||
|
||||
void Session::addModule(const QByteArray &data)
|
||||
{
|
||||
QString modApp = fromTEXT(data);
|
||||
|
||||
if (!modCmdNames.contains(modApp))
|
||||
{
|
||||
startModProc(modApp);
|
||||
}
|
||||
}
|
||||
|
||||
void Session::rmModule(const QByteArray &data)
|
||||
{
|
||||
QString modApp = fromTEXT(data);
|
||||
|
||||
if (modCmdNames.contains(modApp) && (modApp != QCoreApplication::applicationFilePath()))
|
||||
{
|
||||
for (auto&& cmdName : modCmdNames[modApp])
|
||||
{
|
||||
quint16 cmdId16 = cmdRealNames.key(cmdName);
|
||||
|
||||
emit killCmd16(cmdId16);
|
||||
|
||||
cmdRealNames.remove(cmdId16);
|
||||
cmdUniqueNames.remove(cmdId16);
|
||||
cmdAppById.remove(cmdId16);
|
||||
cmdIds.removeOne(cmdId16);
|
||||
}
|
||||
|
||||
modCmdNames.remove(modApp);
|
||||
}
|
||||
}
|
||||
|
||||
void Session::closeSubChannel(const QByteArray &data)
|
||||
{
|
||||
QByteArray oldSubChs = QByteArray(openSubChs, MAX_OPEN_SUB_CHANNELS * BLKSIZE_SUB_CHANNEL);
|
||||
|
||||
if (rmBlockFromBlockset(data.data(), openSubChs, MAX_OPEN_SUB_CHANNELS, BLKSIZE_SUB_CHANNEL))
|
||||
{
|
||||
rmBlockFromBlockset(data.data(), openWritableSubChs, MAX_OPEN_SUB_CHANNELS, BLKSIZE_SUB_CHANNEL);
|
||||
|
||||
if (rd8BitFromBlock(activeUpdate))
|
||||
{
|
||||
castPeerStat(oldSubChs, false);
|
||||
containsActiveCh(openSubChs, activeUpdate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Session::openSubChannel(const QByteArray &data)
|
||||
{
|
||||
if (addBlockToBlockset(data.data(), openSubChs, MAX_OPEN_SUB_CHANNELS, BLKSIZE_SUB_CHANNEL))
|
||||
{
|
||||
containsActiveCh(openSubChs, activeUpdate);
|
||||
rd8BitFromBlock(activeUpdate);
|
||||
}
|
||||
}
|
|
@ -1,821 +0,0 @@
|
|||
#include "cmd_executor.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/>.
|
||||
|
||||
CmdExecutor::CmdExecutor(RWSharedObjs *rwShare, SharedObjs *rdOnlyShare, QSharedMemory *debugInfo, QObject *parent) : QObject(parent)
|
||||
{
|
||||
rwShare->commands = &commands;
|
||||
rwShare->activeLoopCmds = &activeLoopCmds;
|
||||
rwShare->pausedCmds = &pausedCmds;
|
||||
rwShare->moreInputCmds = &moreInputCmds;
|
||||
rwShare->cmdNames = &cmdNames;
|
||||
|
||||
rdOnlyShare->activeLoopCmds = &activeLoopCmds;
|
||||
rdOnlyShare->pausedCmds = &pausedCmds;
|
||||
rdOnlyShare->moreInputCmds = &moreInputCmds;
|
||||
rdOnlyShare->cmdNames = &cmdNames;
|
||||
|
||||
loopIndex = 0;
|
||||
exeDebugInfo = debugInfo;
|
||||
rdSharedObjs = rdOnlyShare;
|
||||
rwSharedObjs = rwShare;
|
||||
internalCmds = nullptr;
|
||||
|
||||
connect(this, &CmdExecutor::loop, this, &CmdExecutor::exeCmd);
|
||||
}
|
||||
|
||||
void CmdExecutor::buildCmdLoaders()
|
||||
{
|
||||
internalCmds = new InternalCommandLoader(rwSharedObjs, this);
|
||||
|
||||
cmdLoaders.insert(INTERN_MOD_NAME, internalCmds);
|
||||
|
||||
Query db(this);
|
||||
|
||||
db.setType(Query::PULL, TABLE_MODULES);
|
||||
db.addColumn(COLUMN_MOD_NAME);
|
||||
db.addCondition(COLUMN_LOCKED, false);
|
||||
db.exec();
|
||||
|
||||
for (int i = 0; i < db.rows(); ++i)
|
||||
{
|
||||
loadModFile(db.getData(COLUMN_MOD_NAME, i).toString());
|
||||
}
|
||||
}
|
||||
|
||||
void CmdExecutor::wrCrashDebugInfo(const QString &msg)
|
||||
{
|
||||
if (exeDebugInfo->isAttached())
|
||||
{
|
||||
exeDebugInfo->lock();
|
||||
|
||||
QByteArray data = toTEXT(msg).leftJustified(EXE_DEBUG_INFO_SIZE, static_cast<char>(0), true);
|
||||
|
||||
memcpy(exeDebugInfo->data(), data.data(), EXE_DEBUG_INFO_SIZE);
|
||||
|
||||
exeDebugInfo->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void CmdExecutor::connectExternCmd(ExternCommand *cmd, quint16 cmdId, const QString &cmdName)
|
||||
{
|
||||
wrCrashDebugInfo(" exe func: connectExternCmd()\n cmd id: " + QString::number(cmdId) + "\n cmd name: " + cmdName);
|
||||
|
||||
auto *cmdOutput = new CommandOutput(cmd);
|
||||
|
||||
connect(cmdOutput, &CommandOutput::dataOut, this, &CmdExecutor::externDataToIPC);
|
||||
|
||||
connectCommon(cmd, cmdOutput, cmdId, cmdName);
|
||||
}
|
||||
|
||||
void CmdExecutor::connectInternCmd(InternCommand *cmd, quint16 cmdId, const QString &cmdName)
|
||||
{
|
||||
wrCrashDebugInfo(" exe func: connectInternCmd()\n cmd id: " + QString::number(cmdId) + "\n cmd name: " + cmdName);
|
||||
|
||||
auto *cmdOutput = new CommandOutput(cmd);
|
||||
|
||||
connect(cmdOutput, &CommandOutput::dataOut, this, &CmdExecutor::internDataToIPC);
|
||||
|
||||
connect(cmd, &InternCommand::backendDataOut, this, &CmdExecutor::backendFromCmd);
|
||||
connect(cmd, &InternCommand::authOk, this, &CmdExecutor::authOk);
|
||||
connect(cmd, &InternCommand::termAllCommands, this, &CmdExecutor::termAllCommands);
|
||||
connect(cmd, &InternCommand::termCommandId, this, &CmdExecutor::termCommandId);
|
||||
connect(cmd, &InternCommand::reloadCommands, this, &CmdExecutor::buildCommands);
|
||||
|
||||
connectCommon(cmd, cmdOutput, cmdId, cmdName);
|
||||
}
|
||||
|
||||
void CmdExecutor::connectCommon(ExternCommand *cmd, CommandOutput *cmdOutput, quint16 cmdId, const QString &cmdName)
|
||||
{
|
||||
wrCrashDebugInfo(" exe func: connectCommon()\n cmd id: " + QString::number(cmdId) + "\n cmd name: " + cmdName);
|
||||
|
||||
connect(cmdOutput, &CommandOutput::closeChById, this, &CmdExecutor::closeChById);
|
||||
connect(cmdOutput, &CommandOutput::openChById, this, &CmdExecutor::openChById);
|
||||
connect(cmdOutput, &CommandOutput::closeChByName, this, &CmdExecutor::closeChByName);
|
||||
connect(cmdOutput, &CommandOutput::openChByName, this, &CmdExecutor::openChByName);
|
||||
connect(cmdOutput, &CommandOutput::cmdFinished, this, &CmdExecutor::commandFinished);
|
||||
connect(cmdOutput, &CommandOutput::enableLoop, this, &CmdExecutor::enableLoop);
|
||||
connect(cmdOutput, &CommandOutput::enableMoreInput, this, &CmdExecutor::enableMoreInput);
|
||||
|
||||
connect(cmd, &ExternCommand::closeChById, cmdOutput, &CommandOutput::closeChIdFromCmdObj);
|
||||
connect(cmd, &ExternCommand::openChById, cmdOutput, &CommandOutput::openChIdFromCmdObj);
|
||||
connect(cmd, &ExternCommand::closeChByName, cmdOutput, &CommandOutput::closeChNameFromCmdObj);
|
||||
connect(cmd, &ExternCommand::openChByName, cmdOutput, &CommandOutput::openChNameFromCmdObj);
|
||||
connect(cmd, &ExternCommand::cmdFinished, cmdOutput, &CommandOutput::finished);
|
||||
connect(cmd, &ExternCommand::enableLoop, cmdOutput, &CommandOutput::enableLoopFromCmdObj);
|
||||
connect(cmd, &ExternCommand::enableMoreInput, cmdOutput, &CommandOutput::enableMoreInputFromCmdObj);
|
||||
connect(cmd, &ExternCommand::dataToClient, cmdOutput, &CommandOutput::dataFromCmdObj);
|
||||
|
||||
connect(cmd, &ExternCommand::castToPeers, this, &CmdExecutor::castToPeers);
|
||||
connect(cmd, &ExternCommand::toPeer, this, &CmdExecutor::toPeer);
|
||||
connect(cmd, &ExternCommand::closeSession, this, &CmdExecutor::endSession);
|
||||
connect(cmd, &ExternCommand::logout, this, &CmdExecutor::logout);
|
||||
|
||||
cmd->cmdId = cmdId;
|
||||
cmd->inMoreInputMode = false;
|
||||
cmd->inLoopMode = false;
|
||||
cmd->errSent = false;
|
||||
|
||||
cmd->setObjectName(cmdName);
|
||||
cmdOutput->setCmdId(cmdId);
|
||||
}
|
||||
|
||||
void CmdExecutor::enableLoop(quint16 cmdId, bool state)
|
||||
{
|
||||
if (state)
|
||||
{
|
||||
uniqueAdd(cmdId, activeLoopCmds);
|
||||
}
|
||||
else
|
||||
{
|
||||
activeLoopCmds.removeAll(cmdId);
|
||||
}
|
||||
}
|
||||
|
||||
void CmdExecutor::enableMoreInput(quint16 cmdId, bool state)
|
||||
{
|
||||
if (state)
|
||||
{
|
||||
uniqueAdd(cmdId, moreInputCmds);
|
||||
}
|
||||
else
|
||||
{
|
||||
moreInputCmds.removeAll(cmdId);
|
||||
}
|
||||
}
|
||||
|
||||
void CmdExecutor::preExe(ExternCommand *cmdObj, quint16 cmdId)
|
||||
{
|
||||
cmdObj->cmdId = cmdId;
|
||||
cmdObj->errSent = false;
|
||||
}
|
||||
|
||||
void CmdExecutor::preExe(const QList<ExternCommand *> &cmdObjs, quint16 cmdId)
|
||||
{
|
||||
for (auto cmdObj : cmdObjs)
|
||||
{
|
||||
preExe(cmdObj, cmdId);
|
||||
}
|
||||
}
|
||||
|
||||
void CmdExecutor::exeCmd(quint16 cmdId, const QByteArray &data, uchar typeId)
|
||||
{
|
||||
wrCrashDebugInfo(" exe func: exeCmd()\n cmd id: " + QString::number(cmdId) + "\n type id: " + QString::number(typeId));
|
||||
|
||||
if (!commands.contains(cmdId))
|
||||
{
|
||||
emit dataToSession(cmdId, toTEXT("err: The requested command id: '" + QString::number(cmdId) + "' does not exists.\n"), ERR);
|
||||
emit dataToSession(cmdId, QByteArray(), IDLE);
|
||||
}
|
||||
else if (!pausedCmds.contains(cmdId))
|
||||
{
|
||||
ExternCommand *cmdObj = commands[cmdId];
|
||||
|
||||
preExe(cmdObj, cmdId);
|
||||
preExe(cmdObj->internCommands.values(), cmdId);
|
||||
|
||||
cmdObj->procBin(rdSharedObjs, data, typeId);
|
||||
|
||||
if (!activeLoopCmds.contains(cmdId) && !moreInputCmds.contains(cmdId))
|
||||
{
|
||||
emit cmdObj->cmdFinished();
|
||||
}
|
||||
|
||||
nextLoopCmd();
|
||||
}
|
||||
}
|
||||
|
||||
void CmdExecutor::nextLoopCmd()
|
||||
{
|
||||
if (!activeLoopCmds.isEmpty())
|
||||
{
|
||||
if (loopIndex == activeLoopCmds.size())
|
||||
{
|
||||
loopIndex = 0;
|
||||
}
|
||||
|
||||
wrCrashDebugInfo(" exe func: nextLoopCmd()\n loop index: " + QString::number(loopIndex));
|
||||
|
||||
emit loop(activeLoopCmds[loopIndex++], QByteArray(), TEXT);
|
||||
}
|
||||
}
|
||||
|
||||
void CmdExecutor::termCommandObj(quint16 cmdId, ExternCommand *cmd, bool del)
|
||||
{
|
||||
wrCrashDebugInfo(" exe func: termCommandObj()\n cmd id: " + QString::number(cmdId));
|
||||
|
||||
if (moreInputCmds.contains(cmdId) || activeLoopCmds.contains(cmdId))
|
||||
{
|
||||
cmd->term();
|
||||
|
||||
cmd->inLoopMode = false;
|
||||
cmd->inMoreInputMode = false;
|
||||
|
||||
for (auto internObj : cmd->internCommands.values())
|
||||
{
|
||||
if (internObj->inLoopMode || internObj->inMoreInputMode)
|
||||
{
|
||||
internObj->term();
|
||||
|
||||
internObj->inLoopMode = false;
|
||||
internObj->inMoreInputMode = false;
|
||||
}
|
||||
}
|
||||
|
||||
emit dataToSession(cmdId, QByteArray(), IDLE);
|
||||
}
|
||||
|
||||
moreInputCmds.removeAll(cmdId);
|
||||
activeLoopCmds.removeAll(cmdId);
|
||||
pausedCmds.removeAll(cmdId);
|
||||
|
||||
if (del)
|
||||
{
|
||||
wrCrashDebugInfo(" exe func: termCommandObj()\n cmd id: " + QString::number(cmdId) + "\n note: deleting intern commands");
|
||||
|
||||
for (auto internObj : cmd->internCommands.values())
|
||||
{
|
||||
internObj->aboutToDelete();
|
||||
internObj->deleteLater();
|
||||
}
|
||||
|
||||
wrCrashDebugInfo(" exe func: termCommandObj()\n cmd id: " + QString::number(cmdId) + "\n note: calling the command object's aboutToDelete()");
|
||||
|
||||
cmd->aboutToDelete();
|
||||
cmd->deleteLater();
|
||||
|
||||
commands.remove(cmdId);
|
||||
cmdNames.remove(cmdId);
|
||||
|
||||
for (auto&& list : cmdIdsByModName.values())
|
||||
{
|
||||
if (list.contains(cmdId))
|
||||
{
|
||||
list.removeAll(cmdId);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
emit dataToSession(ASYNC_RM_CMD, wrInt(cmdId, 16), CMD_ID);
|
||||
}
|
||||
}
|
||||
|
||||
void CmdExecutor::termCommandId(quint16 cmdId)
|
||||
{
|
||||
if (commands.contains(cmdId))
|
||||
{
|
||||
termCommandObj(cmdId, commands[cmdId]);
|
||||
}
|
||||
}
|
||||
|
||||
void CmdExecutor::termCommandsInList(const QList<quint16> &cmds, bool del)
|
||||
{
|
||||
for (auto&& cmdId : cmds)
|
||||
{
|
||||
termCommandObj(cmdId, commands[cmdId], del);
|
||||
}
|
||||
}
|
||||
|
||||
void CmdExecutor::termAllCommands()
|
||||
{
|
||||
termCommandsInList(moreInputCmds, false);
|
||||
termCommandsInList(activeLoopCmds, false);
|
||||
termCommandsInList(pausedCmds, false);
|
||||
}
|
||||
|
||||
void CmdExecutor::close()
|
||||
{
|
||||
termCommandsInList(commands.keys(), true);
|
||||
|
||||
for (auto cmdLoader : cmdLoaders.values())
|
||||
{
|
||||
cmdLoader->aboutToDelete();
|
||||
cmdLoader->deleteLater();
|
||||
}
|
||||
|
||||
for (auto plugin : plugins.values())
|
||||
{
|
||||
plugin->unload();
|
||||
plugin->deleteLater();
|
||||
}
|
||||
|
||||
cleanupDbConnection();
|
||||
|
||||
emit okToDelete();
|
||||
}
|
||||
|
||||
void CmdExecutor::commandFinished(quint16 cmdId)
|
||||
{
|
||||
emit dataToSession(cmdId, QByteArray(), IDLE);
|
||||
|
||||
moreInputCmds.removeAll(cmdId);
|
||||
activeLoopCmds.removeAll(cmdId);
|
||||
pausedCmds.removeAll(cmdId);
|
||||
}
|
||||
|
||||
QString CmdExecutor::makeCmdUnique(const QString &name)
|
||||
{
|
||||
QString strNum;
|
||||
QStringList names = cmdNames.values();
|
||||
|
||||
for (int j = 1; names.contains(QString(name + strNum).toLower()); ++j)
|
||||
{
|
||||
strNum = "_" + QString::number(j);
|
||||
}
|
||||
|
||||
return QString(name + strNum).toLower();
|
||||
}
|
||||
|
||||
void CmdExecutor::procInternRequest(ExternCommand *cmd, quint16 cmdId, const QString &cmdName)
|
||||
{
|
||||
wrCrashDebugInfo(" exe func: procInternRequest()\n cmd id: " + QString::number(cmdId));
|
||||
|
||||
QStringList internCmdNames = internalCmds->cmdList();
|
||||
|
||||
for (auto&& reqCmdName : cmd->internRequest())
|
||||
{
|
||||
if (internCmdNames.contains(reqCmdName, Qt::CaseInsensitive))
|
||||
{
|
||||
InternCommand *cmdObj = internalCmds->cmdObj(reqCmdName);
|
||||
|
||||
if (cmdObj != nullptr)
|
||||
{
|
||||
connectInternCmd(cmdObj, cmdId, cmdName);
|
||||
|
||||
cmdObj->setParent(cmd);
|
||||
cmd->internCommands.insert(reqCmdName, cmdObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
quint16 CmdExecutor::getModIdOffs(const QString &name)
|
||||
{
|
||||
if (name == INTERN_MOD_NAME)
|
||||
{
|
||||
return MAX_CMDS_PER_MOD;
|
||||
}
|
||||
else
|
||||
{
|
||||
Query db(this);
|
||||
|
||||
db.setType(Query::PULL, TABLE_MODULES);
|
||||
db.addColumn(COLUMN_CMD_ID_OFFS);
|
||||
db.addCondition(COLUMN_MOD_NAME, name);
|
||||
db.exec();
|
||||
|
||||
return static_cast<quint16>(db.getData(COLUMN_CMD_ID_OFFS).toUInt());
|
||||
}
|
||||
}
|
||||
|
||||
QString CmdExecutor::getModFile(const QString &modName)
|
||||
{
|
||||
Query db(this);
|
||||
|
||||
db.setType(Query::PULL, TABLE_MODULES);
|
||||
db.addColumn(COLUMN_MOD_MAIN);
|
||||
db.addCondition(COLUMN_MOD_NAME, modName);
|
||||
db.exec();
|
||||
|
||||
return db.getData(COLUMN_MOD_MAIN).toString();
|
||||
}
|
||||
|
||||
void CmdExecutor::loadModFile(const QString &modName)
|
||||
{
|
||||
bool modOk = false;
|
||||
QStringList ver = QCoreApplication::applicationVersion().split('.');
|
||||
QString mainFilePath = getModFile(modName);
|
||||
QString path = QFileInfo(mainFilePath).path();
|
||||
auto *lib = new QLibrary(mainFilePath, this);
|
||||
|
||||
lib->load();
|
||||
|
||||
ModImportFunc importFunc = reinterpret_cast<ModImportFunc>(lib->resolve(MOD_IMPORT_FUNC));
|
||||
|
||||
if (!importFunc)
|
||||
{
|
||||
qDebug() << "CmdExecutor::loadModFile() err: failed to load mod lib file: " << mainFilePath << " reason: " << lib->errorString();
|
||||
}
|
||||
else
|
||||
{
|
||||
wrCrashDebugInfo(" exe func: loadModFile()\n path: " + mainFilePath + " \nmod name: " + modName + " \nnote: calling the module's import function.");
|
||||
|
||||
CommandLoader *cmdLoader = importFunc();
|
||||
|
||||
wrCrashDebugInfo(" exe func: loadModFile()\n path: " + mainFilePath + " \nmod name: " + modName + " \nnote: running import rev negotiations.");
|
||||
|
||||
if (!cmdLoader)
|
||||
{
|
||||
qDebug() << "CmdExecutor::loadModFile() err: failed to load mod lib file: " << mainFilePath << " reason: the CommandLoader object returned by the import function is null.";
|
||||
}
|
||||
else if (cmdLoader->rev() < IMPORT_REV)
|
||||
{
|
||||
qDebug() << "CmdExecutor::loadModFile() err: failed to load mod lib file: " << mainFilePath << " reason: module import rev " << cmdLoader->rev() << " not compatible with host rev " << IMPORT_REV << ".";
|
||||
}
|
||||
else if (!cmdLoader->hostRevOk(IMPORT_REV, ver[0].toUShort(), ver[1].toUShort(), ver[2].toUShort()))
|
||||
{
|
||||
qDebug() << "CmdExecutor::loadModFile() err: failed to load mod lib file: " << mainFilePath << " the module rejected the host rev/version. reason: " << cmdLoader->lastError() << ".";
|
||||
}
|
||||
else
|
||||
{
|
||||
modOk = true;
|
||||
|
||||
wrCrashDebugInfo(" exe func: loadModFile()\n path: " + mainFilePath + " \nmod name: " + modName + " \nnote: calling the module's modPath() function.");
|
||||
|
||||
cmdLoader->modPath(path);
|
||||
|
||||
cmdLoaders.insert(modName, cmdLoader);
|
||||
plugins.insert(modName, lib);
|
||||
}
|
||||
}
|
||||
|
||||
if (!modOk)
|
||||
{
|
||||
lib->unload();
|
||||
lib->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
void CmdExecutor::unloadModFile(const QString &modName)
|
||||
{
|
||||
if (cmdIdsByModName.contains(modName))
|
||||
{
|
||||
termCommandsInList(cmdIdsByModName[modName], true);
|
||||
|
||||
wrCrashDebugInfo(" exe func: unloadModFile()\n mod name: " + modName + "\n note: calling the modules's aboutToDelete().");
|
||||
|
||||
cmdLoaders[modName]->aboutToDelete();
|
||||
cmdLoaders[modName]->deleteLater();
|
||||
|
||||
wrCrashDebugInfo(" exe func: unloadModFile()\n mod name: " + modName + "\n note: calling the modules's library unload function.");
|
||||
|
||||
plugins[modName]->unload();
|
||||
plugins[modName]->deleteLater();
|
||||
|
||||
cmdIdsByModName.remove(modName);
|
||||
cmdLoaders.remove(modName);
|
||||
plugins.remove(modName);
|
||||
}
|
||||
}
|
||||
|
||||
void CmdExecutor::addCommandToList(quint16 cmdId, const QString &cmdName, const QString &modName, ExternCommand *cmdObj)
|
||||
{
|
||||
procInternRequest(cmdObj, cmdId, cmdName);
|
||||
|
||||
commands.insert(cmdId, cmdObj);
|
||||
cmdNames.insert(cmdId, cmdName);
|
||||
|
||||
if (cmdIdsByModName.contains(modName))
|
||||
{
|
||||
cmdIdsByModName[modName].append(cmdId);
|
||||
}
|
||||
else
|
||||
{
|
||||
QList<quint16> list;
|
||||
|
||||
list.append(cmdId);
|
||||
cmdIdsByModName.insert(modName, list);
|
||||
}
|
||||
|
||||
emit dataToSession(ASYNC_ADD_CMD, toNEW_CMD(cmdId, cmdName, cmdObj), NEW_CMD);
|
||||
}
|
||||
|
||||
bool CmdExecutor::allowCmdLoad(const QString &cmdName, const QString &modName, const QStringList &exemptList)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
if (exemptList.contains(cmdName, Qt::CaseInsensitive))
|
||||
{
|
||||
ret = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Query db(this);
|
||||
|
||||
db.setType(Query::PULL, TABLE_CMD_RANKS);
|
||||
db.addColumn(COLUMN_HOST_RANK);
|
||||
db.addCondition(COLUMN_COMMAND, cmdName);
|
||||
db.addCondition(COLUMN_MOD_NAME, modName);
|
||||
db.exec();
|
||||
|
||||
if (db.rows())
|
||||
{
|
||||
uint cmdRank = db.getData(COLUMN_HOST_RANK).toUInt();
|
||||
|
||||
if (cmdRank >= *rdSharedObjs->hostRank)
|
||||
{
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
else if (*rdSharedObjs->hostRank == 1)
|
||||
{
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CmdExecutor::loadInternCmd(CommandLoader *loader, const QString &cmdName, const QString &uniqueName, quint16 id)
|
||||
{
|
||||
auto *cmdObj = reinterpret_cast<InternCommand*>(loader->cmdObj(cmdName));
|
||||
|
||||
if (cmdObj != nullptr)
|
||||
{
|
||||
connectInternCmd(cmdObj, id, uniqueName);
|
||||
addCommandToList(id, uniqueName, INTERN_MOD_NAME, cmdObj);
|
||||
}
|
||||
}
|
||||
|
||||
void CmdExecutor::loadExternCmd(CommandLoader *loader, const QString &modName, const QString &cmdName, const QString &uniqueName, quint16 id)
|
||||
{
|
||||
ExternCommand *cmdObj = loader->cmdObj(cmdName);
|
||||
|
||||
if (cmdObj != nullptr)
|
||||
{
|
||||
connectExternCmd(cmdObj, id, uniqueName);
|
||||
addCommandToList(id, uniqueName, modName, cmdObj);
|
||||
}
|
||||
}
|
||||
|
||||
void CmdExecutor::loadCmd(CommandLoader *loader, quint16 cmdId, const QString &modName, const QString &cmdName, const QString &uniqueCmdName)
|
||||
{
|
||||
wrCrashDebugInfo(" exe func: loadCmd()\n cmd id: " + QString::number(cmdId) + "\n cmd name: " + cmdName);
|
||||
|
||||
if (modName == INTERN_MOD_NAME)
|
||||
{
|
||||
loadInternCmd(loader, cmdName, uniqueCmdName, cmdId);
|
||||
}
|
||||
else
|
||||
{
|
||||
loadExternCmd(loader, modName, cmdName, uniqueCmdName, cmdId);
|
||||
}
|
||||
}
|
||||
|
||||
void CmdExecutor::loadCmds(CommandLoader *loader, quint16 idOffs, const QString &modName)
|
||||
{
|
||||
wrCrashDebugInfo(" exe func: loadCmds()\n mod name: " + modName + "\n id offs: " + QString::number(idOffs));
|
||||
|
||||
QStringList list = loader->cmdList();
|
||||
QStringList pub = loader->pubCmdList();
|
||||
QStringList exempt = loader->rankExemptList();
|
||||
|
||||
list.sort(Qt::CaseInsensitive);
|
||||
|
||||
for (quint16 id = 0; (id < list.size()) && (id < MAX_CMDS_PER_MOD); ++id)
|
||||
{
|
||||
QString unique = makeCmdUnique(list[id]);
|
||||
quint16 cmdId = idOffs + id;
|
||||
|
||||
if (validCommandName(unique))
|
||||
{
|
||||
if (commands.contains(cmdId))
|
||||
{
|
||||
if (!allowCmdLoad(list[id], modName, exempt))
|
||||
{
|
||||
termCommandObj(cmdId, commands[cmdId], true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rdSharedObjs->userName->isEmpty())
|
||||
{
|
||||
if (pub.contains(list[id], Qt::CaseInsensitive))
|
||||
{
|
||||
loadCmd(loader, cmdId, modName, list[id], unique);
|
||||
}
|
||||
}
|
||||
else if (allowCmdLoad(list[id], modName, exempt))
|
||||
{
|
||||
loadCmd(loader, cmdId, modName, list[id], unique);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "CmdExecutor::getCmdNames() err: command object name '" << unique << "' is not valid.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CmdExecutor::buildCommands()
|
||||
{
|
||||
for (auto&& loaderName : cmdLoaders.keys())
|
||||
{
|
||||
loadCmds(cmdLoaders[loaderName], getModIdOffs(loaderName), loaderName);
|
||||
}
|
||||
}
|
||||
|
||||
bool CmdExecutor::externBlockedTypeId(uchar typeId)
|
||||
{
|
||||
// the internal host objects will handle sending the following TypeIDs to the clients
|
||||
// and peers. any attempt to do so via ExternCommand object will be blocked since these
|
||||
// data types can cause some behaviour issues if sent at an unexpected time.
|
||||
|
||||
return (typeId == PRIV_IPC) || (typeId == PUB_IPC) || (typeId == PING_PEERS) ||
|
||||
(typeId == PEER_STAT) || (typeId == MY_INFO) || (typeId == PEER_INFO) ||
|
||||
(typeId == HOST_CERT) || (typeId == IDLE) || (typeId == NEW_CMD);
|
||||
}
|
||||
|
||||
bool CmdExecutor::p2pBlockedTypeId(uchar typeId)
|
||||
{
|
||||
// this is used to block P2P specific typeIDs. only toPeers() or internDataToIPC()
|
||||
// should be allowed to send these frame types, all others use this to block them.
|
||||
|
||||
return (typeId == P2P_REQUEST) || (typeId == P2P_OPEN) || (typeId == P2P_CLOSE);
|
||||
}
|
||||
|
||||
void CmdExecutor::externDataToIPC(quint16 cmdId, const QByteArray &data, uchar typeId)
|
||||
{
|
||||
if (!externBlockedTypeId(typeId) && !p2pBlockedTypeId(typeId))
|
||||
{
|
||||
emit dataToSession(cmdId, data, typeId);
|
||||
}
|
||||
}
|
||||
|
||||
void CmdExecutor::internDataToIPC(quint16 cmdId, const QByteArray &data, uchar typeId)
|
||||
{
|
||||
if ((typeId != IDLE) && (typeId != NEW_CMD))
|
||||
{
|
||||
emit dataToSession(cmdId, data, typeId);
|
||||
}
|
||||
}
|
||||
|
||||
void CmdExecutor::castToPeers(const QByteArray &data, uchar typeId)
|
||||
{
|
||||
if (!externBlockedTypeId(typeId) && !p2pBlockedTypeId(typeId))
|
||||
{
|
||||
QByteArray castHeader = *rdSharedObjs->wrAbleChIds + wrInt(typeId, 8);
|
||||
|
||||
emit dataToSession(ASYNC_CAST, castHeader + data, PUB_IPC);
|
||||
}
|
||||
}
|
||||
|
||||
void CmdExecutor::toPeer(const QByteArray &dst, const QByteArray &data, uchar typeId)
|
||||
{
|
||||
if (!externBlockedTypeId(typeId) && (dst.size() == 28))
|
||||
{
|
||||
QByteArray p2pHeader = dst + *rdSharedObjs->sessionId + wrInt(typeId, 8);
|
||||
|
||||
if (typeId == P2P_REQUEST)
|
||||
{
|
||||
if (!rdSharedObjs->p2pPending->contains(dst))
|
||||
{
|
||||
rwSharedObjs->p2pPending->append(dst);
|
||||
|
||||
emit dataToSession(ASYNC_P2P, p2pHeader + toPEER_INFO(rdSharedObjs), PUB_IPC);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((typeId == P2P_CLOSE) || (typeId == P2P_OPEN))
|
||||
{
|
||||
if (rdSharedObjs->p2pPending->contains(dst) || rdSharedObjs->p2pAccepted->contains(dst))
|
||||
{
|
||||
if (typeId == P2P_CLOSE)
|
||||
{
|
||||
rwSharedObjs->p2pPending->removeAll(dst);
|
||||
rwSharedObjs->p2pAccepted->removeAll(dst);
|
||||
|
||||
emit dataToSession(ASYNC_P2P, p2pHeader + dst, PUB_IPC);
|
||||
}
|
||||
else if (!rdSharedObjs->p2pAccepted->contains(dst))
|
||||
{
|
||||
rwSharedObjs->p2pPending->removeAll(dst);
|
||||
rwSharedObjs->p2pAccepted->append(dst);
|
||||
|
||||
emit dataToSession(ASYNC_P2P, p2pHeader + dst, PUB_IPC);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
emit dataToSession(ASYNC_P2P, p2pHeader + data, PUB_IPC);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CmdExecutor::backendFromCmd(quint16 cmdId, const QByteArray &data, uchar typeId)
|
||||
{
|
||||
if ((typeId == PUB_IPC) || (typeId == PRIV_IPC) || (typeId == PUB_IPC_WITH_FEEDBACK))
|
||||
{
|
||||
emit dataToSession(cmdId, data, typeId);
|
||||
}
|
||||
}
|
||||
|
||||
void CmdExecutor::openOrCloseChByName(quint16 cmdId, const QString &ch, const QString &sub, bool open)
|
||||
{
|
||||
if (!validChName(ch))
|
||||
{
|
||||
emit dataToSession(cmdId, toTEXT("err: '" + ch + "' is not a valid channel name.\n"), ERR);
|
||||
}
|
||||
else if (!validChName(sub))
|
||||
{
|
||||
emit dataToSession(cmdId, toTEXT("err: '" + sub + "' is not a valid sub channel name.\n"), ERR);
|
||||
}
|
||||
else if (!channelSubExists(ch, sub))
|
||||
{
|
||||
emit dataToSession(cmdId, toTEXT("err: Sub-channel: '" + sub + "' does not exists.\n"), ERR);
|
||||
}
|
||||
else
|
||||
{
|
||||
Query db(this);
|
||||
|
||||
db.setType(Query::PULL, TABLE_SUB_CHANNELS);
|
||||
db.addColumn(COLUMN_CHANNEL_ID);
|
||||
db.addColumn(COLUMN_SUB_CH_ID);
|
||||
db.addCondition(COLUMN_SUB_CH_NAME, sub);
|
||||
db.addCondition(COLUMN_CHANNEL_NAME, ch);
|
||||
db.exec();
|
||||
|
||||
if (open)
|
||||
{
|
||||
openChById(cmdId, db.getData(COLUMN_CHANNEL_ID).toULongLong(), static_cast<uchar>(db.getData(COLUMN_SUB_CH_ID).toUInt()));
|
||||
}
|
||||
else
|
||||
{
|
||||
closeChById(cmdId, db.getData(COLUMN_CHANNEL_ID).toULongLong(), static_cast<uchar>(db.getData(COLUMN_SUB_CH_ID).toUInt()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CmdExecutor::openChByName(quint16 cmdId, const QString &ch, const QString &sub)
|
||||
{
|
||||
openOrCloseChByName(cmdId, ch, sub, true);
|
||||
}
|
||||
|
||||
void CmdExecutor::closeChByName(quint16 cmdId, const QString &ch, const QString &sub)
|
||||
{
|
||||
openOrCloseChByName(cmdId, ch, sub, false);
|
||||
}
|
||||
|
||||
void CmdExecutor::openChById(quint16 cmdId, quint64 chId, uchar subId)
|
||||
{
|
||||
QByteArray id = wrInt(chId, 64) + wrInt(subId, 8);
|
||||
|
||||
if (chId == 0)
|
||||
{
|
||||
emit dataToSession(cmdId, toTEXT("err: '0' is not a valid channel id. it must an unsigned integer between 1-18446744073709551615.\n"), ERR);
|
||||
}
|
||||
else if (countChs(*rdSharedObjs->chIds) == 6)
|
||||
{
|
||||
emit dataToSession(cmdId, toTEXT("err: The maximum amount of open sub-channels reached (6).\n"), ERR);
|
||||
}
|
||||
else if (containsChId(id, *rdSharedObjs->chIds))
|
||||
{
|
||||
emit dataToSession(cmdId, toTEXT("err: The requested sub-channel is already open.\n"), ERR);
|
||||
}
|
||||
else if (!channelSubExists(chId, subId))
|
||||
{
|
||||
emit dataToSession(cmdId, toTEXT("err: The requested sub-channel does not exists.\n"), ERR);
|
||||
}
|
||||
else if (channelAccessLevel(rdSharedObjs, chId) > lowestAcessLevel(chId, subId))
|
||||
{
|
||||
emit dataToSession(cmdId, toTEXT("err: Access denied.\n"), ERR);
|
||||
}
|
||||
else
|
||||
{
|
||||
wrOpenCh(rwSharedObjs, id);
|
||||
}
|
||||
}
|
||||
|
||||
void CmdExecutor::closeChById(quint16 cmdId, quint64 chId, uchar subId)
|
||||
{
|
||||
QByteArray id = wrInt(chId, 64) + wrInt(subId, 8);
|
||||
|
||||
if (chId == 0)
|
||||
{
|
||||
emit dataToSession(cmdId, toTEXT("err: '0' is not a valid channel id. it must an integer between 1-18446744073709551615.\n"), ERR);
|
||||
}
|
||||
else if (!containsChId(id, *rdSharedObjs->chIds))
|
||||
{
|
||||
emit dataToSession(cmdId, toTEXT("err: The requested sub-channel is not open.\n"), ERR);
|
||||
}
|
||||
else
|
||||
{
|
||||
QByteArray peerStat;
|
||||
|
||||
wrCloseCh(rwSharedObjs, id, peerStat);
|
||||
|
||||
if (!peerStat.isEmpty())
|
||||
{
|
||||
emit dataToSession(ASYNC_LIMITED_CAST, peerStat, PUB_IPC);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,108 +0,0 @@
|
|||
#ifndef CMD_EXECUTOR_H
|
||||
#define CMD_EXECUTOR_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 "int_loader.h"
|
||||
|
||||
typedef CommandLoader *(*ModImportFunc)();
|
||||
|
||||
class CmdExecutor : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
|
||||
SharedObjs *rdSharedObjs;
|
||||
RWSharedObjs *rwSharedObjs;
|
||||
InternalCommandLoader *internalCmds;
|
||||
QSharedMemory *exeDebugInfo;
|
||||
QHash<QString, CommandLoader*> cmdLoaders;
|
||||
QHash<QString, QLibrary*> plugins;
|
||||
QHash<QString, QList<quint16> > cmdIdsByModName;
|
||||
QList<quint16> moreInputCmds;
|
||||
QList<quint16> activeLoopCmds;
|
||||
QList<quint16> pausedCmds;
|
||||
QHash<quint16, QString> cmdNames;
|
||||
QHash<quint16, ExternCommand*> commands;
|
||||
int loopIndex;
|
||||
|
||||
void nextLoopCmd();
|
||||
void preExe(ExternCommand *cmdObj, quint16 cmdId);
|
||||
void preExe(const QList<ExternCommand*> &cmdObjs, quint16 cmdId);
|
||||
void procInternRequest(ExternCommand *cmd, quint16 cmdId, const QString &cmdName);
|
||||
void connectCommon(ExternCommand *cmd, CommandOutput *cmdOutput, quint16 cmdId, const QString &cmdName);
|
||||
void connectInternCmd(InternCommand *cmd, quint16 cmdId, const QString &cmdName);
|
||||
void connectExternCmd(ExternCommand *cmd, quint16 cmdId, const QString &cmdName);
|
||||
void openOrCloseChByName(quint16 cmdId, const QString &ch, const QString &sub, bool open);
|
||||
void loadCmd(CommandLoader *loader, quint16 cmdId, const QString &modName, const QString &cmdName, const QString &uniqueCmdName);
|
||||
void loadCmds(CommandLoader *loader, quint16 idOffs, const QString &modName);
|
||||
void loadInternCmd(CommandLoader *loader, const QString &cmdName, const QString &uniqueName, quint16 id);
|
||||
void loadExternCmd(CommandLoader *loader, const QString &modName, const QString &cmdName, const QString &uniqueName, quint16 id);
|
||||
void addCommandToList(quint16 cmdId, const QString &cmdName, const QString &modName, ExternCommand *cmdObj);
|
||||
bool externBlockedTypeId(uchar typeId);
|
||||
bool p2pBlockedTypeId(uchar typeId);
|
||||
bool allowCmdLoad(const QString &cmdName, const QString &modName, const QStringList &exemptList);
|
||||
QString makeCmdUnique(const QString &name);
|
||||
QString getModFile(const QString &modName);
|
||||
quint16 getModIdOffs(const QString &name);
|
||||
|
||||
private slots:
|
||||
|
||||
void termAllCommands();
|
||||
void enableMoreInput(quint16 cmdId, bool state);
|
||||
void enableLoop(quint16 cmdId, bool state);
|
||||
void openChById(quint16 cmdId, quint64 chId, uchar subId);
|
||||
void openChByName(quint16 cmdId, const QString &ch, const QString &sub);
|
||||
void closeChById(quint16 cmdId, quint64 chId, uchar subId);
|
||||
void closeChByName(quint16 cmdId, const QString &ch, const QString &sub);
|
||||
void termCommandId(quint16 cmdId);
|
||||
void termCommandObj(quint16 cmdId, ExternCommand *cmd, bool del = false);
|
||||
void termCommandsInList(const QList<quint16> &cmds, bool del = false);
|
||||
void commandFinished(quint16 cmdId);
|
||||
void externDataToIPC(quint16 cmdId, const QByteArray &data, uchar typeId);
|
||||
void internDataToIPC(quint16 cmdId, const QByteArray &data, uchar typeId);
|
||||
void castToPeers(const QByteArray &data, uchar typeId);
|
||||
void toPeer(const QByteArray &dst, const QByteArray &data, uchar typeId);
|
||||
|
||||
public slots:
|
||||
|
||||
void close();
|
||||
void buildCommands();
|
||||
void buildCmdLoaders();
|
||||
void wrCrashDebugInfo(const QString &msg);
|
||||
void unloadModFile(const QString &modName);
|
||||
void loadModFile(const QString &modName);
|
||||
void exeCmd(quint16 cmdId, const QByteArray &data, uchar typeId);
|
||||
void backendFromCmd(quint16 cmdId, const QByteArray &data, uchar typeId);
|
||||
|
||||
signals:
|
||||
|
||||
void endSession();
|
||||
void logout();
|
||||
void authOk();
|
||||
void okToDelete();
|
||||
void dataToSession(quint16 cmdId, const QByteArray &data, uchar typeId);
|
||||
void loop(quint16 cmdId, const QByteArray &data, uchar typeId);
|
||||
|
||||
public:
|
||||
|
||||
explicit CmdExecutor(RWSharedObjs *rwShare, SharedObjs *rdOnlyShare, QSharedMemory *debugInfo, QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
#endif // CMD_EXECUTOR_H
|
219
src/cmd_object.cpp
Normal file
219
src/cmd_object.cpp
Normal file
|
@ -0,0 +1,219 @@
|
|||
#include "cmd_object.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/>.
|
||||
|
||||
IPCWorker::IPCWorker(const QString &pipe, QObject *parent) : QObject(parent)
|
||||
{
|
||||
pipeName = pipe;
|
||||
idleTimer = new IdleTimer(this);
|
||||
ipcSocket = new QLocalSocket(this);
|
||||
flags = 0;
|
||||
|
||||
connect(ipcSocket, &QLocalSocket::readyRead, this, &IPCWorker::rdFromIPC);
|
||||
connect(ipcSocket, &QLocalSocket::disconnected, this, &IPCWorker::ipcClosed);
|
||||
connect(ipcSocket, &QLocalSocket::connected, this, &IPCWorker::ipcOpened);
|
||||
connect(idleTimer, &IdleTimer::timeout, this, &IPCWorker::termProc);
|
||||
|
||||
idleTimer->attach(ipcSocket, 60000); //1min idle timeout
|
||||
}
|
||||
|
||||
void IPCWorker::rdFromIPC()
|
||||
{
|
||||
if (flags & FRAME_RDY)
|
||||
{
|
||||
if (ipcSocket->bytesAvailable() >= ipcDataSize)
|
||||
{
|
||||
emit dataOut(ipcSocket->read(ipcDataSize), ipcTypeId);
|
||||
|
||||
flags ^= FRAME_RDY;
|
||||
|
||||
rdFromIPC();
|
||||
}
|
||||
}
|
||||
else if (ipcSocket->bytesAvailable() >= (FRAME_HEADER_SIZE - 4))
|
||||
{
|
||||
QByteArray header = ipcSocket->read(FRAME_HEADER_SIZE - 4);
|
||||
|
||||
ipcTypeId = static_cast<quint8>(header[0]);
|
||||
ipcDataSize = static_cast<quint32>(rdInt(header.mid(1, 3)));
|
||||
flags |= FRAME_RDY;
|
||||
|
||||
rdFromIPC();
|
||||
}
|
||||
}
|
||||
|
||||
void IPCWorker::dataIn(const QByteArray &data, quint8 typeId)
|
||||
{
|
||||
// format: [typeId][payload_len][payload]
|
||||
|
||||
ipcSocket->write(wrInt(typeId, 8) + wrInt(data.size(), MAX_FRAME_BITS) + data);
|
||||
}
|
||||
|
||||
void IPCWorker::connectIPC()
|
||||
{
|
||||
ipcSocket->connectToServer(pipeName);
|
||||
}
|
||||
|
||||
CmdObject::CmdObject(QObject *parent) : MemShare(parent)
|
||||
{
|
||||
flags = 0;
|
||||
|
||||
QStringList args = QCoreApplication::instance()->arguments();
|
||||
QString pipe = getParam("-pipe_name", args);
|
||||
QString sMemKey = getParam("-mem_ses", args);
|
||||
QString hMemKey = getParam("-mem_host", args);
|
||||
|
||||
if (attachSharedMem(sMemKey, hMemKey))
|
||||
{
|
||||
ipcWorker = new IPCWorker(pipe, nullptr);
|
||||
keepAliveTimer = new QTimer(this);
|
||||
|
||||
auto *thr = new QThread(nullptr);
|
||||
|
||||
serializeThread(thr);
|
||||
setupDataBlocks();
|
||||
|
||||
connect(thr, &QThread::started, ipcWorker, &IPCWorker::connectIPC);
|
||||
|
||||
connect(this, &CmdObject::destroyed, thr, &QThread::deleteLater);
|
||||
connect(this, &CmdObject::procOut, ipcWorker, &IPCWorker::dataIn);
|
||||
|
||||
connect(keepAliveTimer, &QTimer::timeout, this, &CmdObject::keepAlive);
|
||||
|
||||
connect(ipcWorker, &IPCWorker::dataOut, this, &CmdObject::preProc);
|
||||
connect(ipcWorker, &IPCWorker::termProc, this, &CmdObject::kill);
|
||||
connect(ipcWorker, &IPCWorker::ipcClosed, this, &CmdObject::term);
|
||||
connect(ipcWorker, &IPCWorker::ipcOpened, this, &CmdObject::onIPCConnected);
|
||||
|
||||
keepAliveTimer->setSingleShot(false);
|
||||
keepAliveTimer->setInterval(30000); //30sec keep alive
|
||||
ipcWorker->moveToThread(thr);
|
||||
thr->start();
|
||||
}
|
||||
else
|
||||
{
|
||||
kill();
|
||||
}
|
||||
}
|
||||
|
||||
void CmdObject::term()
|
||||
{
|
||||
if (flags & (MORE_INPUT | HALT_STATE | LOOPING))
|
||||
{
|
||||
flags = 0;
|
||||
|
||||
postProc();
|
||||
}
|
||||
}
|
||||
|
||||
void CmdObject::kill()
|
||||
{
|
||||
term();
|
||||
|
||||
QCoreApplication::instance()->exit();
|
||||
}
|
||||
|
||||
void CmdObject::preProc(const QByteArray &data, quint8 typeId)
|
||||
{
|
||||
if (typeId == TERM_CMD)
|
||||
{
|
||||
term();
|
||||
}
|
||||
else if (typeId == KILL_CMD)
|
||||
{
|
||||
kill();
|
||||
}
|
||||
else if (typeId == HALT_CMD)
|
||||
{
|
||||
if (flags & LOOPING)
|
||||
{
|
||||
flags |= HALT_STATE;
|
||||
flags &= ~LOOPING;
|
||||
}
|
||||
}
|
||||
else if (typeId == RESUME_CMD)
|
||||
{
|
||||
if (flags & HALT_STATE)
|
||||
{
|
||||
flags |= LOOPING;
|
||||
flags &= ~HALT_STATE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sharedMem->lock();
|
||||
|
||||
procIn(data, typeId);
|
||||
|
||||
sharedMem->unlock();
|
||||
|
||||
postProc();
|
||||
}
|
||||
}
|
||||
|
||||
void CmdObject::postProc()
|
||||
{
|
||||
if (flags & LOOPING)
|
||||
{
|
||||
preProc(QByteArray(), TEXT);
|
||||
}
|
||||
else if (flags & (MORE_INPUT | HALT_STATE))
|
||||
{
|
||||
keepAliveTimer->start();
|
||||
}
|
||||
else
|
||||
{
|
||||
keepAliveTimer->stop();
|
||||
|
||||
emit procOut(QByteArray(), IDLE);
|
||||
}
|
||||
}
|
||||
|
||||
void CmdObject::mainTxt(const QString &txt)
|
||||
{
|
||||
emit procOut(toTEXT(txt), TEXT);
|
||||
}
|
||||
|
||||
void CmdObject::errTxt(const QString &txt)
|
||||
{
|
||||
emit procOut(toTEXT(txt), ERR);
|
||||
}
|
||||
|
||||
void CmdObject::privTxt(const QString &txt)
|
||||
{
|
||||
emit procOut(toTEXT(txt), PRIV_TEXT);
|
||||
}
|
||||
|
||||
void CmdObject::bigTxt(const QString &txt)
|
||||
{
|
||||
emit procOut(toTEXT(txt), BIG_TEXT);
|
||||
}
|
||||
|
||||
void CmdObject::async(quint16 asyncId, quint8 asyncType, const QByteArray &data)
|
||||
{
|
||||
emit procOut(wrInt(asyncId, 16) + data, asyncType);
|
||||
}
|
||||
|
||||
void CmdObject::keepAlive()
|
||||
{
|
||||
async(ASYNC_KEEP_ALIVE, PRIV_IPC);
|
||||
}
|
||||
|
||||
QString CmdObject::libName()
|
||||
{
|
||||
return QCoreApplication::applicationName() + " v" + QCoreApplication::applicationVersion() + " " + QString::number(QSysInfo::WordSize) + "Bit";
|
||||
}
|
99
src/cmd_object.h
Normal file
99
src/cmd_object.h
Normal file
|
@ -0,0 +1,99 @@
|
|||
#ifndef CMDOBJECT_H
|
||||
#define CMDOBJECT_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"
|
||||
|
||||
class IPCWorker : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private slots:
|
||||
|
||||
void rdFromIPC();
|
||||
|
||||
private:
|
||||
|
||||
IdleTimer *idleTimer;
|
||||
QLocalSocket *ipcSocket;
|
||||
quint32 flags;
|
||||
quint8 ipcTypeId;
|
||||
quint32 ipcDataSize;
|
||||
QString pipeName;
|
||||
|
||||
public slots:
|
||||
|
||||
void dataIn(const QByteArray &data, quint8 typeId);
|
||||
|
||||
public:
|
||||
|
||||
explicit IPCWorker(const QString &pipe, QObject *parent = nullptr);
|
||||
|
||||
public slots:
|
||||
|
||||
void connectIPC();
|
||||
|
||||
signals:
|
||||
|
||||
void dataOut(const QByteArray &data, quint8 typeId);
|
||||
void ipcClosed();
|
||||
void ipcOpened();
|
||||
void termProc();
|
||||
};
|
||||
|
||||
//----------------------
|
||||
|
||||
class CmdObject : public MemShare
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
protected:
|
||||
|
||||
QTimer *keepAliveTimer;
|
||||
IPCWorker *ipcWorker;
|
||||
quint32 flags;
|
||||
|
||||
void mainTxt(const QString &txt);
|
||||
void errTxt(const QString &txt);
|
||||
void privTxt(const QString &txt);
|
||||
void bigTxt(const QString &txt);
|
||||
void async(quint16 asyncId, quint8 asyncType, const QByteArray &data = QByteArray());
|
||||
void postProc();
|
||||
QString libName();
|
||||
|
||||
virtual void procIn(const QByteArray &, quint8) {}
|
||||
|
||||
protected slots:
|
||||
|
||||
void preProc(const QByteArray &data, quint8 typeId);
|
||||
void keepAlive();
|
||||
void term();
|
||||
void kill();
|
||||
|
||||
virtual void onIPCConnected() {}
|
||||
|
||||
public:
|
||||
|
||||
explicit CmdObject(QObject *parent = nullptr);
|
||||
|
||||
signals:
|
||||
|
||||
void procOut(const QByteArray &data, quint8 typeId);
|
||||
};
|
||||
|
||||
#endif // CMDOBJECT_H
|
643
src/cmd_proc.cpp
Normal file
643
src/cmd_proc.cpp
Normal file
|
@ -0,0 +1,643 @@
|
|||
#include "cmd_proc.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/>.
|
||||
|
||||
ModProcess::ModProcess(const QString &app, const QString &memSes, const QString &memHos, const QString &pipe, QObject *parent) : QProcess(parent)
|
||||
{
|
||||
flags = 0;
|
||||
ipcTypeId = 0;
|
||||
ipcDataSize = 0;
|
||||
hostRank = 0;
|
||||
modCmdNames = nullptr;
|
||||
cmdUniqueNames = nullptr;
|
||||
cmdRealNames = nullptr;
|
||||
cmdAppById = nullptr;
|
||||
cmdIds = nullptr;
|
||||
ipcSocket = nullptr;
|
||||
ipcServ = new QLocalServer(this);
|
||||
idleTimer = new IdleTimer(this);
|
||||
sesMemKey = memSes;
|
||||
hostMemKey = memHos;
|
||||
pipeName = pipe;
|
||||
|
||||
ipcServ->setMaxPendingConnections(1);
|
||||
|
||||
connect(this, &QProcess::readyReadStandardError, this, &ModProcess::rdFromStdErr);
|
||||
connect(this, &QProcess::readyReadStandardOutput, this, &ModProcess::rdFromStdOut);
|
||||
connect(this, &QProcess::errorOccurred, this, &ModProcess::err);
|
||||
connect(this, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(onFinished(int,QProcess::ExitStatus)));
|
||||
|
||||
connect(ipcServ, &QLocalServer::newConnection, this, &ModProcess::newIPCLink);
|
||||
connect(idleTimer, &IdleTimer::timeout, this, &ModProcess::kill);
|
||||
|
||||
setProgram(app);
|
||||
}
|
||||
|
||||
void ModProcess::rdFromStdErr()
|
||||
{
|
||||
emit dataToClient(toCmdId32(ASYNC_SYS_MSG, 0), toTEXT(readAllStandardError()), ERR);
|
||||
}
|
||||
|
||||
void ModProcess::rdFromStdOut()
|
||||
{
|
||||
emit dataToClient(toCmdId32(ASYNC_SYS_MSG, 0), toTEXT(readAllStandardOutput()), TEXT);
|
||||
}
|
||||
|
||||
quint16 ModProcess::genCmdId()
|
||||
{
|
||||
quint16 ret = 256;
|
||||
|
||||
if (flags & SESSION_PARAMS_SET)
|
||||
{
|
||||
while(cmdIds->contains(ret)) ret++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
QString ModProcess::makeCmdUnique(const QString &name)
|
||||
{
|
||||
QString strNum;
|
||||
QStringList names = cmdUniqueNames->values();
|
||||
|
||||
for (int i = 1; names.contains(name + strNum); ++i)
|
||||
{
|
||||
strNum = "_" + QString::number(i);
|
||||
}
|
||||
|
||||
return QString(name + strNum).toLower();
|
||||
}
|
||||
|
||||
bool ModProcess::isCmdLoaded(const QString &name)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
if (modCmdNames->contains(program()))
|
||||
{
|
||||
if (modCmdNames->value(program()).contains(name))
|
||||
{
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ModProcess::allowCmdLoad(const QString &cmdName)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
if (flags & (LOADING_PUB_CMDS | LOADING_EXEMPT_CMDS))
|
||||
{
|
||||
ret = true;
|
||||
}
|
||||
else if (!cmdRanks.contains(cmdName))
|
||||
{
|
||||
ret = (hostRank == 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = (cmdRanks[cmdName] >= hostRank);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ModProcess::onDataFromProc(quint8 typeId, const QByteArray &data)
|
||||
{
|
||||
if ((typeId == NEW_CMD) && (flags & SESSION_PARAMS_SET))
|
||||
{
|
||||
QString cmdName = fromTEXT(data.mid(3, 128)).trimmed().toLower();
|
||||
|
||||
if (isCmdLoaded(cmdName))
|
||||
{
|
||||
if (!allowCmdLoad(cmdName))
|
||||
{
|
||||
quint16 cmdId = cmdRealNames->key(cmdName);
|
||||
|
||||
cmdIds->removeOne(cmdId);
|
||||
cmdRealNames->remove(cmdId);
|
||||
cmdUniqueNames->remove(cmdId);
|
||||
cmdAppById->remove(cmdId);
|
||||
|
||||
if (modCmdNames->contains(program()))
|
||||
{
|
||||
modCmdNames->operator[](program()).removeOne(cmdName);
|
||||
}
|
||||
|
||||
emit cmdUnloaded(cmdId);
|
||||
emit dataToClient(toCmdId32(ASYNC_RM_CMD, 0), wrInt(cmdId, 16), CMD_ID);
|
||||
}
|
||||
}
|
||||
else if (allowCmdLoad(cmdName))
|
||||
{
|
||||
quint16 cmdId = genCmdId();
|
||||
QByteArray cmdIdBa = wrInt(cmdId, 16);
|
||||
QString unique = makeCmdUnique(cmdName);
|
||||
|
||||
cmdIds->append(cmdId);
|
||||
cmdRealNames->insert(cmdId, cmdName);
|
||||
cmdUniqueNames->insert(cmdId, unique);
|
||||
cmdAppById->insert(cmdId, program());
|
||||
|
||||
if (modCmdNames->contains(program()))
|
||||
{
|
||||
modCmdNames->operator[](program()).append(cmdName);
|
||||
}
|
||||
else
|
||||
{
|
||||
QStringList list = QStringList() << cmdName;
|
||||
|
||||
modCmdNames->insert(program(), list);
|
||||
}
|
||||
|
||||
QByteArray frame = cmdIdBa + data.mid(2, 1) + fixedToTEXT(unique, 128) + data.mid(131);
|
||||
|
||||
emit dataToClient(toCmdId32(ASYNC_ADD_CMD, 0), frame, NEW_CMD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ModProcess::rdFromIPC()
|
||||
{
|
||||
if (flags & FRAME_RDY)
|
||||
{
|
||||
if (ipcSocket->bytesAvailable() >= ipcDataSize)
|
||||
{
|
||||
onDataFromProc(ipcTypeId, ipcSocket->read(ipcDataSize));
|
||||
|
||||
flags ^= FRAME_RDY;
|
||||
|
||||
rdFromIPC();
|
||||
}
|
||||
}
|
||||
else if (ipcSocket->bytesAvailable() >= (FRAME_HEADER_SIZE - 4))
|
||||
{
|
||||
QByteArray header = ipcSocket->read(FRAME_HEADER_SIZE - 4);
|
||||
|
||||
ipcTypeId = static_cast<quint8>(header[0]);
|
||||
ipcDataSize = static_cast<quint32>(rdInt(header.mid(1, 3)));
|
||||
flags |= FRAME_RDY;
|
||||
|
||||
rdFromIPC();
|
||||
}
|
||||
}
|
||||
|
||||
void ModProcess::ipcDisconnected()
|
||||
{
|
||||
if (ipcSocket != nullptr)
|
||||
{
|
||||
ipcSocket->deleteLater();
|
||||
}
|
||||
|
||||
ipcSocket = nullptr;
|
||||
}
|
||||
|
||||
void ModProcess::newIPCLink()
|
||||
{
|
||||
if (ipcSocket != nullptr)
|
||||
{
|
||||
ipcServ->nextPendingConnection()->deleteLater();
|
||||
}
|
||||
else
|
||||
{
|
||||
ipcSocket = ipcServ->nextPendingConnection();
|
||||
|
||||
connect(ipcSocket, &QLocalSocket::readyRead, this, &ModProcess::rdFromIPC);
|
||||
connect(ipcSocket, &QLocalSocket::disconnected, this, &ModProcess::ipcDisconnected);
|
||||
|
||||
idleTimer->attach(ipcSocket, 120000); //2min idle timeout
|
||||
|
||||
onReady();
|
||||
}
|
||||
}
|
||||
|
||||
void ModProcess::setSessionParams(QHash<quint16, QString> *uniqueNames,
|
||||
QHash<quint16, QString> *realNames,
|
||||
QHash<quint16, QString> *appById,
|
||||
QHash<QString, QStringList> *namesForMod,
|
||||
QList<quint16> *ids,
|
||||
quint32 rnk)
|
||||
{
|
||||
flags |= SESSION_PARAMS_SET;
|
||||
modCmdNames = namesForMod;
|
||||
cmdUniqueNames = uniqueNames;
|
||||
cmdRealNames = realNames;
|
||||
cmdAppById = appById;
|
||||
cmdIds = ids;
|
||||
hostRank = rnk;
|
||||
|
||||
Query db(this);
|
||||
|
||||
db.setType(Query::PULL, TABLE_CMD_RANKS);
|
||||
db.addColumn(COLUMN_HOST_RANK);
|
||||
db.addColumn(COLUMN_COMMAND);
|
||||
db.addCondition(COLUMN_MOD_MAIN, program());
|
||||
db.exec();
|
||||
|
||||
for (int i = 0; i < db.rows(); ++i)
|
||||
{
|
||||
cmdRanks.insert(db.getData(COLUMN_COMMAND, i).toString(), db.getData(COLUMN_HOST_RANK, i).toUInt());
|
||||
}
|
||||
}
|
||||
|
||||
void ModProcess::onFailToStart()
|
||||
{
|
||||
emit dataToClient(toCmdId32(ASYNC_SYS_MSG, 0), toTEXT("\nerr: A module failed to start so some commands may not have loaded. detailed error information was logged for admin review.\n"), ERR);
|
||||
}
|
||||
|
||||
void ModProcess::err(QProcess::ProcessError error)
|
||||
{
|
||||
if (error == QProcess::FailedToStart)
|
||||
{
|
||||
qDebug() << "err: Module process: " << program() << " failed to start. reason: " << errorString();
|
||||
|
||||
emit finished(1, QProcess::CrashExit);
|
||||
|
||||
onFailToStart();
|
||||
}
|
||||
}
|
||||
|
||||
bool ModProcess::openPipe()
|
||||
{
|
||||
bool ret = ipcServ->listen(pipeName);
|
||||
|
||||
fullPipe = ipcServ->fullServerName();
|
||||
|
||||
if (!ipcServ->isListening())
|
||||
{
|
||||
QFile::remove(fullPipe);
|
||||
|
||||
ret = ipcServ->listen(pipeName);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ModProcess::startProc(const QStringList &args)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
if (openPipe())
|
||||
{
|
||||
fullPipe = ipcServ->fullServerName();
|
||||
|
||||
setArguments(QStringList() << "-pipe_name" << fullPipe << "-mem_ses" << sesMemKey << "-mem_host" << hostMemKey << args);
|
||||
start();
|
||||
}
|
||||
else
|
||||
{
|
||||
setErrorString("Unable to open pipe: " + fullPipe + " " + ipcServ->errorString());
|
||||
|
||||
emit errorOccurred(QProcess::FailedToStart);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ModProcess::loadPublicCmds()
|
||||
{
|
||||
flags |= LOADING_PUB_CMDS;
|
||||
|
||||
return startProc(QStringList() << "-public_cmds");
|
||||
}
|
||||
|
||||
bool ModProcess::loadUserCmds()
|
||||
{
|
||||
flags |= LOADING_USER_CMDS;
|
||||
|
||||
return startProc(QStringList() << "-user_cmds");
|
||||
}
|
||||
|
||||
bool ModProcess::loadExemptCmds()
|
||||
{
|
||||
flags |= LOADING_EXEMPT_CMDS;
|
||||
|
||||
return startProc(QStringList() << "-exempt_cmds");
|
||||
}
|
||||
|
||||
void ModProcess::cleanupPipe()
|
||||
{
|
||||
ipcServ->close();
|
||||
|
||||
if (QFile::exists(fullPipe))
|
||||
{
|
||||
QFile::remove(fullPipe);
|
||||
}
|
||||
|
||||
ipcDisconnected();
|
||||
}
|
||||
|
||||
void ModProcess::onReady()
|
||||
{
|
||||
QStringList hostVer = QCoreApplication::applicationVersion().split('.');
|
||||
QByteArray verFrame;
|
||||
|
||||
verFrame.append(wrInt(hostVer[0].toULongLong(), 16));
|
||||
verFrame.append(wrInt(hostVer[1].toULongLong(), 16));
|
||||
verFrame.append(wrInt(hostVer[2].toULongLong(), 16));
|
||||
|
||||
wrIpcFrame(HOST_VER, verFrame);
|
||||
}
|
||||
|
||||
void ModProcess::onFinished(int exitCode, QProcess::ExitStatus exitStatus)
|
||||
{
|
||||
Q_UNUSED(exitCode)
|
||||
Q_UNUSED(exitStatus)
|
||||
|
||||
cleanupPipe();
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
void ModProcess::wrIpcFrame(quint8 typeId, const QByteArray &data)
|
||||
{
|
||||
if (ipcSocket != nullptr)
|
||||
{
|
||||
ipcSocket->write(wrInt(typeId, 8) + wrInt(data.size(), MAX_FRAME_BITS) + data);
|
||||
}
|
||||
}
|
||||
|
||||
CmdProcess::CmdProcess(quint32 id, const QString &cmd, const QString &modApp, const QString &memSes, const QString &memHos, const QString &pipe, QObject *parent) : ModProcess(modApp, memSes, memHos, pipe, parent)
|
||||
{
|
||||
cmdId = id;
|
||||
cmdName = cmd;
|
||||
cmdIdle = false;
|
||||
}
|
||||
|
||||
void CmdProcess::setSessionParams(QSharedMemory *mem, char *sesId, char *wrableSubChs)
|
||||
{
|
||||
sesMem = mem;
|
||||
sessionId = sesId;
|
||||
openWritableSubChs = wrableSubChs;
|
||||
}
|
||||
|
||||
void CmdProcess::killCmd()
|
||||
{
|
||||
wrIpcFrame(KILL_CMD, QByteArray());
|
||||
|
||||
QTimer::singleShot(3000, this, SLOT(kill()));
|
||||
}
|
||||
|
||||
void CmdProcess::killCmd16(quint16 id16)
|
||||
{
|
||||
if (toCmdId16(cmdId) == id16)
|
||||
{
|
||||
killCmd();
|
||||
}
|
||||
}
|
||||
|
||||
void CmdProcess::killCmd32(quint32 id32)
|
||||
{
|
||||
if (cmdId == id32)
|
||||
{
|
||||
killCmd();
|
||||
}
|
||||
}
|
||||
|
||||
void CmdProcess::onReady()
|
||||
{
|
||||
emit cmdProcReady(cmdId, this);
|
||||
}
|
||||
|
||||
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, QByteArray(), IDLE);
|
||||
}
|
||||
|
||||
void CmdProcess::onFinished(int exitCode, QProcess::ExitStatus exitStatus)
|
||||
{
|
||||
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, QByteArray(), IDLE);
|
||||
}
|
||||
|
||||
emit cmdProcFinished(cmdId);
|
||||
|
||||
ModProcess::onFinished(exitCode, exitStatus);
|
||||
}
|
||||
|
||||
void CmdProcess::rdFromStdErr()
|
||||
{
|
||||
emit dataToClient(cmdId, toTEXT(readAllStandardError()), ERR);
|
||||
}
|
||||
|
||||
void CmdProcess::rdFromStdOut()
|
||||
{
|
||||
emit dataToClient(cmdId, toTEXT(readAllStandardOutput()), TEXT);
|
||||
}
|
||||
|
||||
void CmdProcess::dataFromSession(quint32 id, const QByteArray &data, quint8 dType)
|
||||
{
|
||||
if (id == cmdId)
|
||||
{
|
||||
cmdIdle = false;
|
||||
|
||||
wrIpcFrame(dType, data);
|
||||
}
|
||||
}
|
||||
|
||||
bool CmdProcess::validAsync(quint16 async, const QByteArray &data, QTextStream &errMsg)
|
||||
{
|
||||
bool ret = true;
|
||||
|
||||
if ((async == ASYNC_USER_DELETED) || (async == ASYNC_RW_MY_INFO) || (async == ASYNC_USER_LOGIN))
|
||||
{
|
||||
if (data.size() != BLKSIZE_USER_ID)
|
||||
{
|
||||
ret = false; errMsg << "the 256bit user id is not " << BLKSIZE_USER_ID << " bytes long.";
|
||||
}
|
||||
}
|
||||
else if (async == ASYNC_USER_RENAMED)
|
||||
{
|
||||
if (data.size() != (BLKSIZE_USER_ID + BLKSIZE_USER_NAME))
|
||||
{
|
||||
ret = false; errMsg << "expected data containing the user id and name to be " << (BLKSIZE_USER_ID + BLKSIZE_USER_NAME) << " bytes long.";
|
||||
}
|
||||
}
|
||||
else if (async == ASYNC_DISP_RENAMED)
|
||||
{
|
||||
if (data.size() != (BLKSIZE_USER_ID + BLKSIZE_DISP_NAME))
|
||||
{
|
||||
ret = false; errMsg << "expected data containing the user id and display name to be " << (BLKSIZE_USER_ID + BLKSIZE_DISP_NAME) << " bytes long.";
|
||||
}
|
||||
}
|
||||
else if (async == ASYNC_MAXSES)
|
||||
{
|
||||
if (data.size() != BLKSIZE_HOST_LOAD)
|
||||
{
|
||||
ret = false; errMsg << "the 32bit max session int is not " << BLKSIZE_HOST_LOAD << " bytes long.";
|
||||
}
|
||||
}
|
||||
else if (async == ASYNC_USER_RANK_CHANGED)
|
||||
{
|
||||
if (data.size() != (BLKSIZE_USER_ID + BLKSIZE_HOST_RANK))
|
||||
{
|
||||
ret = false; errMsg << "expected data containing the user id and host rank to be " << (BLKSIZE_USER_ID + BLKSIZE_HOST_RANK) << " bytes long.";
|
||||
}
|
||||
}
|
||||
else if ((async == ASYNC_CAST) || (async == ASYNC_LIMITED_CAST))
|
||||
{
|
||||
int payloadOffs = (MAX_OPEN_SUB_CHANNELS * BLKSIZE_SUB_CHANNEL) + 1;
|
||||
|
||||
sesMem->lock();
|
||||
|
||||
if (data.size() < payloadOffs)
|
||||
{
|
||||
ret = false; errMsg << "cast header is not at least " << payloadOffs << " bytes long.";
|
||||
}
|
||||
else if (memcmp(data.data(), openWritableSubChs, static_cast<quint32>(payloadOffs - 1)) != 0)
|
||||
{
|
||||
ret = false; errMsg << "the open sub-channels (writable) does not match the actual open sub-channels.";
|
||||
}
|
||||
else if (rd8BitFromBlock(data.data() + (payloadOffs - 1)) == PING_PEERS)
|
||||
{
|
||||
// casting PING_PEERS to active update sessions are blocked.
|
||||
// command processes should use ASYNC_PING_PEERS instead.
|
||||
|
||||
ret = false; errMsg << "attempted to cast PING_PEERS which is forbidden for module commands.";
|
||||
}
|
||||
|
||||
sesMem->unlock();
|
||||
}
|
||||
else if (async == ASYNC_TO_PEER)
|
||||
{
|
||||
ret = false; errMsg << "ASYNC_TO_PEER is forbidden for module commands.";
|
||||
}
|
||||
else if (async == ASYNC_P2P)
|
||||
{
|
||||
int payloadOffs = ((BLKSIZE_SESSION_ID * 2) + 1);
|
||||
|
||||
if (data.size() < payloadOffs)
|
||||
{
|
||||
ret = false; errMsg << "p2p header is not at least " << payloadOffs << " bytes long.";
|
||||
}
|
||||
else if (memcmp(data.data() + BLKSIZE_SESSION_ID, sessionId, BLKSIZE_SESSION_ID) != 0)
|
||||
{
|
||||
// make sure P2P async commands source session id is the actual the local
|
||||
// session. fraudulent P2P async's are blocked.
|
||||
|
||||
ret = false; errMsg << "the source session id does not match the actual session id.";
|
||||
}
|
||||
}
|
||||
else if (async == ASYNC_CLOSE_P2P)
|
||||
{
|
||||
if (data.size() < BLKSIZE_SESSION_ID)
|
||||
{
|
||||
ret = false; errMsg << "p2p header is not at least " << BLKSIZE_SESSION_ID << " bytes long.";
|
||||
}
|
||||
else if (memcmp(data.data(), sessionId, BLKSIZE_SESSION_ID) != 0)
|
||||
{
|
||||
// make sure P2P async commands source session id is the actual the local
|
||||
// session. fraudulent P2P async's are blocked.
|
||||
|
||||
ret = false; errMsg << "the source session id does not match the actual session id.";
|
||||
}
|
||||
}
|
||||
else if ((async == ASYNC_OPEN_SUBCH) || (async == ASYNC_CLOSE_SUBCH))
|
||||
{
|
||||
if (data.size() != BLKSIZE_SUB_CHANNEL)
|
||||
{
|
||||
ret = false; errMsg << "the 72bit sub-channel id is not " << BLKSIZE_SUB_CHANNEL << " bytes long.";
|
||||
}
|
||||
}
|
||||
else if ((async == ASYNC_RM_SUB_CH) || (async == ASYNC_SUB_CH_LEVEL_CHG) ||
|
||||
(async == ASYNC_RM_RDONLY) || (async == ASYNC_ADD_RDONLY) ||
|
||||
(async == ASYNC_CH_ACT_FLAG) || (async == ASYNC_NEW_SUB_CH) ||
|
||||
(async == ASYNC_RENAME_SUB_CH))
|
||||
{
|
||||
if (data.size() < BLKSIZE_SUB_CHANNEL)
|
||||
{
|
||||
ret = false; errMsg << "a 72bit sub-channel id header is not present.";
|
||||
}
|
||||
}
|
||||
else if ((cmdId == ASYNC_NEW_CH_MEMBER) || (cmdId == ASYNC_INVITED_TO_CH) ||
|
||||
(cmdId == ASYNC_INVITE_ACCEPTED) || (cmdId == ASYNC_RM_CH_MEMBER) ||
|
||||
(cmdId == ASYNC_MEM_LEVEL_CHANGED))
|
||||
{
|
||||
if (data.size() < (BLKSIZE_USER_ID + BLKSIZE_CHANNEL_ID))
|
||||
{
|
||||
ret = false; errMsg << "the channel member info header is not at least " << (BLKSIZE_USER_ID + BLKSIZE_CHANNEL_ID) << "bytes long.";
|
||||
}
|
||||
}
|
||||
else if ((cmdId == ASYNC_RENAME_CH) || (cmdId == ASYNC_DEL_CH))
|
||||
{
|
||||
if (data.size() < BLKSIZE_CHANNEL_ID)
|
||||
{
|
||||
ret = false; errMsg << "a 64bit channel id header was not found.";
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CmdProcess::onDataFromProc(quint8 typeId, const QByteArray &data)
|
||||
{
|
||||
if ((typeId == PRIV_IPC) || (typeId == PUB_IPC) || (typeId == PUB_IPC_WITH_FEEDBACK))
|
||||
{
|
||||
if (data.size() >= 2)
|
||||
{
|
||||
quint16 async = rd16BitFromBlock(data.data());
|
||||
|
||||
// ASYNC_KEEP_ALIVE is blocked but not considered an error. it has already done
|
||||
// it's job by getting transffered so it doesn't need to go any further.
|
||||
|
||||
if (async != ASYNC_KEEP_ALIVE)
|
||||
{
|
||||
QByteArray payload = rdFromBlock(data.data() + 2, static_cast<quint32>(data.size() - 2));
|
||||
|
||||
QString errMsg;
|
||||
QTextStream errTxt(&errMsg);
|
||||
|
||||
if (validAsync(async, payload, errTxt))
|
||||
{
|
||||
if (typeId == PRIV_IPC)
|
||||
{
|
||||
emit privIPC(async, payload);
|
||||
}
|
||||
else if (typeId == PUB_IPC)
|
||||
{
|
||||
emit pubIPC(async, payload);
|
||||
}
|
||||
else
|
||||
{
|
||||
emit pubIPCWithFeedBack(async, payload);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "async id: " << async << " from command id: " << toCmdId16(cmdId) << " blocked. reason: " << errMsg;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (typeId == IDLE)
|
||||
{
|
||||
cmdIdle = true;
|
||||
}
|
||||
|
||||
emit dataToClient(cmdId, data, typeId);
|
||||
}
|
||||
}
|
||||
|
||||
bool CmdProcess::startCmdProc()
|
||||
{
|
||||
return startProc(QStringList() << "-run_cmd" << cmdName);
|
||||
}
|
144
src/cmd_proc.h
Normal file
144
src/cmd_proc.h
Normal file
|
@ -0,0 +1,144 @@
|
|||
#ifndef CMD_PROC_H
|
||||
#define CMD_PROC_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"
|
||||
|
||||
class ModProcess : public QProcess
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
|
||||
QHash<QString, quint32> cmdRanks;
|
||||
QHash<QString, QStringList> *modCmdNames;
|
||||
QHash<quint16, QString> *cmdUniqueNames;
|
||||
QHash<quint16, QString> *cmdRealNames;
|
||||
QHash<quint16, QString> *cmdAppById;
|
||||
QList<quint16> *cmdIds;
|
||||
IdleTimer *idleTimer;
|
||||
|
||||
quint16 genCmdId();
|
||||
QString makeCmdUnique(const QString &name);
|
||||
bool allowCmdLoad(const QString &cmdName);
|
||||
|
||||
protected:
|
||||
|
||||
QString pipeName;
|
||||
QString fullPipe;
|
||||
QString sesMemKey;
|
||||
QString hostMemKey;
|
||||
quint8 ipcTypeId;
|
||||
quint32 ipcDataSize;
|
||||
quint32 hostRank;
|
||||
quint32 flags;
|
||||
QLocalServer *ipcServ;
|
||||
QLocalSocket *ipcSocket;
|
||||
|
||||
virtual void onReady();
|
||||
virtual void onFailToStart();
|
||||
virtual void onDataFromProc(quint8 typeId, const QByteArray &data);
|
||||
|
||||
void cleanupPipe();
|
||||
void wrIpcFrame(quint8 typeId, const QByteArray &data);
|
||||
bool startProc(const QStringList &args);
|
||||
bool isCmdLoaded(const QString &name);
|
||||
bool openPipe();
|
||||
|
||||
protected slots:
|
||||
|
||||
virtual void onFinished(int exitCode, QProcess::ExitStatus exitStatus);
|
||||
virtual void rdFromStdErr();
|
||||
virtual void rdFromStdOut();
|
||||
|
||||
void rdFromIPC();
|
||||
void newIPCLink();
|
||||
void ipcDisconnected();
|
||||
void err(QProcess::ProcessError error);
|
||||
|
||||
public:
|
||||
|
||||
explicit ModProcess(const QString &app, const QString &memSes, const QString &memHos, const QString &pipe, QObject *parent = nullptr);
|
||||
|
||||
void setSessionParams(QHash<quint16, QString> *uniqueNames,
|
||||
QHash<quint16, QString> *realNames,
|
||||
QHash<quint16, QString> *appById,
|
||||
QHash<QString, QStringList> *namesForMod,
|
||||
QList<quint16> *ids,
|
||||
quint32 rnk);
|
||||
|
||||
bool loadPublicCmds();
|
||||
bool loadUserCmds();
|
||||
bool loadExemptCmds();
|
||||
|
||||
signals:
|
||||
|
||||
void cmdUnloaded(quint16 cmdId);
|
||||
void dataToClient(quint32 cmdId, const QByteArray &data, quint8 typeId);
|
||||
};
|
||||
|
||||
//----------------------------
|
||||
|
||||
class CmdProcess : public ModProcess
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
|
||||
quint32 cmdId;
|
||||
QString cmdName;
|
||||
bool cmdIdle;
|
||||
QSharedMemory *sesMem;
|
||||
char *sessionId;
|
||||
char *openWritableSubChs;
|
||||
|
||||
void onReady();
|
||||
void onFailToStart();
|
||||
void onFinished(int exitCode, QProcess::ExitStatus exitStatus);
|
||||
void onDataFromProc(quint8 typeId, const QByteArray &data);
|
||||
bool validAsync(quint16 async, const QByteArray &data, QTextStream &errMsg);
|
||||
|
||||
private slots:
|
||||
|
||||
void killCmd();
|
||||
void rdFromStdErr();
|
||||
void rdFromStdOut();
|
||||
|
||||
public slots:
|
||||
|
||||
void killCmd16(quint16 id16);
|
||||
void killCmd32(quint32 id32);
|
||||
|
||||
public:
|
||||
|
||||
explicit CmdProcess(quint32 id, const QString &cmd, const QString &modApp, const QString &memSes, const QString &memHos, const QString &pipe, QObject *parent = nullptr);
|
||||
|
||||
void dataFromSession(quint32 id, const QByteArray &data, quint8 dType);
|
||||
void setSessionParams(QSharedMemory *mem, char *sesId, char *wrableSubChs);
|
||||
bool startCmdProc();
|
||||
|
||||
signals:
|
||||
|
||||
void cmdProcFinished(quint32 id);
|
||||
void cmdProcReady(quint32 id, CmdProcess *obj);
|
||||
void pubIPC(quint16 cmdId, const QByteArray &data);
|
||||
void privIPC(quint16 cmdId, const QByteArray &data);
|
||||
void pubIPCWithFeedBack(quint16 cmdId, const QByteArray &data);
|
||||
};
|
||||
|
||||
#endif // CMD_PROC_H
|
|
@ -16,12 +16,12 @@
|
|||
// along with MRCI under the LICENSE.md file. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
RecoverAcct::RecoverAcct(QObject *parent) : InternCommand(parent) {inputOk = false;}
|
||||
ResetPwRequest::ResetPwRequest(QObject *parent) : InternCommand(parent) {}
|
||||
VerifyEmail::VerifyEmail(QObject *parent) : InternCommand(parent) {}
|
||||
IsEmailVerified::IsEmailVerified(QObject *parent) : InternCommand(parent) {}
|
||||
SetEmailTemplate::SetEmailTemplate(QObject *parent) : InternCommand(parent) {}
|
||||
PreviewEmail::PreviewEmail(QObject *parent) : InternCommand(parent) {}
|
||||
RecoverAcct::RecoverAcct(QObject *parent) : CmdObject(parent) {}
|
||||
ResetPwRequest::ResetPwRequest(QObject *parent) : CmdObject(parent) {}
|
||||
VerifyEmail::VerifyEmail(QObject *parent) : CmdObject(parent) {}
|
||||
IsEmailVerified::IsEmailVerified(QObject *parent) : CmdObject(parent) {}
|
||||
SetEmailTemplate::SetEmailTemplate(QObject *parent) : CmdObject(parent) {}
|
||||
PreviewEmail::PreviewEmail(QObject *parent) : CmdObject(parent) {}
|
||||
|
||||
QString RecoverAcct::cmdName() {return "recover_acct";}
|
||||
QString ResetPwRequest::cmdName() {return "request_pw_reset";}
|
||||
|
@ -30,38 +30,54 @@ QString IsEmailVerified::cmdName() {return "is_email_verified";}
|
|||
QString SetEmailTemplate::cmdName() {return "set_email_template";}
|
||||
QString PreviewEmail::cmdName() {return "preview_email";}
|
||||
|
||||
void RecoverAcct::term()
|
||||
void delRecoverPw(const QByteArray &uId)
|
||||
{
|
||||
emit enableMoreInput(false);
|
||||
|
||||
inputOk = false;
|
||||
}
|
||||
|
||||
void RecoverAcct::delRecoverPw()
|
||||
{
|
||||
Query db(this);
|
||||
Query db;
|
||||
|
||||
db.setType(Query::DEL, TABLE_PW_RECOVERY);
|
||||
db.addCondition(COLUMN_USERNAME, uName);
|
||||
db.addCondition(COLUMN_USER_ID, uId);
|
||||
db.exec();
|
||||
|
||||
db.setType(Query::UPDATE, TABLE_AUTH_LOG);
|
||||
db.addColumn(COLUMN_COUNT, false);
|
||||
db.addCondition(COLUMN_COUNT, true);
|
||||
db.addCondition(COLUMN_RECOVER_ATTEMPT, true);
|
||||
db.addCondition(COLUMN_USERNAME, uName);
|
||||
db.addCondition(COLUMN_USER_ID, uId);
|
||||
db.exec();
|
||||
|
||||
term();
|
||||
}
|
||||
|
||||
void RecoverAcct::addToThreshold(const SharedObjs *sharedObjs)
|
||||
bool expired(const QByteArray &uId)
|
||||
{
|
||||
bool ret = true;
|
||||
|
||||
Query db;
|
||||
|
||||
db.setType(Query::PULL, TABLE_PW_RECOVERY);
|
||||
db.addColumn(COLUMN_TIME);
|
||||
db.addCondition(COLUMN_USER_ID, uId);
|
||||
db.exec();
|
||||
|
||||
QDateTime expiry = db.getData(COLUMN_TIME).toDateTime().addSecs(3600); // pw datetime + 1hour;
|
||||
|
||||
if (expiry > QDateTime::currentDateTime().toUTC())
|
||||
{
|
||||
ret = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
delRecoverPw(uId);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void RecoverAcct::addToThreshold()
|
||||
{
|
||||
Query db(this);
|
||||
|
||||
db.setType(Query::PUSH, TABLE_AUTH_LOG);
|
||||
db.addColumn(COLUMN_USERNAME, uName);
|
||||
db.addColumn(COLUMN_IPADDR, *sharedObjs->sessionAddr);
|
||||
db.addColumn(COLUMN_USER_ID, uId);
|
||||
db.addColumn(COLUMN_IPADDR, rdStringFromBlock(clientIp, BLKSIZE_CLIENT_IP));
|
||||
db.addColumn(COLUMN_AUTH_ATTEMPT, false);
|
||||
db.addColumn(COLUMN_RECOVER_ATTEMPT, true);
|
||||
db.addColumn(COLUMN_COUNT, true);
|
||||
|
@ -72,20 +88,21 @@ void RecoverAcct::addToThreshold(const SharedObjs *sharedObjs)
|
|||
db.addColumn(COLUMN_LOCK_LIMIT);
|
||||
db.exec();
|
||||
|
||||
uint maxAttempts = db.getData(COLUMN_LOCK_LIMIT).toUInt();
|
||||
quint32 maxAttempts = db.getData(COLUMN_LOCK_LIMIT).toUInt();
|
||||
|
||||
db.setType(Query::PULL, TABLE_AUTH_LOG);
|
||||
db.addColumn(COLUMN_IPADDR);
|
||||
db.addCondition(COLUMN_USERNAME, uName);
|
||||
db.addCondition(COLUMN_USER_ID, uId);
|
||||
db.addCondition(COLUMN_RECOVER_ATTEMPT, true);
|
||||
db.addCondition(COLUMN_COUNT, true);
|
||||
db.addCondition(COLUMN_ACCEPTED, false);
|
||||
db.exec();
|
||||
|
||||
if (static_cast<uint>(db.rows()) > maxAttempts)
|
||||
if (static_cast<quint32>(db.rows()) > maxAttempts)
|
||||
{
|
||||
delRecoverPw();
|
||||
term();
|
||||
delRecoverPw(uId);
|
||||
|
||||
flags &= ~MORE_INPUT;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -94,9 +111,9 @@ void RecoverAcct::addToThreshold(const SharedObjs *sharedObjs)
|
|||
}
|
||||
}
|
||||
|
||||
void RecoverAcct::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void RecoverAcct::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
if (moreInputEnabled() && (dType == TEXT))
|
||||
if ((flags & MORE_INPUT) && (dType == TEXT))
|
||||
{
|
||||
QString pw = fromTEXT(binIn);
|
||||
|
||||
|
@ -109,24 +126,25 @@ void RecoverAcct::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn,
|
|||
}
|
||||
else
|
||||
{
|
||||
updatePassword(uName, pw, TABLE_USERS);
|
||||
delRecoverPw();
|
||||
term();
|
||||
updatePassword(uId, pw, TABLE_USERS);
|
||||
delRecoverPw(uId);
|
||||
|
||||
flags &= ~MORE_INPUT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pw.isEmpty())
|
||||
{
|
||||
term();
|
||||
flags &= ~MORE_INPUT;
|
||||
}
|
||||
else if (!validPassword(pw))
|
||||
{
|
||||
addToThreshold(sharedObjs);
|
||||
addToThreshold();
|
||||
}
|
||||
else if (!auth(uName, pw, TABLE_PW_RECOVERY))
|
||||
else if (!auth(uId, pw, TABLE_PW_RECOVERY))
|
||||
{
|
||||
addToThreshold(sharedObjs);
|
||||
addToThreshold();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -142,65 +160,71 @@ void RecoverAcct::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn,
|
|||
QString email = getParam("-email", args);
|
||||
QString name = getParam("-user", args);
|
||||
|
||||
if (!email.isEmpty() && validEmailAddr(email)) name = getUserNameForEmail(email);
|
||||
if (!email.isEmpty() && validEmailAddr(email))
|
||||
{
|
||||
name = getUserNameForEmail(email);
|
||||
}
|
||||
|
||||
if (name.isEmpty() || !validUserName(name))
|
||||
{
|
||||
errTxt("err: The -user or -email argument is empty, not found or invalid.\n");
|
||||
}
|
||||
else if (!userExists(name))
|
||||
else if (!userExists(name, &uId))
|
||||
{
|
||||
errTxt("err: No such user.\n");
|
||||
}
|
||||
else if (!recoverPWExists(name))
|
||||
else if (!recoverPWExists(uId))
|
||||
{
|
||||
errTxt("err: This account does not have a recovery password.\n");
|
||||
}
|
||||
else if (expired(uId))
|
||||
{
|
||||
errTxt("err: The recovery password has expired.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
privTxt("Enter the temporary password (leave blank to cancel): ");
|
||||
|
||||
uName = name;
|
||||
|
||||
emit enableMoreInput(true);
|
||||
inputOk = false;
|
||||
flags |= MORE_INPUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ResetPwRequest::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void ResetPwRequest::procIn(const QByteArray &binIn, uchar dType)
|
||||
{
|
||||
Q_UNUSED(sharedObjs);
|
||||
|
||||
if (dType == TEXT)
|
||||
{
|
||||
QStringList args = parseArgs(binIn, 2);
|
||||
QString email = getParam("-email", args);
|
||||
QString name = getParam("-user", args);
|
||||
QByteArray uId;
|
||||
|
||||
if (!email.isEmpty() && validEmailAddr(email)) name = getUserNameForEmail(email);
|
||||
if (!email.isEmpty() && validEmailAddr(email))
|
||||
{
|
||||
name = getUserNameForEmail(email);
|
||||
}
|
||||
|
||||
if (name.isEmpty() || !validUserName(name))
|
||||
{
|
||||
errTxt("err: The -user or -email argument is empty, not found or invalid.\n");
|
||||
}
|
||||
else if (!userExists(name))
|
||||
else if (!userExists(name, &uId, &email))
|
||||
{
|
||||
errTxt("err: No such user.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
email = getEmailForUser(name);
|
||||
|
||||
QString pw = genPw();
|
||||
QString date = QDateTime::currentDateTimeUtc().toString("YYYY-MM-DD HH:MM:SS");
|
||||
|
||||
if (recoverPWExists(name))
|
||||
if (recoverPWExists(uId))
|
||||
{
|
||||
updatePassword(name, pw, TABLE_PW_RECOVERY);
|
||||
updatePassword(uId, pw, TABLE_PW_RECOVERY);
|
||||
}
|
||||
else
|
||||
{
|
||||
createTempPw(name, email, pw);
|
||||
createTempPw(uId, pw);
|
||||
}
|
||||
|
||||
Query db(this);
|
||||
|
@ -227,40 +251,33 @@ void ResetPwRequest::procBin(const SharedObjs *sharedObjs, const QByteArray &bin
|
|||
|
||||
QProcess::startDetached(expandEnvVariables(app), parseArgs(toTEXT(cmdLine), -1));
|
||||
|
||||
mainTxt("A temporary password was sent to the email address associated with the account.\n");
|
||||
mainTxt("A temporary password was sent to the email address associated with the account. this password will expire in 1hour.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VerifyEmail::term()
|
||||
void VerifyEmail::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
emit enableMoreInput(false);
|
||||
|
||||
code.clear();
|
||||
}
|
||||
|
||||
void VerifyEmail::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
{
|
||||
if (moreInputEnabled() && (dType == TEXT))
|
||||
if ((flags & MORE_INPUT) && (dType == TEXT))
|
||||
{
|
||||
QString txt = fromTEXT(binIn);
|
||||
|
||||
if (txt == code)
|
||||
if (txt.isEmpty())
|
||||
{
|
||||
flags &= ~MORE_INPUT;
|
||||
}
|
||||
else if (txt == code)
|
||||
{
|
||||
Query db(this);
|
||||
|
||||
db.setType(Query::UPDATE, TABLE_USERS);
|
||||
db.addColumn(COLUMN_EMAIL_VERIFIED, true);
|
||||
db.addCondition(COLUMN_USERNAME, *sharedObjs->userName);
|
||||
db.addCondition(COLUMN_USER_ID, uId);
|
||||
db.exec();
|
||||
|
||||
emit backendDataOut(ASYNC_RW_MY_INFO, toTEXT(*sharedObjs->userName), PUB_IPC_WITH_FEEDBACK);
|
||||
async(ASYNC_RW_MY_INFO, PUB_IPC_WITH_FEEDBACK, uId);
|
||||
|
||||
term();
|
||||
}
|
||||
else if (txt.isEmpty())
|
||||
{
|
||||
term();
|
||||
flags &= ~MORE_INPUT;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -270,7 +287,9 @@ void VerifyEmail::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn,
|
|||
}
|
||||
else if (dType == TEXT)
|
||||
{
|
||||
QString email = getEmailForUser(*sharedObjs->userName);
|
||||
uId = rdFromBlock(userId, BLKSIZE_USER_ID);
|
||||
|
||||
QString email = getEmailForUser(uId);
|
||||
|
||||
if (email.isEmpty())
|
||||
{
|
||||
|
@ -278,8 +297,7 @@ void VerifyEmail::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn,
|
|||
}
|
||||
else
|
||||
{
|
||||
QString date = QDateTime::currentDateTimeUtc().toString("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
flags |= MORE_INPUT;
|
||||
code = QString::number(QRandomGenerator::global()->bounded(100000, 999999));
|
||||
|
||||
Query db(this);
|
||||
|
@ -291,13 +309,15 @@ void VerifyEmail::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn,
|
|||
db.addColumn(COLUMN_MAIL_SEND);
|
||||
db.exec();
|
||||
|
||||
QString uName = rdStringFromBlock(userName, BLKSIZE_USER_NAME);
|
||||
QString date = QDateTime::currentDateTimeUtc().toString("yyyy-MM-dd HH:mm:ss");
|
||||
QString subject = db.getData(COLUMN_CONFIRM_SUBJECT).toString();
|
||||
QString body = db.getData(COLUMN_CONFIRM_MSG).toString();
|
||||
QString app = db.getData(COLUMN_MAILERBIN).toString();
|
||||
QString cmdLine = db.getData(COLUMN_MAIL_SEND).toString();
|
||||
|
||||
body.replace(DATE_SUB, date);
|
||||
body.replace(USERNAME_SUB, *sharedObjs->userName);
|
||||
body.replace(USERNAME_SUB, uName);
|
||||
body.replace(CONFIRM_CODE_SUB, code);
|
||||
|
||||
cmdLine.replace(TARGET_EMAIL_SUB, email);
|
||||
|
@ -307,51 +327,32 @@ void VerifyEmail::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn,
|
|||
QProcess::startDetached(expandEnvVariables(app), parseArgs(toTEXT(cmdLine), -1));
|
||||
|
||||
privTxt("A confirmation code was sent to your email address: " + email + "\n\n" + "Please enter that code now or leave blank to cancel: ");
|
||||
|
||||
emit enableMoreInput(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IsEmailVerified::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void IsEmailVerified::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
Q_UNUSED(binIn);
|
||||
Q_UNUSED(binIn)
|
||||
|
||||
if (dType == TEXT)
|
||||
{
|
||||
QByteArray uId = rdFromBlock(userId, BLKSIZE_USER_ID);
|
||||
|
||||
Query db(this);
|
||||
|
||||
db.setType(Query::PULL, TABLE_USERS);
|
||||
db.addColumn(COLUMN_EMAIL_VERIFIED);
|
||||
db.addCondition(COLUMN_USERNAME, *sharedObjs->userName);
|
||||
db.addCondition(COLUMN_USER_ID, uId);
|
||||
db.exec();
|
||||
|
||||
mainTxt(boolStr(db.getData(COLUMN_EMAIL_VERIFIED).toBool()) + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
bool SetEmailTemplate::handlesGenfile()
|
||||
void SetEmailTemplate::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void SetEmailTemplate::term()
|
||||
{
|
||||
emit enableMoreInput(false);
|
||||
|
||||
textFromFile = false;
|
||||
dataSent = 0;
|
||||
|
||||
subject.clear();
|
||||
bodyText.clear();
|
||||
len.clear();
|
||||
}
|
||||
|
||||
void SetEmailTemplate::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
{
|
||||
Q_UNUSED(sharedObjs);
|
||||
|
||||
if (moreInputEnabled() && (dType == GEN_FILE))
|
||||
if ((flags & MORE_INPUT) && (dType == GEN_FILE))
|
||||
{
|
||||
bodyText.append(fromTEXT(binIn));
|
||||
|
||||
|
@ -361,8 +362,6 @@ void SetEmailTemplate::procBin(const SharedObjs *sharedObjs, const QByteArray &b
|
|||
|
||||
if (dataSent >= len.toInt())
|
||||
{
|
||||
emit enableMoreInput(false);
|
||||
|
||||
mainTxt("\nUpload complete.\n");
|
||||
proc();
|
||||
}
|
||||
|
@ -371,6 +370,7 @@ void SetEmailTemplate::procBin(const SharedObjs *sharedObjs, const QByteArray &b
|
|||
{
|
||||
QStringList args = parseArgs(binIn, 9);
|
||||
|
||||
dataSent = 0;
|
||||
textFromFile = argExists("-client_file", args);
|
||||
subject = getParam("-subject", args);
|
||||
bodyText = getParam("-body", args);
|
||||
|
@ -392,22 +392,18 @@ void SetEmailTemplate::procBin(const SharedObjs *sharedObjs, const QByteArray &b
|
|||
if (eType == NONE)
|
||||
{
|
||||
errTxt("err: Which template do you want to change? -reset_template or -confirm_template not found.\n");
|
||||
term();
|
||||
}
|
||||
else if (textFromFile && !isInt(len))
|
||||
{
|
||||
errTxt("err: '" + len + "' given in -len is not a valid integer.\n");
|
||||
term();
|
||||
}
|
||||
else if (textFromFile && (len.toInt() <= 0))
|
||||
{
|
||||
errTxt("err: The text file size cannot be 0 or less than 0.\n");
|
||||
term();
|
||||
}
|
||||
else if (textFromFile && (len.toInt() > 20000))
|
||||
{
|
||||
errTxt("err: The text file size is too large. it cannot exceed 20,000 bytes or 10,000 chars.\n");
|
||||
term();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -429,9 +425,10 @@ void SetEmailTemplate::procBin(const SharedObjs *sharedObjs, const QByteArray &b
|
|||
|
||||
bodyText.clear();
|
||||
|
||||
emit enableMoreInput(true);
|
||||
emit dataToClient(toTEXT("-to_host"), GEN_FILE);
|
||||
emit dataToClient(QByteArray(), GEN_FILE);
|
||||
flags |= MORE_INPUT;
|
||||
|
||||
emit procOut(toTEXT("-to_host"), GEN_FILE);
|
||||
emit procOut(QByteArray(), GEN_FILE);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -518,10 +515,10 @@ void SetEmailTemplate::proc()
|
|||
if (execQuery) db.exec();
|
||||
}
|
||||
|
||||
term();
|
||||
flags &= ~MORE_INPUT;
|
||||
}
|
||||
|
||||
void PreviewEmail::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void PreviewEmail::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
if (dType == TEXT)
|
||||
{
|
||||
|
@ -565,11 +562,12 @@ void PreviewEmail::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn
|
|||
db.addColumn(subjectColumn);
|
||||
db.exec();
|
||||
|
||||
QString uName = rdStringFromBlock(userName, BLKSIZE_USER_NAME);
|
||||
QString subject = db.getData(subjectColumn).toString();
|
||||
QString body = db.getData(bodyColumn).toString();
|
||||
|
||||
body.replace(DATE_SUB, date);
|
||||
body.replace(USERNAME_SUB, *sharedObjs->userName);
|
||||
body.replace(USERNAME_SUB, uName);
|
||||
body.replace(codeSub, code);
|
||||
|
||||
QString txt;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "../common.h"
|
||||
#include "../cmd_object.h"
|
||||
|
||||
enum TemplateType
|
||||
{
|
||||
|
@ -26,31 +27,32 @@ enum TemplateType
|
|||
NONE
|
||||
};
|
||||
|
||||
class RecoverAcct : public InternCommand
|
||||
bool expired(const QByteArray &uId);
|
||||
void delRecoverPw(const QByteArray &uId);
|
||||
|
||||
class RecoverAcct : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
|
||||
QString uName;
|
||||
QByteArray uId;
|
||||
bool inputOk;
|
||||
|
||||
void delRecoverPw();
|
||||
void addToThreshold(const SharedObjs *sharedObjs);
|
||||
void addToThreshold();
|
||||
|
||||
public:
|
||||
|
||||
static QString cmdName();
|
||||
|
||||
void term();
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit RecoverAcct(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//---------------
|
||||
|
||||
class ResetPwRequest : public InternCommand
|
||||
class ResetPwRequest : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -58,34 +60,34 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, uchar dType);
|
||||
|
||||
explicit ResetPwRequest(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//----------------
|
||||
|
||||
class VerifyEmail : public InternCommand
|
||||
class VerifyEmail : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
|
||||
QString code;
|
||||
QByteArray uId;
|
||||
|
||||
public:
|
||||
|
||||
static QString cmdName();
|
||||
|
||||
void term();
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit VerifyEmail(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//----------------
|
||||
|
||||
class IsEmailVerified : public InternCommand
|
||||
class IsEmailVerified : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -93,14 +95,14 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit IsEmailVerified(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//------------------
|
||||
|
||||
class SetEmailTemplate : public InternCommand
|
||||
class SetEmailTemplate : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -119,16 +121,14 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
bool handlesGenfile();
|
||||
void term();
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit SetEmailTemplate(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//-----------------
|
||||
|
||||
class PreviewEmail : public InternCommand
|
||||
class PreviewEmail : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -136,7 +136,7 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit PreviewEmail(QObject *parent = nullptr);
|
||||
};
|
||||
|
|
|
@ -16,32 +16,31 @@
|
|||
// along with MRCI under the LICENSE.md file. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
CloseHost::CloseHost(QObject *parent) : InternCommand(parent) {}
|
||||
RestartHost::RestartHost(QObject *parent) : InternCommand(parent) {}
|
||||
ServSettings::ServSettings(QObject *parent) : InternCommand(parent) {}
|
||||
CloseHost::CloseHost(QObject *parent) : CmdObject(parent) {}
|
||||
RestartHost::RestartHost(QObject *parent) : CmdObject(parent) {}
|
||||
ServSettings::ServSettings(QObject *parent) : CmdObject(parent) {}
|
||||
|
||||
QString CloseHost::cmdName() {return "close_host";}
|
||||
QString RestartHost::cmdName() {return "restart_host";}
|
||||
QString ServSettings::cmdName() {return "host_config";}
|
||||
|
||||
void CloseHost::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void CloseHost::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
Q_UNUSED(sharedObjs);
|
||||
|
||||
if (dType == TEXT)
|
||||
{
|
||||
if (moreInputEnabled())
|
||||
if (flags & MORE_INPUT)
|
||||
{
|
||||
QString input = fromTEXT(binIn);
|
||||
|
||||
if (input == "CLOSE")
|
||||
{
|
||||
emit enableMoreInput(false);
|
||||
emit backendDataOut(ASYNC_EXIT, QByteArray(), PRIV_IPC);
|
||||
flags &= ~MORE_INPUT;
|
||||
|
||||
async(ASYNC_EXIT, PRIV_IPC);
|
||||
}
|
||||
else if (input.isEmpty())
|
||||
{
|
||||
emit enableMoreInput(false);
|
||||
flags &= ~MORE_INPUT;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -51,31 +50,30 @@ void CloseHost::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, u
|
|||
}
|
||||
else
|
||||
{
|
||||
emit enableMoreInput(true);
|
||||
flags |= MORE_INPUT;
|
||||
|
||||
mainTxt("You are about to shutdown the host instance, type: 'CLOSE' to proceed or leave blank to cancel: ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RestartHost::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void RestartHost::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
Q_UNUSED(sharedObjs);
|
||||
|
||||
if (dType == TEXT)
|
||||
{
|
||||
if (moreInputEnabled())
|
||||
if (flags & MORE_INPUT)
|
||||
{
|
||||
QString input = fromTEXT(binIn);
|
||||
|
||||
if (input == "RESTART")
|
||||
{
|
||||
emit enableMoreInput(false);
|
||||
emit backendDataOut(ASYNC_RESTART, QByteArray(), PRIV_IPC);
|
||||
flags &= ~MORE_INPUT;
|
||||
|
||||
async(ASYNC_RESTART, PRIV_IPC);
|
||||
}
|
||||
else if (input.isEmpty())
|
||||
{
|
||||
emit enableMoreInput(false);
|
||||
flags &= ~MORE_INPUT;
|
||||
}
|
||||
else if (!input.isEmpty())
|
||||
{
|
||||
|
@ -85,21 +83,13 @@ void RestartHost::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn,
|
|||
}
|
||||
else
|
||||
{
|
||||
emit enableMoreInput(true);
|
||||
flags |= MORE_INPUT;
|
||||
|
||||
mainTxt("You are about to re-start the host instance, type: 'RESTART' to proceed or leave blank to cancel: ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ServSettings::term()
|
||||
{
|
||||
emit enableMoreInput(false);
|
||||
|
||||
level = 0;
|
||||
select = 0;
|
||||
}
|
||||
|
||||
void ServSettings::printSettings()
|
||||
{
|
||||
Query db(this);
|
||||
|
@ -109,10 +99,7 @@ void ServSettings::printSettings()
|
|||
db.addColumn(COLUMN_BAN_LIMIT);
|
||||
db.addColumn(COLUMN_LOCK_LIMIT);
|
||||
db.addColumn(COLUMN_MAXSESSIONS);
|
||||
db.addColumn(COLUMN_ZIPBIN);
|
||||
db.addColumn(COLUMN_ZIPCOMPRESS);
|
||||
db.addColumn(COLUMN_ZIPEXTRACT);
|
||||
db.addColumn(COLUMN_INITGROUP);
|
||||
db.addColumn(COLUMN_INITRANK);
|
||||
db.addColumn(COLUMN_MAILERBIN);
|
||||
db.addColumn(COLUMN_MAIL_SEND);
|
||||
db.addColumn(COLUMN_ENABLE_CONFIRM);
|
||||
|
@ -137,12 +124,8 @@ void ServSettings::printSettings()
|
|||
txtOut << "Autoban Threshold: " << db.getData(COLUMN_BAN_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 << "Initial Group: " << db.getData(COLUMN_INITGROUP).toString() << endl;
|
||||
txtOut << "Initial Host Rank: " << db.getData(COLUMN_INITRANK).toUInt() << endl;
|
||||
txtOut << "Database Path: " << sqlDataPath() << endl;
|
||||
txtOut << "Modules Install Path: " << modDataPath() << endl;
|
||||
txtOut << "Archiver Executable: " << db.getData(COLUMN_ZIPBIN).toString() << endl;
|
||||
txtOut << "Archiver Compress Command: " << db.getData(COLUMN_ZIPCOMPRESS).toString() << endl;
|
||||
txtOut << "Archiver Extract Command: " << db.getData(COLUMN_ZIPEXTRACT).toString() << endl;
|
||||
txtOut << "Mailer Executable: " << db.getData(COLUMN_MAILERBIN).toString() << endl;
|
||||
txtOut << "Mailer Command: " << db.getData(COLUMN_MAIL_SEND).toString() << endl << endl;
|
||||
|
||||
|
@ -158,12 +141,10 @@ void ServSettings::printOptions()
|
|||
|
||||
txtOut << "[01] Autoban Threshold [02] Autolock Threshold" << endl;
|
||||
txtOut << "[03] Max Sessions [04] Public Registration" << endl;
|
||||
txtOut << "[05] Initial Group [06] Archiver Exe" << endl;
|
||||
txtOut << "[07] Compress Command [08] Extract Command" << endl;
|
||||
txtOut << "[09] Mailer Exe [10] Mailer Command" << endl;
|
||||
txtOut << "[11] Password Resets [12] Email Verify" << endl;
|
||||
txtOut << "[13] Active Update [14] Max Sub-Channels" << endl;
|
||||
txtOut << "[00] Exit" << endl << endl;
|
||||
txtOut << "[05] Initial Rank [06] Mailer Exe" << endl;
|
||||
txtOut << "[07] Mailer Command [08] Password Resets" << endl;
|
||||
txtOut << "[09] Email Verify [10] Active Update" << endl;
|
||||
txtOut << "[11] Max Sub-Channels [00] Exit" << endl << endl;
|
||||
txtOut << "Select an option: ";
|
||||
|
||||
level = 1;
|
||||
|
@ -182,13 +163,11 @@ void ServSettings::returnToStart()
|
|||
printOptions();
|
||||
}
|
||||
|
||||
void ServSettings::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void ServSettings::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
Q_UNUSED(sharedObjs);
|
||||
|
||||
if (dType == TEXT)
|
||||
{
|
||||
if (moreInputEnabled())
|
||||
if (flags & MORE_INPUT)
|
||||
{
|
||||
if (level == 1)
|
||||
{
|
||||
|
@ -212,7 +191,7 @@ void ServSettings::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn
|
|||
else if ((select == 2) && ok)
|
||||
{
|
||||
txtOut << "" << endl;
|
||||
txtOut << "The autolock 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 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;
|
||||
|
@ -245,47 +224,14 @@ void ServSettings::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn
|
|||
else if ((select == 5) && ok)
|
||||
{
|
||||
txtOut << "" << endl;
|
||||
txtOut << "The initial group is the group any new user rergistered using the" << endl;
|
||||
txtOut << "new_user command is attached to. the group must already exists and" << endl;
|
||||
txtOut << "will not be allowed to get deleted as long as it is the initial" << endl;
|
||||
txtOut << "group." << endl << endl;
|
||||
txtOut << "Enter a new group (leave blank to cancel): ";
|
||||
txtOut << "The initial host rank is the rank all new user accounts are registered" << endl;
|
||||
txtOut << "with when created. the host rank itself is an integer value that" << endl;
|
||||
txtOut << "determine what commands each user can or cannot run." << endl << endl;
|
||||
txtOut << "Enter a new value (leave blank to cancel): ";
|
||||
|
||||
level = 2;
|
||||
}
|
||||
else if ((select == 6) && ok)
|
||||
{
|
||||
txtOut << "" << endl;
|
||||
txtOut << "This is the path to zip archiver's executable file that the" << endl;
|
||||
txtOut << "host can call when it needs to extract or create archive files" << endl;
|
||||
txtOut << "like .zip, .tar, etc.." << endl << endl;
|
||||
txtOut << "Enter a new path (leave blank to cancel): ";
|
||||
|
||||
level = 2;
|
||||
}
|
||||
else if ((select == 7) && ok)
|
||||
{
|
||||
txtOut << "" << endl;
|
||||
txtOut << "This is the command line the host will use when calling the archiver" << endl;
|
||||
txtOut << "to create a zip file. it must contain the keywords " << OUTPUT_DIR_SUB << endl;
|
||||
txtOut << "and " << INPUT_DIR_SUB << ". the host will substitute these keywords for" << endl;
|
||||
txtOut << "for the actual input/output directories when calling the command." << endl << endl;
|
||||
txtOut << "Enter a new command line (leave blank to cancel): ";
|
||||
|
||||
level = 2;
|
||||
}
|
||||
else if ((select == 8) && ok)
|
||||
{
|
||||
txtOut << "" << endl;
|
||||
txtOut << "This is the command line the host will use when calling the archiver" << endl;
|
||||
txtOut << "to extract a zip file. it must contain the keywords " << OUTPUT_DIR_SUB << endl;
|
||||
txtOut << "and " << INPUT_DIR_SUB << ". the host will substitute these keywords for" << endl;
|
||||
txtOut << "for the actual input/output directories when calling the command." << endl << endl;
|
||||
txtOut << "Enter a new command line (leave blank to cancel): ";
|
||||
|
||||
level = 2;
|
||||
}
|
||||
else if ((select == 9) && ok)
|
||||
{
|
||||
txtOut << "" << endl;
|
||||
txtOut << "This is the path to the command line email client executable" << endl;
|
||||
|
@ -296,7 +242,7 @@ void ServSettings::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn
|
|||
|
||||
level = 2;
|
||||
}
|
||||
else if ((select == 10) && ok)
|
||||
else if ((select == 7) && ok)
|
||||
{
|
||||
txtOut << "" << endl;
|
||||
txtOut << "This is the command line that will be used with the email client" << endl;
|
||||
|
@ -308,7 +254,7 @@ void ServSettings::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn
|
|||
|
||||
level = 2;
|
||||
}
|
||||
else if ((select == 11) && ok)
|
||||
else if ((select == 8) && ok)
|
||||
{
|
||||
txtOut << "" << endl;
|
||||
txtOut << "This enables automated password resets via email so users can" << endl;
|
||||
|
@ -321,7 +267,7 @@ void ServSettings::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn
|
|||
|
||||
level = 2;
|
||||
}
|
||||
else if ((select == 12) && ok)
|
||||
else if ((select == 9) && ok)
|
||||
{
|
||||
txtOut << "" << endl;
|
||||
txtOut << "This enables automated email confirmations. this tells the" << endl;
|
||||
|
@ -332,7 +278,7 @@ void ServSettings::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn
|
|||
|
||||
level = 2;
|
||||
}
|
||||
else if ((select == 13) && ok)
|
||||
else if ((select == 10) && ok)
|
||||
{
|
||||
txtOut << "" << endl;
|
||||
txtOut << "This option tells the host if all sub-channels should be considered" << endl;
|
||||
|
@ -347,7 +293,7 @@ void ServSettings::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn
|
|||
|
||||
level = 2;
|
||||
}
|
||||
else if ((select == 14) && ok)
|
||||
else if ((select == 11) && ok)
|
||||
{
|
||||
txtOut << "" << endl;
|
||||
txtOut << "This option sets the maximum amount of sub-channels each channel can" << endl;
|
||||
|
@ -358,7 +304,7 @@ void ServSettings::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn
|
|||
}
|
||||
else if ((select == 0) && ok)
|
||||
{
|
||||
term();
|
||||
flags &= ~MORE_INPUT;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -378,10 +324,10 @@ void ServSettings::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn
|
|||
}
|
||||
else
|
||||
{
|
||||
if ((select == 1) || (select == 2) || (select == 3))
|
||||
if ((select == 1) || (select == 2) || (select == 3) || (select == 5))
|
||||
{
|
||||
bool ok;
|
||||
uint num = value.toUInt(&ok, 10);
|
||||
quint32 num = value.toUInt(&ok, 10);
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
|
@ -401,19 +347,20 @@ void ServSettings::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn
|
|||
|
||||
if (select == 1) db.addColumn(COLUMN_BAN_LIMIT, num);
|
||||
else if (select == 2) db.addColumn(COLUMN_LOCK_LIMIT, num);
|
||||
else db.addColumn(COLUMN_MAXSESSIONS, num);
|
||||
else if (select == 3) db.addColumn(COLUMN_MAXSESSIONS, num);
|
||||
else db.addColumn(COLUMN_INITRANK, num);
|
||||
|
||||
db.exec();
|
||||
|
||||
if (select == 5)
|
||||
if (select == 3)
|
||||
{
|
||||
emit backendDataOut(ASYNC_MAXSES, wrInt(num, 32), PRIV_IPC);
|
||||
async(ASYNC_MAXSES, PRIV_IPC, wrInt(num, BLKSIZE_HOST_LOAD * 8));
|
||||
}
|
||||
|
||||
returnToStart();
|
||||
}
|
||||
}
|
||||
else if ((select == 4) || (select == 11) || (select == 12) || (select == 13))
|
||||
else if ((select == 4) || (select == 8) || (select == 9) || (select == 10))
|
||||
{
|
||||
if (!isBool(value))
|
||||
{
|
||||
|
@ -425,8 +372,8 @@ void ServSettings::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn
|
|||
QString column;
|
||||
|
||||
if (select == 4) column = COLUMN_PUB_USERS;
|
||||
else if (select == 11) column = COLUMN_ENABLE_PW_RESET;
|
||||
else if (select == 12) column = COLUMN_ENABLE_CONFIRM;
|
||||
else if (select == 8) column = COLUMN_ENABLE_PW_RESET;
|
||||
else if (select == 9) column = COLUMN_ENABLE_CONFIRM;
|
||||
else column = COLUMN_ACTIVE_UPDATE;
|
||||
|
||||
Query db(this);
|
||||
|
@ -438,30 +385,7 @@ void ServSettings::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn
|
|||
returnToStart();
|
||||
}
|
||||
}
|
||||
else if (select == 5)
|
||||
{
|
||||
if (!validGroupName(value))
|
||||
{
|
||||
errTxt("err: Invalid group name.\n");
|
||||
mainTxt("Enter a new group (leave blank to cancel): ");
|
||||
}
|
||||
else if (!groupExists(value))
|
||||
{
|
||||
errTxt("err: '" + value + "' does not exists.\n");
|
||||
mainTxt("Enter a new group (leave blank to cancel): ");
|
||||
}
|
||||
else
|
||||
{
|
||||
Query db(this);
|
||||
|
||||
db.setType(Query::UPDATE, TABLE_SERV_SETTINGS);
|
||||
db.addColumn(COLUMN_INITGROUP, value);
|
||||
db.exec();
|
||||
|
||||
returnToStart();
|
||||
}
|
||||
}
|
||||
else if ((select == 6) || (select == 9))
|
||||
else if (select == 6)
|
||||
{
|
||||
if (!QFile::exists(expandEnvVariables(value)))
|
||||
{
|
||||
|
@ -472,51 +396,14 @@ void ServSettings::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn
|
|||
{
|
||||
Query db(this);
|
||||
|
||||
QString column;
|
||||
|
||||
if (select == 6) column = COLUMN_ZIPBIN;
|
||||
else column = COLUMN_MAILERBIN;
|
||||
|
||||
db.setType(Query::UPDATE, TABLE_SERV_SETTINGS);
|
||||
db.addColumn(column, value);
|
||||
db.addColumn(COLUMN_MAILERBIN, value);
|
||||
db.exec();
|
||||
|
||||
returnToStart();
|
||||
}
|
||||
}
|
||||
else if ((select == 7) || (select == 8))
|
||||
{
|
||||
if (!value.contains(INPUT_DIR_SUB, Qt::CaseInsensitive))
|
||||
{
|
||||
errTxt("err: The '" + QString(INPUT_DIR_SUB) + "' keyword is missing.\n");
|
||||
mainTxt("Enter a new command line (leave blank to cancel): ");
|
||||
}
|
||||
else if (!value.contains(OUTPUT_DIR_SUB, Qt::CaseInsensitive))
|
||||
{
|
||||
errTxt("err: The '" + QString(OUTPUT_DIR_SUB) + "' keyword is missing.\n");
|
||||
mainTxt("Enter a new command line (leave blank to cancel): ");
|
||||
}
|
||||
else
|
||||
{
|
||||
Query db(this);
|
||||
|
||||
db.setType(Query::UPDATE, TABLE_SERV_SETTINGS);
|
||||
|
||||
if (select == 7)
|
||||
{
|
||||
db.addColumn(COLUMN_ZIPCOMPRESS, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
db.addColumn(COLUMN_ZIPEXTRACT, value);
|
||||
}
|
||||
|
||||
db.exec();
|
||||
|
||||
returnToStart();
|
||||
}
|
||||
}
|
||||
else if (select == 10)
|
||||
else if (select == 7)
|
||||
{
|
||||
if (!value.contains(SUBJECT_SUB, Qt::CaseInsensitive))
|
||||
{
|
||||
|
@ -544,7 +431,7 @@ void ServSettings::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn
|
|||
returnToStart();
|
||||
}
|
||||
}
|
||||
else if (select == 14)
|
||||
else if (select == 11)
|
||||
{
|
||||
if (!isInt(value))
|
||||
{
|
||||
|
@ -572,7 +459,9 @@ void ServSettings::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn
|
|||
}
|
||||
else
|
||||
{
|
||||
emit enableMoreInput(true);
|
||||
select = 0;
|
||||
level = 0;
|
||||
flags |= MORE_INPUT;
|
||||
|
||||
printSettings();
|
||||
printOptions();
|
||||
|
|
|
@ -18,8 +18,9 @@
|
|||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "../common.h"
|
||||
#include "../cmd_object.h"
|
||||
|
||||
class CloseHost : public InternCommand
|
||||
class CloseHost : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -27,14 +28,14 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit CloseHost(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//--------------------------------------
|
||||
|
||||
class RestartHost : public InternCommand
|
||||
class RestartHost : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -42,14 +43,14 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit RestartHost(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//--------------------------------------
|
||||
|
||||
class ServSettings : public InternCommand
|
||||
class ServSettings : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -66,8 +67,7 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void term();
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit ServSettings(QObject *parent = nullptr);
|
||||
};
|
||||
|
|
|
@ -16,40 +16,31 @@
|
|||
// along with MRCI under the LICENSE.md file. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
Auth::Auth(QObject *parent) : InternCommand(parent) {}
|
||||
Auth::Auth(QObject *parent) : CmdObject(parent) {}
|
||||
|
||||
AuthLog::AuthLog(QObject *parent) : TableViewer(parent)
|
||||
{
|
||||
setParams(TABLE_AUTH_LOG, QStringList() << COLUMN_TIME
|
||||
<< COLUMN_IPADDR
|
||||
<< COLUMN_USERNAME
|
||||
<< COLUMN_AUTH_ATTEMPT
|
||||
<< COLUMN_RECOVER_ATTEMPT
|
||||
<< COLUMN_COUNT
|
||||
<< COLUMN_ACCEPTED, true);
|
||||
setParams(TABLE_AUTH_LOG, false);
|
||||
addJointColumn(TABLE_USERS, COLUMN_USER_ID);
|
||||
addTableColumn(TABLE_AUTH_LOG, COLUMN_TIME);
|
||||
addTableColumn(TABLE_AUTH_LOG, COLUMN_IPADDR);
|
||||
addTableColumn(TABLE_USERS, COLUMN_USERNAME);
|
||||
addTableColumn(TABLE_AUTH_LOG, COLUMN_AUTH_ATTEMPT);
|
||||
addTableColumn(TABLE_AUTH_LOG, COLUMN_RECOVER_ATTEMPT);
|
||||
addTableColumn(TABLE_AUTH_LOG, COLUMN_COUNT);
|
||||
addTableColumn(TABLE_AUTH_LOG, COLUMN_ACCEPTED);
|
||||
}
|
||||
|
||||
QString Auth::cmdName() {return "auth";}
|
||||
QString AuthLog::cmdName() {return "ls_auth_log";}
|
||||
|
||||
void Auth::term()
|
||||
{
|
||||
emit enableMoreInput(false);
|
||||
|
||||
newPassword = false;
|
||||
newUserName = false;
|
||||
loginOk = false;
|
||||
|
||||
uName.clear();
|
||||
}
|
||||
|
||||
void Auth::addToThreshold(const SharedObjs *sharedObjs)
|
||||
void Auth::addToThreshold()
|
||||
{
|
||||
Query db(this);
|
||||
|
||||
db.setType(Query::PUSH, TABLE_AUTH_LOG);
|
||||
db.addColumn(COLUMN_USERNAME, uName);
|
||||
db.addColumn(COLUMN_IPADDR, *sharedObjs->sessionAddr);
|
||||
db.addColumn(COLUMN_USER_ID, uId);
|
||||
db.addColumn(COLUMN_IPADDR, ip);
|
||||
db.addColumn(COLUMN_AUTH_ATTEMPT, true);
|
||||
db.addColumn(COLUMN_RECOVER_ATTEMPT, false);
|
||||
db.addColumn(COLUMN_COUNT, true);
|
||||
|
@ -58,7 +49,7 @@ void Auth::addToThreshold(const SharedObjs *sharedObjs)
|
|||
|
||||
db.setType(Query::PULL, TABLE_SERV_SETTINGS);
|
||||
|
||||
uint maxAttempts = 0;
|
||||
quint32 maxAttempts = 0;
|
||||
bool isRoot = false;
|
||||
|
||||
if (noCaseMatch(ROOT_USER, uName))
|
||||
|
@ -80,37 +71,38 @@ void Auth::addToThreshold(const SharedObjs *sharedObjs)
|
|||
|
||||
db.setType(Query::PULL, TABLE_AUTH_LOG);
|
||||
db.addColumn(COLUMN_IPADDR);
|
||||
db.addCondition(COLUMN_USERNAME, uName);
|
||||
db.addCondition(COLUMN_USER_ID, uId);
|
||||
db.addCondition(COLUMN_AUTH_ATTEMPT, true);
|
||||
db.addCondition(COLUMN_COUNT, true);
|
||||
db.addCondition(COLUMN_ACCEPTED, false);
|
||||
|
||||
if (isRoot) db.addCondition(COLUMN_IPADDR, *sharedObjs->sessionAddr);
|
||||
if (isRoot) db.addCondition(COLUMN_IPADDR, ip);
|
||||
|
||||
db.exec();
|
||||
|
||||
if (static_cast<uint>(db.rows()) > maxAttempts)
|
||||
if (static_cast<quint32>(db.rows()) > maxAttempts)
|
||||
{
|
||||
if (isRoot)
|
||||
{
|
||||
if (!QHostAddress(*sharedObjs->sessionAddr).isLoopback())
|
||||
if (!QHostAddress(ip).isLoopback())
|
||||
{
|
||||
db.setType(Query::PUSH, TABLE_IPBANS);
|
||||
db.addColumn(COLUMN_IPADDR, *sharedObjs->sessionAddr);
|
||||
db.addColumn(COLUMN_IPADDR, ip);
|
||||
db.exec();
|
||||
|
||||
emit closeSession();
|
||||
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_USERNAME, uName);
|
||||
db.addCondition(COLUMN_USER_ID, uId);
|
||||
db.exec();
|
||||
}
|
||||
|
||||
term();
|
||||
flags &= ~MORE_INPUT;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -119,48 +111,43 @@ void Auth::addToThreshold(const SharedObjs *sharedObjs)
|
|||
}
|
||||
}
|
||||
|
||||
void Auth::confirmAuth(const SharedObjs *sharedObjs)
|
||||
void Auth::confirmAuth()
|
||||
{
|
||||
*rwSharedObjs->userName = uName;
|
||||
*rwSharedObjs->displayName = dName;
|
||||
*rwSharedObjs->userId = uId;
|
||||
*rwSharedObjs->groupName = getUserGroup(uName);
|
||||
*rwSharedObjs->hostRank = getRankForGroup(*sharedObjs->groupName);
|
||||
|
||||
Query db(this);
|
||||
|
||||
db.setType(Query::UPDATE, TABLE_AUTH_LOG);
|
||||
db.addColumn(COLUMN_COUNT, false);
|
||||
db.addCondition(COLUMN_COUNT, true);
|
||||
db.addCondition(COLUMN_USERNAME, uName);
|
||||
db.addCondition(COLUMN_USER_ID, uId);
|
||||
db.addCondition(COLUMN_AUTH_ATTEMPT, true);
|
||||
|
||||
if (noCaseMatch(ROOT_USER, uName))
|
||||
{
|
||||
db.addCondition(COLUMN_IPADDR, *sharedObjs->sessionAddr);
|
||||
db.addCondition(COLUMN_IPADDR, ip);
|
||||
}
|
||||
|
||||
db.exec();
|
||||
|
||||
db.setType(Query::PUSH, TABLE_AUTH_LOG);
|
||||
db.addColumn(COLUMN_USERNAME, uName);
|
||||
db.addColumn(COLUMN_IPADDR, *sharedObjs->sessionAddr);
|
||||
db.addColumn(COLUMN_USER_ID, uId);
|
||||
db.addColumn(COLUMN_IPADDR, ip);
|
||||
db.addColumn(COLUMN_COUNT, false);
|
||||
db.addColumn(COLUMN_ACCEPTED, true);
|
||||
db.addColumn(COLUMN_AUTH_ATTEMPT, true);
|
||||
db.addColumn(COLUMN_RECOVER_ATTEMPT, false);
|
||||
db.exec();
|
||||
|
||||
mainTxt("Access granted.\n");
|
||||
flags &= ~MORE_INPUT;
|
||||
|
||||
emit authOk();
|
||||
async(ASYNC_USER_LOGIN, PRIV_IPC, uId);
|
||||
mainTxt("Access granted.\n");
|
||||
}
|
||||
|
||||
void Auth::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void Auth::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
if (dType == TEXT)
|
||||
{
|
||||
if (moreInputEnabled())
|
||||
if (flags & MORE_INPUT)
|
||||
{
|
||||
QString text = fromTEXT(binIn);
|
||||
|
||||
|
@ -171,7 +158,8 @@ void Auth::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar
|
|||
if (text.isEmpty())
|
||||
{
|
||||
mainTxt("\n");
|
||||
term();
|
||||
|
||||
flags &= ~MORE_INPUT;
|
||||
}
|
||||
else if (!validPassword(text))
|
||||
{
|
||||
|
@ -180,13 +168,13 @@ void Auth::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar
|
|||
}
|
||||
else
|
||||
{
|
||||
updatePassword(uName, text, TABLE_USERS);
|
||||
updatePassword(uId, text, TABLE_USERS);
|
||||
|
||||
Query db(this);
|
||||
|
||||
db.setType(Query::UPDATE, TABLE_USERS);
|
||||
db.addColumn(COLUMN_NEED_PASS, false);
|
||||
db.addCondition(COLUMN_USERNAME, uName);
|
||||
db.addCondition(COLUMN_USER_ID, uId);
|
||||
db.exec();
|
||||
|
||||
newPassword = false;
|
||||
|
@ -197,8 +185,7 @@ void Auth::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar
|
|||
}
|
||||
else
|
||||
{
|
||||
confirmAuth(sharedObjs);
|
||||
term();
|
||||
confirmAuth();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -207,7 +194,8 @@ void Auth::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar
|
|||
if (text.isEmpty())
|
||||
{
|
||||
mainTxt("\n");
|
||||
term();
|
||||
|
||||
flags &= ~MORE_INPUT;
|
||||
}
|
||||
else if (!validUserName(text))
|
||||
{
|
||||
|
@ -226,31 +214,31 @@ void Auth::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar
|
|||
db.setType(Query::UPDATE, TABLE_USERS);
|
||||
db.addColumn(COLUMN_NEED_NAME, false);
|
||||
db.addColumn(COLUMN_USERNAME, text);
|
||||
db.addCondition(COLUMN_USERNAME, uName);
|
||||
db.addCondition(COLUMN_USER_ID, uId);
|
||||
db.exec();
|
||||
|
||||
emit backendDataOut(ASYNC_USER_RENAMED, toTEXT("-old '" + escapeChars(uName, '\\', '\'') + "' -new '" + escapeChars(text, '\\', '\'') + "'"), PUB_IPC);
|
||||
async(ASYNC_USER_RENAMED, PUB_IPC, uId + fixedToTEXT(text, BLKSIZE_USER_NAME));
|
||||
|
||||
uName = text;
|
||||
newUserName = false;
|
||||
|
||||
confirmAuth(sharedObjs);
|
||||
term();
|
||||
confirmAuth();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (text.isEmpty())
|
||||
{
|
||||
mainTxt("\n");
|
||||
term();
|
||||
|
||||
flags &= ~MORE_INPUT;
|
||||
}
|
||||
else if (!validPassword(text))
|
||||
{
|
||||
addToThreshold(sharedObjs);
|
||||
addToThreshold();
|
||||
}
|
||||
else if (!auth(uName, text, TABLE_USERS))
|
||||
else if (!auth(uId, text, TABLE_USERS))
|
||||
{
|
||||
addToThreshold(sharedObjs);
|
||||
addToThreshold();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -266,8 +254,7 @@ void Auth::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar
|
|||
}
|
||||
else
|
||||
{
|
||||
confirmAuth(sharedObjs);
|
||||
term();
|
||||
confirmAuth();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -277,40 +264,40 @@ void Auth::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar
|
|||
QString email = getParam("-email", args);
|
||||
QString name = getParam("-user", args);
|
||||
|
||||
if (!email.isEmpty() && validEmailAddr(email)) name = getUserNameForEmail(email);
|
||||
if (!email.isEmpty() && validEmailAddr(email))
|
||||
{
|
||||
name = getUserNameForEmail(email);
|
||||
}
|
||||
|
||||
if (name.isEmpty() || !validUserName(name))
|
||||
{
|
||||
errTxt("err: The -user or -email argument is empty, not found or invalid.\n");
|
||||
}
|
||||
else if (!userExists(name))
|
||||
else if (!userExists(name, &uId))
|
||||
{
|
||||
errTxt("err: No such user.\n");
|
||||
}
|
||||
else if (isLocked(name))
|
||||
else if (isLocked(uId))
|
||||
{
|
||||
errTxt("err: The requested user account is locked.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
emit enableMoreInput(true);
|
||||
|
||||
uName = name;
|
||||
|
||||
Query db(this);
|
||||
|
||||
db.setType(Query::PULL, TABLE_USERS);
|
||||
db.addColumn(COLUMN_DISPLAY_NAME);
|
||||
db.addColumn(COLUMN_NEED_NAME);
|
||||
db.addColumn(COLUMN_NEED_PASS);
|
||||
db.addColumn(COLUMN_USER_ID);
|
||||
db.addCondition(COLUMN_USERNAME, uName);
|
||||
db.addCondition(COLUMN_USER_ID, uId);
|
||||
db.exec();
|
||||
|
||||
loginOk = false;
|
||||
uName = name;
|
||||
flags |= MORE_INPUT;
|
||||
ip = rdStringFromBlock(clientIp, BLKSIZE_CLIENT_IP);
|
||||
newPassword = db.getData(COLUMN_NEED_PASS).toBool();
|
||||
newUserName = db.getData(COLUMN_NEED_NAME).toBool();
|
||||
dName = db.getData(COLUMN_DISPLAY_NAME).toString();
|
||||
uId = db.getData(COLUMN_USER_ID).toByteArray();
|
||||
|
||||
privTxt("Enter password (leave blank to cancel): ");
|
||||
}
|
||||
|
|
|
@ -18,9 +18,10 @@
|
|||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "../common.h"
|
||||
#include "../cmd_object.h"
|
||||
#include "table_viewer.h"
|
||||
|
||||
class Auth : public InternCommand
|
||||
class Auth : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -28,20 +29,19 @@ private:
|
|||
|
||||
QByteArray uId;
|
||||
QString uName;
|
||||
QString dName;
|
||||
QString ip;
|
||||
bool loginOk;
|
||||
bool newPassword;
|
||||
bool newUserName;
|
||||
|
||||
void confirmAuth(const SharedObjs *sharedObjs);
|
||||
void addToThreshold(const SharedObjs *sharedObjs);
|
||||
void confirmAuth();
|
||||
void addToThreshold();
|
||||
|
||||
public:
|
||||
|
||||
static QString cmdName();
|
||||
|
||||
void term();
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit Auth(QObject *parent = nullptr);
|
||||
};
|
||||
|
|
|
@ -18,20 +18,25 @@
|
|||
|
||||
ListBans::ListBans(QObject *parent) : TableViewer(parent)
|
||||
{
|
||||
setParams(TABLE_IPBANS, QStringList() << COLUMN_TIME << COLUMN_IPADDR, true);
|
||||
setParams(TABLE_IPBANS, true);
|
||||
addTableColumn(TABLE_IPBANS, COLUMN_TIME);
|
||||
addTableColumn(TABLE_IPBANS, COLUMN_IPADDR);
|
||||
}
|
||||
|
||||
BanIP::BanIP(QObject *parent) : InternCommand(parent) {}
|
||||
UnBanIP::UnBanIP(QObject *parent) : InternCommand(parent) {}
|
||||
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 BanIP::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void ListBans::onDel()
|
||||
{
|
||||
Q_UNUSED(sharedObjs);
|
||||
async(ASYNC_UPDATE_BANS, PRIV_IPC);
|
||||
}
|
||||
|
||||
void BanIP::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
if (dType == TEXT)
|
||||
{
|
||||
QStringList args = parseArgs(binIn, 2);
|
||||
|
@ -54,14 +59,14 @@ void BanIP::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar
|
|||
db.setType(Query::PUSH, TABLE_IPBANS);
|
||||
db.addColumn(COLUMN_IPADDR, addr.toString());
|
||||
db.exec();
|
||||
|
||||
async(ASYNC_UPDATE_BANS, PRIV_IPC);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UnBanIP::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void UnBanIP::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
Q_UNUSED(sharedObjs);
|
||||
|
||||
if (dType == TEXT)
|
||||
{
|
||||
QStringList args = parseArgs(binIn, 2);
|
||||
|
@ -84,6 +89,8 @@ void UnBanIP::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uch
|
|||
db.setType(Query::DEL, TABLE_IPBANS);
|
||||
db.addCondition(COLUMN_IPADDR, addr.toString());
|
||||
db.exec();
|
||||
|
||||
async(ASYNC_UPDATE_BANS, PRIV_IPC);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,12 +18,17 @@
|
|||
// <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();
|
||||
|
@ -33,7 +38,7 @@ public:
|
|||
|
||||
//---------------------------------
|
||||
|
||||
class BanIP : public InternCommand
|
||||
class BanIP : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -41,14 +46,14 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit BanIP(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//--------------------------------
|
||||
|
||||
class UnBanIP : public InternCommand
|
||||
class UnBanIP : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -56,7 +61,7 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit UnBanIP(QObject *parent = nullptr);
|
||||
};
|
||||
|
|
|
@ -16,17 +16,22 @@
|
|||
// along with MRCI under the LICENSE.md file. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
Cast::Cast(QObject *parent) : InternCommand(parent) {}
|
||||
OpenSubChannel::OpenSubChannel(QObject *parent) : InternCommand(parent) {}
|
||||
CloseSubChannel::CloseSubChannel(QObject *parent) : InternCommand(parent) {}
|
||||
LsOpenChannels::LsOpenChannels(QObject *parent) : InternCommand(parent) {}
|
||||
PingPeers::PingPeers(QObject *parent) : InternCommand(parent) {}
|
||||
AddRDOnlyFlag::AddRDOnlyFlag(QObject *parent) : InternCommand(parent) {}
|
||||
RemoveRDOnlyFlag::RemoveRDOnlyFlag(QObject *parent) : InternCommand(parent) {}
|
||||
Cast::Cast(QObject *parent) : CmdObject(parent) {}
|
||||
OpenSubChannel::OpenSubChannel(QObject *parent) : CmdObject(parent) {}
|
||||
CloseSubChannel::CloseSubChannel(QObject *parent) : CmdObject(parent) {}
|
||||
LsOpenChannels::LsOpenChannels(QObject *parent) : CmdObject(parent) {}
|
||||
PingPeers::PingPeers(QObject *parent) : CmdObject(parent) {}
|
||||
AddRDOnlyFlag::AddRDOnlyFlag(QObject *parent) : CmdObject(parent) {}
|
||||
RemoveRDOnlyFlag::RemoveRDOnlyFlag(QObject *parent) : CmdObject(parent) {}
|
||||
|
||||
ListRDonlyFlags::ListRDonlyFlags(QObject *parent) : TableViewer(parent)
|
||||
{
|
||||
setParams(TABLE_RDONLY_CAST, QStringList() << COLUMN_SUB_CH_ID << COLUMN_ACCESS_LEVEL << COLUMN_CHANNEL_NAME, false);
|
||||
setParams(TABLE_RDONLY_CAST, false);
|
||||
addJointColumn(TABLE_CHANNELS, COLUMN_CHANNEL_ID);
|
||||
addTableColumn(TABLE_CHANNELS, COLUMN_CHANNEL_NAME);
|
||||
addTableColumn(TABLE_RDONLY_CAST, COLUMN_CHANNEL_ID);
|
||||
addTableColumn(TABLE_RDONLY_CAST, COLUMN_SUB_CH_ID);
|
||||
addTableColumn(TABLE_RDONLY_CAST, COLUMN_ACCESS_LEVEL);
|
||||
}
|
||||
|
||||
QString Cast::cmdName() {return "cast";}
|
||||
|
@ -38,22 +43,48 @@ QString AddRDOnlyFlag::cmdName() {return "add_rdonly_flag";}
|
|||
QString RemoveRDOnlyFlag::cmdName() {return "rm_rdonly_flag";}
|
||||
QString ListRDonlyFlags::cmdName() {return "ls_rdonly_flags";}
|
||||
|
||||
void Cast::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
bool canOpenSubChannel(const QByteArray &uId, const char *override, quint64 chId, quint8 subId)
|
||||
{
|
||||
Q_UNUSED(sharedObjs);
|
||||
int uLevel = channelAccessLevel(uId, override, chId);
|
||||
int sLevel = lowestAcessLevel(chId, subId);
|
||||
|
||||
emit castToPeers(binIn, dType);
|
||||
return uLevel <= sLevel;
|
||||
}
|
||||
|
||||
void OpenSubChannel::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
int lowestAcessLevel(quint64 chId, quint8 subId)
|
||||
{
|
||||
Q_UNUSED(sharedObjs);
|
||||
int ret = 5000;
|
||||
|
||||
Query db;
|
||||
|
||||
db.setType(Query::PULL, TABLE_SUB_CHANNELS);
|
||||
db.addColumn(COLUMN_LOWEST_LEVEL);
|
||||
db.addCondition(COLUMN_CHANNEL_ID, chId);
|
||||
db.addCondition(COLUMN_SUB_CH_ID, subId);
|
||||
db.exec();
|
||||
|
||||
if (db.rows())
|
||||
{
|
||||
ret = db.getData(COLUMN_LOWEST_LEVEL).toInt();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Cast::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
async(ASYNC_CAST, dType, binIn);
|
||||
}
|
||||
|
||||
void OpenSubChannel::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
if (dType == TEXT)
|
||||
{
|
||||
QStringList args = parseArgs(binIn, 4);
|
||||
QString ch = getParam("-ch_name", args);
|
||||
QString sub = getParam("-sub_name", args);
|
||||
quint64 chId;
|
||||
quint8 subId;
|
||||
|
||||
if (ch.isEmpty())
|
||||
{
|
||||
|
@ -63,22 +94,34 @@ void OpenSubChannel::procBin(const SharedObjs *sharedObjs, const QByteArray &bin
|
|||
{
|
||||
errTxt("err: Sub-Channel name (-sub_name) argument not found or is empty.\n");
|
||||
}
|
||||
else if (!channelExists(ch, &chId))
|
||||
{
|
||||
errTxt("err: The requested channel does not exists.\n");
|
||||
}
|
||||
else if (!channelSubExists(chId, sub, &subId))
|
||||
{
|
||||
errTxt("err: The requested sub-channel does not exists.\n");
|
||||
}
|
||||
else if (!canOpenSubChannel(rdFromBlock(userId, BLKSIZE_USER_ID), chOwnerOverride, chId, subId))
|
||||
{
|
||||
errTxt("err: Access denied.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
emit openChByName(ch, sub);
|
||||
async(ASYNC_OPEN_SUBCH, PRIV_IPC, wrInt(chId, 64) + wrInt(subId, 8));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CloseSubChannel::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void CloseSubChannel::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
Q_UNUSED(sharedObjs);
|
||||
|
||||
if (dType == TEXT)
|
||||
{
|
||||
QStringList args = parseArgs(binIn, 4);
|
||||
QString ch = getParam("-ch_name", args);
|
||||
QString sub = getParam("-sub_name", args);
|
||||
quint64 chId;
|
||||
quint8 subId;
|
||||
|
||||
if (ch.isEmpty())
|
||||
{
|
||||
|
@ -88,16 +131,24 @@ void CloseSubChannel::procBin(const SharedObjs *sharedObjs, const QByteArray &bi
|
|||
{
|
||||
errTxt("err: Sub-Channel name (-sub_name) argument not found or is empty.\n");
|
||||
}
|
||||
else if (!channelExists(ch, &chId))
|
||||
{
|
||||
errTxt("err: The requested channel does not exists.\n");
|
||||
}
|
||||
else if (!channelSubExists(chId, sub, &subId))
|
||||
{
|
||||
errTxt("err: The requested sub-channel does not exists.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
emit closeChByName(ch, sub);
|
||||
async(ASYNC_CLOSE_SUBCH, PRIV_IPC, wrInt(chId, 64) + wrInt(subId, 8));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LsOpenChannels::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void LsOpenChannels::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
Q_UNUSED(binIn);
|
||||
Q_UNUSED(binIn)
|
||||
|
||||
if (dType == TEXT)
|
||||
{
|
||||
|
@ -115,28 +166,28 @@ void LsOpenChannels::procBin(const SharedObjs *sharedObjs, const QByteArray &bin
|
|||
tableData.append(QStringList() << COLUMN_CHANNEL_NAME << COLUMN_SUB_CH_NAME << COLUMN_CHANNEL_ID << COLUMN_SUB_CH_ID << "read_only");
|
||||
tableData.append(separators);
|
||||
|
||||
for (int i = 0; i < sharedObjs->chIds->size(); i += 9)
|
||||
for (int i = 0; i < MAX_OPEN_SUB_CHANNELS; i += BLKSIZE_SUB_CHANNEL)
|
||||
{
|
||||
quint64 chId = rdInt(QByteArray::fromRawData(sharedObjs->chIds->data() + i, 8));
|
||||
quint64 subId = rdInt(QByteArray::fromRawData(sharedObjs->chIds->data() + (i + 8), 1));
|
||||
quint64 chId = rd64BitFromBlock(openSubChs + i);
|
||||
quint8 subId = rd8BitFromBlock(openSubChs + (i + 8));
|
||||
|
||||
if (chId)
|
||||
{
|
||||
QStringList columnData;
|
||||
|
||||
db.setType(Query::PULL, TABLE_SUB_CHANNELS);
|
||||
db.addColumn(COLUMN_SUB_CH_NAME);
|
||||
db.addColumn(COLUMN_CHANNEL_NAME);
|
||||
db.setType(Query::INNER_JOIN_PULL, TABLE_SUB_CHANNELS);
|
||||
db.addTableColumn(TABLE_SUB_CHANNELS, COLUMN_SUB_CH_NAME);
|
||||
db.addTableColumn(TABLE_CHANNELS, COLUMN_CHANNEL_NAME);
|
||||
db.addJoinCondition(COLUMN_CHANNEL_ID, TABLE_CHANNELS);
|
||||
db.addCondition(COLUMN_CHANNEL_ID, chId);
|
||||
db.addCondition(COLUMN_SUB_CH_ID, subId);
|
||||
db.exec();
|
||||
|
||||
QByteArray subCh = QByteArray::fromRawData(sharedObjs->chIds->data() + i, 9);
|
||||
QString chName = db.getData(COLUMN_CHANNEL_NAME).toString();
|
||||
QString subName = db.getData(COLUMN_SUB_CH_NAME).toString();
|
||||
QString rdOnly;
|
||||
|
||||
if (chPos(subCh, *sharedObjs->wrAbleChIds) != -1)
|
||||
if (posOfBlock(openSubChs + i, openWritableSubChs, MAX_OPEN_SUB_CHANNELS, BLKSIZE_SUB_CHANNEL) == -1)
|
||||
{
|
||||
rdOnly = "1";
|
||||
}
|
||||
|
@ -166,7 +217,7 @@ void LsOpenChannels::procBin(const SharedObjs *sharedObjs, const QByteArray &bin
|
|||
{
|
||||
for (int i = 0; i < row.size(); ++i)
|
||||
{
|
||||
mainTxt(row[i].leftJustified(justLens[i] + 2, ' '));
|
||||
mainTxt(row[i].leftJustified(justLens[i] + 4, ' '));
|
||||
}
|
||||
|
||||
mainTxt("\n");
|
||||
|
@ -174,27 +225,24 @@ void LsOpenChannels::procBin(const SharedObjs *sharedObjs, const QByteArray &bin
|
|||
}
|
||||
}
|
||||
|
||||
void PingPeers::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void PingPeers::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
Q_UNUSED(binIn);
|
||||
Q_UNUSED(binIn)
|
||||
|
||||
if (dType == TEXT)
|
||||
{
|
||||
if (!(*sharedObjs->activeUpdate))
|
||||
if (rd8BitFromBlock(activeUpdate) == 0)
|
||||
{
|
||||
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
|
||||
{
|
||||
QByteArray castHeader = *sharedObjs->chIds + wrInt(PING_PEERS, 8);
|
||||
QByteArray data = toPEER_INFO(sharedObjs);
|
||||
|
||||
emit backendDataOut(ASYNC_LIMITED_CAST, castHeader + data, PUB_IPC);
|
||||
async(ASYNC_PING_PEERS, PUB_IPC);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AddRDOnlyFlag::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void AddRDOnlyFlag::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
if (dType == TEXT)
|
||||
{
|
||||
|
@ -202,6 +250,7 @@ void AddRDOnlyFlag::procBin(const SharedObjs *sharedObjs, const QByteArray &binI
|
|||
QString chName = getParam("-ch_name", args);
|
||||
QString subId = getParam("-sub_id", args);
|
||||
QString level = getParam("-level", args);
|
||||
quint64 chId;
|
||||
|
||||
if (chName.isEmpty())
|
||||
{
|
||||
|
@ -227,34 +276,36 @@ void AddRDOnlyFlag::procBin(const SharedObjs *sharedObjs, const QByteArray &binI
|
|||
{
|
||||
errTxt("err: Invalid privilage level. valid range (1-5).\n");
|
||||
}
|
||||
else if (!channelExists(chName))
|
||||
else if (!channelExists(chName, &chId))
|
||||
{
|
||||
errTxt("err: Channel name '" + chName + "' does not exists.\n");
|
||||
}
|
||||
else if (channelAccessLevel(sharedObjs, chName) > ADMIN)
|
||||
else if (channelAccessLevel(rdFromBlock(userId, BLKSIZE_USER_ID), chOwnerOverride, chId) > ADMIN)
|
||||
{
|
||||
errTxt("err: Access denied.\n");
|
||||
}
|
||||
else if (rdOnlyFlagExists(chName, static_cast<uchar>(subId.toInt()), level.toInt()))
|
||||
else if (rdOnlyFlagExists(chName, static_cast<quint8>(subId.toInt()), level.toInt()))
|
||||
{
|
||||
errTxt("err: A read only flag for sub-id: " + QString::number(subId.toInt()) + " level: " + QString::number(level.toInt()) + " already exists.\n");
|
||||
errTxt("err: A read only flag for sub_id: " + QString::number(subId.toInt()) + " level: " + QString::number(level.toInt()) + " already exists.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
QByteArray frame = wrInt(chId, 64) + wrInt(subId.toUInt(), 8) + wrInt(level.toUInt(), 8);
|
||||
|
||||
Query db(this);
|
||||
|
||||
db.setType(Query::PUSH, TABLE_RDONLY_CAST);
|
||||
db.addColumn(COLUMN_CHANNEL_NAME, chName);
|
||||
db.addColumn(COLUMN_CHANNEL_ID, chId);
|
||||
db.addColumn(COLUMN_SUB_CH_ID, subId.toInt());
|
||||
db.addColumn(COLUMN_ACCESS_LEVEL, level.toInt());
|
||||
db.exec();
|
||||
|
||||
emit backendDataOut(ASYNC_ADD_RDONLY, toTEXT(args.join(' ')), PUB_IPC_WITH_FEEDBACK);
|
||||
async(ASYNC_ADD_RDONLY, PUB_IPC_WITH_FEEDBACK, frame);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveRDOnlyFlag::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void RemoveRDOnlyFlag::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
if (dType == TEXT)
|
||||
{
|
||||
|
@ -262,6 +313,7 @@ void RemoveRDOnlyFlag::procBin(const SharedObjs *sharedObjs, const QByteArray &b
|
|||
QString chName = getParam("-ch_name", args);
|
||||
QString subId = getParam("-sub_id", args);
|
||||
QString level = getParam("-level", args);
|
||||
quint64 chId;
|
||||
|
||||
if (chName.isEmpty())
|
||||
{
|
||||
|
@ -287,45 +339,48 @@ void RemoveRDOnlyFlag::procBin(const SharedObjs *sharedObjs, const QByteArray &b
|
|||
{
|
||||
errTxt("err: Invalid privilage level. valid range (1-5).\n");
|
||||
}
|
||||
else if (!channelExists(chName))
|
||||
else if (!channelExists(chName, &chId))
|
||||
{
|
||||
errTxt("err: Channel name '" + chName + "' does not exists.\n");
|
||||
}
|
||||
else if (channelAccessLevel(sharedObjs, chName) > ADMIN)
|
||||
else if (channelAccessLevel(rdFromBlock(userId, BLKSIZE_USER_ID), chOwnerOverride, chId) > ADMIN)
|
||||
{
|
||||
errTxt("err: Access denied.\n");
|
||||
}
|
||||
else if (!rdOnlyFlagExists(chName, static_cast<uchar>(subId.toInt()), level.toInt()))
|
||||
else if (!rdOnlyFlagExists(chName, static_cast<quint8>(subId.toInt()), level.toInt()))
|
||||
{
|
||||
errTxt("err: A read only flag for sub-id: " + QString::number(subId.toInt()) + " level: " + QString::number(level.toInt()) + " does not exists.\n");
|
||||
errTxt("err: A read only flag for sub_id: " + QString::number(subId.toInt()) + " level: " + QString::number(level.toInt()) + " does not exists.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
QByteArray frame = wrInt(chId, 64) + wrInt(subId.toUInt(), 8) + wrInt(level.toUInt(), 8);
|
||||
|
||||
Query db(this);
|
||||
|
||||
db.setType(Query::DEL, TABLE_RDONLY_CAST);
|
||||
db.addCondition(COLUMN_CHANNEL_NAME, chName);
|
||||
db.addCondition(COLUMN_CHANNEL_ID, chId);
|
||||
db.addCondition(COLUMN_SUB_CH_ID, subId.toInt());
|
||||
db.addCondition(COLUMN_ACCESS_LEVEL, level.toInt());
|
||||
db.exec();
|
||||
|
||||
emit backendDataOut(ASYNC_RM_RDONLY, toTEXT(args.join(' ')), PUB_IPC_WITH_FEEDBACK);
|
||||
async(ASYNC_RM_RDONLY, PUB_IPC_WITH_FEEDBACK, frame);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ListRDonlyFlags::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void ListRDonlyFlags::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
if (dType == TEXT)
|
||||
{
|
||||
if (moreInputEnabled())
|
||||
if (flags & MORE_INPUT)
|
||||
{
|
||||
TableViewer::procBin(sharedObjs, binIn, dType);
|
||||
TableViewer::procIn(binIn, dType);
|
||||
}
|
||||
else
|
||||
{
|
||||
QStringList args = parseArgs(binIn, 2);
|
||||
QString chName = getParam("-ch_name", args);
|
||||
quint64 chId;
|
||||
|
||||
if (chName.isEmpty())
|
||||
{
|
||||
|
@ -335,19 +390,19 @@ void ListRDonlyFlags::procBin(const SharedObjs *sharedObjs, const QByteArray &bi
|
|||
{
|
||||
errTxt("err: Invalid channel name.\n");
|
||||
}
|
||||
else if (!channelExists(chName))
|
||||
else if (!channelExists(chName, &chId))
|
||||
{
|
||||
errTxt("err: Channel name '" + chName + "' does not exists.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (channelAccessLevel(sharedObjs, chName) > REGULAR)
|
||||
if (channelAccessLevel(rdFromBlock(userId, BLKSIZE_USER_ID), chOwnerOverride, chId) > REGULAR)
|
||||
{
|
||||
TableViewer::procBin(sharedObjs, 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);
|
||||
}
|
||||
else
|
||||
{
|
||||
TableViewer::procBin(sharedObjs, toTEXT("-" + QString(COLUMN_CHANNEL_NAME) + " " + chName), dType);
|
||||
TableViewer::procIn(toTEXT("-" + QString(COLUMN_CHANNEL_NAME) + " " + chName), dType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,9 +18,13 @@
|
|||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "../common.h"
|
||||
#include "../cmd_object.h"
|
||||
#include "table_viewer.h"
|
||||
|
||||
class Cast : public InternCommand
|
||||
bool canOpenSubChannel(const QByteArray &uId, const char *override, quint64 chId, quint8 subId);
|
||||
int lowestAcessLevel(quint64 chId, quint8 subId);
|
||||
|
||||
class Cast : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -28,14 +32,14 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit Cast(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//----------------------------------
|
||||
|
||||
class OpenSubChannel : public InternCommand
|
||||
class OpenSubChannel : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -43,14 +47,14 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit OpenSubChannel(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//-----------------------------------
|
||||
|
||||
class CloseSubChannel : public InternCommand
|
||||
class CloseSubChannel : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -58,14 +62,14 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit CloseSubChannel(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//----------------------------------
|
||||
|
||||
class LsOpenChannels : public InternCommand
|
||||
class LsOpenChannels : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -73,14 +77,14 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit LsOpenChannels(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//----------------------------------
|
||||
|
||||
class PingPeers : public InternCommand
|
||||
class PingPeers : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -88,14 +92,14 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit PingPeers(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//---------------------------------
|
||||
|
||||
class AddRDOnlyFlag : public InternCommand
|
||||
class AddRDOnlyFlag : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -103,14 +107,14 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit AddRDOnlyFlag(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//-------------------------------
|
||||
|
||||
class RemoveRDOnlyFlag : public InternCommand
|
||||
class RemoveRDOnlyFlag : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -118,7 +122,7 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit RemoveRDOnlyFlag(QObject *parent = nullptr);
|
||||
};
|
||||
|
@ -133,7 +137,7 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit ListRDonlyFlags(QObject *parent = nullptr);
|
||||
};
|
||||
|
|
|
@ -18,22 +18,21 @@
|
|||
|
||||
ListCerts::ListCerts(QObject *parent) : TableViewer(parent)
|
||||
{
|
||||
setParams(TABLE_CERT_DATA, QStringList() << COLUMN_COMMON_NAME, false);
|
||||
setParams(TABLE_CERT_DATA, false);
|
||||
addTableColumn(TABLE_CERT_DATA, COLUMN_COMMON_NAME);
|
||||
}
|
||||
|
||||
CertInfo::CertInfo(QObject *parent) : InternCommand(parent) {}
|
||||
AddCert::AddCert(QObject *parent) : InternCommand(parent) {}
|
||||
RemoveCert::RemoveCert(QObject *parent) : InternCommand(parent) {}
|
||||
CertInfo::CertInfo(QObject *parent) : CmdObject(parent) {}
|
||||
AddCert::AddCert(QObject *parent) : CmdObject(parent) {}
|
||||
RemoveCert::RemoveCert(QObject *parent) : CmdObject(parent) {}
|
||||
|
||||
QString ListCerts::cmdName() {return "ls_certs";}
|
||||
QString CertInfo::cmdName() {return "cert_info";}
|
||||
QString AddCert::cmdName() {return "add_cert";}
|
||||
QString RemoveCert::cmdName() {return "rm_cert";}
|
||||
|
||||
void CertInfo::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void CertInfo::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
Q_UNUSED(sharedObjs);
|
||||
|
||||
if (dType == TEXT)
|
||||
{
|
||||
QStringList args = parseArgs(binIn, 2);
|
||||
|
@ -75,15 +74,6 @@ void CertInfo::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uc
|
|||
}
|
||||
}
|
||||
|
||||
void AddCert::term()
|
||||
{
|
||||
coName.clear();
|
||||
certBa.clear();
|
||||
privBa.clear();
|
||||
|
||||
emit enableMoreInput(false);
|
||||
}
|
||||
|
||||
void AddCert::run()
|
||||
{
|
||||
Query db(this);
|
||||
|
@ -94,27 +84,25 @@ void AddCert::run()
|
|||
db.addColumn(COLUMN_PRIV_KEY, privBa);
|
||||
db.exec();
|
||||
|
||||
term();
|
||||
flags &= ~MORE_INPUT;
|
||||
}
|
||||
|
||||
void AddCert::ask()
|
||||
{
|
||||
emit enableMoreInput(true);
|
||||
flags |= MORE_INPUT;
|
||||
|
||||
mainTxt("Common name: '" + coName + "' already exists. do you want to replace it? (y/n): ");
|
||||
}
|
||||
|
||||
void AddCert::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void AddCert::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
Q_UNUSED(sharedObjs);
|
||||
|
||||
if ((dType == TEXT) && moreInputEnabled())
|
||||
if ((dType == TEXT) && (flags & MORE_INPUT))
|
||||
{
|
||||
QString ans = fromTEXT(binIn);
|
||||
|
||||
if (noCaseMatch("n", ans))
|
||||
{
|
||||
term();
|
||||
flags &= ~MORE_INPUT;
|
||||
}
|
||||
else if (noCaseMatch("y", ans))
|
||||
{
|
||||
|
@ -159,7 +147,7 @@ void AddCert::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uch
|
|||
}
|
||||
else if (!validCommonName(coName))
|
||||
{
|
||||
errTxt("err: The common name must be less than or equal to 200 chars long and contain no spaces.\n");
|
||||
errTxt("err: The common name must be less than or equal to 136 chars long and contain no spaces.\n");
|
||||
}
|
||||
else if (!certFile.open(QFile::ReadOnly))
|
||||
{
|
||||
|
@ -210,34 +198,25 @@ void RemoveCert::run()
|
|||
db.addCondition(COLUMN_COMMON_NAME, coName);
|
||||
db.exec();
|
||||
|
||||
term();
|
||||
}
|
||||
|
||||
void RemoveCert::term()
|
||||
{
|
||||
emit enableMoreInput(false);
|
||||
|
||||
coName.clear();
|
||||
flags &= ~MORE_INPUT;
|
||||
}
|
||||
|
||||
void RemoveCert::ask()
|
||||
{
|
||||
emit enableMoreInput(true);
|
||||
flags |= MORE_INPUT;
|
||||
|
||||
mainTxt("Are you sure you want to remove the cert for common name: " + coName + "? (y/n): ");
|
||||
}
|
||||
|
||||
void RemoveCert::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void RemoveCert::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
Q_UNUSED(sharedObjs);
|
||||
|
||||
if ((dType == TEXT) && moreInputEnabled())
|
||||
if ((dType == TEXT) && (flags & MORE_INPUT))
|
||||
{
|
||||
QString ans = fromTEXT(binIn);
|
||||
|
||||
if (noCaseMatch("n", ans))
|
||||
{
|
||||
term();
|
||||
flags &= ~MORE_INPUT;
|
||||
}
|
||||
else if (noCaseMatch("y", ans))
|
||||
{
|
||||
|
@ -260,7 +239,7 @@ void RemoveCert::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn,
|
|||
}
|
||||
else if (!validCommonName(name))
|
||||
{
|
||||
errTxt("err: The common name must be lass than or equal to 200 chars long and contain no spaces.\n");
|
||||
errTxt("err: Invalid common name.\n");
|
||||
}
|
||||
else if (!certExists(name))
|
||||
{
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "../common.h"
|
||||
#include "../cmd_object.h"
|
||||
#include "../make_cert.h"
|
||||
#include "table_viewer.h"
|
||||
|
||||
|
@ -34,7 +35,7 @@ public:
|
|||
|
||||
//--------------------------
|
||||
|
||||
class CertInfo : public InternCommand
|
||||
class CertInfo : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -42,14 +43,14 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit CertInfo(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//----------------------------
|
||||
|
||||
class AddCert : public InternCommand
|
||||
class AddCert : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -67,15 +68,14 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void term();
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit AddCert(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//-----------------------------
|
||||
|
||||
class RemoveCert : public InternCommand
|
||||
class RemoveCert : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -90,8 +90,7 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void term();
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit RemoveCert(QObject *parent = nullptr);
|
||||
};
|
||||
|
|
|
@ -16,39 +16,57 @@
|
|||
// along with MRCI under the LICENSE.md file. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
CreateChannel::CreateChannel(QObject *parent) : InternCommand(parent) {}
|
||||
RemoveChannel::RemoveChannel(QObject *parent) : InternCommand(parent) {}
|
||||
RenameChannel::RenameChannel(QObject *parent) : InternCommand(parent) {}
|
||||
SetActiveState::SetActiveState(QObject *parent) : InternCommand(parent) {}
|
||||
CreateSubCh::CreateSubCh(QObject *parent) : InternCommand(parent) {}
|
||||
RemoveSubCh::RemoveSubCh(QObject *parent) : InternCommand(parent) {}
|
||||
RenameSubCh::RenameSubCh(QObject *parent) : InternCommand(parent) {}
|
||||
InviteToCh::InviteToCh(QObject *parent) : InternCommand(parent) {}
|
||||
DeclineChInvite::DeclineChInvite(QObject *parent) : InternCommand(parent) {}
|
||||
AcceptChInvite::AcceptChInvite(QObject *parent) : InternCommand(parent) {}
|
||||
RemoveChMember::RemoveChMember(QObject *parent) : InternCommand(parent) {}
|
||||
SetMemberLevel::SetMemberLevel(QObject *parent) : InternCommand(parent) {}
|
||||
SetSubAcessLevel::SetSubAcessLevel(QObject *parent) : InternCommand(parent) {}
|
||||
OwnerOverride::OwnerOverride(QObject *parent) : InternCommand(parent) {}
|
||||
CreateChannel::CreateChannel(QObject *parent) : CmdObject(parent) {}
|
||||
RemoveChannel::RemoveChannel(QObject *parent) : CmdObject(parent) {}
|
||||
RenameChannel::RenameChannel(QObject *parent) : CmdObject(parent) {}
|
||||
SetActiveState::SetActiveState(QObject *parent) : CmdObject(parent) {}
|
||||
CreateSubCh::CreateSubCh(QObject *parent) : CmdObject(parent) {}
|
||||
RemoveSubCh::RemoveSubCh(QObject *parent) : CmdObject(parent) {}
|
||||
RenameSubCh::RenameSubCh(QObject *parent) : CmdObject(parent) {}
|
||||
InviteToCh::InviteToCh(QObject *parent) : CmdObject(parent) {}
|
||||
DeclineChInvite::DeclineChInvite(QObject *parent) : CmdObject(parent) {}
|
||||
AcceptChInvite::AcceptChInvite(QObject *parent) : CmdObject(parent) {}
|
||||
RemoveChMember::RemoveChMember(QObject *parent) : CmdObject(parent) {}
|
||||
SetMemberLevel::SetMemberLevel(QObject *parent) : CmdObject(parent) {}
|
||||
SetSubAcessLevel::SetSubAcessLevel(QObject *parent) : CmdObject(parent) {}
|
||||
OwnerOverride::OwnerOverride(QObject *parent) : CmdObject(parent) {}
|
||||
|
||||
ListChannels::ListChannels(QObject *parent) : TableViewer(parent)
|
||||
{
|
||||
setParams(TABLE_CH_MEMBERS, QStringList() << COLUMN_CHANNEL_ID << COLUMN_CHANNEL_NAME << COLUMN_PENDING_INVITE << COLUMN_ACCESS_LEVEL << COLUMN_USERNAME, false);
|
||||
setParams(TABLE_CH_MEMBERS, false);
|
||||
addTableColumn(TABLE_CH_MEMBERS, COLUMN_CHANNEL_ID);
|
||||
addTableColumn(TABLE_CHANNELS, COLUMN_CHANNEL_NAME);
|
||||
addTableColumn(TABLE_CH_MEMBERS, COLUMN_PENDING_INVITE);
|
||||
addTableColumn(TABLE_CH_MEMBERS, COLUMN_ACCESS_LEVEL);
|
||||
addJointColumn(TABLE_CHANNELS, COLUMN_CHANNEL_ID);
|
||||
addJointColumn(TABLE_USERS, COLUMN_USER_ID);
|
||||
}
|
||||
|
||||
ListSubCh::ListSubCh(QObject *parent) : TableViewer(parent)
|
||||
{
|
||||
setParams(TABLE_SUB_CHANNELS, QStringList() << COLUMN_CHANNEL_NAME << COLUMN_CHANNEL_ID << COLUMN_SUB_CH_ID << COLUMN_SUB_CH_NAME << COLUMN_LOWEST_LEVEL << COLUMN_ACTIVE_UPDATE, false);
|
||||
setParams(TABLE_SUB_CHANNELS, false);
|
||||
addTableColumn(TABLE_SUB_CHANNELS, COLUMN_SUB_CH_ID);
|
||||
addTableColumn(TABLE_SUB_CHANNELS, COLUMN_SUB_CH_NAME);
|
||||
addTableColumn(TABLE_SUB_CHANNELS, COLUMN_LOWEST_LEVEL);
|
||||
addTableColumn(TABLE_SUB_CHANNELS, COLUMN_ACTIVE_UPDATE);
|
||||
}
|
||||
|
||||
SearchChannels::SearchChannels(QObject *parent) : TableViewer(parent)
|
||||
{
|
||||
setParams(TABLE_CHANNELS, QStringList() << COLUMN_CHANNEL_ID << COLUMN_CHANNEL_NAME, false);
|
||||
setParams(TABLE_CHANNELS, false);
|
||||
addTableColumn(TABLE_CHANNELS, COLUMN_CHANNEL_ID);
|
||||
addTableColumn(TABLE_CHANNELS, COLUMN_CHANNEL_NAME);
|
||||
}
|
||||
|
||||
ListMembers::ListMembers(QObject *parent) : TableViewer(parent)
|
||||
{
|
||||
setParams(TABLE_CH_MEMBERS, QStringList() << COLUMN_CHANNEL_ID << COLUMN_CHANNEL_NAME << COLUMN_PENDING_INVITE << COLUMN_ACCESS_LEVEL << COLUMN_USERNAME, false);
|
||||
setParams(TABLE_CH_MEMBERS, false);
|
||||
addTableColumn(TABLE_CH_MEMBERS, COLUMN_CHANNEL_ID);
|
||||
addTableColumn(TABLE_USERS, COLUMN_USERNAME);
|
||||
addTableColumn(TABLE_USERS, COLUMN_DISPLAY_NAME);
|
||||
addTableColumn(TABLE_CH_MEMBERS, COLUMN_PENDING_INVITE);
|
||||
addTableColumn(TABLE_CH_MEMBERS, COLUMN_ACCESS_LEVEL);
|
||||
addJointColumn(TABLE_USERS, COLUMN_USER_ID);
|
||||
}
|
||||
|
||||
QString CreateChannel::cmdName() {return "add_ch";}
|
||||
|
@ -70,26 +88,51 @@ QString SetSubAcessLevel::cmdName() {return "set_sub_ch_level";}
|
|||
QString ListMembers::cmdName() {return "ls_ch_members";}
|
||||
QString OwnerOverride::cmdName() {return "ch_owner_override";}
|
||||
|
||||
void ListChannels::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
QByteArray createChMemberAsyncFrame(quint64 chId, const QByteArray &userId, bool invite, quint8 level, const QString &userName, const QString &dispName, const QString &chName)
|
||||
{
|
||||
Q_UNUSED(binIn);
|
||||
QByteArray ret;
|
||||
|
||||
if (moreInputEnabled())
|
||||
ret.append(wrInt(chId, 64));
|
||||
ret.append(userId);
|
||||
|
||||
if (invite)
|
||||
{
|
||||
TableViewer::procBin(sharedObjs, binIn, dType);
|
||||
ret.append(wrInt(1, 8));
|
||||
}
|
||||
else
|
||||
{
|
||||
TableViewer::procBin(sharedObjs, toTEXT("-" + QString(COLUMN_USERNAME) + " " + *sharedObjs->userName), dType);
|
||||
ret.append(wrInt(0, 8));
|
||||
}
|
||||
|
||||
ret.append(wrInt(level, 8));
|
||||
ret.append(nullTermTEXT(userName));
|
||||
ret.append(nullTermTEXT(dispName));
|
||||
ret.append(nullTermTEXT(chName));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ListChannels::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
Q_UNUSED(binIn)
|
||||
|
||||
if (flags & MORE_INPUT)
|
||||
{
|
||||
TableViewer::procIn(binIn, dType);
|
||||
}
|
||||
else
|
||||
{
|
||||
TableViewer::procIn(toTEXT("-" + QString(COLUMN_USERNAME) + " " + rdStringFromBlock(userName, BLKSIZE_USER_NAME)), dType);
|
||||
}
|
||||
}
|
||||
|
||||
void ListSubCh::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void ListSubCh::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
if (dType == TEXT)
|
||||
{
|
||||
QStringList args = parseArgs(binIn, 2);
|
||||
QString chName = getParam("-ch_name", args);
|
||||
quint64 chId;
|
||||
|
||||
if (chName.isEmpty())
|
||||
{
|
||||
|
@ -99,31 +142,31 @@ void ListSubCh::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, u
|
|||
{
|
||||
errTxt("err: Invalid channel name.\n");
|
||||
}
|
||||
else if (!channelExists(chName))
|
||||
else if (!channelExists(chName, &chId))
|
||||
{
|
||||
errTxt("err: Channel name '" + chName + "' does not exists.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (channelAccessLevel(sharedObjs, getChId(chName)) > REGULAR)
|
||||
if (channelAccessLevel(rdFromBlock(userId, BLKSIZE_USER_ID), chOwnerOverride, chId) > REGULAR)
|
||||
{
|
||||
TableViewer::procBin(sharedObjs, 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);
|
||||
}
|
||||
else
|
||||
{
|
||||
TableViewer::procBin(sharedObjs, toTEXT("-" + QString(COLUMN_CHANNEL_NAME) + " " + chName), dType);
|
||||
TableViewer::procIn(toTEXT("-" + QString(COLUMN_CHANNEL_NAME) + " " + chName), dType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SearchChannels::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void SearchChannels::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
if (dType == TEXT)
|
||||
{
|
||||
if (moreInputEnabled())
|
||||
if (flags & MORE_INPUT)
|
||||
{
|
||||
TableViewer::procBin(sharedObjs, binIn, dType);
|
||||
TableViewer::procIn(binIn, dType);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -141,33 +184,35 @@ void SearchChannels::procBin(const SharedObjs *sharedObjs, const QByteArray &bin
|
|||
}
|
||||
else if (!name.isEmpty())
|
||||
{
|
||||
TableViewer::procBin(sharedObjs, toTEXT("-" + QString(COLUMN_CHANNEL_NAME) + " " + name), dType);
|
||||
TableViewer::procIn(toTEXT("-" + QString(COLUMN_CHANNEL_NAME) + " " + name), dType);
|
||||
}
|
||||
else if (!chId.isEmpty())
|
||||
{
|
||||
TableViewer::procBin(sharedObjs, toTEXT("-" + QString(COLUMN_CHANNEL_ID) + " " + chId), dType);
|
||||
TableViewer::procIn(toTEXT("-" + QString(COLUMN_CHANNEL_ID) + " " + chId), dType);
|
||||
}
|
||||
else
|
||||
{
|
||||
TableViewer::procBin(sharedObjs, QByteArray(), dType);
|
||||
TableViewer::procIn(QByteArray(), dType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ListMembers::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void ListMembers::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
if (dType == TEXT)
|
||||
{
|
||||
if (moreInputEnabled())
|
||||
if (flags & MORE_INPUT)
|
||||
{
|
||||
TableViewer::procBin(sharedObjs, binIn, dType);
|
||||
TableViewer::procIn(binIn, dType);
|
||||
}
|
||||
else
|
||||
{
|
||||
QStringList args = parseArgs(binIn, 2);
|
||||
QStringList args = parseArgs(binIn, 6);
|
||||
QString chName = getParam("-ch_name", args);
|
||||
QString userFind = getParam("-find", args);
|
||||
QString userFind = getParam("-user_name", args);
|
||||
QString dispFind = getParam("-disp_name", args);
|
||||
quint64 chId;
|
||||
|
||||
if (chName.isEmpty())
|
||||
{
|
||||
|
@ -177,7 +222,11 @@ void ListMembers::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn,
|
|||
{
|
||||
errTxt("err: Invalid channel name.\n");
|
||||
}
|
||||
else if (channelAccessLevel(sharedObjs, chName) > REGULAR)
|
||||
else if (!channelExists(chName, &chId))
|
||||
{
|
||||
errTxt("err: Channel name '" + chName + "' does not exists.\n");
|
||||
}
|
||||
else if (channelAccessLevel(rdFromBlock(userId, BLKSIZE_USER_ID), chOwnerOverride, chId) > REGULAR)
|
||||
{
|
||||
errTxt("err: You are not currently a member of the channel: '" + chName + "'\n");
|
||||
}
|
||||
|
@ -187,21 +236,27 @@ void ListMembers::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn,
|
|||
|
||||
if (!userFind.isEmpty())
|
||||
{
|
||||
argsBa.append(" " + toTEXT("-" + QString(COLUMN_USERNAME) + " " + userFind));
|
||||
argsBa.append(toTEXT(" -" + QString(COLUMN_USERNAME) + " " + userFind));
|
||||
}
|
||||
|
||||
TableViewer::procBin(sharedObjs, argsBa, dType);
|
||||
if (!dispFind.isEmpty())
|
||||
{
|
||||
argsBa.append(toTEXT(" -" + QString(COLUMN_DISPLAY_NAME) + " " + dispFind));
|
||||
}
|
||||
|
||||
TableViewer::procIn(argsBa, dType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CreateChannel::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void CreateChannel::procIn(const QByteArray &binIn, uchar dType)
|
||||
{
|
||||
if (dType == TEXT)
|
||||
{
|
||||
QStringList args = parseArgs(binIn, 2);
|
||||
QString chName = getParam("-ch_name", args);
|
||||
quint64 chId;
|
||||
|
||||
if (chName.isEmpty())
|
||||
{
|
||||
|
@ -211,7 +266,7 @@ void CreateChannel::procBin(const SharedObjs *sharedObjs, const QByteArray &binI
|
|||
{
|
||||
errTxt("err: Invalid channel name. it must be between 4-32 chars long and contain no spaces.\n");
|
||||
}
|
||||
else if (channelExists(chName))
|
||||
else if (channelExists(chName, &chId))
|
||||
{
|
||||
errTxt("err: Channel name '" + chName + "' already exists.\n");
|
||||
}
|
||||
|
@ -223,34 +278,31 @@ void CreateChannel::procBin(const SharedObjs *sharedObjs, const QByteArray &binI
|
|||
db.addColumn(COLUMN_CHANNEL_NAME, chName);
|
||||
db.exec();
|
||||
|
||||
quint64 chId = getChId(chName);
|
||||
QByteArray uId = rdFromBlock(userId, BLKSIZE_USER_ID);
|
||||
QString uName = rdStringFromBlock(userName, BLKSIZE_USER_NAME);
|
||||
QString dName = rdStringFromBlock(displayName, BLKSIZE_DISP_NAME);
|
||||
|
||||
db.setType(Query::PUSH, TABLE_CH_MEMBERS);
|
||||
db.addColumn(COLUMN_CHANNEL_ID, chId);
|
||||
db.addColumn(COLUMN_USERNAME, *sharedObjs->userName);
|
||||
db.addColumn(COLUMN_CHANNEL_NAME, chName);
|
||||
db.addColumn(COLUMN_USER_ID, uId);
|
||||
db.addColumn(COLUMN_ACCESS_LEVEL, OWNER);
|
||||
db.addColumn(COLUMN_PENDING_INVITE, false);
|
||||
db.exec();
|
||||
|
||||
args.append("-user");
|
||||
args.append("'" + escapeChars(*sharedObjs->userName, '\\', '\'') + "'");
|
||||
args.append("-level");
|
||||
args.append(QString::number(OWNER));
|
||||
args.append("-ch_id");
|
||||
args.append(QString::number(chId));
|
||||
QByteArray frame = createChMemberAsyncFrame(chId, uId, false, OWNER, uName, dName, chName);
|
||||
|
||||
emit backendDataOut(ASYNC_NEW_CH_MEMBER, toTEXT(args.join(' ')), PUB_IPC_WITH_FEEDBACK);
|
||||
async(ASYNC_NEW_CH_MEMBER, PUB_IPC_WITH_FEEDBACK, frame);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveChannel::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void RemoveChannel::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
if (dType == TEXT)
|
||||
{
|
||||
QStringList args = parseArgs(binIn, 2);
|
||||
QString chName = getParam("-ch_name", args);
|
||||
quint64 chId;
|
||||
|
||||
if (chName.isEmpty())
|
||||
{
|
||||
|
@ -260,39 +312,35 @@ void RemoveChannel::procBin(const SharedObjs *sharedObjs, const QByteArray &binI
|
|||
{
|
||||
errTxt("err: Invalid channel name.\n");
|
||||
}
|
||||
else if (!channelExists(chName))
|
||||
else if (!channelExists(chName, &chId))
|
||||
{
|
||||
errTxt("err: Channel name '" + chName + "' does not exists.\n");
|
||||
}
|
||||
else if (channelAccessLevel(sharedObjs, chName) != OWNER)
|
||||
else if (channelAccessLevel(rdFromBlock(userId, BLKSIZE_USER_ID), chOwnerOverride, chId) != OWNER)
|
||||
{
|
||||
errTxt("err: Only the channel owner can delete it.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
quint64 id = getChId(chName);
|
||||
|
||||
Query db(this);
|
||||
|
||||
db.setType(Query::DEL, TABLE_CHANNELS);
|
||||
db.addCondition(COLUMN_CHANNEL_NAME, chName);
|
||||
db.addCondition(COLUMN_CHANNEL_ID, chId);
|
||||
db.exec();
|
||||
|
||||
args.append("-ch_id");
|
||||
args.append(QString::number(id));
|
||||
|
||||
emit backendDataOut(ASYNC_DEL_CH, toTEXT(args.join(' ')), PUB_IPC_WITH_FEEDBACK);
|
||||
async(ASYNC_DEL_CH, PUB_IPC_WITH_FEEDBACK, wrInt(chId, 64));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RenameChannel::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void RenameChannel::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
if (dType == TEXT)
|
||||
{
|
||||
QStringList args = parseArgs(binIn, 4);
|
||||
QString chName = getParam("-ch_name", args);
|
||||
QString newName = getParam("-new_name", args);
|
||||
quint64 chId;
|
||||
|
||||
if (chName.isEmpty())
|
||||
{
|
||||
|
@ -310,11 +358,11 @@ void RenameChannel::procBin(const SharedObjs *sharedObjs, const QByteArray &binI
|
|||
{
|
||||
errTxt("err: Invalid new channel name. it must be between 4-32 chars long and contain no spaces.\n");
|
||||
}
|
||||
else if (!channelExists(chName))
|
||||
else if (!channelExists(chName, &chId))
|
||||
{
|
||||
errTxt("err: Channel name '" + chName + "' does not exists.\n");
|
||||
}
|
||||
else if (channelAccessLevel(sharedObjs, chName) != OWNER)
|
||||
else if (channelAccessLevel(rdFromBlock(userId, BLKSIZE_USER_ID), chOwnerOverride, chId) != OWNER)
|
||||
{
|
||||
errTxt("err: Only the channel owner can rename it.\n");
|
||||
}
|
||||
|
@ -328,15 +376,17 @@ void RenameChannel::procBin(const SharedObjs *sharedObjs, const QByteArray &binI
|
|||
|
||||
db.setType(Query::UPDATE, TABLE_CHANNELS);
|
||||
db.addColumn(COLUMN_CHANNEL_NAME, newName);
|
||||
db.addCondition(COLUMN_CHANNEL_NAME, chName);
|
||||
db.addCondition(COLUMN_CHANNEL_ID, chId);
|
||||
db.exec();
|
||||
|
||||
emit backendDataOut(ASYNC_RENAME_CH, toTEXT(args.join(' ')), PUB_IPC_WITH_FEEDBACK);
|
||||
QByteArray frame = wrInt(chId, 64) + nullTermTEXT(newName);
|
||||
|
||||
async(ASYNC_RENAME_CH, PUB_IPC_WITH_FEEDBACK, frame);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SetActiveState::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void SetActiveState::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
if (dType == TEXT)
|
||||
{
|
||||
|
@ -344,6 +394,8 @@ void SetActiveState::procBin(const SharedObjs *sharedObjs, const QByteArray &bin
|
|||
QString chName = getParam("-ch_name", args);
|
||||
QString subName = getParam("-sub_name", args);
|
||||
QString state = getParam("-state", args);
|
||||
quint64 chId;
|
||||
quint8 subId;
|
||||
|
||||
if (chName.isEmpty())
|
||||
{
|
||||
|
@ -369,15 +421,15 @@ void SetActiveState::procBin(const SharedObjs *sharedObjs, const QByteArray &bin
|
|||
{
|
||||
errTxt("err: '" + state + "' is not a valid boolean value. it must be 0 or 1.\n");
|
||||
}
|
||||
else if (!channelExists(chName))
|
||||
else if (!channelExists(chName, &chId))
|
||||
{
|
||||
errTxt("err: Channel name '" + chName + "' does not exists.\n");
|
||||
}
|
||||
else if (channelAccessLevel(sharedObjs, chName) > ADMIN)
|
||||
else if (channelAccessLevel(rdFromBlock(userId, BLKSIZE_USER_ID), chOwnerOverride, chId) > ADMIN)
|
||||
{
|
||||
errTxt("err: Access denied.\n");
|
||||
}
|
||||
else if (!channelSubExists(chName, subName))
|
||||
else if (!channelSubExists(chId, subName, &subId))
|
||||
{
|
||||
errTxt("err: Sub-channel name '" + chName + "' does not exists.\n");
|
||||
}
|
||||
|
@ -387,8 +439,8 @@ void SetActiveState::procBin(const SharedObjs *sharedObjs, const QByteArray &bin
|
|||
|
||||
db.setType(Query::UPDATE, TABLE_SUB_CHANNELS);
|
||||
db.addColumn(COLUMN_ACTIVE_UPDATE, static_cast<bool>(state.toInt()));
|
||||
db.addCondition(COLUMN_CHANNEL_NAME, chName);
|
||||
db.addCondition(COLUMN_SUB_CH_NAME, subName);
|
||||
db.addCondition(COLUMN_CHANNEL_ID, chId);
|
||||
db.addCondition(COLUMN_SUB_CH_ID, subId);
|
||||
db.exec();
|
||||
|
||||
if (globalActiveFlag())
|
||||
|
@ -397,20 +449,21 @@ void SetActiveState::procBin(const SharedObjs *sharedObjs, const QByteArray &bin
|
|||
}
|
||||
else
|
||||
{
|
||||
emit backendDataOut(ASYNC_CH_ACT_FLAG, toTEXT(args.join(' ')), PUB_IPC_WITH_FEEDBACK);
|
||||
async(ASYNC_CH_ACT_FLAG, PUB_IPC_WITH_FEEDBACK, wrInt(chId, 64) + wrInt(subId, 8));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CreateSubCh::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void CreateSubCh::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
if (dType == TEXT)
|
||||
{
|
||||
QStringList args = parseArgs(binIn, 4);
|
||||
QString chName = getParam("-ch_name", args);
|
||||
QString subName = getParam("-sub_name", args);
|
||||
int subId = 0;
|
||||
quint64 chId;
|
||||
quint8 subId;
|
||||
|
||||
if (chName.isEmpty())
|
||||
{
|
||||
|
@ -428,56 +481,50 @@ void CreateSubCh::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn,
|
|||
{
|
||||
errTxt("err: Invalid sub-channel name. it must be between 4-32 chars long and contain no spaces.\n");
|
||||
}
|
||||
else if (!channelExists(chName))
|
||||
else if (!channelExists(chName, &chId))
|
||||
{
|
||||
errTxt("err: Channel name '" + chName + "' does not exists.\n");
|
||||
}
|
||||
else if (channelAccessLevel(sharedObjs, chName) > ADMIN)
|
||||
else if (channelAccessLevel(rdFromBlock(userId, BLKSIZE_USER_ID), chOwnerOverride, chId) > ADMIN)
|
||||
{
|
||||
errTxt("err: Access denied.\n");
|
||||
}
|
||||
else if (channelSubExists(chName, subName))
|
||||
else if (channelSubExists(chId, subName))
|
||||
{
|
||||
errTxt("err: Sub-channel name '" + subName + "' already exists.\n");
|
||||
}
|
||||
else if (!genSubId(chName, &subId))
|
||||
else if (!genSubId(chId, &subId))
|
||||
{
|
||||
errTxt("err: This channel has reached the maximum amount sub-channels it can have (" + QString::number(maxSubChannels()) + ").\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
quint64 chId = getChId(chName);
|
||||
|
||||
Query db(this);
|
||||
|
||||
db.setType(Query::PUSH, TABLE_SUB_CHANNELS);
|
||||
db.addColumn(COLUMN_SUB_CH_NAME, subName);
|
||||
db.addColumn(COLUMN_SUB_CH_ID, subId);
|
||||
db.addColumn(COLUMN_LOWEST_LEVEL, REGULAR);
|
||||
db.addColumn(COLUMN_CHANNEL_NAME, chName);
|
||||
db.addColumn(COLUMN_CHANNEL_ID, chId);
|
||||
db.addColumn(COLUMN_ACTIVE_UPDATE, false);
|
||||
db.exec();
|
||||
|
||||
args.append("-ch_id");
|
||||
args.append(QString::number(chId));
|
||||
args.append("-level");
|
||||
args.append(QString::number(REGULAR));
|
||||
args.append("-sub_id");
|
||||
args.append(QString::number(subId));
|
||||
QByteArray frame = wrInt(chId, 64) + wrInt(subId, 8) + wrInt(REGULAR, 8) + wrInt(0, 8) + nullTermTEXT(subName);
|
||||
|
||||
emit backendDataOut(ASYNC_NEW_SUB_CH, toTEXT(args.join(' ')), PUB_IPC_WITH_FEEDBACK);
|
||||
async(ASYNC_NEW_SUB_CH, PUB_IPC_WITH_FEEDBACK, frame);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveSubCh::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void RemoveSubCh::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
if (dType == TEXT)
|
||||
{
|
||||
QStringList args = parseArgs(binIn, 4);
|
||||
QString chName = getParam("-ch_name", args);
|
||||
QString subName = getParam("-sub_name", args);
|
||||
quint64 chId;
|
||||
quint8 subId;
|
||||
|
||||
if (chName.isEmpty())
|
||||
{
|
||||
|
@ -495,37 +542,33 @@ void RemoveSubCh::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn,
|
|||
{
|
||||
errTxt("err: Invalid sub-channel name.\n");
|
||||
}
|
||||
else if (channelAccessLevel(sharedObjs, chName) > ADMIN)
|
||||
else if (!channelExists(chName, &chId))
|
||||
{
|
||||
errTxt("err: Channel name '" + chName + "' does not exists.\n");
|
||||
}
|
||||
else if (channelAccessLevel(rdFromBlock(userId, BLKSIZE_USER_ID), chOwnerOverride, chId) > ADMIN)
|
||||
{
|
||||
errTxt("err: Access denied.\n");
|
||||
}
|
||||
else if (!channelSubExists(chName, subName))
|
||||
else if (!channelSubExists(chId, subName, &subId))
|
||||
{
|
||||
errTxt("err: Sub-channel name '" + subName + "' does not exists.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
quint64 chId = getChId(chName);
|
||||
uchar subId = getSubId(chName, subName);
|
||||
|
||||
Query db(this);
|
||||
|
||||
db.setType(Query::DEL, TABLE_SUB_CHANNELS);
|
||||
db.addCondition(COLUMN_CHANNEL_NAME, chName);
|
||||
db.addCondition(COLUMN_SUB_CH_NAME, subName);
|
||||
db.addCondition(COLUMN_CHANNEL_ID, chId);
|
||||
db.addCondition(COLUMN_SUB_CH_ID, subId);
|
||||
db.exec();
|
||||
|
||||
args.append("-ch_id");
|
||||
args.append(QString::number(chId));
|
||||
args.append("-sub_id");
|
||||
args.append(QString::number(subId));
|
||||
|
||||
emit backendDataOut(ASYNC_RM_SUB_CH, toTEXT(args.join(' ')), PUB_IPC_WITH_FEEDBACK);
|
||||
async(ASYNC_RM_SUB_CH, PUB_IPC_WITH_FEEDBACK, wrInt(chId, 64) + wrInt(subId, 8));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RenameSubCh::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void RenameSubCh::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
if (dType == TEXT)
|
||||
{
|
||||
|
@ -533,6 +576,8 @@ void RenameSubCh::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn,
|
|||
QString chName = getParam("-ch_name", args);
|
||||
QString subName = getParam("-sub_name", args);
|
||||
QString newName = getParam("-new_name", args);
|
||||
quint64 chId;
|
||||
quint8 subId;
|
||||
|
||||
if (chName.isEmpty())
|
||||
{
|
||||
|
@ -558,11 +603,15 @@ void RenameSubCh::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn,
|
|||
{
|
||||
errTxt("err: Invalid new sub-channel name. it must be between 4-32 chars long and contain no spaces.\n");
|
||||
}
|
||||
else if (channelAccessLevel(sharedObjs, chName) > ADMIN)
|
||||
else if (!channelExists(chName, &chId))
|
||||
{
|
||||
errTxt("err: Channel name '" + chName + "' does not exists.\n");
|
||||
}
|
||||
else if (channelAccessLevel(rdFromBlock(userId, BLKSIZE_USER_ID), chOwnerOverride, chId) > ADMIN)
|
||||
{
|
||||
errTxt("err: Access denied.\n");
|
||||
}
|
||||
else if (!channelSubExists(chName, subName))
|
||||
else if (!channelSubExists(chId, subName, &subId))
|
||||
{
|
||||
errTxt("err: Sub-channel name '" + subName + "' does not exists.\n");
|
||||
}
|
||||
|
@ -572,22 +621,26 @@ void RenameSubCh::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn,
|
|||
|
||||
db.setType(Query::UPDATE, TABLE_SUB_CHANNELS);
|
||||
db.addColumn(COLUMN_SUB_CH_NAME, newName);
|
||||
db.addCondition(COLUMN_SUB_CH_NAME, subName);
|
||||
db.addCondition(COLUMN_CHANNEL_NAME, chName);
|
||||
db.addCondition(COLUMN_CHANNEL_ID, chId);
|
||||
db.addCondition(COLUMN_SUB_CH_ID, subId);
|
||||
db.exec();
|
||||
|
||||
emit backendDataOut(ASYNC_RENAME_SUB_CH, toTEXT(args.join(' ')), PUB_IPC_WITH_FEEDBACK);
|
||||
QByteArray frame = wrInt(chId, 64) + wrInt(subId, 8) + nullTermTEXT(newName);
|
||||
|
||||
async(ASYNC_RENAME_SUB_CH, PUB_IPC_WITH_FEEDBACK, frame);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InviteToCh::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void InviteToCh::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
if (dType == TEXT)
|
||||
{
|
||||
QStringList args = parseArgs(binIn, 4);
|
||||
QString chName = getParam("-ch_name", args);
|
||||
QString uName = getParam("-user", args);
|
||||
QByteArray uId;
|
||||
quint64 chId;
|
||||
|
||||
if (chName.isEmpty())
|
||||
{
|
||||
|
@ -605,23 +658,23 @@ void InviteToCh::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn,
|
|||
{
|
||||
errTxt("err: Invalid user name.\n");
|
||||
}
|
||||
else if (!channelExists(chName))
|
||||
else if (!channelExists(chName, &chId))
|
||||
{
|
||||
errTxt("err: Channel name '" + chName + "' does not exists.\n");
|
||||
}
|
||||
else if (!userExists(uName))
|
||||
else if (!userExists(uName, &uId))
|
||||
{
|
||||
errTxt("err: User name '" + uName + "' does not exists.\n");
|
||||
}
|
||||
else if (channelAccessLevel(sharedObjs, chName) > OFFICER)
|
||||
else if (channelAccessLevel(rdFromBlock(userId, BLKSIZE_USER_ID), chOwnerOverride, chId) > OFFICER)
|
||||
{
|
||||
errTxt("err: Access denied.\n");
|
||||
}
|
||||
else if (inviteExists(uName, chName))
|
||||
else if (inviteExists(uId, chId))
|
||||
{
|
||||
errTxt("err: User name '" + uName + "' already has an invitation to channel '" + chName + ".'\n");
|
||||
}
|
||||
else if (channelAccessLevel(uName, chName) < PUBLIC)
|
||||
else if (channelAccessLevel(uId, chId) < PUBLIC)
|
||||
{
|
||||
errTxt("err: User name '" + uName + "' is already a member of the requested channel '" + chName + ".'\n");
|
||||
}
|
||||
|
@ -630,34 +683,36 @@ void InviteToCh::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn,
|
|||
Query db(this);
|
||||
|
||||
db.setType(Query::PUSH, TABLE_CH_MEMBERS);
|
||||
db.addColumn(COLUMN_USERNAME, uName);
|
||||
db.addColumn(COLUMN_CHANNEL_NAME, chName);
|
||||
db.addColumn(COLUMN_CHANNEL_ID, getChId(chName));
|
||||
db.addColumn(COLUMN_USER_ID, uId);
|
||||
db.addColumn(COLUMN_CHANNEL_ID, chId);
|
||||
db.addColumn(COLUMN_PENDING_INVITE, true);
|
||||
db.addColumn(COLUMN_ACCESS_LEVEL, REGULAR);
|
||||
db.exec();
|
||||
|
||||
emit backendDataOut(ASYNC_INVITED_TO_CH, toTEXT(args.join(' ')), PUB_IPC_WITH_FEEDBACK);
|
||||
QByteArray frame = createChMemberAsyncFrame(chId, uId, true, REGULAR, uName, getDispName(uId), chName);
|
||||
|
||||
async(ASYNC_INVITED_TO_CH, PUB_IPC_WITH_FEEDBACK, frame);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeclineChInvite::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void DeclineChInvite::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
if (dType == TEXT)
|
||||
{
|
||||
QStringList args = parseArgs(binIn, 2);
|
||||
QString chName = getParam("-ch_name", args);
|
||||
quint64 chId;
|
||||
|
||||
if (chName.isEmpty())
|
||||
{
|
||||
errTxt("err: The channel name (-ch_name) argument was not found or is empty.\n");
|
||||
}
|
||||
else if (!channelExists(chName))
|
||||
else if (!channelExists(chName, &chId))
|
||||
{
|
||||
errTxt("err: Channel name '" + chName + "' does not exists.\n");
|
||||
}
|
||||
else if (!inviteExists(*sharedObjs->userName, chName))
|
||||
else if (!inviteExists(rdFromBlock(userId, BLKSIZE_USER_ID), chId))
|
||||
{
|
||||
errTxt("err: You don't currently have an invitation to channel '" + chName + ".'\n");
|
||||
}
|
||||
|
@ -666,36 +721,32 @@ void DeclineChInvite::procBin(const SharedObjs *sharedObjs, const QByteArray &bi
|
|||
Query db(this);
|
||||
|
||||
db.setType(Query::DEL, TABLE_CH_MEMBERS);
|
||||
db.addCondition(COLUMN_CHANNEL_NAME, chName);
|
||||
db.addCondition(COLUMN_USERNAME, *sharedObjs->userName);
|
||||
db.addCondition(COLUMN_CHANNEL_ID, chId);
|
||||
db.addCondition(COLUMN_USER_ID, rdFromBlock(userId, BLKSIZE_USER_ID));
|
||||
db.exec();
|
||||
|
||||
args.append("-ch_id");
|
||||
args.append(QString::number(getChId(chName)));
|
||||
args.append("-user");
|
||||
args.append("'" + escapeChars(*sharedObjs->userName, '\\', '\'') + "'");
|
||||
|
||||
emit backendDataOut(ASYNC_RM_CH_MEMBER, toTEXT(args.join(' ')), PUB_IPC_WITH_FEEDBACK);
|
||||
async(ASYNC_RM_CH_MEMBER, PUB_IPC_WITH_FEEDBACK, wrInt(chId, 64) + rdFromBlock(userId, BLKSIZE_USER_ID));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AcceptChInvite::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void AcceptChInvite::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
if (dType == TEXT)
|
||||
{
|
||||
QStringList args = parseArgs(binIn, 2);
|
||||
QString chName = getParam("-ch_name", args);
|
||||
quint64 chId;
|
||||
|
||||
if (chName.isEmpty())
|
||||
{
|
||||
errTxt("err: The channel name (-ch_name) argument was not found or is empty.\n");
|
||||
}
|
||||
else if (!channelExists(chName))
|
||||
else if (!channelExists(chName, &chId))
|
||||
{
|
||||
errTxt("err: Channel name '" + chName + "' does not exists.\n");
|
||||
}
|
||||
else if (!inviteExists(*sharedObjs->userName, chName))
|
||||
else if (!inviteExists(rdFromBlock(userId, BLKSIZE_USER_ID), chId))
|
||||
{
|
||||
errTxt("err: You don't currently have an invitation to channel '" + chName + ".'\n");
|
||||
}
|
||||
|
@ -705,25 +756,52 @@ void AcceptChInvite::procBin(const SharedObjs *sharedObjs, const QByteArray &bin
|
|||
|
||||
db.setType(Query::UPDATE, TABLE_CH_MEMBERS);
|
||||
db.addColumn(COLUMN_PENDING_INVITE, false);
|
||||
db.addCondition(COLUMN_CHANNEL_NAME, chName);
|
||||
db.addCondition(COLUMN_USERNAME, *sharedObjs->userName);
|
||||
db.addCondition(COLUMN_CHANNEL_ID, chId);
|
||||
db.addCondition(COLUMN_USER_ID, rdFromBlock(userId, BLKSIZE_USER_ID));
|
||||
db.exec();
|
||||
|
||||
args.append("-user");
|
||||
args.append("'" + escapeChars(*sharedObjs->userName, '\\', '\'') + "'");
|
||||
|
||||
emit backendDataOut(ASYNC_INVITE_ACCEPTED, toTEXT(args.join(' ')), PUB_IPC_WITH_FEEDBACK);
|
||||
async(ASYNC_INVITE_ACCEPTED, PUB_IPC_WITH_FEEDBACK, wrInt(chId, 64) + rdFromBlock(userId, BLKSIZE_USER_ID));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveChMember::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
bool RemoveChMember::allowMemberDel(const QByteArray &uId, quint64 chId)
|
||||
{
|
||||
QByteArray myId = rdFromBlock(userId, BLKSIZE_USER_ID);
|
||||
bool ret = false;
|
||||
bool leaving = (uId == myId);
|
||||
int targetLevel = channelAccessLevel(uId, chId);
|
||||
int myLevel = channelAccessLevel(myId, chOwnerOverride, BLKSIZE_USER_ID);
|
||||
|
||||
if (leaving && (myLevel == OWNER))
|
||||
{
|
||||
errTxt("err: The channel owner cannot leave the channel. please assign a new owner before doing so.\n");
|
||||
}
|
||||
else if (targetLevel == PUBLIC)
|
||||
{
|
||||
errTxt("err: The target user is not a member of the channel.\n");
|
||||
}
|
||||
else if (leaving)
|
||||
{
|
||||
ret = myLevel != PUBLIC;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = myLevel < targetLevel;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void RemoveChMember::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
if (dType == TEXT)
|
||||
{
|
||||
QStringList args = parseArgs(binIn, 4);
|
||||
QString chName = getParam("-ch_name", args);
|
||||
QString uName = getParam("-user", args);
|
||||
QByteArray uId;
|
||||
quint64 chId;
|
||||
|
||||
if (chName.isEmpty())
|
||||
{
|
||||
|
@ -741,38 +819,41 @@ void RemoveChMember::procBin(const SharedObjs *sharedObjs, const QByteArray &bin
|
|||
{
|
||||
errTxt("err: Invalid user name.\n");
|
||||
}
|
||||
else if (!channelExists(chName))
|
||||
else if (!channelExists(chName, &chId))
|
||||
{
|
||||
errTxt("err: Channel name '" + chName + "' does not exists.\n");
|
||||
}
|
||||
else if (!userExists(uName))
|
||||
else if (!userExists(uName, &uId))
|
||||
{
|
||||
errTxt("err: User name '" + uName + "' does not exists.\n");
|
||||
}
|
||||
else if (!allowMemberDel(sharedObjs, uName, chName))
|
||||
else if (!allowMemberDel(uId, chId))
|
||||
{
|
||||
errTxt("err: Access denied.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
quint64 id = getChId(chName);
|
||||
|
||||
Query db(this);
|
||||
|
||||
db.setType(Query::DEL, TABLE_CH_MEMBERS);
|
||||
db.addCondition(COLUMN_CHANNEL_NAME, chName);
|
||||
db.addCondition(COLUMN_USERNAME, uName);
|
||||
db.addCondition(COLUMN_CHANNEL_ID, chId);
|
||||
db.addCondition(COLUMN_USER_ID, uId);
|
||||
db.exec();
|
||||
|
||||
args.append("-ch_id");
|
||||
args.append(QString::number(id));
|
||||
|
||||
emit backendDataOut(ASYNC_RM_CH_MEMBER, toTEXT(args.join(' ')), PUB_IPC_WITH_FEEDBACK);
|
||||
async(ASYNC_RM_CH_MEMBER, PUB_IPC_WITH_FEEDBACK, wrInt(chId, 64) + uId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SetMemberLevel::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
bool SetMemberLevel::allowLevelChange(const QByteArray &uId, int newLevel, quint64 chId)
|
||||
{
|
||||
int targetLevel = channelAccessLevel(uId, chId);
|
||||
int myLevel = channelAccessLevel(rdFromBlock(userId, BLKSIZE_USER_ID), chOwnerOverride, BLKSIZE_USER_ID);
|
||||
|
||||
return (newLevel >= myLevel) && (targetLevel > myLevel);
|
||||
}
|
||||
|
||||
void SetMemberLevel::procIn(const QByteArray &binIn, uchar dType)
|
||||
{
|
||||
if (dType == TEXT)
|
||||
{
|
||||
|
@ -780,6 +861,8 @@ void SetMemberLevel::procBin(const SharedObjs *sharedObjs, const QByteArray &bin
|
|||
QString chName = getParam("-ch_name", args);
|
||||
QString uName = getParam("-user", args);
|
||||
QString level = getParam("-level", args);
|
||||
quint64 chId;
|
||||
QByteArray uId;
|
||||
|
||||
if (chName.isEmpty())
|
||||
{
|
||||
|
@ -805,72 +888,54 @@ void SetMemberLevel::procBin(const SharedObjs *sharedObjs, const QByteArray &bin
|
|||
{
|
||||
errTxt("err: Invalid privilege level. it must be an integer between 1-4.\n");
|
||||
}
|
||||
else if (!channelExists(chName))
|
||||
else if (!channelExists(chName, &chId))
|
||||
{
|
||||
errTxt("err: Channel name '" + chName + "' does not exists.\n");
|
||||
}
|
||||
else if (!userExists(uName))
|
||||
else if (!userExists(uName, &uId))
|
||||
{
|
||||
errTxt("err: User name '" + uName + "' does not exists.\n");
|
||||
}
|
||||
else if (!allowLevelChange(sharedObjs, level.toInt(), chName))
|
||||
else if (!allowLevelChange(uId, level.toInt(), chId))
|
||||
{
|
||||
errTxt("err: Access denied.\n");
|
||||
}
|
||||
else if (channelAccessLevel(uName, chName) < PUBLIC)
|
||||
{
|
||||
errTxt("err: The target user '" + uName + "' is not a member of the channel.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
quint64 id = getChId(chName);
|
||||
|
||||
Query db(this);
|
||||
|
||||
db.setType(Query::PULL, TABLE_CH_MEMBERS);
|
||||
db.addColumn(COLUMN_USERNAME);
|
||||
db.addColumn(COLUMN_USER_ID);
|
||||
db.addCondition(COLUMN_ACCESS_LEVEL, OWNER);
|
||||
db.addCondition(COLUMN_CHANNEL_NAME, chName);
|
||||
db.addCondition(COLUMN_CHANNEL_ID, chId);
|
||||
db.exec();
|
||||
|
||||
QString owner = db.getData(COLUMN_USERNAME).toString();
|
||||
int newLevel = level.toInt();
|
||||
QByteArray owner = db.getData(COLUMN_USER_ID).toByteArray();
|
||||
|
||||
db.setType(Query::UPDATE, TABLE_CH_MEMBERS);
|
||||
db.addColumn(COLUMN_ACCESS_LEVEL, level.toInt());
|
||||
db.addCondition(COLUMN_CHANNEL_NAME, chName);
|
||||
db.addCondition(COLUMN_USERNAME, uName);
|
||||
db.addColumn(COLUMN_ACCESS_LEVEL, newLevel);
|
||||
db.addCondition(COLUMN_CHANNEL_ID, chId);
|
||||
db.addCondition(COLUMN_USER_ID, uId);
|
||||
db.exec();
|
||||
|
||||
args.append("-ch_id");
|
||||
args.append(QString::number(id));
|
||||
|
||||
emit backendDataOut(ASYNC_MEM_LEVEL_CHANGED, toTEXT(args.join(' ')), PUB_IPC_WITH_FEEDBACK);
|
||||
async(ASYNC_MEM_LEVEL_CHANGED, PUB_IPC_WITH_FEEDBACK, wrInt(chId, 64) + uId + wrInt(newLevel, 8));
|
||||
|
||||
if (level.toInt() == OWNER)
|
||||
{
|
||||
db.setType(Query::UPDATE, TABLE_CH_MEMBERS);
|
||||
db.addColumn(COLUMN_ACCESS_LEVEL, ADMIN);
|
||||
db.addCondition(COLUMN_CHANNEL_NAME, chName);
|
||||
db.addCondition(COLUMN_USERNAME, owner);
|
||||
db.addCondition(COLUMN_CHANNEL_ID, chId);
|
||||
db.addCondition(COLUMN_USER_ID, owner);
|
||||
db.exec();
|
||||
|
||||
args.clear();
|
||||
args.append("-user");
|
||||
args.append("'" + escapeChars(owner, '\\', '\'') + "'");
|
||||
args.append("-ch_name");
|
||||
args.append("'" + escapeChars(chName, '\\', '\'') + "'");
|
||||
args.append("-ch_id");
|
||||
args.append(QString::number(id));
|
||||
args.append("-level");
|
||||
args.append(QString::number(ADMIN));
|
||||
|
||||
emit backendDataOut(ASYNC_MEM_LEVEL_CHANGED, toTEXT(args.join(' ')), PUB_IPC_WITH_FEEDBACK);
|
||||
async(ASYNC_MEM_LEVEL_CHANGED, PUB_IPC_WITH_FEEDBACK, wrInt(chId, 64) + owner + wrInt(ADMIN, 8));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SetSubAcessLevel::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void SetSubAcessLevel::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
if (dType == TEXT)
|
||||
{
|
||||
|
@ -878,6 +943,8 @@ void SetSubAcessLevel::procBin(const SharedObjs *sharedObjs, const QByteArray &b
|
|||
QString chName = getParam("-ch_name", args);
|
||||
QString subName = getParam("-sub_name", args);
|
||||
QString level = getParam("-level", args);
|
||||
quint64 chId;
|
||||
quint8 subId;
|
||||
|
||||
if (chName.isEmpty())
|
||||
{
|
||||
|
@ -903,41 +970,35 @@ void SetSubAcessLevel::procBin(const SharedObjs *sharedObjs, const QByteArray &b
|
|||
{
|
||||
errTxt("err: Invalid privilege level. it must be an integer between 1-5.\n");
|
||||
}
|
||||
else if (channelAccessLevel(sharedObjs, chName) > ADMIN)
|
||||
else if (!channelExists(chName, &chId))
|
||||
{
|
||||
errTxt("err: Channel name '" + chName + "' does not exists.\n");
|
||||
}
|
||||
else if (channelAccessLevel(rdFromBlock(userId, BLKSIZE_USER_ID), chOwnerOverride, chId) > ADMIN)
|
||||
{
|
||||
errTxt("err: Access denied.\n");
|
||||
}
|
||||
else if (!channelSubExists(chName, subName))
|
||||
else if (!channelSubExists(chId, subName, &subId))
|
||||
{
|
||||
errTxt("err: Sub-channel name '" + subName + "' does not exists.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
quint64 chId = getChId(chName);
|
||||
uchar subId = getSubId(chName, subName);
|
||||
|
||||
Query db(this);
|
||||
|
||||
db.setType(Query::UPDATE, TABLE_SUB_CHANNELS);
|
||||
db.addColumn(COLUMN_LOWEST_LEVEL, level.toInt());
|
||||
db.addCondition(COLUMN_SUB_CH_NAME, subName);
|
||||
db.addCondition(COLUMN_CHANNEL_NAME, chName);
|
||||
db.addCondition(COLUMN_SUB_CH_ID, subId);
|
||||
db.addCondition(COLUMN_CHANNEL_ID, chId);
|
||||
db.exec();
|
||||
|
||||
args.append("-ch_id");
|
||||
args.append(QString::number(chId));
|
||||
args.append("-sub_id");
|
||||
args.append(QString::number(subId));
|
||||
|
||||
emit backendDataOut(ASYNC_SUB_CH_LEVEL_CHG, toTEXT(args.join(' ')), PUB_IPC_WITH_FEEDBACK);
|
||||
async(ASYNC_SUB_CH_LEVEL_CHG, PUB_IPC_WITH_FEEDBACK, wrInt(chId, 64) + wrInt(subId, 8) + wrInt(level.toInt(), 8));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OwnerOverride::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void OwnerOverride::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
Q_UNUSED(sharedObjs);
|
||||
|
||||
if (dType == TEXT)
|
||||
{
|
||||
QStringList args = parseArgs(binIn, 2);
|
||||
|
@ -953,7 +1014,7 @@ void OwnerOverride::procBin(const SharedObjs *sharedObjs, const QByteArray &binI
|
|||
}
|
||||
else
|
||||
{
|
||||
*rwSharedObjs->chOwnerOverride = state.toInt();
|
||||
wr8BitToBlock(static_cast<quint8>(state.toUInt()), chOwnerOverride);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,9 +18,12 @@
|
|||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "../common.h"
|
||||
#include "../cmd_object.h"
|
||||
#include "table_viewer.h"
|
||||
|
||||
class CreateChannel : public InternCommand
|
||||
QByteArray createChMemberAsyncFrame(quint64 chId, const QByteArray &userId, bool invite, quint8 level, const QString &userName, const QString &dispName, const QString &chName);
|
||||
|
||||
class CreateChannel : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -28,14 +31,14 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, uchar dType);
|
||||
|
||||
explicit CreateChannel(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//-----------------------
|
||||
|
||||
class RemoveChannel : public InternCommand
|
||||
class RemoveChannel : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -43,14 +46,14 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit RemoveChannel(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//----------------------
|
||||
|
||||
class RenameChannel : public InternCommand
|
||||
class RenameChannel : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -58,14 +61,14 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit RenameChannel(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//------------------------
|
||||
|
||||
class SetActiveState : public InternCommand
|
||||
class SetActiveState : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -73,14 +76,14 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit SetActiveState(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//-------------------------
|
||||
|
||||
class CreateSubCh : public InternCommand
|
||||
class CreateSubCh : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -88,14 +91,14 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit CreateSubCh(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//-------------------------
|
||||
|
||||
class RemoveSubCh : public InternCommand
|
||||
class RemoveSubCh : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -103,14 +106,14 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit RemoveSubCh(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//--------------------------
|
||||
|
||||
class RenameSubCh : public InternCommand
|
||||
class RenameSubCh : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -118,7 +121,7 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit RenameSubCh(QObject *parent = nullptr);
|
||||
};
|
||||
|
@ -133,7 +136,7 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit ListSubCh(QObject *parent = nullptr);
|
||||
};
|
||||
|
@ -148,7 +151,7 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit ListChannels(QObject *parent = nullptr);
|
||||
};
|
||||
|
@ -163,14 +166,14 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit SearchChannels(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//------------------------------
|
||||
|
||||
class InviteToCh : public InternCommand
|
||||
class InviteToCh : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -178,14 +181,14 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit InviteToCh(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//-------------------------------
|
||||
|
||||
class DeclineChInvite : public InternCommand
|
||||
class DeclineChInvite : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -193,14 +196,14 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit DeclineChInvite(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//-------------------------------
|
||||
|
||||
class AcceptChInvite : public InternCommand
|
||||
class AcceptChInvite : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -208,44 +211,48 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit AcceptChInvite(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//------------------------------
|
||||
|
||||
class RemoveChMember : public InternCommand
|
||||
class RemoveChMember : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
bool allowMemberDel(const QByteArray &uId, quint64 chId);
|
||||
|
||||
public:
|
||||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit RemoveChMember(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//------------------------------
|
||||
|
||||
class SetMemberLevel : public InternCommand
|
||||
class SetMemberLevel : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
bool allowLevelChange(const QByteArray &uId, int newLevel, quint64 chId);
|
||||
|
||||
public:
|
||||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, uchar dType);
|
||||
|
||||
explicit SetMemberLevel(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//------------------------------
|
||||
|
||||
class SetSubAcessLevel : public InternCommand
|
||||
class SetSubAcessLevel : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -253,7 +260,7 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit SetSubAcessLevel(QObject *parent = nullptr);
|
||||
};
|
||||
|
@ -268,14 +275,14 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit ListMembers(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//-----------------------------
|
||||
|
||||
class OwnerOverride : public InternCommand
|
||||
class OwnerOverride : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -283,7 +290,7 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit OwnerOverride(QObject *parent = nullptr);
|
||||
};
|
||||
|
|
|
@ -16,26 +16,42 @@
|
|||
// along with MRCI under the LICENSE.md file. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
LsCmdRanks::LsCmdRanks(QObject *parent) : TableViewer(parent)
|
||||
bool commandHasRank(const QString &mod, const QString &cmdName)
|
||||
{
|
||||
setParams(TABLE_CMD_RANKS, QStringList() << COLUMN_COMMAND << COLUMN_HOST_RANK, false);
|
||||
Query db;
|
||||
|
||||
db.setType(Query::PULL, TABLE_CMD_RANKS);
|
||||
db.addColumn(COLUMN_COMMAND);
|
||||
db.addCondition(COLUMN_MOD_MAIN, mod);
|
||||
db.addCondition(COLUMN_COMMAND, cmdName);
|
||||
db.exec();
|
||||
|
||||
return db.rows();
|
||||
}
|
||||
|
||||
AssignCmdRank::AssignCmdRank(QObject *parent) : InternCommand(parent) {}
|
||||
RemoveCmdRank::RemoveCmdRank(QObject *parent) : InternCommand(parent) {}
|
||||
LsCmdRanks::LsCmdRanks(QObject *parent) : TableViewer(parent)
|
||||
{
|
||||
setParams(TABLE_CMD_RANKS, false);
|
||||
|
||||
addTableColumn(TABLE_CMD_RANKS, COLUMN_MOD_MAIN);
|
||||
addTableColumn(TABLE_CMD_RANKS, COLUMN_COMMAND);
|
||||
addTableColumn(TABLE_CMD_RANKS, COLUMN_HOST_RANK);
|
||||
}
|
||||
|
||||
AssignCmdRank::AssignCmdRank(QObject *parent) : CmdObject(parent) {}
|
||||
RemoveCmdRank::RemoveCmdRank(QObject *parent) : CmdObject(parent) {}
|
||||
|
||||
QString LsCmdRanks::cmdName() {return "ls_ranked_cmds";}
|
||||
QString AssignCmdRank::cmdName() {return "add_ranked_cmd";}
|
||||
QString RemoveCmdRank::cmdName() {return "rm_ranked_cmd";}
|
||||
|
||||
void AssignCmdRank::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void AssignCmdRank::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
Q_UNUSED(sharedObjs);
|
||||
|
||||
if (dType == TEXT)
|
||||
{
|
||||
QStringList args = parseArgs(binIn, 4);
|
||||
QStringList args = parseArgs(binIn, 6);
|
||||
QString cmdName = getParam("-command", args);
|
||||
QString mod = getParam("-mod", args);
|
||||
QString rank = getParam("-rank", args);
|
||||
|
||||
if (cmdName.isEmpty())
|
||||
|
@ -48,15 +64,19 @@ void AssignCmdRank::procBin(const SharedObjs *sharedObjs, const QByteArray &binI
|
|||
}
|
||||
else if (!isInt(rank))
|
||||
{
|
||||
errTxt("err: The given rank is not a valid unsigned integer.\n");
|
||||
errTxt("err: The given rank is not a valid 32bit unsigned integer.\n");
|
||||
}
|
||||
else if (!validCommandName(cmdName))
|
||||
{
|
||||
errTxt("err: Invalid command name. it must be 1-64 chars long and can only contain letters, numbers, '_' or '?'.\n");
|
||||
errTxt("err: Invalid command name. it must be 1-64 chars long and contain no spaces.\n");
|
||||
}
|
||||
else if (commandHasRank(cmdName))
|
||||
else if (!validModPath(mod))
|
||||
{
|
||||
errTxt("err: The given command name already has an assigned rank.\n");
|
||||
errTxt("err: Invalid module path. it cannot contain any of the following chars '|*:\"?<>'\n");
|
||||
}
|
||||
else if (commandHasRank(mod, cmdName))
|
||||
{
|
||||
errTxt("err: The given mod - command name combo already has an assigned rank.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -64,22 +84,22 @@ void AssignCmdRank::procBin(const SharedObjs *sharedObjs, const QByteArray &binI
|
|||
|
||||
db.setType(Query::PUSH, TABLE_CMD_RANKS);
|
||||
db.addColumn(COLUMN_COMMAND, cmdName);
|
||||
db.addColumn(COLUMN_MOD_MAIN, mod);
|
||||
db.addColumn(COLUMN_HOST_RANK, rank.toUInt());
|
||||
db.exec();
|
||||
|
||||
emit backendDataOut(ASYNC_CMD_RANKS_CHANGED, QByteArray(), PUB_IPC_WITH_FEEDBACK);
|
||||
async(ASYNC_CMD_RANKS_CHANGED, PUB_IPC_WITH_FEEDBACK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveCmdRank::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void RemoveCmdRank::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
Q_UNUSED(sharedObjs);
|
||||
|
||||
if (dType == TEXT)
|
||||
{
|
||||
QStringList args = parseArgs(binIn, 2);
|
||||
QStringList args = parseArgs(binIn, 4);
|
||||
QString cmdName = getParam("-command", args);
|
||||
QString mod = getParam("-mod", args);
|
||||
|
||||
if (cmdName.isEmpty())
|
||||
{
|
||||
|
@ -89,9 +109,13 @@ void RemoveCmdRank::procBin(const SharedObjs *sharedObjs, const QByteArray &binI
|
|||
{
|
||||
errTxt("err: Invalid command name.\n");
|
||||
}
|
||||
else if (!commandHasRank(cmdName))
|
||||
else if (!validModPath(mod))
|
||||
{
|
||||
errTxt("err: The given command name does not have an assigned rank.\n");
|
||||
errTxt("err: Invalid module path.\n");
|
||||
}
|
||||
else if (!commandHasRank(mod, cmdName))
|
||||
{
|
||||
errTxt("err: The given mod - command name combo does not have an assigned rank.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -99,9 +123,10 @@ void RemoveCmdRank::procBin(const SharedObjs *sharedObjs, const QByteArray &binI
|
|||
|
||||
db.setType(Query::DEL, TABLE_CMD_RANKS);
|
||||
db.addCondition(COLUMN_COMMAND, cmdName);
|
||||
db.addCondition(COLUMN_MOD_MAIN, mod);
|
||||
db.exec();
|
||||
|
||||
emit backendDataOut(ASYNC_CMD_RANKS_CHANGED, QByteArray(), PUB_IPC_WITH_FEEDBACK);
|
||||
async(ASYNC_CMD_RANKS_CHANGED, PUB_IPC_WITH_FEEDBACK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,8 +18,11 @@
|
|||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "../common.h"
|
||||
#include "../cmd_object.h"
|
||||
#include "table_viewer.h"
|
||||
|
||||
bool commandHasRank(const QString &mod, const QString &cmdName);
|
||||
|
||||
class LsCmdRanks : public TableViewer
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -33,7 +36,7 @@ public:
|
|||
|
||||
//------------------------
|
||||
|
||||
class AssignCmdRank : public InternCommand
|
||||
class AssignCmdRank : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -41,14 +44,14 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit AssignCmdRank(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//------------------------
|
||||
|
||||
class RemoveCmdRank : public InternCommand
|
||||
class RemoveCmdRank : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -56,7 +59,7 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit RemoveCmdRank(QObject *parent = nullptr);
|
||||
};
|
||||
|
|
|
@ -1,105 +0,0 @@
|
|||
#include "cmd_state.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/>.
|
||||
|
||||
Term::Term(QObject *parent) : InternCommand(parent) {}
|
||||
Pause::Pause(QObject *parent) : InternCommand(parent) {}
|
||||
Resume::Resume(QObject *parent) : InternCommand(parent) {}
|
||||
|
||||
QString Term::cmdName() {return "term";}
|
||||
QString Pause::cmdName() {return "pause";}
|
||||
QString Resume::cmdName() {return "resume";}
|
||||
|
||||
void Term::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
{
|
||||
if (dType == CMD_ID)
|
||||
{
|
||||
if (binIn.isEmpty())
|
||||
{
|
||||
emit termAllCommands();
|
||||
}
|
||||
else
|
||||
{
|
||||
auto cmdId = static_cast<quint16>(rdInt(binIn));
|
||||
|
||||
if (!sharedObjs->cmdNames->contains(cmdId))
|
||||
{
|
||||
errTxt("err: No such command id: '" + QString::number(cmdId) + "'\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
emit termCommandId(cmdId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Pause::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
{
|
||||
if (dType == CMD_ID)
|
||||
{
|
||||
if (binIn.isEmpty())
|
||||
{
|
||||
*rwSharedObjs->pausedCmds = *rwSharedObjs->activeLoopCmds;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto cmdId = static_cast<quint16>(rdInt(binIn));
|
||||
|
||||
if (!sharedObjs->cmdNames->contains(cmdId))
|
||||
{
|
||||
errTxt("err: No such command id: '" + QString::number(cmdId) + "'\n");
|
||||
}
|
||||
else if (!sharedObjs->activeLoopCmds->contains(cmdId))
|
||||
{
|
||||
errTxt("err: The command is not currently in a loop state.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
uniqueAdd(cmdId, *rwSharedObjs->pausedCmds);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Resume::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
{
|
||||
if (dType == CMD_ID)
|
||||
{
|
||||
if (binIn.isEmpty())
|
||||
{
|
||||
rwSharedObjs->pausedCmds->clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
auto cmdId = static_cast<quint16>(rdInt(binIn));
|
||||
|
||||
if (!sharedObjs->cmdNames->contains(cmdId))
|
||||
{
|
||||
errTxt("err: No such command id: '" + QString::number(cmdId) + "'\n");
|
||||
}
|
||||
else if (!sharedObjs->pausedCmds->contains(cmdId))
|
||||
{
|
||||
errTxt("err: The command is not currently in a paused state.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
rwSharedObjs->pausedCmds->removeAll(cmdId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
#ifndef CMD_STATE_H
|
||||
#define CMD_STATE_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"
|
||||
|
||||
class Term : public InternCommand
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
|
||||
explicit Term(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//-----------------------
|
||||
|
||||
class Pause : public InternCommand
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
|
||||
explicit Pause(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//----------------------
|
||||
|
||||
class Resume : public InternCommand
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
|
||||
explicit Resume(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
#endif // CMD_STATE_H
|
|
@ -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);
|
||||
}
|
|
@ -1,163 +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
|
||||
|
||||
#include <QObject>
|
||||
#include <QTextCodec>
|
||||
#include <QHash>
|
||||
|
||||
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 errState();
|
||||
virtual bool handlesGenfile() {return false;}
|
||||
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;}
|
||||
};
|
||||
|
||||
#endif // EXTERN_COMMAND_H
|
|
@ -16,16 +16,63 @@
|
|||
// along with MRCI under the LICENSE.md file. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
DownloadFile::DownloadFile(QObject *parent) : InternCommand(parent) {file = new QFile(this);}
|
||||
UploadFile::UploadFile(QObject *parent) : InternCommand(parent) {file = new QFile(this);}
|
||||
Delete::Delete(QObject *parent) : InternCommand(parent) {}
|
||||
Copy::Copy(QObject *parent) : InternCommand(parent) {src = new QFile(this); dst = new QFile(this);}
|
||||
QByteArray toFILE_INFO(const QFileInfo &info)
|
||||
{
|
||||
// this function converts some information extracted from a QFileInfo object to
|
||||
// a FILE_INFO frame.
|
||||
|
||||
// format: [1byte(flags)][8bytes(createTime)][8bytes(modTime)][8bytes(fileSize)]
|
||||
// [TEXT(fileName)][TEXT(symLinkTarget)]
|
||||
|
||||
// note: the TEXT strings are 16bit NULL terminated meaning 2 bytes of 0x00
|
||||
// indicate the end of the string.
|
||||
|
||||
// note: the integer data found in flags, modTime, createTime and fileSize
|
||||
// are formatted in little endian byte order (unsigned).
|
||||
|
||||
char flags = 0;
|
||||
|
||||
if (info.isFile()) flags |= IS_FILE;
|
||||
if (info.isDir()) flags |= IS_DIR;
|
||||
if (info.isSymLink()) flags |= IS_SYMLNK;
|
||||
if (info.isReadable()) flags |= CAN_READ;
|
||||
if (info.isWritable()) flags |= CAN_WRITE;
|
||||
if (info.isExecutable()) flags |= CAN_EXE;
|
||||
if (info.exists()) flags |= EXISTS;
|
||||
|
||||
QByteArray ret;
|
||||
QByteArray strTerm(2, 0);
|
||||
|
||||
ret.append(flags);
|
||||
ret.append(wrInt(info.birthTime().toMSecsSinceEpoch(), 64));
|
||||
ret.append(wrInt(info.lastModified().toMSecsSinceEpoch(), 64));
|
||||
ret.append(wrInt(info.size(), 64));
|
||||
ret.append(toTEXT(info.fileName()) + strTerm);
|
||||
ret.append(toTEXT(info.symLinkTarget() + strTerm));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
QByteArray toFILE_INFO(const QString &path)
|
||||
{
|
||||
return toFILE_INFO(QFileInfo(path));
|
||||
}
|
||||
|
||||
void mkPathForFile(const QString &path)
|
||||
{
|
||||
mkPath(QFileInfo(path).absolutePath());
|
||||
}
|
||||
|
||||
DownloadFile::DownloadFile(QObject *parent) : CmdObject(parent) {file = new QFile(this);}
|
||||
UploadFile::UploadFile(QObject *parent) : CmdObject(parent) {file = new QFile(this);}
|
||||
Delete::Delete(QObject *parent) : CmdObject(parent) {}
|
||||
Copy::Copy(QObject *parent) : CmdObject(parent) {src = new QFile(this); dst = new QFile(this);}
|
||||
Move::Move(QObject *parent) : Copy(parent) {}
|
||||
MakePath::MakePath(QObject *parent) : InternCommand(parent) {}
|
||||
ListFiles::ListFiles(QObject *parent) : InternCommand(parent) {}
|
||||
FileInfo::FileInfo(QObject *parent) : InternCommand(parent) {}
|
||||
ChangeDir::ChangeDir(QObject *parent) : InternCommand(parent) {}
|
||||
Tree::Tree(QObject *parent) : InternCommand(parent) {}
|
||||
MakePath::MakePath(QObject *parent) : CmdObject(parent) {}
|
||||
ListFiles::ListFiles(QObject *parent) : CmdObject(parent) {}
|
||||
FileInfo::FileInfo(QObject *parent) : CmdObject(parent) {}
|
||||
ChangeDir::ChangeDir(QObject *parent) : CmdObject(parent) {}
|
||||
Tree::Tree(QObject *parent) : CmdObject(parent) {}
|
||||
|
||||
QString DownloadFile::cmdName() {return "fs_download";}
|
||||
QString UploadFile::cmdName() {return "fs_upload";}
|
||||
|
@ -38,22 +85,14 @@ QString FileInfo::cmdName() {return "fs_info";}
|
|||
QString ChangeDir::cmdName() {return "fs_cd";}
|
||||
QString Tree::cmdName() {return "fs_tree";}
|
||||
|
||||
bool DownloadFile::handlesGenfile()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void DownloadFile::term()
|
||||
void DownloadFile::clear()
|
||||
{
|
||||
file->close();
|
||||
|
||||
buffSize = static_cast<qint64>(qPow(2, MAX_FRAME_BITS) - 1);
|
||||
ssMode = false;
|
||||
dataSent = 0;
|
||||
len = 0;
|
||||
|
||||
emit enableLoop(false);
|
||||
emit enableMoreInput(false);
|
||||
flags = 0;
|
||||
}
|
||||
|
||||
void DownloadFile::sendChunk()
|
||||
|
@ -64,26 +103,26 @@ void DownloadFile::sendChunk()
|
|||
|
||||
dataSent += data.size();
|
||||
|
||||
emit dataToClient(data, GEN_FILE);
|
||||
emit procOut(data, GEN_FILE);
|
||||
|
||||
mainTxt(QString::number(dataSent) + "/" + QString::number(len) + "\n");
|
||||
|
||||
if ((dataSent >= len) || file->atEnd())
|
||||
{
|
||||
term();
|
||||
clear();
|
||||
}
|
||||
}
|
||||
|
||||
void DownloadFile::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void DownloadFile::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
Q_UNUSED(sharedObjs)
|
||||
|
||||
if ((dType == GEN_FILE) && (moreInputEnabled() || loopEnabled()))
|
||||
if ((dType == GEN_FILE) && (flags & (MORE_INPUT | LOOPING)))
|
||||
{
|
||||
sendChunk();
|
||||
}
|
||||
else if (dType == GEN_FILE)
|
||||
{
|
||||
clear();
|
||||
|
||||
QStringList args = parseArgs(binIn, 11);
|
||||
QString path = getParam("-remote_file", args);
|
||||
QString offStr = getParam("-offset", args);
|
||||
|
@ -119,8 +158,8 @@ void DownloadFile::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn
|
|||
{
|
||||
QString genfileRet = "-from_host";
|
||||
|
||||
ssMode = argExists("-single_step", args);
|
||||
len = lenStr.toLongLong();
|
||||
flags |= MORE_INPUT;
|
||||
|
||||
if ((len == 0) || (len > file->size()))
|
||||
{
|
||||
|
@ -129,33 +168,28 @@ void DownloadFile::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn
|
|||
len = file->size();
|
||||
}
|
||||
|
||||
if (!argExists("-single_step", args))
|
||||
{
|
||||
flags |= LOOPING;
|
||||
}
|
||||
|
||||
file->seek(offStr.toLongLong());
|
||||
|
||||
emit enableMoreInput(true);
|
||||
emit enableLoop(!ssMode);
|
||||
emit dataToClient(toTEXT(genfileRet), GEN_FILE);
|
||||
emit procOut(toTEXT(genfileRet), GEN_FILE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool UploadFile::handlesGenfile()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void UploadFile::term()
|
||||
void UploadFile::clear()
|
||||
{
|
||||
file->close();
|
||||
|
||||
force = false;
|
||||
confirm = false;
|
||||
ssMode = false;
|
||||
dataReceived = 0;
|
||||
len = 0;
|
||||
flags = 0;
|
||||
mode = nullptr;
|
||||
|
||||
emit enableLoop(false);
|
||||
emit enableMoreInput(false);
|
||||
}
|
||||
|
||||
void UploadFile::wrToFile(const QByteArray &data)
|
||||
|
@ -168,11 +202,11 @@ void UploadFile::wrToFile(const QByteArray &data)
|
|||
|
||||
if (dataReceived >= len)
|
||||
{
|
||||
term();
|
||||
clear();
|
||||
}
|
||||
else if (ssMode)
|
||||
else if (flags & SINGLE_STEP_MODE)
|
||||
{
|
||||
emit dataToClient(QByteArray(), GEN_FILE);
|
||||
emit procOut(QByteArray(), GEN_FILE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -187,19 +221,17 @@ void UploadFile::run()
|
|||
{
|
||||
if (file->open(mode))
|
||||
{
|
||||
emit dataToClient(QByteArray(), GEN_FILE);
|
||||
emit procOut(QByteArray(), GEN_FILE);
|
||||
}
|
||||
else
|
||||
{
|
||||
errTxt("err: Unable to open the remote file for writing. reason: " + file->errorString() + "\n");
|
||||
term();
|
||||
clear();
|
||||
}
|
||||
}
|
||||
|
||||
void UploadFile::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void UploadFile::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
Q_UNUSED(sharedObjs)
|
||||
|
||||
if (((dType == GEN_FILE) || (dType == TEXT)) && confirm)
|
||||
{
|
||||
QString ans = fromTEXT(binIn);
|
||||
|
@ -212,19 +244,21 @@ void UploadFile::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn,
|
|||
}
|
||||
else if (noCaseMatch("n", ans))
|
||||
{
|
||||
term();
|
||||
clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
ask();
|
||||
}
|
||||
}
|
||||
else if ((dType == GEN_FILE) && moreInputEnabled())
|
||||
else if ((dType == GEN_FILE) && (flags & MORE_INPUT))
|
||||
{
|
||||
wrToFile(binIn);
|
||||
}
|
||||
else if (dType == GEN_FILE)
|
||||
{
|
||||
clear();
|
||||
|
||||
QStringList args = parseArgs(binIn, 11);
|
||||
QString lenStr = getParam("-len", args);
|
||||
QString offStr = getParam("-offset", args);
|
||||
|
@ -233,8 +267,19 @@ void UploadFile::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn,
|
|||
|
||||
file->setFileName(dst);
|
||||
|
||||
if (argExists("-truncate", args)) mode = QFile::ReadWrite | QFile::Truncate;
|
||||
else mode = QFile::ReadWrite;
|
||||
if (argExists("-truncate", args))
|
||||
{
|
||||
mode = QFile::ReadWrite | QFile::Truncate;
|
||||
}
|
||||
else
|
||||
{
|
||||
mode = QFile::ReadWrite;
|
||||
}
|
||||
|
||||
if (argExists("-single_step", args))
|
||||
{
|
||||
flags |= SINGLE_STEP_MODE;
|
||||
}
|
||||
|
||||
if (dst.isEmpty())
|
||||
{
|
||||
|
@ -254,14 +299,13 @@ void UploadFile::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn,
|
|||
}
|
||||
else
|
||||
{
|
||||
ssMode = argExists("-single_step", args);
|
||||
force = argExists("-force", args);
|
||||
len = lenStr.toLongLong();
|
||||
flags |= MORE_INPUT;
|
||||
|
||||
file->seek(offStr.toLongLong());
|
||||
|
||||
emit enableMoreInput(true);
|
||||
emit dataToClient(toTEXT("-to_host"), GEN_FILE);
|
||||
emit procOut(toTEXT("-to_host"), GEN_FILE);
|
||||
|
||||
if (exists && !force) ask();
|
||||
else run();
|
||||
|
@ -269,16 +313,9 @@ void UploadFile::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn,
|
|||
}
|
||||
}
|
||||
|
||||
void Delete::term()
|
||||
{
|
||||
emit enableMoreInput(false);
|
||||
|
||||
path.clear();
|
||||
}
|
||||
|
||||
void Delete::ask()
|
||||
{
|
||||
emit enableMoreInput(true);
|
||||
flags |= MORE_INPUT;
|
||||
|
||||
mainTxt("Are you sure you want to delete the object? (y/n): ");
|
||||
}
|
||||
|
@ -287,7 +324,9 @@ void Delete::run()
|
|||
{
|
||||
bool ok;
|
||||
|
||||
if (QFileInfo(path).isFile() || QFileInfo(path).isSymLink())
|
||||
QFileInfo info(path);
|
||||
|
||||
if (info.isFile() || info.isSymLink())
|
||||
{
|
||||
ok = QFile::remove(path);
|
||||
}
|
||||
|
@ -296,26 +335,35 @@ void Delete::run()
|
|||
ok = QDir(path).removeRecursively();
|
||||
}
|
||||
|
||||
if (!ok) errTxt("err: Could not delete '" + path + "' for an unknown reason.\n");
|
||||
if (!ok && !info.exists())
|
||||
{
|
||||
errTxt("err: '" + path + "' already does not exists.\n");
|
||||
}
|
||||
else if (!ok && info.isWritable())
|
||||
{
|
||||
errTxt("err: Could not delete '" + path + "' for an unknown reason.\n");
|
||||
}
|
||||
else if (!ok)
|
||||
{
|
||||
errTxt("err: Could not delete '" + path + ".' permission denied.\n");
|
||||
}
|
||||
}
|
||||
|
||||
void Delete::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void Delete::procIn(const QByteArray &binIn, uchar dType)
|
||||
{
|
||||
Q_UNUSED(sharedObjs)
|
||||
|
||||
if (moreInputEnabled() && (dType == TEXT))
|
||||
if ((flags & MORE_INPUT) && (dType == TEXT))
|
||||
{
|
||||
QString ans = fromTEXT(binIn);
|
||||
|
||||
if (noCaseMatch("y", ans))
|
||||
{
|
||||
emit enableMoreInput(false);
|
||||
flags &= ~MORE_INPUT;
|
||||
|
||||
run();
|
||||
}
|
||||
else if (noCaseMatch("n", ans))
|
||||
{
|
||||
term();
|
||||
flags &= ~MORE_INPUT;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -348,12 +396,13 @@ void Delete::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, ucha
|
|||
}
|
||||
}
|
||||
|
||||
void Copy::term()
|
||||
void Copy::clear()
|
||||
{
|
||||
fromQueue = false;
|
||||
procedAFile = false;
|
||||
yToAll = false;
|
||||
nToAll = false;
|
||||
flags = 0;
|
||||
|
||||
src->close();
|
||||
dst->close();
|
||||
|
@ -362,14 +411,11 @@ void Copy::term()
|
|||
srcPath.clear();
|
||||
dstPath.clear();
|
||||
oriSrcPath.clear();
|
||||
|
||||
emit enableLoop(false);
|
||||
emit enableMoreInput(false);
|
||||
}
|
||||
|
||||
void Copy::ask()
|
||||
{
|
||||
emit enableMoreInput(true);
|
||||
flags |= MORE_INPUT;
|
||||
|
||||
QString opts;
|
||||
|
||||
|
@ -427,7 +473,7 @@ void Copy::run()
|
|||
else
|
||||
{
|
||||
errTxt("err: Unable to re-create the source symlink at the destination path. writing to the path is not possible/denied.\n");
|
||||
term();
|
||||
clear();
|
||||
}
|
||||
}
|
||||
else if (QFileInfo(srcPath).isDir())
|
||||
|
@ -435,19 +481,19 @@ void Copy::run()
|
|||
mkPath(dstPath);
|
||||
listDir(queue, srcPath, dstPath);
|
||||
|
||||
emit enableLoop(true);
|
||||
flags |= LOOPING;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!dst->open(QFile::WriteOnly | QFile::Truncate))
|
||||
{
|
||||
errTxt("err: Unable to open the destination file '" + dstPath + "' for writing. reason: " + dst->errorString() + "\n");
|
||||
term();
|
||||
clear();
|
||||
}
|
||||
else if (!src->open(QFile::ReadOnly))
|
||||
{
|
||||
errTxt("err: Unable to open the source file '" + srcPath + "' for reading. reason: " + src->errorString() + "\n");
|
||||
term();
|
||||
clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -455,16 +501,14 @@ void Copy::run()
|
|||
|
||||
mainTxt("'" + srcPath + "' --> '" + dstPath + "'\n\n");
|
||||
|
||||
emit enableLoop(true);
|
||||
flags |= LOOPING;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Copy::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void Copy::procIn(const QByteArray &binIn, uchar dType)
|
||||
{
|
||||
Q_UNUSED(sharedObjs)
|
||||
|
||||
if (loopEnabled())
|
||||
if (flags & LOOPING)
|
||||
{
|
||||
if (src->isOpen() || dst->isOpen())
|
||||
{
|
||||
|
@ -497,7 +541,7 @@ void Copy::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar
|
|||
|
||||
if (exists && !yToAll && !nToAll)
|
||||
{
|
||||
enableLoop(false);
|
||||
flags &= ~LOOPING;
|
||||
|
||||
ask();
|
||||
}
|
||||
|
@ -509,43 +553,50 @@ void Copy::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar
|
|||
else
|
||||
{
|
||||
preFinish();
|
||||
term();
|
||||
clear();
|
||||
}
|
||||
}
|
||||
else if ((dType == TEXT) && moreInputEnabled())
|
||||
else if ((dType == TEXT) && (flags & MORE_INPUT))
|
||||
{
|
||||
QString ans = fromTEXT(binIn);
|
||||
|
||||
if (noCaseMatch("y", ans))
|
||||
{
|
||||
emit enableLoop(fromQueue);
|
||||
emit enableMoreInput(false);
|
||||
if (fromQueue) flags |= LOOPING;
|
||||
|
||||
flags &= ~MORE_INPUT;
|
||||
|
||||
run();
|
||||
}
|
||||
else if (noCaseMatch("n", ans))
|
||||
{
|
||||
emit enableLoop(fromQueue);
|
||||
emit enableMoreInput(false);
|
||||
flags &= ~MORE_INPUT;
|
||||
|
||||
if (!loopEnabled()) term();
|
||||
if (fromQueue)
|
||||
{
|
||||
flags |= LOOPING;
|
||||
}
|
||||
else
|
||||
{
|
||||
clear();
|
||||
}
|
||||
}
|
||||
else if (fromQueue)
|
||||
{
|
||||
if (noCaseMatch("y-all", ans))
|
||||
{
|
||||
emit enableLoop(fromQueue);
|
||||
emit enableMoreInput(false);
|
||||
if (fromQueue) flags |= LOOPING;
|
||||
|
||||
flags &= ~MORE_INPUT;
|
||||
yToAll = true;
|
||||
|
||||
run();
|
||||
}
|
||||
else if (noCaseMatch("n-all", ans))
|
||||
{
|
||||
emit enableLoop(fromQueue);
|
||||
emit enableMoreInput(false);
|
||||
if (fromQueue) flags |= LOOPING;
|
||||
|
||||
flags &= ~MORE_INPUT;
|
||||
nToAll = true;
|
||||
}
|
||||
else
|
||||
|
@ -560,6 +611,8 @@ void Copy::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar
|
|||
}
|
||||
else if (dType == TEXT)
|
||||
{
|
||||
clear();
|
||||
|
||||
QStringList args = parseArgs(binIn, 5);
|
||||
bool force = argExists("-force", args);
|
||||
|
||||
|
@ -574,19 +627,19 @@ void Copy::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar
|
|||
|
||||
if (srcPath.isEmpty())
|
||||
{
|
||||
errTxt("err: The source file (-src) argument was not found or is empty.\n");
|
||||
errTxt("err: The source (-src) argument was not found or is empty.\n");
|
||||
}
|
||||
else if (dstPath.isEmpty())
|
||||
{
|
||||
errTxt("err: The destination file (-dst) argument was not found or is empty.\n");
|
||||
errTxt("err: The destination (-dst) argument was not found or is empty.\n");
|
||||
}
|
||||
else if (!QFileInfo(srcPath).exists())
|
||||
{
|
||||
errTxt("err: The source file does not exists.\n");
|
||||
errTxt("err: The source does not exists.\n");
|
||||
}
|
||||
else if (dstExists && !matchedFsObjTypes(srcPath, dstPath))
|
||||
{
|
||||
errTxt("err: The existing destination object type does not match the source object type.\n");
|
||||
errTxt("err: The existing destination object type (file,dir,symmlink) does not match the source object type.\n");
|
||||
}
|
||||
else if (permissionsOk(dstExists))
|
||||
{
|
||||
|
@ -615,7 +668,7 @@ void Move::runOnMatchingVolume()
|
|||
if (!QFile::rename(srcPath, dstPath))
|
||||
{
|
||||
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");
|
||||
term();
|
||||
clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -652,10 +705,8 @@ bool Move::permissionsOk(bool dstExists)
|
|||
return ret;
|
||||
}
|
||||
|
||||
void MakePath::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void MakePath::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
Q_UNUSED(sharedObjs)
|
||||
|
||||
if (dType == TEXT)
|
||||
{
|
||||
QStringList args = parseArgs(binIn, 2);
|
||||
|
@ -672,10 +723,8 @@ void MakePath::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uc
|
|||
}
|
||||
}
|
||||
|
||||
void ListFiles::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void ListFiles::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
Q_UNUSED(sharedObjs)
|
||||
|
||||
if (dType == TEXT)
|
||||
{
|
||||
QStringList args = parseArgs(binIn, 4);
|
||||
|
@ -723,7 +772,7 @@ void ListFiles::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, u
|
|||
{
|
||||
if (infoFrame)
|
||||
{
|
||||
emit dataToClient(toFILE_INFO(info), FILE_INFO);
|
||||
emit procOut(toFILE_INFO(info), FILE_INFO);
|
||||
}
|
||||
else if (info.isDir())
|
||||
{
|
||||
|
@ -738,10 +787,8 @@ void ListFiles::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, u
|
|||
}
|
||||
}
|
||||
|
||||
void FileInfo::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void FileInfo::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
Q_UNUSED(sharedObjs)
|
||||
|
||||
if (dType == TEXT)
|
||||
{
|
||||
QStringList args = parseArgs(binIn, 3);
|
||||
|
@ -762,7 +809,7 @@ void FileInfo::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uc
|
|||
{
|
||||
if (infoFrame)
|
||||
{
|
||||
emit dataToClient(toFILE_INFO(info), FILE_INFO);
|
||||
emit procOut(toFILE_INFO(info), FILE_INFO);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -792,10 +839,8 @@ void FileInfo::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uc
|
|||
}
|
||||
}
|
||||
|
||||
void ChangeDir::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void ChangeDir::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
Q_UNUSED(sharedObjs)
|
||||
|
||||
if (dType == TEXT)
|
||||
{
|
||||
QStringList args = parseArgs(binIn, 3);
|
||||
|
@ -818,14 +863,16 @@ void ChangeDir::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, u
|
|||
QDir::setCurrent(path);
|
||||
|
||||
mainTxt(QDir::currentPath() + "\n");
|
||||
async(ASYNC_SET_DIR, PRIV_IPC, toTEXT(path));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Tree::term()
|
||||
void Tree::clear()
|
||||
{
|
||||
queue.clear();
|
||||
|
||||
flags = 0;
|
||||
infoFrames = false;
|
||||
noHidden = false;
|
||||
}
|
||||
|
@ -851,7 +898,7 @@ void Tree::printList(const QString &path)
|
|||
{
|
||||
if (infoFrames)
|
||||
{
|
||||
emit dataToClient(toFILE_INFO(info), FILE_INFO);
|
||||
emit procOut(toFILE_INFO(info), FILE_INFO);
|
||||
}
|
||||
else if (info.isDir())
|
||||
{
|
||||
|
@ -870,21 +917,17 @@ void Tree::printList(const QString &path)
|
|||
|
||||
if (queue.isEmpty())
|
||||
{
|
||||
term();
|
||||
|
||||
emit enableLoop(false);
|
||||
clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
emit enableLoop(true);
|
||||
flags |= LOOPING;
|
||||
}
|
||||
}
|
||||
|
||||
void Tree::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void Tree::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
Q_UNUSED(sharedObjs)
|
||||
|
||||
if (loopEnabled())
|
||||
if (flags & LOOPING)
|
||||
{
|
||||
printList(queue.takeFirst().filePath());
|
||||
}
|
||||
|
|
|
@ -18,8 +18,13 @@
|
|||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "../common.h"
|
||||
#include "../cmd_object.h"
|
||||
|
||||
class DownloadFile : public InternCommand
|
||||
QByteArray toFILE_INFO(const QString &path);
|
||||
QByteArray toFILE_INFO(const QFileInfo &info);
|
||||
void mkPathForFile(const QString &path);
|
||||
|
||||
class DownloadFile : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -29,7 +34,6 @@ private:
|
|||
qint64 buffSize;
|
||||
qint64 len;
|
||||
qint64 dataSent;
|
||||
bool ssMode;
|
||||
|
||||
void sendChunk();
|
||||
|
||||
|
@ -37,16 +41,15 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
bool handlesGenfile();
|
||||
void term();
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void clear();
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit DownloadFile(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//-----------------------
|
||||
|
||||
class UploadFile : public InternCommand
|
||||
class UploadFile : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -68,16 +71,15 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
bool handlesGenfile();
|
||||
void term();
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void clear();
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit UploadFile(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//-----------------------
|
||||
|
||||
class Delete : public InternCommand
|
||||
class Delete : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -92,15 +94,14 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void term();
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, uchar dType);
|
||||
|
||||
explicit Delete(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//------------------------
|
||||
|
||||
class Copy : public InternCommand
|
||||
class Copy : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -130,8 +131,8 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void term();
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void clear();
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit Copy(QObject *parent = nullptr);
|
||||
};
|
||||
|
@ -159,7 +160,7 @@ public:
|
|||
|
||||
//-----------------------
|
||||
|
||||
class MakePath : public InternCommand
|
||||
class MakePath : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -167,14 +168,14 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit MakePath(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//-----------------------
|
||||
|
||||
class ListFiles : public InternCommand
|
||||
class ListFiles : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -182,14 +183,14 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit ListFiles(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//-----------------------
|
||||
|
||||
class FileInfo : public InternCommand
|
||||
class FileInfo : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -197,14 +198,14 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit FileInfo(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//-----------------------
|
||||
|
||||
class ChangeDir : public InternCommand
|
||||
class ChangeDir : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -212,14 +213,14 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit ChangeDir(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//--------------------------
|
||||
|
||||
class Tree : public InternCommand
|
||||
class Tree : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -235,8 +236,8 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void term();
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void clear();
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit Tree(QObject *parent = nullptr);
|
||||
};
|
||||
|
|
|
@ -1,286 +0,0 @@
|
|||
#include "groups.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/>.
|
||||
|
||||
ListGroups::ListGroups(QObject *parent) : TableViewer(parent)
|
||||
{
|
||||
setParams(TABLE_GROUPS, QStringList() << COLUMN_GRNAME << COLUMN_HOST_RANK, false);
|
||||
}
|
||||
|
||||
CreateGroup::CreateGroup(QObject *parent) : InternCommand(parent) {}
|
||||
RemoveGroup::RemoveGroup(QObject *parent) : InternCommand(parent) {}
|
||||
TransGroup::TransGroup(QObject *parent) : InternCommand(parent) {}
|
||||
SetGroupRank::SetGroupRank(QObject *parent) : InternCommand(parent) {}
|
||||
RenameGroup::RenameGroup(QObject *parent) : InternCommand(parent) {}
|
||||
|
||||
QString ListGroups::cmdName() {return "ls_groups";}
|
||||
QString CreateGroup::cmdName() {return "add_group";}
|
||||
QString RemoveGroup::cmdName() {return "rm_group";}
|
||||
QString TransGroup::cmdName() {return "trans_group";}
|
||||
QString SetGroupRank::cmdName() {return "set_group_rank";}
|
||||
QString RenameGroup::cmdName() {return "rename_group";}
|
||||
|
||||
void CreateGroup::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
{
|
||||
Q_UNUSED(sharedObjs);
|
||||
|
||||
if (dType == TEXT)
|
||||
{
|
||||
QStringList args = parseArgs(binIn, 2);
|
||||
QString grName = getParam("-name", args);
|
||||
|
||||
if (grName.isEmpty())
|
||||
{
|
||||
errTxt("err: The group name argument (-name) was not found or is empty.\n");
|
||||
}
|
||||
else if (!validGroupName(grName))
|
||||
{
|
||||
errTxt("err: The group name must be 1-12 chars long and contain no spaces.\n");
|
||||
}
|
||||
else if (groupExists(grName))
|
||||
{
|
||||
errTxt("err: The requested group already exists.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
Query db(this);
|
||||
|
||||
db.setType(Query::PUSH, TABLE_GROUPS);
|
||||
db.addColumn(COLUMN_GRNAME, grName);
|
||||
db.addColumn(COLUMN_HOST_RANK, 2);
|
||||
db.exec();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveGroup::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
{
|
||||
if (dType == TEXT)
|
||||
{
|
||||
QStringList args = parseArgs(binIn, 2);
|
||||
QString grName = getParam("-name", args);
|
||||
|
||||
if (grName.isEmpty())
|
||||
{
|
||||
errTxt("err: The group name (-name) argument was not found or is empty.\n");
|
||||
}
|
||||
else if (noCaseMatch(ROOT_USER, grName))
|
||||
{
|
||||
errTxt("err: '" + QString(ROOT_USER) + "' is a protected group, you cannot delete it.\n");
|
||||
}
|
||||
else if (!validGroupName(grName))
|
||||
{
|
||||
errTxt("err: Invalid group name.\n");
|
||||
}
|
||||
else if (!groupExists(grName))
|
||||
{
|
||||
errTxt("err: No such group found in the database.\n");
|
||||
}
|
||||
else if (noCaseMatch(grName, initGroup()))
|
||||
{
|
||||
errTxt("err: '" + grName + "' is the initial group for new users, unable to delete it.\n");
|
||||
}
|
||||
else if (!checkRank(*sharedObjs->groupName, grName))
|
||||
{
|
||||
errTxt("err: The target group out ranks or is equal to your own group. access denied.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
Query db(this);
|
||||
|
||||
db.setType(Query::DEL, TABLE_GROUPS);
|
||||
db.addCondition(COLUMN_GRNAME, grName);
|
||||
|
||||
if (!db.exec())
|
||||
{
|
||||
errTxt("err: Unable to delete group. some user accounts might still be attached to it.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TransGroup::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
{
|
||||
if (dType == TEXT)
|
||||
{
|
||||
QStringList args = parseArgs(binIn, 4);
|
||||
QString src = getParam("-src", args);
|
||||
QString dst = getParam("-dst", args);
|
||||
|
||||
if (src.isEmpty())
|
||||
{
|
||||
errTxt("err: The source group (-src) argument was not found or is empty.\n");
|
||||
}
|
||||
else if (dst.isEmpty())
|
||||
{
|
||||
errTxt("err: The destination group (-dst) argument was not found or is empty.\n");
|
||||
}
|
||||
else if (noCaseMatch(src, ROOT_USER) || noCaseMatch(dst, ROOT_USER))
|
||||
{
|
||||
errTxt("err: Unable to transfer to or from protected group '" + QString(ROOT_USER) + "'\n");
|
||||
}
|
||||
else if (!validGroupName(src))
|
||||
{
|
||||
errTxt("err: Invalid source group name.\n");
|
||||
}
|
||||
else if (!validGroupName(dst))
|
||||
{
|
||||
errTxt("err: Invalid destination group name.\n");
|
||||
}
|
||||
else if (!groupExists(src))
|
||||
{
|
||||
errTxt("err: '" + src + "' does not exists.\n");
|
||||
}
|
||||
else if (!groupExists(dst))
|
||||
{
|
||||
errTxt("err: '" + dst + "' does not exists.\n");
|
||||
}
|
||||
else if (!checkRank(*sharedObjs->groupName, src))
|
||||
{
|
||||
errTxt("err: The source group out ranks your own group. access denied.\n");
|
||||
}
|
||||
else if (!checkRank(*sharedObjs->groupName, dst))
|
||||
{
|
||||
errTxt("err: The destination group out ranks or is equal to your own group. access denied.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
Query db(this);
|
||||
|
||||
db.setType(Query::UPDATE, TABLE_USERS);
|
||||
db.addColumn(COLUMN_GRNAME, dst);
|
||||
db.addCondition(COLUMN_GRNAME, src);
|
||||
db.exec();
|
||||
|
||||
emit backendDataOut(ASYNC_GRP_TRANS, toTEXT(args.join(' ')), PUB_IPC_WITH_FEEDBACK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SetGroupRank::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
{
|
||||
if (dType == TEXT)
|
||||
{
|
||||
QStringList args = parseArgs(binIn, 4);
|
||||
QString grName = getParam("-name", args);
|
||||
QString rank = getParam("-rank", args);
|
||||
|
||||
if (grName.isEmpty())
|
||||
{
|
||||
errTxt("err: The group name (-name) argument was not found or is empty.\n");
|
||||
}
|
||||
else if (noCaseMatch(ROOT_USER, grName))
|
||||
{
|
||||
errTxt("err: '" + QString(ROOT_USER) + "' is a protected group, you cannot change it.\n");
|
||||
}
|
||||
else if (!validGroupName(grName))
|
||||
{
|
||||
errTxt("err: Invalid group name.\n");
|
||||
}
|
||||
else if (!isInt(rank))
|
||||
{
|
||||
errTxt("err: Invalid rank.\n");
|
||||
}
|
||||
else if (rank.toUInt() < *sharedObjs->hostRank)
|
||||
{
|
||||
errTxt("err: you cannot set a rank higher than your own.\n");
|
||||
}
|
||||
else if (!groupExists(grName))
|
||||
{
|
||||
errTxt("err: Group name '" + grName + "' does not exists.\n");
|
||||
}
|
||||
else if (!checkRank(*sharedObjs->groupName, grName))
|
||||
{
|
||||
errTxt("err: The target group out ranks or is equal to your own group. access denied.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
Query db(this);
|
||||
|
||||
db.setType(Query::UPDATE, TABLE_GROUPS);
|
||||
db.addColumn(COLUMN_HOST_RANK, rank.toUInt());
|
||||
db.addCondition(COLUMN_GRNAME, grName);
|
||||
db.exec();
|
||||
|
||||
emit backendDataOut(ASYNC_GROUP_UPDATED, toTEXT(args.join(' ')), PUB_IPC_WITH_FEEDBACK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RenameGroup::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
{
|
||||
if (dType == TEXT)
|
||||
{
|
||||
QStringList args = parseArgs(binIn, 4);
|
||||
QString name = getParam("-name", args);
|
||||
QString newName = getParam("-new_name", args);
|
||||
|
||||
if (name.isEmpty())
|
||||
{
|
||||
errTxt("err: The group name (-name) argument was not found or is empty.\n");
|
||||
}
|
||||
else if (newName.isEmpty())
|
||||
{
|
||||
errTxt("err: The new name (-new_name) argument was not found or is empty.\n");
|
||||
}
|
||||
else if (noCaseMatch(name, ROOT_USER))
|
||||
{
|
||||
errTxt("err: Cannot rename protected group '" + QString(ROOT_USER) + "'\n");
|
||||
}
|
||||
else if (noCaseMatch(newName, ROOT_USER))
|
||||
{
|
||||
errTxt("err: Cannot use '" + QString(ROOT_USER) + "' for a new name. it is reserved.\n");
|
||||
}
|
||||
else if (!validGroupName(name))
|
||||
{
|
||||
errTxt("err: Invalid group name.\n");
|
||||
}
|
||||
else if (!validGroupName(newName))
|
||||
{
|
||||
errTxt("err: Invalid new group name. the group name must be between 1-12 chars long and contain no spaces.\n");
|
||||
}
|
||||
else if (!groupExists(name))
|
||||
{
|
||||
errTxt("err: Group name '" + name + "' does not exists.\n");
|
||||
}
|
||||
else if (groupExists(newName))
|
||||
{
|
||||
errTxt("err: Group name '" + newName + "' already exists.\n");
|
||||
}
|
||||
else if (!checkRank(*sharedObjs->groupName, name))
|
||||
{
|
||||
errTxt("err: The target group out ranks or is equal to your own group. access denied.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
Query db(this);
|
||||
|
||||
db.setType(Query::UPDATE, TABLE_GROUPS);
|
||||
db.addColumn(COLUMN_GRNAME, newName);
|
||||
db.addCondition(COLUMN_GRNAME, name);
|
||||
db.exec();
|
||||
|
||||
args.clear();
|
||||
args.append("-src");
|
||||
args.append("'" + escapeChars(name, '\\', '\'') + "'");
|
||||
args.append("-dst");
|
||||
args.append("'" + escapeChars(newName, '\\', '\'') + "'");
|
||||
|
||||
emit backendDataOut(ASYNC_GROUP_RENAMED, toTEXT(args.join(' ')), PUB_IPC_WITH_FEEDBACK);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,109 +0,0 @@
|
|||
#ifndef GROUP_CMDS_H
|
||||
#define GROUP_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 "table_viewer.h"
|
||||
|
||||
class ListGroups : public TableViewer
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
static QString cmdName();
|
||||
|
||||
explicit ListGroups(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//--------------------------------------
|
||||
|
||||
class CreateGroup : public InternCommand
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
|
||||
explicit CreateGroup(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//--------------------------------------
|
||||
|
||||
class RemoveGroup : public InternCommand
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
|
||||
explicit RemoveGroup(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//--------------------------------------
|
||||
|
||||
class TransGroup : public InternCommand
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
|
||||
explicit TransGroup(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
class SetGroupRank : public InternCommand
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
|
||||
explicit SetGroupRank(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//------------------------------------
|
||||
|
||||
class RenameGroup : public InternCommand
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
|
||||
explicit RenameGroup(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
#endif // GROUP_CMDS_H
|
|
@ -18,103 +18,130 @@
|
|||
|
||||
IPHist::IPHist(QObject *parent) : TableViewer(parent)
|
||||
{
|
||||
setParams(TABLE_IPHIST, QStringList() << COLUMN_TIME << COLUMN_IPADDR << COLUMN_SESSION_ID << COLUMN_CLIENT_VER << COLUMN_LOGENTRY, true);
|
||||
setParams(TABLE_IPHIST, true);
|
||||
addTableColumn(TABLE_IPHIST, COLUMN_TIME);
|
||||
addTableColumn(TABLE_IPHIST, COLUMN_IPADDR);
|
||||
addTableColumn(TABLE_IPHIST, COLUMN_APP_NAME);
|
||||
addTableColumn(TABLE_IPHIST, COLUMN_SESSION_ID);
|
||||
addTableColumn(TABLE_IPHIST, COLUMN_LOGENTRY);
|
||||
}
|
||||
|
||||
ListDBG::ListDBG(QObject *parent) : TableViewer(parent)
|
||||
{
|
||||
setParams(TABLE_DMESG, QStringList() << COLUMN_TIME << COLUMN_LOGENTRY, true);
|
||||
setParams(TABLE_DMESG, true);
|
||||
addTableColumn(TABLE_DMESG, COLUMN_TIME);
|
||||
addTableColumn(TABLE_DMESG, COLUMN_LOGENTRY);
|
||||
}
|
||||
|
||||
ListCommands::ListCommands(QObject *parent) : InternCommand(parent) {}
|
||||
HostInfo::HostInfo(QObject *parent) : InternCommand(parent) {}
|
||||
MyInfo::MyInfo(QObject *parent) : InternCommand(parent) {}
|
||||
CmdInfo::CmdInfo(QObject *parent) : InternCommand(parent) {}
|
||||
ListCommands::ListCommands(const QStringList &cmdList, const QStringList &gen, QObject *parent) : CmdObject(parent)
|
||||
{
|
||||
list = cmdList;
|
||||
genfileList = gen;
|
||||
}
|
||||
|
||||
HostInfo::HostInfo(QObject *parent) : CmdObject(parent) {}
|
||||
MyInfo::MyInfo(QObject *parent) : CmdObject(parent) {}
|
||||
|
||||
QString ListCommands::cmdName() {return "ls_cmds";}
|
||||
QString HostInfo::cmdName() {return "host_info";}
|
||||
QString IPHist::cmdName() {return "ls_act_log";}
|
||||
QString ListDBG::cmdName() {return "ls_dbg";}
|
||||
QString MyInfo::cmdName() {return "my_info";}
|
||||
QString CmdInfo::cmdName() {return "cmd_info";}
|
||||
|
||||
bool ListCommands::strInRowTxt(const QString &str, const QStringList &rowTxt)
|
||||
QString ListCommands::parseMd(const QString &cmdName, int offset)
|
||||
{
|
||||
bool ret = false;
|
||||
QFile file(":/docs/intern_commands/" + cmdName + ".md", this);
|
||||
QByteArray data;
|
||||
|
||||
for (auto&& strInList : rowTxt)
|
||||
if (!file.open(QFile::ReadOnly))
|
||||
{
|
||||
if (strInList.contains(str, Qt::CaseInsensitive))
|
||||
qDebug() << "err: internal command: " << cmdName << " does not have a document file.";
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = true;
|
||||
data = file.readAll();
|
||||
|
||||
int targetTags = offset * 6;
|
||||
int pos = -1;
|
||||
int len = 0;
|
||||
|
||||
for (int i = 0, tags = 0; i < data.size(); ++i)
|
||||
{
|
||||
if (data[i] == '#')
|
||||
{
|
||||
++tags;
|
||||
|
||||
if (pos != -1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (tags == targetTags)
|
||||
{
|
||||
len++;
|
||||
|
||||
return ret;
|
||||
if (pos == -1)
|
||||
{
|
||||
pos = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data = data.mid(pos, len).trimmed();
|
||||
|
||||
if (offset == 2)
|
||||
{
|
||||
data.chop(3);
|
||||
data.remove(0, 3);
|
||||
}
|
||||
}
|
||||
|
||||
file.close();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void ListCommands::procBin(const SharedObjs *sharedObjs, const QByteArray &data, uchar dType)
|
||||
QString ListCommands::shortText(const QString &cmdName)
|
||||
{
|
||||
Q_UNUSED(sharedObjs);
|
||||
return parseMd(cmdName, 1);
|
||||
}
|
||||
|
||||
if (dType == TEXT)
|
||||
{
|
||||
QString find = getParam("-find", parseArgs(data, 2));
|
||||
QStringList cmdNames = sharedObjs->cmdNames->values();
|
||||
QList<QStringList> tableData;
|
||||
QStringList separators;
|
||||
QList<int> justLens;
|
||||
QString ListCommands::ioText(const QString &cmdName)
|
||||
{
|
||||
return parseMd(cmdName, 2);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; ++i)
|
||||
QString ListCommands::longText(const QString &cmdName)
|
||||
{
|
||||
return parseMd(cmdName, 3);
|
||||
}
|
||||
|
||||
void ListCommands::onIPCConnected()
|
||||
{
|
||||
for (auto&& cmdName : list)
|
||||
{
|
||||
justLens.append(12);
|
||||
separators.append("-------");
|
||||
QByteArray frame;
|
||||
QByteArray boolByte = QByteArray(1, 0x00);
|
||||
|
||||
if (genfileList.contains(cmdName))
|
||||
{
|
||||
boolByte = QByteArray(1, 0x01);
|
||||
}
|
||||
|
||||
cmdNames.sort(Qt::CaseInsensitive);
|
||||
tableData.append(QStringList() << "command_id" << "command_name" << "summary");
|
||||
tableData.append(separators);
|
||||
frame.append(QByteArray(2, 0x00));
|
||||
frame.append(boolByte);
|
||||
frame.append(fixedToTEXT(cmdName, BLKSIZE_CMD_NAME));
|
||||
frame.append(fixedToTEXT(libName(), BLKSIZE_LIB_NAME));
|
||||
frame.append(nullTermTEXT(shortText(cmdName)));
|
||||
frame.append(nullTermTEXT(ioText(cmdName)));
|
||||
frame.append(nullTermTEXT(longText(cmdName)));
|
||||
|
||||
for (auto&& cmdName: cmdNames)
|
||||
{
|
||||
QStringList rowData;
|
||||
quint16 id = sharedObjs->cmdNames->key(cmdName);
|
||||
|
||||
rowData.append(QString::number(id));
|
||||
rowData.append(cmdName);
|
||||
rowData.append(rwSharedObjs->commands->value(id)->shortText());
|
||||
|
||||
if (find.isEmpty() || strInRowTxt(find, rowData))
|
||||
{
|
||||
for (int k = 0; k < justLens.size(); ++k)
|
||||
{
|
||||
if (justLens[k] < rowData[k].size()) justLens[k] = rowData[k].size();
|
||||
}
|
||||
|
||||
tableData.append(rowData);
|
||||
}
|
||||
}
|
||||
|
||||
mainTxt("\n");
|
||||
|
||||
for (auto&& row : tableData)
|
||||
{
|
||||
for (int i = 0; i < row.size(); ++i)
|
||||
{
|
||||
mainTxt(row[i].leftJustified(justLens[i] + 2, ' '));
|
||||
}
|
||||
|
||||
mainTxt("\n");
|
||||
}
|
||||
emit procOut(frame, NEW_CMD);
|
||||
}
|
||||
}
|
||||
|
||||
void HostInfo::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void HostInfo::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
Q_UNUSED(binIn);
|
||||
Q_UNUSED(sharedObjs);
|
||||
Q_UNUSED(binIn)
|
||||
|
||||
if (dType == TEXT)
|
||||
{
|
||||
|
@ -129,12 +156,18 @@ void HostInfo::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uc
|
|||
QString txt;
|
||||
QTextStream txtOut(&txt);
|
||||
|
||||
txtOut << "Application: " << QCoreApplication::applicationName() << " v" << QCoreApplication::applicationVersion() << " " << QSysInfo::WordSize << "Bit" << endl;
|
||||
hostSharedMem->lock();
|
||||
|
||||
quint32 sesCount = rd32BitFromBlock(hostLoad);
|
||||
quint32 maxSes = db.getData(COLUMN_MAXSESSIONS).toUInt();
|
||||
|
||||
hostSharedMem->unlock();
|
||||
|
||||
txtOut << "Application: " << libName() << endl;
|
||||
txtOut << "Qt Base: " << QT_VERSION_STR << endl;
|
||||
txtOut << "Import Rev: " << IMPORT_REV << endl;
|
||||
txtOut << "Host Name: " << QSysInfo::machineHostName() << endl;
|
||||
txtOut << "Host OS: " << QSysInfo::prettyProductName() << endl;
|
||||
txtOut << "Load: " << rdSessionLoad() << "/" << db.getData(COLUMN_MAXSESSIONS).toUInt() << endl;
|
||||
txtOut << "Load: " << sesCount << "/" << maxSes << endl;
|
||||
txtOut << "Listening Addr: " << db.getData(COLUMN_IPADDR).toString() << endl;
|
||||
txtOut << "Listening Port: " << db.getData(COLUMN_PORT).toUInt() << endl;
|
||||
|
||||
|
@ -142,103 +175,46 @@ void HostInfo::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uc
|
|||
}
|
||||
}
|
||||
|
||||
void MyInfo::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void MyInfo::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
Q_UNUSED(binIn);
|
||||
Q_UNUSED(binIn)
|
||||
|
||||
if (dType == TEXT)
|
||||
{
|
||||
QString txt;
|
||||
QTextStream txtOut(&txt);
|
||||
|
||||
txtOut << "Session id: " << sharedObjs->sessionId->toHex() << endl;
|
||||
txtOut << "IP Address: " << *sharedObjs->sessionAddr << endl;
|
||||
txtOut << "Logged-in: " << boolStr(!sharedObjs->userName->isEmpty()) << endl;
|
||||
txtOut << "App Name: " << *sharedObjs->appName << endl;
|
||||
QString sesId = rdFromBlock(sessionId, BLKSIZE_SESSION_ID).toHex();
|
||||
QString ip = rdStringFromBlock(clientIp, BLKSIZE_CLIENT_IP);
|
||||
QString app = rdStringFromBlock(appName, BLKSIZE_APP_NAME);
|
||||
|
||||
if (!sharedObjs->userName->isEmpty())
|
||||
txtOut << "Session id: " << sesId << endl;
|
||||
txtOut << "IP Address: " << ip << endl;
|
||||
txtOut << "App Name: " << app << endl;
|
||||
|
||||
if (!isEmptyBlock(userId, BLKSIZE_USER_ID))
|
||||
{
|
||||
QByteArray uId = rdFromBlock(userId, BLKSIZE_USER_ID);
|
||||
|
||||
Query db(this);
|
||||
|
||||
db.setType(Query::PULL, TABLE_USERS);
|
||||
db.addColumn(COLUMN_EMAIL);
|
||||
db.addColumn(COLUMN_TIME);
|
||||
db.addColumn(COLUMN_EMAIL_VERIFIED);
|
||||
db.addCondition(COLUMN_USERNAME, *sharedObjs->userName);
|
||||
db.addCondition(COLUMN_USER_ID, uId);
|
||||
db.exec();
|
||||
|
||||
txtOut << "User Name: " << *sharedObjs->userName << endl;
|
||||
txtOut << "Group Name: " << *sharedObjs->groupName << endl;
|
||||
txtOut << "Display Name: " << *sharedObjs->displayName << endl;
|
||||
txtOut << "User ID: " << sharedObjs->userId->toHex() << endl;
|
||||
txtOut << "User Name: " << rdStringFromBlock(userName, BLKSIZE_USER_NAME) << endl;
|
||||
txtOut << "Display Name: " << rdStringFromBlock(displayName, BLKSIZE_DISP_NAME) << endl;
|
||||
txtOut << "User id: " << uId.toHex() << endl;
|
||||
txtOut << "Email: " << db.getData(COLUMN_EMAIL).toString() << endl;
|
||||
txtOut << "Register Date: " << db.getData(COLUMN_TIME).toString() << endl;
|
||||
txtOut << "Email Verified: " << boolStr(db.getData(COLUMN_EMAIL_VERIFIED).toBool()) << endl;
|
||||
txtOut << "Owner Override: " << boolStr(*sharedObjs->chOwnerOverride) << endl;
|
||||
txtOut << "Host Rank: " << *sharedObjs->hostRank << endl;
|
||||
txtOut << "Owner Override: " << boolStr(rd8BitFromBlock(chOwnerOverride)) << endl;
|
||||
txtOut << "Host Rank: " << rd32BitFromBlock(hostRank) << endl;
|
||||
}
|
||||
|
||||
mainTxt(txt);
|
||||
}
|
||||
}
|
||||
|
||||
void CmdInfo::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
{
|
||||
if (dType == TEXT)
|
||||
{
|
||||
QStringList args = parseArgs(binIn, 2);
|
||||
QString name = getParam("-cmd_name", args);
|
||||
QString cmdId = getParam("-cmd_id", args);
|
||||
|
||||
if (name.isEmpty() && cmdId.isEmpty())
|
||||
{
|
||||
errTxt("err: Command name (-cmd_name) of command id (-cmd_id) parameter not found or is empty.\n");
|
||||
}
|
||||
else if (!name.isEmpty() && !validCommandName(name))
|
||||
{
|
||||
errTxt("err: Command name '" + name + "' is not valid.\n");
|
||||
}
|
||||
else if (!cmdId.isEmpty() && !isInt(cmdId))
|
||||
{
|
||||
errTxt("err: Command id '" + cmdId + "' is not a valid integer.\n");
|
||||
}
|
||||
else if (!name.isEmpty() && !sharedObjs->cmdNames->values().contains(name.toLower()))
|
||||
{
|
||||
errTxt("err: No such command name '" + name + "'\n");
|
||||
}
|
||||
else if (!cmdId.isEmpty() && !sharedObjs->cmdNames->contains(cmdId.toUShort()))
|
||||
{
|
||||
errTxt("err: No such command id '" + cmdId + "'\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!name.isEmpty())
|
||||
{
|
||||
cmdId = QString::number(sharedObjs->cmdNames->key(name));
|
||||
}
|
||||
|
||||
if (!cmdId.isEmpty())
|
||||
{
|
||||
name = sharedObjs->cmdNames->value(cmdId.toUShort());
|
||||
}
|
||||
|
||||
QString txt;
|
||||
QTextStream txtOut(&txt);
|
||||
|
||||
ExternCommand *cmdObj = rwSharedObjs->commands->value(cmdId.toUShort());
|
||||
|
||||
txtOut << "Command name: " << name << endl;
|
||||
txtOut << "Command id: " << cmdId << endl;
|
||||
txtOut << "Gen file: " << boolStr(cmdObj->handlesGenfile()) << endl << endl;
|
||||
|
||||
txtOut << "IO:" << endl << endl;
|
||||
txtOut << cmdObj->ioText() << endl << endl;
|
||||
txtOut << "Summary:" << endl << endl;
|
||||
txtOut << cmdObj->shortText() << endl << endl;
|
||||
txtOut << "Details:" << endl << endl;
|
||||
|
||||
mainTxt(txt);
|
||||
bigTxt(cmdObj->longText());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,28 +18,35 @@
|
|||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "../common.h"
|
||||
#include "../cmd_object.h"
|
||||
#include "table_viewer.h"
|
||||
|
||||
class ListCommands : public InternCommand
|
||||
class ListCommands : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
|
||||
bool strInRowTxt(const QString &str, const QStringList &rowTxt);
|
||||
QStringList list;
|
||||
QStringList genfileList;
|
||||
|
||||
QString parseMd(const QString &cmdName, int offset);
|
||||
QString shortText(const QString &cmdName);
|
||||
QString ioText(const QString &cmdName);
|
||||
QString longText(const QString &cmdName);
|
||||
|
||||
private slots:
|
||||
|
||||
void onIPCConnected();
|
||||
|
||||
public:
|
||||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &data, uchar dType);
|
||||
|
||||
explicit ListCommands(QObject *parent = nullptr);
|
||||
explicit ListCommands(const QStringList &cmdList, const QStringList &gen, QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//--------------------------------------
|
||||
|
||||
class HostInfo : public InternCommand
|
||||
class HostInfo : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -47,7 +54,7 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit HostInfo(QObject *parent = nullptr);
|
||||
};
|
||||
|
@ -67,7 +74,7 @@ public:
|
|||
|
||||
//------------------------------------
|
||||
|
||||
class MyInfo : public InternCommand
|
||||
class MyInfo : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -75,7 +82,7 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit MyInfo(QObject *parent = nullptr);
|
||||
};
|
||||
|
@ -93,19 +100,4 @@ public:
|
|||
explicit ListDBG(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//----------------------------------
|
||||
|
||||
class CmdInfo : public InternCommand
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
|
||||
explicit CmdInfo(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
#endif // INFO_H
|
||||
|
|
|
@ -18,338 +18,88 @@
|
|||
|
||||
ListMods::ListMods(QObject *parent) : TableViewer(parent)
|
||||
{
|
||||
setParams(TABLE_MODULES, QStringList() << COLUMN_MOD_NAME << COLUMN_MOD_MAIN << COLUMN_LOCKED << COLUMN_CMD_ID_OFFS, false);
|
||||
setParams(TABLE_MODULES, false);
|
||||
addTableColumn(TABLE_MODULES, COLUMN_MOD_MAIN);
|
||||
}
|
||||
|
||||
UploadMod::UploadMod(QObject *parent) : InternCommand(parent)
|
||||
{
|
||||
dSize = 0;
|
||||
fileBuff = new QTemporaryFile(this);
|
||||
proc = new QProcess(this);
|
||||
|
||||
proc->setProcessChannelMode(QProcess::SeparateChannels);
|
||||
|
||||
connect(proc, SIGNAL(finished(int)), this, SLOT(procFinished(int)));
|
||||
connect(proc, SIGNAL(readyReadStandardOutput()), this, SLOT(rdTextFromProc()));
|
||||
connect(proc, SIGNAL(readyReadStandardError()), this, SLOT(rdErrFromProc()));
|
||||
}
|
||||
|
||||
DelMod::DelMod(QObject *parent) : InternCommand(parent) {}
|
||||
UploadMod::UploadMod(QObject *parent) : CmdObject(parent) {}
|
||||
DelMod::DelMod(QObject *parent) : CmdObject(parent) {}
|
||||
|
||||
QString ListMods::cmdName() {return "ls_mods";}
|
||||
QString DelMod::cmdName() {return "rm_mod";}
|
||||
QString UploadMod::cmdName() {return "add_mod";}
|
||||
|
||||
QString rmFileSuffix(const QString &filePath)
|
||||
bool UploadMod::isExecutable(const QString &path)
|
||||
{
|
||||
QString suffix = "." + QFileInfo(filePath).suffix();
|
||||
QFileInfo info(expandEnvVariables(path));
|
||||
|
||||
return filePath.left(filePath.size() - suffix.size());
|
||||
return info.exists() && info.isExecutable();
|
||||
}
|
||||
|
||||
bool validFileOnlyName(const QString &fileName)
|
||||
void UploadMod::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
QString forbidden = "/\\:*?\"<>|";
|
||||
bool ret = true;
|
||||
|
||||
if (fileName.contains(".."))
|
||||
{
|
||||
ret = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto&& chr : forbidden)
|
||||
{
|
||||
if (fileName.contains(chr, Qt::CaseInsensitive))
|
||||
{
|
||||
ret = false;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool UploadMod::handlesGenfile()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UploadMod::libExists(const QString &path)
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
|
||||
return QFileInfo::exists(path + ".dll") ||
|
||||
QFileInfo::exists(path + ".DLL");
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
|
||||
return QFileInfo::exists(path + ".so");
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_AIX
|
||||
|
||||
return QFileInfo::exists(path + ".a");
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
|
||||
return QFileInfo::exists(path + ".so") ||
|
||||
QFileInfo::exists(path + ".dylib") ||
|
||||
QFileInfo::exists(path + ".bundle");
|
||||
#endif
|
||||
}
|
||||
|
||||
void UploadMod::clearOnfailure()
|
||||
{
|
||||
QDir(modPath).removeRecursively();
|
||||
|
||||
Query db(this);
|
||||
|
||||
db.setType(Query::DEL, TABLE_MODULES);
|
||||
db.addCondition(COLUMN_MOD_NAME, modName);
|
||||
db.exec();
|
||||
}
|
||||
|
||||
void UploadMod::procFinished(int exStatus)
|
||||
{
|
||||
if (exStatus != 0)
|
||||
{
|
||||
errTxt("\nerr: The file operation stopped on error.\n");
|
||||
clearOnfailure();
|
||||
}
|
||||
else if (!libExists(modPath + "/main"))
|
||||
{
|
||||
errTxt("\nerr: The module's main library file does not exists or is not supported.\n");
|
||||
clearOnfailure();
|
||||
}
|
||||
else
|
||||
{
|
||||
Query db(this);
|
||||
|
||||
db.setType(Query::UPDATE, TABLE_MODULES);
|
||||
db.addColumn(COLUMN_LOCKED, false);
|
||||
db.addCondition(COLUMN_MOD_NAME, modName);
|
||||
db.exec();
|
||||
|
||||
emit backendDataOut(ASYNC_ENABLE_MOD, toTEXT(modName), PUB_IPC_WITH_FEEDBACK);
|
||||
|
||||
mainTxt("\nFinished...");
|
||||
}
|
||||
|
||||
term();
|
||||
}
|
||||
|
||||
void UploadMod::term()
|
||||
{
|
||||
if (proc->state() == QProcess::Running)
|
||||
{
|
||||
proc->blockSignals(true);
|
||||
proc->kill();
|
||||
}
|
||||
|
||||
fileBuff->close();
|
||||
|
||||
modPath.clear();
|
||||
modName.clear();
|
||||
|
||||
dSize = 0;
|
||||
|
||||
emit enableMoreInput(false);
|
||||
}
|
||||
|
||||
void UploadMod::rdErrFromProc()
|
||||
{
|
||||
errTxt(proc->readAllStandardError());
|
||||
}
|
||||
|
||||
void UploadMod::rdTextFromProc()
|
||||
{
|
||||
mainTxt(proc->readAllStandardOutput());
|
||||
}
|
||||
|
||||
void UploadMod::procStartError(QProcess::ProcessError err)
|
||||
{
|
||||
if (err == QProcess::FailedToStart)
|
||||
{
|
||||
errTxt("err: Could not start the host archiver. reason: " + proc->errorString() + "\n");
|
||||
clearOnfailure();
|
||||
term();
|
||||
}
|
||||
}
|
||||
|
||||
void UploadMod::setup()
|
||||
{
|
||||
mkPath(modPath);
|
||||
|
||||
if (QLibrary::isLibrary(clientFile))
|
||||
{
|
||||
QString suffix = QFileInfo(clientFile).completeSuffix();
|
||||
QString dst = modPath + "/main." + suffix;
|
||||
|
||||
mainTxt("copy file: " + fileBuff->fileName() + " --> " + dst + "\n");
|
||||
|
||||
if (QFile::copy(fileBuff->fileName(), dst))
|
||||
{
|
||||
procFinished(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
procFinished(1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Query db(this);
|
||||
|
||||
db.setType(Query::PULL, TABLE_SERV_SETTINGS);
|
||||
db.addColumn(COLUMN_ZIPBIN);
|
||||
db.addColumn(COLUMN_ZIPEXTRACT);
|
||||
db.exec();
|
||||
|
||||
QString exePath = db.getData(COLUMN_ZIPBIN).toString();
|
||||
QString cmdLine = db.getData(COLUMN_ZIPEXTRACT).toString();
|
||||
|
||||
cmdLine.replace(INPUT_DIR_SUB, "'" + fileBuff->fileName() + "'");
|
||||
cmdLine.replace(OUTPUT_DIR_SUB, "'" + modPath + "'");
|
||||
|
||||
proc->blockSignals(false);
|
||||
proc->setProgram(expandEnvVariables(exePath));
|
||||
proc->setArguments(parseArgs(toTEXT(cmdLine), -1));
|
||||
proc->start();
|
||||
}
|
||||
}
|
||||
|
||||
void UploadMod::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
{
|
||||
Q_UNUSED(sharedObjs)
|
||||
|
||||
if (moreInputEnabled() && (dType == GEN_FILE) && (proc->state() == QProcess::NotRunning))
|
||||
{
|
||||
if (fileBuff->write(binIn.data(), binIn.size()) == -1)
|
||||
{
|
||||
errTxt("err: Temp file write failure, unable to continue.\n");
|
||||
clearOnfailure();
|
||||
term();
|
||||
}
|
||||
else
|
||||
{
|
||||
mainTxt(QString::number(fileBuff->pos()) + "/" + QString::number(dSize) + "\n");
|
||||
|
||||
if (fileBuff->size() >= dSize)
|
||||
{
|
||||
mainTxt("\nUpload complete...setting up.\n\n");
|
||||
setup();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (dType == GEN_FILE)
|
||||
{
|
||||
QStringList args = parseArgs(binIn, -1);
|
||||
QString name = getParam("-name", args);
|
||||
QString len = getParam("-len", args);
|
||||
bool sOk = false;
|
||||
|
||||
clientFile = getParam("-client_file", args);
|
||||
dSize = len.toLongLong(&sOk, 10);
|
||||
modPath = modDataPath() + "/" + name;
|
||||
modName = name;
|
||||
|
||||
if (name.isEmpty())
|
||||
{
|
||||
errTxt("err: Module name (-name) argument not found or is empty.\n");
|
||||
}
|
||||
else if (len.isEmpty())
|
||||
{
|
||||
errTxt("err: Data length (-len) argument not found or is empty.\n");
|
||||
}
|
||||
if (maxedInstalledMods())
|
||||
{
|
||||
errTxt("err: Host maximum amount of installed modules has been reached.\n");
|
||||
}
|
||||
else if (!sOk)
|
||||
{
|
||||
errTxt("err: The given data length is not a valid integer.\n");
|
||||
}
|
||||
else if (name.size() > 64)
|
||||
{
|
||||
errTxt("err: The module name cannot be larger than 64 chars long.\n");
|
||||
}
|
||||
else if (!validFileOnlyName(name))
|
||||
{
|
||||
errTxt("err: Module names cannot contain the following chars: /\\:*?\"<>| or the updir sequence: '..'\n");
|
||||
}
|
||||
else if (modExists(name))
|
||||
{
|
||||
errTxt("err: A module of the same name already exists.\n");
|
||||
}
|
||||
else if (!fileBuff->open())
|
||||
{
|
||||
errTxt("err: Could not open a new temp file for reading/writing.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
Query db(this);
|
||||
|
||||
db.setType(Query::PULL, TABLE_MODULES);
|
||||
db.addColumn(COLUMN_MOD_NAME);
|
||||
db.exec();
|
||||
|
||||
quint16 idOffs = static_cast<quint16>((db.rows() + 2) * MAX_CMDS_PER_MOD) + 1;
|
||||
|
||||
db.setType(Query::PUSH, TABLE_MODULES);
|
||||
db.addColumn(COLUMN_MOD_NAME, name);
|
||||
db.addColumn(COLUMN_MOD_MAIN, modPath + "/main");
|
||||
db.addColumn(COLUMN_CMD_ID_OFFS, idOffs);
|
||||
db.addColumn(COLUMN_LOCKED, true);
|
||||
db.exec();
|
||||
|
||||
mainTxt("Input hooked...uploading data.\n\n");
|
||||
|
||||
emit enableMoreInput(true);
|
||||
emit dataToClient(toTEXT("-to_host"), GEN_FILE);
|
||||
emit dataToClient(QByteArray(), GEN_FILE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DelMod::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
{
|
||||
Q_UNUSED(sharedObjs)
|
||||
|
||||
if (dType == TEXT)
|
||||
{
|
||||
QStringList args = parseArgs(binIn, 2);
|
||||
QString name = getParam("-name", args);
|
||||
QString path = getParam("-mod_path", args);
|
||||
|
||||
if (name.isEmpty())
|
||||
if (path.isEmpty())
|
||||
{
|
||||
errTxt("err: Module name argument (-name) was not found or is empty.\n");
|
||||
errTxt("err: The path to module executable (-mod_path) argument not found or is empty.\n");
|
||||
}
|
||||
else if (!validFileOnlyName(name))
|
||||
else if (!validModPath(path))
|
||||
{
|
||||
errTxt("err: Module names cannot contain the following chars: /\\:*?\"<>| or the updir sequence: '..'\n");
|
||||
errTxt("err: The module path cannot contain the following chars: :*?\"<>|\n");
|
||||
}
|
||||
else if (!modExists(name))
|
||||
else if (modExists(path))
|
||||
{
|
||||
errTxt("err: No such module found: '" + name + "'\n");
|
||||
errTxt("err: The module already exists.\n");
|
||||
}
|
||||
else if (!isExecutable(path))
|
||||
{
|
||||
errTxt("err: Executable: " + path + " does not exists or does not have execution permissions.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
Query db(this);
|
||||
|
||||
db.setType(Query::UPDATE, TABLE_MODULES);
|
||||
db.addColumn(COLUMN_LOCKED, true);
|
||||
db.addCondition(COLUMN_MOD_NAME, name);
|
||||
db.setType(Query::PUSH, TABLE_MODULES);
|
||||
db.addColumn(COLUMN_MOD_MAIN, path);
|
||||
db.exec();
|
||||
|
||||
emit backendDataOut(ASYNC_DISABLE_MOD, toTEXT(name), PRIV_IPC);
|
||||
emit backendDataOut(ASYNC_DISABLE_MOD, toTEXT(name), PUB_IPC_WITH_FEEDBACK);
|
||||
async(ASYNC_ENABLE_MOD, PUB_IPC_WITH_FEEDBACK, toTEXT(path));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DelMod::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
if (dType == TEXT)
|
||||
{
|
||||
QStringList args = parseArgs(binIn, 2);
|
||||
QString path = getParam("-mod_path", args);
|
||||
|
||||
if (path.isEmpty())
|
||||
{
|
||||
errTxt("err: The path to module executable (-mod_path) argument not found or is empty.\n");
|
||||
}
|
||||
else if (!validModPath(path))
|
||||
{
|
||||
errTxt("err: The module path cannot contain the following chars: :*?\"<>|\n");
|
||||
}
|
||||
else if (!modExists(path))
|
||||
{
|
||||
errTxt("err: No such module found: '" + path + "'\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
Query db(this);
|
||||
|
||||
db.setType(Query::DEL, TABLE_MODULES);
|
||||
db.addCondition(COLUMN_MOD_MAIN, path);
|
||||
db.exec();
|
||||
|
||||
async(ASYNC_DISABLE_MOD, PUB_IPC_WITH_FEEDBACK, toTEXT(path));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,49 +18,32 @@
|
|||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "../common.h"
|
||||
#include "../cmd_object.h"
|
||||
#include "table_viewer.h"
|
||||
|
||||
QString rmFileSuffix(const QString &filePath);
|
||||
bool validFileOnlyName(const QString &fileName);
|
||||
|
||||
class UploadMod : public InternCommand
|
||||
class UploadMod : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
|
||||
QProcess *proc;
|
||||
QString clientFile;
|
||||
QString modName;
|
||||
QString modPath;
|
||||
QTemporaryFile *fileBuff;
|
||||
qint64 dSize;
|
||||
|
||||
void clearOnfailure();
|
||||
void setup();
|
||||
bool libExists(const QString &path);
|
||||
|
||||
private slots:
|
||||
|
||||
void rdTextFromProc();
|
||||
void rdErrFromProc();
|
||||
void procFinished(int exStatus);
|
||||
void procStartError(QProcess::ProcessError err);
|
||||
bool isExecutable(const QString &path);
|
||||
|
||||
public:
|
||||
|
||||
static QString cmdName();
|
||||
|
||||
bool handlesGenfile();
|
||||
void term();
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit UploadMod(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//-------------------------------
|
||||
|
||||
class DelMod : public InternCommand
|
||||
class DelMod : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -68,7 +51,7 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit DelMod(QObject *parent = nullptr);
|
||||
};
|
||||
|
|
|
@ -16,11 +16,11 @@
|
|||
// along with MRCI under the LICENSE.md file. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
ToPeer::ToPeer(QObject *parent) : InternCommand(parent) {}
|
||||
P2PRequest::P2PRequest(QObject *parent) : InternCommand(parent) {}
|
||||
P2POpen::P2POpen(QObject *parent) : InternCommand(parent) {}
|
||||
P2PClose::P2PClose(QObject *parent) : InternCommand(parent) {}
|
||||
LsP2P::LsP2P(QObject *parent) : InternCommand(parent) {}
|
||||
ToPeer::ToPeer(QObject *parent) : CmdObject(parent) {}
|
||||
P2PRequest::P2PRequest(QObject *parent) : CmdObject(parent) {}
|
||||
P2POpen::P2POpen(QObject *parent) : CmdObject(parent) {}
|
||||
P2PClose::P2PClose(QObject *parent) : CmdObject(parent) {}
|
||||
LsP2P::LsP2P(QObject *parent) : CmdObject(parent) {}
|
||||
|
||||
QString ToPeer::cmdName() {return "to_peer";}
|
||||
QString P2PRequest::cmdName() {return "p2p_request";}
|
||||
|
@ -28,92 +28,133 @@ QString P2POpen::cmdName() {return "p2p_open";}
|
|||
QString P2PClose::cmdName() {return "p2p_close";}
|
||||
QString LsP2P::cmdName() {return "ls_p2p";}
|
||||
|
||||
void ToPeer::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void ToPeer::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
QByteArray peerId = binIn.left(28);
|
||||
|
||||
if (!sharedObjs->p2pAccepted->contains(peerId))
|
||||
if (binIn.size() >= BLKSIZE_SESSION_ID)
|
||||
{
|
||||
errTxt("err: You don't current have an open p2p connection with the requested peer.");
|
||||
errTxt("err: The p2p data does not contain a session id header.\n");
|
||||
}
|
||||
if (posOfBlock(binIn.data(), p2pAccepted, MAX_P2P_LINKS, BLKSIZE_SESSION_ID) == -1)
|
||||
{
|
||||
errTxt("err: You don't currently have an open p2p connection with the requested peer.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
emit toPeer(peerId, binIn.mid(28), dType);
|
||||
quint32 len = static_cast<quint32>(binIn.size());
|
||||
QByteArray dst = rdFromBlock(binIn.data(), BLKSIZE_SESSION_ID);
|
||||
QByteArray src = rdFromBlock(sessionId, BLKSIZE_SESSION_ID);
|
||||
QByteArray data = rdFromBlock(binIn.data() + BLKSIZE_SESSION_ID, len - BLKSIZE_SESSION_ID);
|
||||
QByteArray typeBa = wrInt(dType, 8);
|
||||
|
||||
async(ASYNC_P2P, PUB_IPC, dst + src + typeBa + data);
|
||||
}
|
||||
}
|
||||
|
||||
void P2PRequest::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void P2PRequest::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
if (dType == SESSION_ID)
|
||||
{
|
||||
if (binIn.size() != 28)
|
||||
if (binIn.size() != BLKSIZE_SESSION_ID)
|
||||
{
|
||||
errTxt("err: The given client session id does not equal 28 bytes.");
|
||||
errTxt("err: The given client session id does not equal " + QString::number(BLKSIZE_SESSION_ID) + " bytes.\n");
|
||||
}
|
||||
else if (sharedObjs->p2pAccepted->contains(binIn))
|
||||
else if (posOfBlock(binIn.data(), p2pAccepted, MAX_P2P_LINKS, BLKSIZE_SESSION_ID) != -1)
|
||||
{
|
||||
errTxt("err: You already have an open p2p connection with the requested peer.");
|
||||
errTxt("err: You already have an open p2p connection with the requested peer.\n");
|
||||
}
|
||||
else if (sharedObjs->p2pPending->contains(binIn))
|
||||
else if (posOfBlock(binIn.data(), p2pPending, MAX_P2P_LINKS, BLKSIZE_SESSION_ID) != -1)
|
||||
{
|
||||
errTxt("err: There is already a pending p2p request for this peer.");
|
||||
errTxt("err: There is already a pending p2p request for this peer.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
emit toPeer(binIn, QByteArray(), P2P_REQUEST);
|
||||
QByteArray dst = rdFromBlock(binIn.data(), BLKSIZE_SESSION_ID);
|
||||
QByteArray src = rdFromBlock(sessionId, BLKSIZE_SESSION_ID);
|
||||
QByteArray typeBa = wrInt(P2P_REQUEST, 8);
|
||||
|
||||
async(ASYNC_P2P, PUB_IPC, dst + src + typeBa + dst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void P2POpen::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void P2POpen::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
if (dType == SESSION_ID)
|
||||
{
|
||||
if (binIn.size() != 28)
|
||||
if (binIn.size() != BLKSIZE_SESSION_ID)
|
||||
{
|
||||
errTxt("err: The given client session id does not equal 28 bytes.");
|
||||
errTxt("err: The given client session id does not equal " + QString::number(BLKSIZE_SESSION_ID) + " bytes.\n");
|
||||
}
|
||||
else if (sharedObjs->p2pAccepted->contains(binIn))
|
||||
else if (posOfBlock(binIn.data(), p2pAccepted, MAX_P2P_LINKS, BLKSIZE_SESSION_ID) != -1)
|
||||
{
|
||||
errTxt("err: You already have an open p2p connection with the requested peer.");
|
||||
errTxt("err: You already have an open p2p connection with the requested peer.\n");
|
||||
}
|
||||
else if (!sharedObjs->p2pPending->contains(binIn))
|
||||
else if (posOfBlock(binIn.data(), p2pPending, MAX_P2P_LINKS, BLKSIZE_SESSION_ID) != -1)
|
||||
{
|
||||
errTxt("err: There is no pending p2p request for the given peer.");
|
||||
errTxt("err: There is no pending p2p request for the given peer.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
emit toPeer(binIn, QByteArray(), P2P_OPEN);
|
||||
QByteArray dst = rdFromBlock(binIn.data(), BLKSIZE_SESSION_ID);
|
||||
QByteArray src = rdFromBlock(sessionId, BLKSIZE_SESSION_ID);
|
||||
QByteArray typeBa = wrInt(P2P_OPEN, 8);
|
||||
|
||||
async(ASYNC_P2P, PUB_IPC, dst + src + typeBa + dst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void P2PClose::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void P2PClose::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
if (dType == SESSION_ID)
|
||||
{
|
||||
if (binIn.size() != 28)
|
||||
if (binIn.size() != BLKSIZE_SESSION_ID)
|
||||
{
|
||||
errTxt("err: The given client session id does not equal 28 bytes.");
|
||||
errTxt("err: The given client session id does not equal " + QString::number(BLKSIZE_SESSION_ID) + " bytes.\n");
|
||||
}
|
||||
else if (!sharedObjs->p2pAccepted->contains(binIn) && !sharedObjs->p2pPending->contains(binIn))
|
||||
else if ((posOfBlock(binIn.data(), p2pAccepted, MAX_P2P_LINKS, BLKSIZE_SESSION_ID) != -1) &&
|
||||
(posOfBlock(binIn.data(), p2pPending, MAX_P2P_LINKS, BLKSIZE_SESSION_ID) != -1))
|
||||
{
|
||||
errTxt("err: There is no pending p2p request or p2p connection with the given peer.");
|
||||
errTxt("err: There is no pending p2p request or p2p connection with the given peer.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
emit toPeer(binIn, QByteArray(), P2P_CLOSE);
|
||||
QByteArray dst = rdFromBlock(binIn.data(), BLKSIZE_SESSION_ID);
|
||||
QByteArray src = rdFromBlock(sessionId, BLKSIZE_SESSION_ID);
|
||||
QByteArray typeBa = wrInt(P2P_CLOSE, 8);
|
||||
|
||||
async(P2P_CLOSE, PUB_IPC, dst + src + typeBa + dst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LsP2P::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
QList<QByteArray> LsP2P::lsBlocks(const char *blocks, int maxBlocks, int sizeOfBlock)
|
||||
{
|
||||
Q_UNUSED(binIn);
|
||||
QList<QByteArray> ret;
|
||||
|
||||
QByteArray blank(sizeOfBlock, 0x00);
|
||||
|
||||
for (int i = 0; i < (maxBlocks * sizeOfBlock); i += sizeOfBlock)
|
||||
{
|
||||
QByteArray block = rdFromBlock(blocks + i, static_cast<quint32>(sizeOfBlock));
|
||||
|
||||
if (block != blank)
|
||||
{
|
||||
ret.append(block);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void LsP2P::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
Q_UNUSED(binIn)
|
||||
|
||||
if (dType == TEXT)
|
||||
{
|
||||
QList<QByteArray> peerIds = *sharedObjs->p2pAccepted + *sharedObjs->p2pPending;
|
||||
QList<QByteArray> peerIds = lsBlocks(p2pAccepted, MAX_P2P_LINKS, BLKSIZE_SESSION_ID) +
|
||||
lsBlocks(p2pPending, MAX_P2P_LINKS, BLKSIZE_SESSION_ID);
|
||||
QList<QStringList> tableData;
|
||||
QStringList separators;
|
||||
QList<int> justLens;
|
||||
|
@ -132,7 +173,7 @@ void LsP2P::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar
|
|||
QString pending = "0";
|
||||
QStringList columnData;
|
||||
|
||||
if (sharedObjs->p2pPending->contains(peerId))
|
||||
if (posOfBlock(peerId.data(), p2pPending, MAX_P2P_LINKS, BLKSIZE_SESSION_ID) != -1)
|
||||
{
|
||||
pending = "1";
|
||||
}
|
||||
|
@ -154,7 +195,7 @@ void LsP2P::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar
|
|||
{
|
||||
for (int i = 0; i < row.size(); ++i)
|
||||
{
|
||||
mainTxt(row[i].leftJustified(justLens[i] + 2, ' '));
|
||||
mainTxt(row[i].leftJustified(justLens[i] + 4, ' '));
|
||||
}
|
||||
|
||||
mainTxt("\n");
|
||||
|
|
|
@ -18,8 +18,9 @@
|
|||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "../common.h"
|
||||
#include "../cmd_object.h"
|
||||
|
||||
class ToPeer : public InternCommand
|
||||
class ToPeer : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -27,14 +28,14 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit ToPeer(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//----------------------------------
|
||||
|
||||
class P2PRequest : public InternCommand
|
||||
class P2PRequest : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -42,14 +43,14 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit P2PRequest(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//-----------------------------------
|
||||
|
||||
class P2POpen : public InternCommand
|
||||
class P2POpen : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -57,14 +58,14 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit P2POpen(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//----------------------------------
|
||||
|
||||
class P2PClose : public InternCommand
|
||||
class P2PClose : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -72,22 +73,26 @@ public:
|
|||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit P2PClose(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
//----------------------------------
|
||||
|
||||
class LsP2P : public InternCommand
|
||||
class LsP2P : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
|
||||
QList<QByteArray> lsBlocks(const char* blocks, int maxBlocks, int sizeOfBlock);
|
||||
|
||||
public:
|
||||
|
||||
static QString cmdName();
|
||||
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit LsP2P(QObject *parent = nullptr);
|
||||
};
|
||||
|
|
|
@ -16,201 +16,245 @@
|
|||
// along with MRCI under the LICENSE.md file. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
TableViewer::TableViewer(QObject *parent) : InternCommand(parent)
|
||||
TableViewer::TableViewer(QObject *parent) : CmdObject(parent)
|
||||
{
|
||||
delOption = false;
|
||||
|
||||
term();
|
||||
idle();
|
||||
}
|
||||
|
||||
void TableViewer::term()
|
||||
void TableViewer::idle()
|
||||
{
|
||||
emit enableMoreInput(false);
|
||||
|
||||
del = false;
|
||||
flags = 0;
|
||||
offset = 0;
|
||||
|
||||
cachedArgs.clear();
|
||||
db.setType(Query::PULL, "");
|
||||
delMode = false;
|
||||
condAdded = false;
|
||||
}
|
||||
|
||||
void TableViewer::setParams(const QString &tbl, const QStringList &colms, bool allowDel)
|
||||
void TableViewer::setParams(const QString &mainTbl, bool allowDel)
|
||||
{
|
||||
columns = colms;
|
||||
table = tbl;
|
||||
rdQuery.setType(Query::INNER_JOIN_PULL, mainTbl);
|
||||
delQuery.setType(Query::DEL, mainTbl);
|
||||
|
||||
delOption = allowDel;
|
||||
}
|
||||
|
||||
void TableViewer::procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType)
|
||||
void TableViewer::addTableColumn(const QString &tbl, const QString &column)
|
||||
{
|
||||
Q_UNUSED(sharedObjs);
|
||||
|
||||
if (dType == TEXT)
|
||||
if (columnType(column) == "BLOB")
|
||||
{
|
||||
QStringList args = parseArgs(binIn, -1);
|
||||
bool close = false;
|
||||
|
||||
if (delOption && argExists("-delete", args))
|
||||
{
|
||||
del = true;
|
||||
blobIndexes.append(columns.size());
|
||||
}
|
||||
|
||||
if (moreInputEnabled() && !del)
|
||||
if (columnRows.isEmpty())
|
||||
{
|
||||
if (args.contains("q", Qt::CaseInsensitive))
|
||||
{
|
||||
close = true;
|
||||
columnRows.append(QStringList());
|
||||
columnRows.append(QStringList());
|
||||
}
|
||||
else
|
||||
|
||||
tables.append(tbl);
|
||||
columns.append(column);
|
||||
rdQuery.addTableColumn(tbl, column);
|
||||
|
||||
columnRows[0].append(column);
|
||||
columnRows[1].append("-------");
|
||||
}
|
||||
|
||||
void TableViewer::addJointColumn(const QString &tbl, const QString &column)
|
||||
{
|
||||
rdQuery.addJoinCondition(column, tbl);
|
||||
}
|
||||
|
||||
void TableViewer::nextPage()
|
||||
{
|
||||
rdQuery.setQueryLimit(MAX_LS_ENTRIES, offset);
|
||||
rdQuery.exec();
|
||||
|
||||
dispData();
|
||||
|
||||
if (rdQuery.rows() == MAX_LS_ENTRIES)
|
||||
{
|
||||
offset += MAX_LS_ENTRIES;
|
||||
args = cachedArgs;
|
||||
}
|
||||
}
|
||||
|
||||
if (close)
|
||||
{
|
||||
term();
|
||||
}
|
||||
else if (moreInputEnabled() && del)
|
||||
{
|
||||
QString ans = fromTEXT(binIn);
|
||||
|
||||
if (noCaseMatch("y", ans))
|
||||
{
|
||||
db.exec();
|
||||
|
||||
term();
|
||||
}
|
||||
else if (noCaseMatch("n", ans))
|
||||
{
|
||||
term();
|
||||
askPage();
|
||||
}
|
||||
else
|
||||
{
|
||||
mainTxt("continue? (y/n): ");
|
||||
idle();
|
||||
}
|
||||
}
|
||||
else
|
||||
}
|
||||
|
||||
void TableViewer::addWhereConds(const QStringList &userArgs)
|
||||
{
|
||||
if (delOption)
|
||||
{
|
||||
if (del)
|
||||
{
|
||||
db.setType(Query::DEL, table);
|
||||
}
|
||||
else
|
||||
{
|
||||
db.setType(Query::PULL, table);
|
||||
db.setQueryLimit(MAX_LS_ENTRIES, offset);
|
||||
delMode = argExists("-delete", userArgs);
|
||||
}
|
||||
|
||||
bool noDelParams = true;
|
||||
rdQuery.clearConditions();
|
||||
delQuery.clearConditions();
|
||||
|
||||
for (int i = 0; i < columns.size(); ++i)
|
||||
{
|
||||
if (!del) db.addColumn(columns[i]);
|
||||
QString value = getParam("-" + columns[i], userArgs);
|
||||
|
||||
QString param = getParam("-" + columns[i], args);
|
||||
|
||||
if (!param.isEmpty())
|
||||
if (!value.isEmpty())
|
||||
{
|
||||
if (del)
|
||||
if (delMode)
|
||||
{
|
||||
if (noDelParams) mainTxt("\n");
|
||||
mainTxt("delete parameter: " + columns[i] + " ~= " + value + "\n");
|
||||
|
||||
mainTxt("delete param: " + columns[i] + " = " + param + "\n");
|
||||
|
||||
noDelParams = false;
|
||||
condAdded = true;
|
||||
}
|
||||
|
||||
db.addCondition(columns[i], param, Query::LIKE);
|
||||
rdQuery.addCondition(columns[i], value, Query::LIKE, tables[i]);
|
||||
delQuery.addCondition(columns[i], value, Query::LIKE, tables[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (del)
|
||||
if (condAdded)
|
||||
{
|
||||
emit enableMoreInput(true);
|
||||
|
||||
if (noDelParams) mainTxt("\nabout to delete ALL entries in this table.\n");
|
||||
|
||||
mainTxt("\ncontinue? (y/n): ");
|
||||
}
|
||||
else
|
||||
{
|
||||
db.exec();
|
||||
|
||||
QStringList separators;
|
||||
QList<QStringList> tableData;
|
||||
QList<int> justLens;
|
||||
|
||||
for (int i = 0; i < columns.size(); ++i)
|
||||
{
|
||||
justLens.append(0);
|
||||
separators.append("-------");
|
||||
}
|
||||
|
||||
for (int i = 0; i < db.rows() + 2; ++i)
|
||||
{
|
||||
QStringList columnData;
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
columnData = columns;
|
||||
}
|
||||
else if (i == 1)
|
||||
{
|
||||
columnData = separators;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int j = 0; j < columns.size(); ++j)
|
||||
{
|
||||
if (columnType(columns[j]) == "BLOB")
|
||||
{
|
||||
columnData.append(db.getData(columns[j], i - 2).toByteArray().toHex());
|
||||
}
|
||||
else
|
||||
{
|
||||
columnData.append(db.getData(columns[j], i - 2).toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int k = 0; k < justLens.size(); ++k)
|
||||
{
|
||||
if (justLens[k] < columnData[k].size()) justLens[k] = columnData[k].size();
|
||||
}
|
||||
|
||||
tableData.append(columnData);
|
||||
}
|
||||
|
||||
mainTxt("\n");
|
||||
}
|
||||
}
|
||||
|
||||
for (auto&& row : tableData)
|
||||
void TableViewer::askDelete()
|
||||
{
|
||||
if (condAdded)
|
||||
{
|
||||
mainTxt("This will delete rows from the table according to the parameters above. continue (y/n)?: ");
|
||||
}
|
||||
else
|
||||
{
|
||||
mainTxt("This will delete all rows in the table. continue (y/n)?: ");
|
||||
}
|
||||
|
||||
flags |= MORE_INPUT;
|
||||
}
|
||||
|
||||
void TableViewer::askPage()
|
||||
{
|
||||
mainTxt("\nnext page (y/n)?: ");
|
||||
|
||||
flags |= MORE_INPUT;
|
||||
}
|
||||
|
||||
QList<QStringList> TableViewer::toStrings(const QList<QList<QVariant> > &data)
|
||||
{
|
||||
QList<QStringList> ret;
|
||||
|
||||
for (auto&& srcRow: data)
|
||||
{
|
||||
QStringList dstRow;
|
||||
|
||||
for (int i = 0; i < srcRow.size(); ++i)
|
||||
{
|
||||
if (blobIndexes.contains(i))
|
||||
{
|
||||
dstRow.append(srcRow[i].toByteArray().toHex());
|
||||
}
|
||||
else
|
||||
{
|
||||
dstRow.append(srcRow[i].toString());
|
||||
}
|
||||
}
|
||||
|
||||
ret.append(dstRow);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
QList<int> TableViewer::getColumnLens(const QList<QStringList> &data)
|
||||
{
|
||||
QList<int> ret;
|
||||
|
||||
for (int i = 0; i < columns.size(); ++i)
|
||||
{
|
||||
ret.append(0);
|
||||
}
|
||||
|
||||
for (auto&& row: data)
|
||||
{
|
||||
for (int i = 0; i < row.size(); ++i)
|
||||
{
|
||||
mainTxt(row[i].leftJustified(justLens[i] + 2, ' '));
|
||||
if (row[i].size() >= ret[i])
|
||||
{
|
||||
ret[i] = row[i].size() + 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void TableViewer::dispData()
|
||||
{
|
||||
QList<QStringList> tableRows = toStrings(rdQuery.allData());
|
||||
QList<int> lens = getColumnLens(columnRows + tableRows);
|
||||
|
||||
for (auto&& row: columnRows + tableRows)
|
||||
{
|
||||
for (int i = 0; i < row.size(); ++i)
|
||||
{
|
||||
mainTxt(row[i].leftJustified(lens[i], ' '));
|
||||
}
|
||||
|
||||
mainTxt("\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (db.rows() == MAX_LS_ENTRIES)
|
||||
void TableViewer::procIn(const QByteArray &binIn, quint8 dType)
|
||||
{
|
||||
if (dType == TEXT)
|
||||
{
|
||||
if (!moreInputEnabled())
|
||||
if (flags & MORE_INPUT)
|
||||
{
|
||||
cachedArgs = args;
|
||||
QString text = fromTEXT(binIn).toLower();
|
||||
|
||||
emit enableMoreInput(true);
|
||||
}
|
||||
if (text == "y")
|
||||
{
|
||||
if (delMode)
|
||||
{
|
||||
delQuery.exec();
|
||||
|
||||
mainTxt("\n[enter or any] more, [q] close: ");
|
||||
mainTxt(delQuery.errDetail());
|
||||
idle();
|
||||
onDel();
|
||||
}
|
||||
else
|
||||
{
|
||||
term();
|
||||
nextPage();
|
||||
}
|
||||
}
|
||||
else if (text == "n")
|
||||
{
|
||||
idle();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (delMode)
|
||||
{
|
||||
askDelete();
|
||||
}
|
||||
else
|
||||
{
|
||||
askPage();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
addWhereConds(parseArgs(binIn, -1));
|
||||
|
||||
if (delMode)
|
||||
{
|
||||
askDelete();
|
||||
}
|
||||
else
|
||||
{
|
||||
nextPage();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,26 +18,42 @@
|
|||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "../common.h"
|
||||
#include "../cmd_object.h"
|
||||
|
||||
class TableViewer : public InternCommand
|
||||
class TableViewer : public CmdObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
protected:
|
||||
|
||||
Query db;
|
||||
QString table;
|
||||
QStringList columns;
|
||||
QStringList cachedArgs;
|
||||
Query rdQuery;
|
||||
Query delQuery;
|
||||
bool condAdded;
|
||||
bool delOption;
|
||||
bool del;
|
||||
uint offset;
|
||||
bool delMode;
|
||||
quint32 offset;
|
||||
QList<QString> columns;
|
||||
QList<QString> tables;
|
||||
QList<int> blobIndexes;
|
||||
QList<QStringList> columnRows;
|
||||
|
||||
QList<QStringList> toStrings(const QList<QList<QVariant> > &data);
|
||||
QList<int> getColumnLens(const QList<QStringList> &data);
|
||||
void addWhereConds(const QStringList &userArgs);
|
||||
void askDelete();
|
||||
void askPage();
|
||||
void dispData();
|
||||
|
||||
virtual void onDel() {}
|
||||
|
||||
public:
|
||||
|
||||
void term();
|
||||
void setParams(const QString &tbl, const QStringList &colms, bool allowDel);
|
||||
void procBin(const SharedObjs *sharedObjs, const QByteArray &binIn, uchar dType);
|
||||
void idle();
|
||||
void nextPage();
|
||||
void addJointColumn(const QString &tbl, const QString &column);
|
||||
void addTableColumn(const QString &tbl, const QString &column);
|
||||
void setParams(const QString &mainTbl, bool allowDel);
|
||||
void procIn(const QByteArray &binIn, quint8 dType);
|
||||
|
||||
explicit TableViewer(QObject *parent = nullptr);
|
||||
};
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user