Versioning system change and support of new MRCI host features
added support for the new PROMPT_TEXT data type id. it is simply treated like any other TEXT type for this application. added a hiddden progress bar below the main text body that will only kick in when it detects a string of the PROG/PROG_LAST data types. refactored "halt" to "yield" on the client's internal command. also refactored "text_settings" to "theme" on the json config file. the config file name will now also include the major version number as a way to verify compatibility as the client is updated. changed the client's versioning system to a 2 number system. more info about this new system was edited into the README.md file. synced the type_id and async_id values with MRCI host. added support for the new MRCI host 4 number versioning system. this client will only care about the tcp_rev part of this new system for now. any changes to the hosts' core commands shouldn't affect compatibility with this client.
This commit is contained in:
parent
34753488ff
commit
3f39ba8767
|
@ -1,6 +1,6 @@
|
|||
# Cmdr #
|
||||
|
||||
Cmdr is a command line terminal emulator client for MRCI host using text input/output. This helps administer MRCI host via local or remote TCP connections encrypted with TLS/SSL using the MRCI protocol. It also supports file transfers to/from the client using the GEN_FILE sub-protocol that MRCI understands.
|
||||
Cmdr is a command line terminal emulator client for MRCI host using text input/output. This help administer MRCI host via local or remote TCP connections encrypted with TLS/SSL using the MRCI protocol. It also supports file transfers to/from the client using the GEN_FILE sub-protocol that MRCI understands.
|
||||
|
||||
### Usage ###
|
||||
|
||||
|
@ -8,13 +8,12 @@ Cmdr have it's own terminal display so there is no command line switches to pass
|
|||
|
||||
### Versioning System ###
|
||||
|
||||
This application uses the typical 3 number versioning system: [major].[minor].[patch]
|
||||
This application uses a 2 number versioning system: [major].[minor]
|
||||
|
||||
* Major - this indicates any major changes to the application or changes that render user data of different majors incompatible.
|
||||
* Minor - this indicates changes to the code that still maintains compatibility with existing user data.
|
||||
* Patch - this indicates changes that won't require any behaviour changes at all.
|
||||
* Major - this indicates any changes that cause old configuration or library files to be incompatible.
|
||||
* Minor - this indicates changes to the code that still maintains compatibility with existing config files or libraries.
|
||||
|
||||
Any increments to major resets minor and patch to 0.
|
||||
Any increments to major resets minor to 0.
|
||||
|
||||
### The Protocol ###
|
||||
|
||||
|
@ -58,19 +57,20 @@ notes:
|
|||
|
||||
* The **appName** is the name of the client application that is connected to the host. It can also contain the client's app version if needed because it doesn't follow any particular standard.
|
||||
|
||||
* The **coName** is the common name of a SSL certificate that is currently installed in the host. Depending on how the host is configured, it can contain more than one installed SSL cert so coName can be used by clients as a way to request which one of the SSL certs to use during the SSL handshake.
|
||||
* The **coName** is the common name of a SSL certificate that is currently installed in the host. Depending on how the host is configured, it can contain more than one installed SSL cert so coName can be used by clients as a way to request which one of the SSL certs to use during the SSL handshake. If the client doesn't know which cert to request, it is good practice to use the address that was used to connect to the host.
|
||||
|
||||
### Host Header ###
|
||||
|
||||
```
|
||||
Format:
|
||||
|
||||
[reply][major][minor][patch][sesId]
|
||||
[reply][major][minor][tcp_rev][mod_rev][sesId]
|
||||
|
||||
reply - 1byte - 8bit little endian unsigned int
|
||||
major - 2bytes - 16bit little endian unsigned int
|
||||
minor - 2bytes - 16bit little endian unsigned int
|
||||
patch - 2bytes - 16bit little endian unsigned int
|
||||
tcp_rev - 2bytes - 16bit little endian unsigned int
|
||||
mod_rev - 2bytes - 16bit little endian unsigned int
|
||||
sesId - 28bytes - 224bit sha3 hash
|
||||
```
|
||||
|
||||
|
@ -82,7 +82,7 @@ notes:
|
|||
* reply = 2, means the client is acceptable but the host will now send it's Pem formatted SSL cert data in a ```HOST_CERT``` mrci frame just after sending it's header. After receiving the cert, the client will then need to send a STARTTLS signal using this cert.
|
||||
* reply = 4, means the host was unable to find the SSL cert associated with the common name sent by the client. The session will auto close at this point.
|
||||
|
||||
* **major**, **minor**, **path** these 3 numeric values are the host version number that also use a 3 number versioning system. This can be used by the client to setup backwards compatibility or determine of if supports the host at all. If not supported, the client can simply disconnect form the host.
|
||||
* **major**, **minor**, **tcp_rev**, **mod_rev** these 4 numeric values are the host version number that uses a 4 number versioning system. This can be used by the client to setup backwards compatibility or determine of if supports the host at all. If not supported, the client can simply disconnect form the host and display an error to the user.
|
||||
|
||||
* **sesId** is the session id. It is a unique 224bit sha3 hash that can be used by the host and client to uniquely identify the current session or past sessions.
|
||||
|
||||
|
@ -106,7 +106,7 @@ makeself
|
|||
Linux_build.sh is a custom script designed to build this project from the source code using qmake, make and makeself. You can pass 2 optional arguments:
|
||||
|
||||
1. The path to the QT bin folder in case you want to compile with a QT install not defined in PATH.
|
||||
2. Path of the output makeself file (usually has a .run extension). If not given, the outfile will be named cmdr-x.x.x.run in the source code folder.
|
||||
2. Path of the output makeself file (usually has a .run extension). If not given, the outfile will be named cmdr-x.x.run in the source code folder.
|
||||
|
||||
Build:
|
||||
```
|
||||
|
@ -115,6 +115,6 @@ sh ./linux_build.sh
|
|||
```
|
||||
Install:
|
||||
```
|
||||
chmod +x ./cmdr-x.x.x.run
|
||||
./cmdr-x.x.x.run
|
||||
chmod +x ./cmdr-x.x.run
|
||||
./cmdr-x.x.run
|
||||
```
|
||||
|
|
|
@ -2,40 +2,36 @@
|
|||
|
||||
An async command is a virtual command that the host can use to send data to the client at any time while connected to the host. As the name implies, the occurance of a client receiving data from an async command is not always the result of running a regular command in the current session. This can occur for example when information in your account is changed by another client connected to the host; your client would not know about this change until an async command is sent notify it of the change. These commands can be called directly or indirectly by a module and are considered "virtual" commands because there is no defined objects attached to them. Instead, async commands are best identified by command id values 1-255.
|
||||
|
||||
Async commands are not only used to send data to the client but also used internally within the host to help objects operating in different processes to communicate with each other. Some async commands in fact are considered internal only because the client should never see any data come from them at anytime. There is also data flow contriants for aysnc commands, meaning some gets blocked if sent from the module or has no effect if sent with the unexpected [IPC](type_ids.md) type id. The list below shows the various data flow contriants each of these async commands have.
|
||||
Async commands are not only used to send data to the client but also used internally within the host to help objects operating in different processes to communicate with each other. Some async commands in fact are considered internal only because the client should never see any data come from them at anytime. There is also data flow contriants for async commands, meaning some gets blocked if sent from the module or has no effect if sent with the unexpected [IPC](type_ids.md) type id. The list below shows the various data flow contriants each of these async commands have.
|
||||
|
||||
Here is a describtion of what the keywords in the list mean:
|
||||
```
|
||||
client - this means the async command id will be used to forward
|
||||
data of any type to client if needed.
|
||||
|
||||
internal - this means the async command will be responded by the
|
||||
session object but the data will not be forwarded to the
|
||||
client or converted to an entirely different async
|
||||
command before sending to the client.
|
||||
internal - this means the async command used by internal host
|
||||
objects only so it never gets forwarded to a client at
|
||||
any time.
|
||||
|
||||
public - this means the session objects will respond to this async
|
||||
command if sent with PUB_IPC or PUB_IPC_WITH_FEEDBACK
|
||||
from the module.
|
||||
public - this means the aysnc command will be broadcasted to all
|
||||
session objects currently connected to the host. which
|
||||
sessions will resond to it depends on the data being
|
||||
sent. some async's broadcasted this way will also feed
|
||||
back to source session depending on the data.
|
||||
|
||||
private - this means only the session object that has a direct IPC
|
||||
connection with the module that sends the async command
|
||||
via PRIV_IPC will respond to it.
|
||||
private - this means the async command will only be sent to the
|
||||
local session.
|
||||
|
||||
none - this means none of the session objects will respond to
|
||||
this async command no matter which of the IPC data types
|
||||
are used. it is resevered for just the session object to
|
||||
send to the client.
|
||||
|
||||
retricted - this means the session object will actively block this
|
||||
async command from being sent from the module (any mode).
|
||||
retricted - this means the async command will be used by the local
|
||||
session object only. any modules/commands sending it
|
||||
will be ignored or blocked.
|
||||
```
|
||||
|
||||
```
|
||||
enum AsyncCommands : quint16
|
||||
{
|
||||
ASYNC_RDY = 1, // client | none
|
||||
ASYNC_SYS_MSG = 2, // client | none
|
||||
ASYNC_RDY = 1, // client | retricted
|
||||
ASYNC_SYS_MSG = 2, // client | retricted
|
||||
ASYNC_EXIT = 3, // internal | private
|
||||
ASYNC_CAST = 4, // client | public
|
||||
ASYNC_MAXSES = 5, // internal | private
|
||||
|
@ -49,7 +45,7 @@ enum AsyncCommands : quint16
|
|||
ASYNC_DISABLE_MOD = 13, // internal | public
|
||||
ASYNC_END_SESSION = 14, // internal | private
|
||||
ASYNC_USER_LOGIN = 15, // internal | private
|
||||
ASYNC_TO_PEER = 16, // client | public | retricted
|
||||
ASYNC_TO_PEER = 16, // client | retricted
|
||||
ASYNC_LIMITED_CAST = 17, // client | public
|
||||
ASYNC_RW_MY_INFO = 18, // internal | public
|
||||
ASYNC_P2P = 19, // client | public
|
||||
|
@ -68,16 +64,17 @@ enum AsyncCommands : quint16
|
|||
ASYNC_SUB_CH_LEVEL_CHG = 32, // client | public
|
||||
ASYNC_ADD_RDONLY = 33, // client | public
|
||||
ASYNC_RM_RDONLY = 34, // client | public
|
||||
ASYNC_ADD_CMD = 35, // client | none
|
||||
ASYNC_RM_CMD = 36, // client | none
|
||||
ASYNC_ADD_CMD = 35, // client | retricted
|
||||
ASYNC_RM_CMD = 36, // client | retricted
|
||||
ASYNC_USER_RENAMED = 37, // internal | public
|
||||
ASYNC_PING_PEERS = 38, // internal | private
|
||||
ASYNC_OPEN_SUBCH = 39, // internal | private
|
||||
ASYNC_CLOSE_SUBCH = 40, // internal | private
|
||||
ASYNC_UPDATE_BANS = 41, // internal | private
|
||||
ASYNC_KEEP_ALIVE = 42, // internal | private
|
||||
ASYNC_SET_DIR = 43, // internal | private
|
||||
ASYNC_DEBUG_TEXT = 44 // internal | private
|
||||
ASYNC_DEBUG_TEXT = 44, // internal | private
|
||||
ASYNC_HOOK_INPUT = 45, // internal | private
|
||||
ASYNC_UNHOOK = 46 // internal | private
|
||||
};
|
||||
```
|
||||
|
||||
|
@ -141,7 +138,7 @@ This internal only async commmand doesn't carry any data. It is used by modules
|
|||
This command carries a 32byte user id hash. This can be used by modules to tell the session object to login as this user.
|
||||
|
||||
```ASYNC_TO_PEER (16)```
|
||||
This is an async command that carry an embedded data frame directly to/from peer sessions without any restrictions. It is prepended with the 224bit hash of the target session id; however, it drops that session id before arriving at the client so it will apppear as a regular mrci frame of any data type. Modules do not have direct access to this, the host internal objects will handle this.
|
||||
This is an async command that carry an embedded data frame directly to/from peer sessions without any restrictions. It is prepended with the 224bit hash of the target session id; however, it drops that session id before arriving at the client so it will apppear as a regular mrci frame of any data type. modules do not have direct access to this, the host internal objects will handle it.
|
||||
```
|
||||
from_module: [28bytes(sessionId)][1byte(typeId)][rest-of-bytes(payload)]
|
||||
to_client: [type_id][cmd_id(16)][branch_id(0)][size_of_payload][payload]
|
||||
|
@ -289,18 +286,21 @@ format: [8bytes(64bit_ch_id)][1byte(8bit_sub_ch_id)]
|
|||
```ASYNC_CLOSE_SUBCH (40)```
|
||||
This is the other half to ASYNC_OPEN_SUBCH that tells the session to close the requested sub-channel.
|
||||
|
||||
```ASYNC_UPDATE_BANS (41)```
|
||||
This internal only async command doesn't carry any data. It can be use by modules to tell the TCPServer object to update it's ip ban list cache from the database. This generally only needs to be used if the ip ban list in the database has changed in anyway.
|
||||
|
||||
```ASYNC_KEEP_ALIVE (42)```
|
||||
This internal only async command doesn't carry any data. The session object normally sends a [KILL_CMD](type_ids.md) to the module when it detects that the module process has not sent an IPC frame in 2 minutes to terminate the module process. If desired, the module can send this async command in regular intervals to reset this 2 minute idle timer to prevent auto termination.
|
||||
|
||||
```ASYNC_SET_DIR (43)```
|
||||
This internal only async command carries a [TEXT](type_ids.md) path that sets the working directory for the session object. All module processes started by the session will use this directory as the working directory and it is not shared among peer sessions. nothing happens if the path is invalid or does not exists.
|
||||
This internal only async command carries a [TEXT](type_ids.md) path that sets the working directory for the local session. All module processes started by the session will use this directory as the working directory and it is not shared among peer sessions. nothing happens if the path is invalid or does not exists.
|
||||
|
||||
```ASYNC_DEBUG_TEXT (44)```
|
||||
This internal only async command carries a [TEXT](type_ids.md) debug message to be logged into the host debug log from the module. Modules can use this to help with debugging issues if it doesn't have direct access to the host database.
|
||||
|
||||
```ASYNC_HOOK_INPUT (45)```
|
||||
This async command doesn't carry any data. This just indicate to the local session that the module command is requesting to hook the tcp data input from the client. when the tcp input is hooked, all data sent from the client is redirected to the command object/process that initiated the hook until reqested to unhook. If the command that initiated the hook terminates in anyway with an active hook, the hook will automatically be removed.
|
||||
|
||||
```ASYNC_UNHOOK (46)```
|
||||
This async command doesn't carry any data. Any module command that sends it tells the local session to unhook the tcp input data from the client if there is an active hook. This doesn't need to come from the command that initiated the hook.
|
||||
|
||||
### 5.3 Open Sub-Channel List ###
|
||||
|
||||
An open sub-channel list is a binary data structure that string togeather up to 6 channel-sub combinations that indicate which channel id and sub id combinations are currently open. Each sub-channel are 9bytes long and the list itself maintians a fixed length of 54bytes so it is padded with 0x00 chars to maintain the fixed length (this padding can appear anywhere in 9byte increments within the list). Each sub-channel is formatted like this:
|
||||
|
|
|
@ -25,15 +25,16 @@ enum TypeID : quint8
|
|||
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,
|
||||
KILL_CMD = 27,
|
||||
HALT_CMD = 28,
|
||||
RESUME_CMD = 29
|
||||
PING_PEERS = 21,
|
||||
CH_MEMBER_INFO = 22,
|
||||
CH_ID = 23,
|
||||
KILL_CMD = 24,
|
||||
YIELD_CMD = 25,
|
||||
RESUME_CMD = 26,
|
||||
PROMPT_TEXT = 27,
|
||||
PROG = 28,
|
||||
PROG_LAST = 29,
|
||||
ASYNC_PAYLOAD = 30
|
||||
};
|
||||
```
|
||||
|
||||
|
@ -71,38 +72,65 @@ arguments:
|
|||
This type id is similar to TEXT except it indicates that this is an error message that can be displayed directly to the user if needed.
|
||||
|
||||
```PRIV_TEXT```
|
||||
This id can be treated exactly like TEXT except this should tell the client to hide or do not echo the next TEXT data that the host is expecting, like a password or other sensitive text data.
|
||||
This id can be treated exactly like TEXT except this tells the client that the command is prompting for private information from the user so it sould hide or do not echo the next TEXT data that the command is expecting, like a password or other sensitive data.
|
||||
|
||||
```PROMPT_TEXT```
|
||||
This is similar to PRIV_TEXT expect it is not asking for private information. It is simply prompting for non-sensitive information from the user.
|
||||
|
||||
```BIG_TEXT```
|
||||
Also formatted exactly like TEXT but this indicates to the client that this is a large body of text that is recommended to be word wrapped when displaying to the user. It can contain line breaks so clients are also recommended to honor those line breaks.
|
||||
|
||||
```IDLE```
|
||||
This doesn't carry any actual data, instead this indicates that the command id and branch id that sent it has finished it's task. Modules that send this doesn't need to terminate it's process.
|
||||
All commands started during the session returns this type id when it has finished it's task. It carries a 16bit unsigned integer indicating the result of the task that the command was running.
|
||||
|
||||
```
|
||||
enum RetCode : quint16
|
||||
{
|
||||
NO_ERRORS = 1, // task execution completed without any issues.
|
||||
ABORTED = 2, // the task aborted via user or host intervention.
|
||||
INVALID_PARAMS = 3, // invalid/missing parameters prevented the task from executing.
|
||||
CRASH = 4, // the command process has crashed.
|
||||
FAILED_TO_START = 5, // the command process could not start.
|
||||
EXECUTION_FAIL = 6, // command specific error prevented execution of the task.
|
||||
CUSTOM = 7 // indicates a custom return code.
|
||||
};
|
||||
|
||||
notes:
|
||||
1. the custom return code can be additional data added to the end of the 16bit
|
||||
integer that can carry additional data about the result of the task. it can
|
||||
be any format that the module itself decides it can should be. nothing is
|
||||
stopping modules from defining return codes beyond the value of 7 but it is
|
||||
advised not to because this enum might be expanded in the future.
|
||||
```
|
||||
|
||||
```TERM_CMD```
|
||||
This type id doesn't carry any actual data. It is used to tell the host to stop/terminate the command id and branch id that was used to send it. It does not actually terminate the module's process within the host, it only simply tells it to stop what it is currently doing. This will also terminate any commands in a prompt/more input state.
|
||||
|
||||
```KILL_CMD```
|
||||
This doesn't carry any actual data, instead can be sent by the client or session object to tell the command-branch id sent in the frame to terminate the module process. Modules that receive this need to send a IDLE frame if a command is still running and then terminate itself. The module will have 3 seconds to do this before it is force killed by the session.
|
||||
This works similarly to TERM_CMD except it will also terminate the module process. The module process will have 3 seconds to shutdown gracefully before it is force killed by the host session.
|
||||
|
||||
```HALT_CMD```
|
||||
This doesn't carry any actual data, instead can be sent by the client or session object to tell the command-branch id sent in the frame to pause/halt the current task that the command is currently running. All modules are not obligated to support this feature but highly recommended.
|
||||
```YIELD_CMD```
|
||||
This type id doesn't carry any actual data, instead can be used to tell the host to pause/yield the command id and branch id that was used to send it. All modules are not obligated to support this feature but it is highly recommended to do so.
|
||||
|
||||
```RESUME_CMD```
|
||||
This is the other half of HALT_CMD that tells the module to resume the command task it was running.
|
||||
This is the other half of YIELD_CMD that tells the host to resume the command that was running.
|
||||
|
||||
```HOST_CERT```
|
||||
Just as the name implies, this data type is used by the host to send the host SSL certificate while setting up an SSL connection.
|
||||
|
||||
```HOST_VER```
|
||||
This data structure carries 3 numeric values that represent the host version as described in section [1.3](protocol.md).
|
||||
This data structure carries 4 numeric values that represent the host version as described in section [1.3](protocol.md).
|
||||
|
||||
```
|
||||
format:
|
||||
1. bytes[0-1] - version major (16bit little endian uint)
|
||||
2. bytes[2-3] - version minor (16bit little endian uint)
|
||||
3. bytes[4-5] - version patch (16bit little endian uint)
|
||||
3. bytes[4-5] - tcp interface rev (16bit little endian uint)
|
||||
4. bytes[6-7] - module interface rev (16bit little endian uint)
|
||||
```
|
||||
|
||||
```PRIV_IPC```
|
||||
This is a data structure used to by modules to run async commands on the local session object only.
|
||||
```ASYNC_PAYLOAD```
|
||||
This is a data structure that can be used by modules to run async commands. Each async command have a specific 16bit command id followed by a payload that can contain any data of any format depending on the async command id. A full discribtion of the async commands and the data they carry can found in section [5.1](async.md) and [5.2](async.md).
|
||||
|
||||
```
|
||||
format:
|
||||
|
@ -110,12 +138,6 @@ This is a data structure used to by modules to run async commands on the local s
|
|||
2. bytes[2-n] - payload (data to be processed by async command)
|
||||
```
|
||||
|
||||
```PUB_IPC```
|
||||
This is formatted exactly like PRIV_IPC except it is used by modules to run async commands on all peer session objects in the host while avoiding a run on the local session object.
|
||||
|
||||
```PUB_IPC_WITH_FEEDBACK```
|
||||
This has the same functionality as PUB_IPC except it is also feedback into the local session object.
|
||||
|
||||
```FILE_INFO```
|
||||
This is a data structure that carries information about a file system object (file,dir,link).
|
||||
|
||||
|
@ -172,7 +194,7 @@ This carry some user account and session information about a peer client connect
|
|||
```
|
||||
|
||||
```PING_PEERS```
|
||||
This is formatted extactly as PEER_INFO except it can be used the ASYNC_LIMITED_CAST [async](async.md) command to tell all peer sessions that receive it to send a PEER_INFO frame about you to their own clients and return PEER_INFO frames about themselves to you.
|
||||
This is formatted extactly as PEER_INFO except it is used by the ASYNC_LIMITED_CAST [async](async.md) command to tell all peer sessions that receive it to send a PEER_INFO frame about the local session to their own clients and return PEER_INFO frames about themselves to the local session.
|
||||
|
||||
```MY_INFO```
|
||||
This contains all of the information found in ```PEER_INFO``` for the local session but also includes the following:
|
||||
|
@ -220,7 +242,7 @@ This type id carries a 64bit unsighed LE int indicating the channel id.
|
|||
format: ```8bytes - 64bit LE unsigned int (channel id)```
|
||||
|
||||
```SESSION_ID```
|
||||
This is a fixed length 28byte(224bit) sha3 hash of a client's session id connected to the host. This is unique to just the client's tcp connection with the host. This can change upon re-connection.
|
||||
This is a fixed length 28byte(224bit) sha3 hash of a client's session id connected to the host. This is unique to just the client's tcp connection with the host. This changes upon re-connection.
|
||||
|
||||
format: ```28bytes - session id (224bit sha3 hash)```
|
||||
|
||||
|
@ -278,12 +300,23 @@ This contains public information about a channel member.
|
|||
1. a 16bit null terminated TEXT formatted string ended with 2 bytes of
|
||||
(0x00) to indicate the end of the string data.
|
||||
|
||||
2. is invite? indicates if this user has received an invite to join
|
||||
2. the member's privilege level can be any of the values discribed in
|
||||
section [4.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.
|
||||
```
|
||||
|
||||
```PROG```
|
||||
This is a 8bit integer value from 0-100 indicating the percentage progress of the command. All long running module commands are encouraged to use this to update the client on command progress; sending it in a 1-5 second pulse rate.
|
||||
|
||||
format: ```1byte - 8bit integer (0-100)```
|
||||
|
||||
```PROG_LAST```
|
||||
This is formatted and treated exactly like PROG except it indicates to the client that this is the last progress update for the current string of progress updates. So at the client side, progress strings/pulses should appear with a single or multiple PROG frame(s) and then end with PROG_LAST. Receiving an IDLE should also end the progress string if seen before PROG_LAST.
|
||||
|
||||
### 3.3 GEN_FILE Example ###
|
||||
|
||||
Setup:
|
||||
|
|
|
@ -5,7 +5,7 @@ installer_file="$2"
|
|||
|
||||
src_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
bin_name="cmdr"
|
||||
app_version="2.2.0"
|
||||
app_version="3.0"
|
||||
app_name="Cmdr"
|
||||
install_dir="/opt/$bin_name"
|
||||
bin_dir="/usr/bin"
|
||||
|
@ -38,7 +38,7 @@ fi
|
|||
if [ $? -eq 0 -a -d "$qt_dir" ]; then
|
||||
|
||||
mkdir -vp $tmp_dir
|
||||
cp -rv $src_dir/. $tmp_dir
|
||||
cp -r $src_dir/. $tmp_dir
|
||||
cd $tmp_dir
|
||||
qmake -config release
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ CmdLine::CmdLine(QWidget *parent) : QComboBox(parent)
|
|||
|
||||
setEditable(true);
|
||||
setDuplicatesEnabled(true);
|
||||
loadTextSettings(localData, this);
|
||||
loadTheme(localData, this);
|
||||
|
||||
if (!localData->contains("command_hist"))
|
||||
{
|
||||
|
|
|
@ -65,13 +65,13 @@ QString Term::longText() {return TXT_Term;}
|
|||
|
||||
Halt::Halt(QObject *parent) : Command(parent)
|
||||
{
|
||||
setObjectName("halt");
|
||||
setObjectName("yield");
|
||||
|
||||
Shared::hookBypass->append(objectName());
|
||||
Shared::clientCmds->insert(objectName(), this);
|
||||
}
|
||||
|
||||
QString Halt::shortText() {return tr("halt/pause the currently running host command.");}
|
||||
QString Halt::shortText() {return tr("yield/pause the currently running host command.");}
|
||||
QString Halt::ioText() {return tr("[none]/[CMD_ID]");}
|
||||
QString Halt::longText() {return TXT_Term;}
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ void Status::dataIn(const QString &argsLine)
|
|||
txtOut << " Client address : " << Shared::socket->localAddress().toString() << endl;
|
||||
txtOut << " Host address : " << Shared::socket->peerAddress().toString() << endl;
|
||||
txtOut << " Session id : " << Shared::sessionId->toHex() << endl;
|
||||
txtOut << " Host version : " << verText(*Shared::servMajor, *Shared::servMinor, *Shared::servPatch) << endl;
|
||||
txtOut << " Host version : " << verText() << endl;
|
||||
txtOut << " GEN_FILE commands : ";
|
||||
|
||||
QStringList genCmds = Shared::genfileCmds->values();
|
||||
|
|
|
@ -20,8 +20,8 @@ void checkArgs(bool *changed, QJsonObject *jsonData, const QString &arg, const Q
|
|||
{
|
||||
if (argExists(arg, args))
|
||||
{
|
||||
QString data = getParam(arg, args);
|
||||
QJsonObject obj = jsonData->value("text_settings").toObject();
|
||||
auto data = getParam(arg, args);
|
||||
auto obj = jsonData->value("theme").toObject();
|
||||
|
||||
if (data.isEmpty())
|
||||
{
|
||||
|
@ -62,7 +62,7 @@ void checkArgs(bool *changed, QJsonObject *jsonData, const QString &arg, const Q
|
|||
|
||||
if (*changed)
|
||||
{
|
||||
jsonData->insert("text_settings", obj);
|
||||
jsonData->insert("theme", obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -108,14 +108,14 @@ QString SetMaxLines::longText() {return TXT_SetMaxLines;}
|
|||
|
||||
void SetColors::dataIn(const QString &argsLine)
|
||||
{
|
||||
bool changed = false;
|
||||
QStringList args = parseArgs(argsLine);
|
||||
auto changed = false;
|
||||
auto args = parseArgs(argsLine);
|
||||
|
||||
checkArgs(&changed, localData, "-text", args, "text_color", "#FBFBD7");
|
||||
checkArgs(&changed, localData, "-error", args, "err_color", "#BB55D8");
|
||||
checkArgs(&changed, localData, "-bg", args, "bg_color", "#363A49");
|
||||
|
||||
QJsonObject obj = localData->value("text_settings").toObject();
|
||||
auto obj = localData->value("theme").toObject();
|
||||
|
||||
cacheTxt(TEXT, "text: " + obj.value("text_color").toString() + "\n");
|
||||
cacheTxt(TEXT, "error: " + obj.value("err_color").toString() + "\n");
|
||||
|
@ -126,13 +126,13 @@ void SetColors::dataIn(const QString &argsLine)
|
|||
|
||||
void SetFont::dataIn(const QString &argsLine)
|
||||
{
|
||||
bool changed = false;
|
||||
QStringList args = parseArgs(argsLine);
|
||||
auto changed = false;
|
||||
auto args = parseArgs(argsLine);
|
||||
|
||||
checkArgs(&changed, localData, "-name", args, "font_family", "courier");
|
||||
checkArgs(&changed, localData, "-size", args, "font_size", "9");
|
||||
|
||||
QJsonObject obj = localData->value("text_settings").toObject();
|
||||
auto obj = localData->value("theme").toObject();
|
||||
|
||||
cacheTxt(TEXT, "family: " + obj.value("font_family").toString() + "\n");
|
||||
cacheTxt(TEXT, "size: " + obj.value("font_size").toString() + "\n");
|
||||
|
@ -142,8 +142,8 @@ void SetFont::dataIn(const QString &argsLine)
|
|||
|
||||
void SetMaxLines::dataIn(const QString &argsLine)
|
||||
{
|
||||
QStringList args = parseArgs(argsLine);
|
||||
QString valStr = getParam("-value", args);
|
||||
auto args = parseArgs(argsLine);
|
||||
auto valStr = getParam("-value", args);
|
||||
|
||||
if (valStr.isEmpty())
|
||||
{
|
||||
|
@ -152,7 +152,7 @@ void SetMaxLines::dataIn(const QString &argsLine)
|
|||
else
|
||||
{
|
||||
bool ok;
|
||||
int val = valStr.toInt(&ok);
|
||||
auto val = valStr.toInt(&ok);
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
// along with Cmdr under the LICENSE.md file. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
void setupTextSettings(QJsonObject *data)
|
||||
void setupThemeSettings(QJsonObject *data)
|
||||
{
|
||||
QString txtColorStr = "#FBFBD7";
|
||||
QString bgColorStr = "#363A49";
|
||||
|
@ -26,9 +26,9 @@ void setupTextSettings(QJsonObject *data)
|
|||
|
||||
QJsonObject obj;
|
||||
|
||||
if (data->contains("text_settings"))
|
||||
if (data->contains("theme"))
|
||||
{
|
||||
obj = data->value("text_settings").toObject();
|
||||
obj = data->value("theme").toObject();
|
||||
|
||||
if (!obj.contains("text_color")) obj.insert("text_color", txtColorStr);
|
||||
if (!obj.contains("err_color")) obj.insert("err_color", errColorStr);
|
||||
|
@ -45,7 +45,7 @@ void setupTextSettings(QJsonObject *data)
|
|||
obj.insert("font_size", fontSize);
|
||||
}
|
||||
|
||||
data->insert("text_settings", obj);
|
||||
data->insert("theme", obj);
|
||||
|
||||
if (!data->contains("max_lines"))
|
||||
{
|
||||
|
@ -55,18 +55,26 @@ void setupTextSettings(QJsonObject *data)
|
|||
saveLocalData(data);
|
||||
}
|
||||
|
||||
void loadTextSettings(QJsonObject *data, QWidget *widget)
|
||||
void loadTheme(QJsonObject *data, QWidget *widget, bool setHighlight)
|
||||
{
|
||||
QString bgColor = data->value("text_settings").toObject().value("bg_color").toString();
|
||||
QString txtColor = data->value("text_settings").toObject().value("text_color").toString();
|
||||
QString fntFamily = data->value("text_settings").toObject().value("font_family").toString();
|
||||
QString fntSize = data->value("text_settings").toObject().value("font_size").toString();
|
||||
QString bgColor = data->value("theme").toObject().value("bg_color").toString();
|
||||
QString txtColor = data->value("theme").toObject().value("text_color").toString();
|
||||
QString fntFamily = data->value("theme").toObject().value("font_family").toString();
|
||||
QString fntSize = data->value("theme").toObject().value("font_size").toString();
|
||||
QPalette pal = widget->palette();
|
||||
QFont fnt = widget->font();
|
||||
|
||||
pal.setColor(QPalette::Active, QPalette::Base, QColor(bgColor));
|
||||
pal.setColor(QPalette::Inactive, QPalette::Base, QColor(bgColor));
|
||||
pal.setColor(QPalette::Active, QPalette::Text, QColor(txtColor));
|
||||
pal.setColor(QPalette::Inactive, QPalette::Text, QColor(txtColor));
|
||||
|
||||
if (setHighlight)
|
||||
{
|
||||
pal.setColor(QPalette::Active, QPalette::Highlight, QColor(txtColor));
|
||||
pal.setColor(QPalette::Inactive, QPalette::Highlight, QColor(txtColor));
|
||||
}
|
||||
|
||||
fnt.setFamily(fntFamily);
|
||||
fnt.setPointSize(fntSize.toInt());
|
||||
|
||||
|
@ -335,9 +343,16 @@ QString boolText(bool state)
|
|||
else return QString("False");
|
||||
}
|
||||
|
||||
QString verText(quint16 maj, quint16 min, quint16 patch)
|
||||
QString verText()
|
||||
{
|
||||
return QString::number(maj) + "." + QString::number(min) + "." + QString::number(patch);
|
||||
QString ret;
|
||||
|
||||
ret.append(QString::number(*Shared::servMajor) + ".");
|
||||
ret.append(QString::number(*Shared::servMinor) + ".");
|
||||
ret.append(QString::number(*Shared::tcpRev) + ".");
|
||||
ret.append(QString::number(*Shared::modRev));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
QString getParam(const QString &key, const QStringList &args)
|
||||
|
@ -395,7 +410,8 @@ QByteArray *Shared::sessionId = nullptr;
|
|||
QString *Shared::clientHookedCmd = nullptr;
|
||||
ushort *Shared::servMajor = nullptr;
|
||||
ushort *Shared::servMinor = nullptr;
|
||||
ushort *Shared::servPatch = nullptr;
|
||||
ushort *Shared::tcpRev = nullptr;
|
||||
ushort *Shared::modRev = nullptr;
|
||||
QString *Shared::hostAddress = nullptr;
|
||||
quint16 *Shared::hostPort = nullptr;
|
||||
quint16 *Shared::termCmdId = nullptr;
|
||||
|
@ -411,6 +427,7 @@ QWidget *Shared::mainWidget = nullptr;
|
|||
QList<quint8> *Shared::idCache = nullptr;
|
||||
QList<QString> *Shared::txtCache = nullptr;
|
||||
ThreadKiller *Shared::theadKiller = nullptr;
|
||||
QProgressBar *Shared::prog = nullptr;
|
||||
|
||||
bool Shared::cacheTxt(CacheOp op, quint8 &typeId, QString &txt)
|
||||
{
|
||||
|
@ -421,7 +438,8 @@ bool Shared::cacheTxt(CacheOp op, quint8 &typeId, QString &txt)
|
|||
|
||||
if (op == TXT_IN)
|
||||
{
|
||||
if ((typeId == TEXT) || (typeId == ERR) || (typeId == BIG_TEXT) || (typeId == PRIV_TEXT))
|
||||
if ((typeId == TEXT) || (typeId == ERR) || (typeId == BIG_TEXT) ||
|
||||
(typeId == PRIV_TEXT) || (typeId == PROMPT_TEXT))
|
||||
{
|
||||
idCache->append(typeId);
|
||||
txtCache->append(txt);
|
||||
|
|
44
src/common.h
44
src/common.h
|
@ -63,6 +63,7 @@
|
|||
#include <QRegExp>
|
||||
#include <QFileInfo>
|
||||
#include <QMutex>
|
||||
#include <QProgressBar>
|
||||
|
||||
#include "cmd_objs/long_txt.h"
|
||||
|
||||
|
@ -71,10 +72,10 @@
|
|||
#define RDBUFF 16777215
|
||||
#define TXT_CODEC "UTF-16LE"
|
||||
#define BOOKMARK_FOLDER "bookmarks"
|
||||
#define CONFIG_FILENAME "config.json"
|
||||
#define CONFIG_FILENAME "config_v3.json"
|
||||
#define APP_NAME "Cmdr"
|
||||
#define APP_TARGET "cmdr"
|
||||
#define APP_VERSION "2.2.0"
|
||||
#define APP_VERSION "3.0"
|
||||
|
||||
enum TypeID : quint8
|
||||
{
|
||||
|
@ -98,15 +99,16 @@ enum TypeID : quint8
|
|||
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,
|
||||
KILL_CMD = 27,
|
||||
HALT_CMD = 28,
|
||||
RESUME_CMD = 29
|
||||
PING_PEERS = 21,
|
||||
CH_MEMBER_INFO = 22,
|
||||
CH_ID = 23,
|
||||
KILL_CMD = 24,
|
||||
YIELD_CMD = 25,
|
||||
RESUME_CMD = 26,
|
||||
PROMPT_TEXT = 27,
|
||||
PROG = 28,
|
||||
PROG_LAST = 29,
|
||||
ASYNC_PAYLOAD = 30
|
||||
};
|
||||
|
||||
enum GenFileType : quint8
|
||||
|
@ -117,11 +119,11 @@ enum GenFileType : quint8
|
|||
|
||||
enum AsyncCommands : quint16
|
||||
{
|
||||
ASYNC_RDY = 1, // client | none
|
||||
ASYNC_SYS_MSG = 2, // client | none
|
||||
ASYNC_RDY = 1, // client | retricted
|
||||
ASYNC_SYS_MSG = 2, // client | retricted
|
||||
ASYNC_CAST = 4, // client | public
|
||||
ASYNC_USER_DELETED = 7, // client | public
|
||||
ASYNC_TO_PEER = 16, // client | public | retricted
|
||||
ASYNC_TO_PEER = 16, // client | retricted
|
||||
ASYNC_LIMITED_CAST = 17, // client | public
|
||||
ASYNC_P2P = 19, // client | public
|
||||
ASYNC_NEW_CH_MEMBER = 21, // client | public
|
||||
|
@ -137,8 +139,8 @@ enum AsyncCommands : quint16
|
|||
ASYNC_SUB_CH_LEVEL_CHG = 32, // client | public
|
||||
ASYNC_ADD_RDONLY = 33, // client | public
|
||||
ASYNC_RM_RDONLY = 34, // client | public
|
||||
ASYNC_ADD_CMD = 35, // client | none
|
||||
ASYNC_RM_CMD = 36, // client | none
|
||||
ASYNC_ADD_CMD = 35, // client | retricted
|
||||
ASYNC_RM_CMD = 36, // client | retricted
|
||||
};
|
||||
|
||||
enum ChannelMemberLevel
|
||||
|
@ -158,8 +160,8 @@ enum UserIOFlags
|
|||
HIDDEN = 1 << 4
|
||||
};
|
||||
|
||||
void setupTextSettings(QJsonObject *data);
|
||||
void loadTextSettings(QJsonObject *data, QWidget *widget);
|
||||
void setupThemeSettings(QJsonObject *data);
|
||||
void loadTheme(QJsonObject *data, QWidget *widget, bool setHighlight = false);
|
||||
void saveLocalData(QJsonObject *obj);
|
||||
void loadLocalData(QJsonObject *obj);
|
||||
void wordWrap(const QString &label, QTextStream &txtOut, const QString &txtIn, QWidget *measureWid);
|
||||
|
@ -175,7 +177,7 @@ QString appDataDir();
|
|||
QString getParam(const QString &key, const QStringList &args);
|
||||
QString extractCmdName(const QByteArray &data);
|
||||
QString boolText(bool state);
|
||||
QString verText(quint16 maj, quint16 min, quint16 patch);
|
||||
QString verText();
|
||||
quint64 rdInt(const QByteArray &bytes);
|
||||
|
||||
class Command;
|
||||
|
@ -200,7 +202,8 @@ public:
|
|||
static QByteArray *sessionId;
|
||||
static ushort *servMajor;
|
||||
static ushort *servMinor;
|
||||
static ushort *servPatch;
|
||||
static ushort *tcpRev;
|
||||
static ushort *modRev;
|
||||
static QString *hostAddress;
|
||||
static QString *clientHookedCmd;
|
||||
static quint16 *hostPort;
|
||||
|
@ -224,6 +227,7 @@ public:
|
|||
static ContextReloader *contextReloader;
|
||||
static QWidget *mainWidget;
|
||||
static ThreadKiller *theadKiller;
|
||||
static QProgressBar *prog;
|
||||
|
||||
enum CacheOp
|
||||
{
|
||||
|
|
78
src/main.cpp
78
src/main.cpp
|
@ -38,6 +38,7 @@ void setupCmdLine();
|
|||
void setupGenFile();
|
||||
void setupSession();
|
||||
void setupText();
|
||||
void setupProgBar();
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
@ -50,7 +51,8 @@ int main(int argc, char *argv[])
|
|||
bool activeDisp = false;
|
||||
ushort servMajor = 0;
|
||||
ushort servMinor = 0;
|
||||
ushort servPatch = 0;
|
||||
ushort tcpRev = 0;
|
||||
ushort modRev = 0;
|
||||
quint16 hostPort = 0;
|
||||
quint16 termCmdId = 0;
|
||||
QByteArray sessionId;
|
||||
|
@ -67,7 +69,7 @@ int main(int argc, char *argv[])
|
|||
QJsonObject localData;
|
||||
|
||||
loadLocalData(&localData);
|
||||
setupTextSettings(&localData);
|
||||
setupThemeSettings(&localData);
|
||||
|
||||
Shared::connectedToHost = &connected;
|
||||
Shared::genfileCmds = &genfileCmds;
|
||||
|
@ -78,7 +80,8 @@ int main(int argc, char *argv[])
|
|||
Shared::sessionId = &sessionId;
|
||||
Shared::servMajor = &servMajor;
|
||||
Shared::servMinor = &servMinor;
|
||||
Shared::servPatch = &servPatch;
|
||||
Shared::tcpRev = &tcpRev;
|
||||
Shared::modRev = &modRev;
|
||||
Shared::hostAddress = &hostAddress;
|
||||
Shared::hostPort = &hostPort;
|
||||
Shared::hookBypass = &hookBypass;
|
||||
|
@ -152,14 +155,14 @@ void ContextReloader::reloadCmdLine()
|
|||
|
||||
void setupClientCmds()
|
||||
{
|
||||
Session *session = Shared::session;
|
||||
CmdLine *cmdLine = Shared::cmdLine;
|
||||
TextWorker *textWorker = Shared::textWorker;
|
||||
TextBody *textBody = Shared::textBody;
|
||||
Genfile *genFile = Shared::genFile;
|
||||
MainWindow *mainWin = Shared::mainWin;
|
||||
ContextReloader *reloader = Shared::contextReloader;
|
||||
ThreadKiller *killer = Shared::theadKiller;
|
||||
auto *session = Shared::session;
|
||||
auto *cmdLine = Shared::cmdLine;
|
||||
auto *textWorker = Shared::textWorker;
|
||||
auto *textBody = Shared::textBody;
|
||||
auto *genFile = Shared::genFile;
|
||||
auto *mainWin = Shared::mainWin;
|
||||
auto *reloader = Shared::contextReloader;
|
||||
auto *killer = Shared::theadKiller;
|
||||
|
||||
QObject::connect(mainWin, &MainWindow::closeApp, killer, &ThreadKiller::quitThreads);
|
||||
|
||||
|
@ -175,7 +178,7 @@ void setupClientCmds()
|
|||
QObject::connect(command, &Command::unsetUserIO, cmdLine, &CmdLine::unsetFlags);
|
||||
|
||||
QObject::connect(command, &Command::termHostCmd, session, &Session::termHostCmd);
|
||||
QObject::connect(command, &Command::haltHostcmd, session, &Session::haltHostCmd);
|
||||
QObject::connect(command, &Command::haltHostcmd, session, &Session::yieldHostCmd);
|
||||
QObject::connect(command, &Command::resumeHostCmd, session, &Session::resumeHostCmd);
|
||||
QObject::connect(command, &Command::connectToHost, session, &Session::connectToServ);
|
||||
QObject::connect(command, &Command::quitApp, session, &Session::disconnectFromServ);
|
||||
|
@ -199,10 +202,10 @@ void setupClientCmds()
|
|||
|
||||
void setupCmdLine()
|
||||
{
|
||||
Session *session = Shared::session;
|
||||
CmdLine *cmdLine = Shared::cmdLine;
|
||||
TextWorker *textWorker = Shared::textWorker;
|
||||
Genfile *genFile = Shared::genFile;
|
||||
auto *session = Shared::session;
|
||||
auto *cmdLine = Shared::cmdLine;
|
||||
auto *textWorker = Shared::textWorker;
|
||||
auto *genFile = Shared::genFile;
|
||||
|
||||
QObject::connect(cmdLine, &CmdLine::dataToHost, session, &Session::binToServer);
|
||||
QObject::connect(cmdLine, &CmdLine::dataToHookedHost, session, &Session::hookedBinToServer);
|
||||
|
@ -216,12 +219,12 @@ void setupCmdLine()
|
|||
|
||||
void setupGenFile()
|
||||
{
|
||||
Session *session = Shared::session;
|
||||
CmdLine *cmdLine = Shared::cmdLine;
|
||||
TextWorker *textWorker = Shared::textWorker;
|
||||
Genfile *genFile = Shared::genFile;
|
||||
ThreadKiller *killer = Shared::theadKiller;
|
||||
QThread *genThr = new QThread(QCoreApplication::instance());
|
||||
auto *session = Shared::session;
|
||||
auto *cmdLine = Shared::cmdLine;
|
||||
auto *textWorker = Shared::textWorker;
|
||||
auto *genFile = Shared::genFile;
|
||||
auto *killer = Shared::theadKiller;
|
||||
auto *genThr = new QThread(QCoreApplication::instance());
|
||||
|
||||
QObject::connect(genFile, &Genfile::termHostCmd, session, &Session::termHostCmd);
|
||||
QObject::connect(genFile, &Genfile::dataOut, session, &Session::hookedBinToServer);
|
||||
|
@ -242,12 +245,12 @@ void setupGenFile()
|
|||
|
||||
void setupSession()
|
||||
{
|
||||
Session *session = Shared::session;
|
||||
CmdLine *cmdLine = Shared::cmdLine;
|
||||
TextWorker *textWorker = Shared::textWorker;
|
||||
Genfile *genFile = Shared::genFile;
|
||||
ThreadKiller *killer = Shared::theadKiller;
|
||||
QThread *sesThr = new QThread(QCoreApplication::instance());
|
||||
auto *session = Shared::session;
|
||||
auto *cmdLine = Shared::cmdLine;
|
||||
auto *textWorker = Shared::textWorker;
|
||||
auto *genFile = Shared::genFile;
|
||||
auto *killer = Shared::theadKiller;
|
||||
auto *sesThr = new QThread(QCoreApplication::instance());
|
||||
|
||||
QObject::connect(session, &Session::hostFinished, genFile, &Genfile::finished);
|
||||
QObject::connect(session, &Session::toGenFile, genFile, &Genfile::dataIn);
|
||||
|
@ -266,11 +269,11 @@ void setupSession()
|
|||
|
||||
void setupText()
|
||||
{
|
||||
TextWorker *textWorker = Shared::textWorker;
|
||||
CmdLine *cmdLine = Shared::cmdLine;
|
||||
TextBody *textBody = Shared::textBody;
|
||||
ThreadKiller *killer = Shared::theadKiller;
|
||||
QThread *txtThr = new QThread(QCoreApplication::instance());
|
||||
auto *textWorker = Shared::textWorker;
|
||||
auto *cmdLine = Shared::cmdLine;
|
||||
auto *textBody = Shared::textBody;
|
||||
auto *killer = Shared::theadKiller;
|
||||
auto *txtThr = new QThread(QCoreApplication::instance());
|
||||
|
||||
QObject::connect(textWorker, &TextWorker::setUserIO, cmdLine, &CmdLine::setFlags);
|
||||
QObject::connect(textWorker, &TextWorker::unsetUserIO, cmdLine, &CmdLine::unsetFlags);
|
||||
|
@ -283,3 +286,12 @@ void setupText()
|
|||
textWorker->moveToThread(txtThr);
|
||||
txtThr->start();
|
||||
}
|
||||
|
||||
void setupProgBar()
|
||||
{
|
||||
auto *session = Shared::session;
|
||||
auto *prog = Shared::prog;
|
||||
|
||||
QObject::connect(session, &Session::setProg, prog, &QProgressBar::setValue);
|
||||
QObject::connect(session, &Session::showProg, prog, &QProgressBar::setVisible);
|
||||
}
|
||||
|
|
|
@ -85,13 +85,26 @@ void MainWindow::closeEvent(QCloseEvent *event)
|
|||
void MainWindow::setCmdLine(QWidget *widget)
|
||||
{
|
||||
widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
mainLayout->insertWidget(1, widget);
|
||||
mainLayout->insertWidget(2, widget);
|
||||
}
|
||||
|
||||
void MainWindow::setTextBody(QWidget *widget)
|
||||
{
|
||||
Shared::prog = new QProgressBar(this);
|
||||
|
||||
Shared::prog->setVisible(false);
|
||||
Shared::prog->setFixedHeight(5);
|
||||
Shared::prog->setTextVisible(false);
|
||||
Shared::prog->setMaximum(100);
|
||||
Shared::prog->setMinimum(0);
|
||||
Shared::prog->setValue(0);
|
||||
Shared::prog->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
|
||||
loadTheme(localData, Shared::prog, true);
|
||||
|
||||
widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
mainLayout->insertWidget(0, widget);
|
||||
mainLayout->insertWidget(1, Shared::prog);
|
||||
}
|
||||
|
||||
void MainWindow::showUi()
|
||||
|
|
|
@ -22,9 +22,12 @@ Session::Session(QObject *parent) : QSslSocket(nullptr)
|
|||
hook = 0;
|
||||
dType = 0;
|
||||
flags = 0;
|
||||
progResetDelay = new QTimer(this);
|
||||
activeProg = false;
|
||||
reconnect = false;
|
||||
|
||||
connect(parent, &QSslSocket::destroyed, this, &Session::deleteLater);
|
||||
connect(progResetDelay, &QTimer::timeout, this, &Session::resetProg);
|
||||
|
||||
connect(this, &Session::encrypted, this, &Session::handShakeDone);
|
||||
connect(this, &Session::connected, this, &Session::isConnected);
|
||||
|
@ -33,6 +36,9 @@ Session::Session(QObject *parent) : QSslSocket(nullptr)
|
|||
connect(this, &Session::loopDataIn, this, &Session::dataIn);
|
||||
|
||||
connect(this, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(sockerr(QAbstractSocket::SocketError)));
|
||||
|
||||
progResetDelay->setInterval(200);
|
||||
progResetDelay->setSingleShot(true);
|
||||
}
|
||||
|
||||
void Session::hookedBinToServer(const QByteArray &data, quint8 typeId)
|
||||
|
@ -93,10 +99,16 @@ void Session::isConnected()
|
|||
// appName = UTF16LE string (padded with 0x00)
|
||||
// coName = UTF16LE string (padded with 0x00)
|
||||
|
||||
// for MRCI host, if the client doesn't need to request a special SSL
|
||||
// cert from the host, it is good practice to fallback to using the
|
||||
// address used to connect to the host as the common name (coName).
|
||||
// in this case, it is used all of the time.
|
||||
|
||||
cacheTxt(TEXT, "Connected.\n");
|
||||
|
||||
auto appName = QString(APP_NAME) + " v" + QString(APP_VERSION);
|
||||
|
||||
QByteArray header;
|
||||
QString appName = QString(APP_NAME) + " v" + QString(APP_VERSION);
|
||||
|
||||
header.append(SERVER_HEADER_TAG);
|
||||
header.append(fixedToTEXT(appName, 134));
|
||||
|
@ -115,9 +127,9 @@ void Session::isConnected()
|
|||
|
||||
void Session::handShakeDone()
|
||||
{
|
||||
QSslCipher cipher = sessionCipher();
|
||||
QString txt;
|
||||
auto cipher = sessionCipher();
|
||||
|
||||
QString txt;
|
||||
QTextStream txtOut(&txt);
|
||||
|
||||
txtOut << "SSL Handshake sucessful." << endl
|
||||
|
@ -140,7 +152,8 @@ void Session::isDisconnected()
|
|||
|
||||
*Shared::servMajor = 0;
|
||||
*Shared::servMinor = 0;
|
||||
*Shared::servPatch = 0;
|
||||
*Shared::tcpRev = 0;
|
||||
*Shared::modRev = 0;
|
||||
*Shared::connectedToHost = false;
|
||||
|
||||
Shared::sessionId->clear();
|
||||
|
@ -194,11 +207,11 @@ void Session::termHostCmd()
|
|||
}
|
||||
}
|
||||
|
||||
void Session::haltHostCmd()
|
||||
void Session::yieldHostCmd()
|
||||
{
|
||||
if (hook != 0)
|
||||
{
|
||||
binToServer(hook, QByteArray(), HALT_CMD);
|
||||
binToServer(hook, QByteArray(), YIELD_CMD);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -278,7 +291,7 @@ void Session::procAsync(const QByteArray &data)
|
|||
{
|
||||
if ((dType == CMD_ID) && (data.size() == 2))
|
||||
{
|
||||
quint16 id = static_cast<quint16>(rdInt(data.mid(0, 2)));
|
||||
auto id = static_cast<quint16>(rdInt(data.mid(0, 2)));
|
||||
|
||||
if (id == hook) hook = 0;
|
||||
|
||||
|
@ -314,6 +327,31 @@ void Session::idle()
|
|||
hook = 0;
|
||||
}
|
||||
|
||||
void Session::resetProg()
|
||||
{
|
||||
emit setProg(0);
|
||||
emit showProg(false);
|
||||
|
||||
activeProg = false;
|
||||
}
|
||||
|
||||
void Session::startProg()
|
||||
{
|
||||
emit showProg(true);
|
||||
|
||||
activeProg = true;
|
||||
}
|
||||
|
||||
void Session::updateProg(int value)
|
||||
{
|
||||
emit setProg(value);
|
||||
|
||||
if (!activeProg)
|
||||
{
|
||||
startProg();
|
||||
}
|
||||
}
|
||||
|
||||
void Session::dataFromHost(const QByteArray &data)
|
||||
{
|
||||
if (isAsync(cmdId))
|
||||
|
@ -322,12 +360,27 @@ void Session::dataFromHost(const QByteArray &data)
|
|||
}
|
||||
else if ((cmdId == hook) && (branId == 0) && (hook != 0))
|
||||
{
|
||||
if ((dType == TEXT) || (dType == PRIV_TEXT) || (dType == BIG_TEXT) || (dType == ERR))
|
||||
if ((dType == TEXT) || (dType == PRIV_TEXT) || (dType == BIG_TEXT) || (dType == ERR) || (dType == PROMPT_TEXT))
|
||||
{
|
||||
cacheTxt(dType, fromTEXT(data));
|
||||
}
|
||||
else if (dType == PROG)
|
||||
{
|
||||
updateProg(rdInt(data));
|
||||
}
|
||||
else if (dType == PROG_LAST)
|
||||
{
|
||||
progResetDelay->start();
|
||||
|
||||
updateProg(rdInt(data));
|
||||
}
|
||||
else if (dType == IDLE)
|
||||
{
|
||||
if (activeProg && !progResetDelay->isActive())
|
||||
{
|
||||
resetProg();
|
||||
}
|
||||
|
||||
idle();
|
||||
}
|
||||
else if ((dType == GEN_FILE) && (flags & GEN_FILE_ON))
|
||||
|
@ -354,7 +407,7 @@ void Session::dataIn()
|
|||
{
|
||||
if (bytesAvailable() >= FRAME_HEADER_LEN)
|
||||
{
|
||||
QByteArray header = read(FRAME_HEADER_LEN);
|
||||
auto header = read(FRAME_HEADER_LEN);
|
||||
|
||||
dType = static_cast<quint8>(header[0]);
|
||||
cmdId = static_cast<quint16>(rdInt(header.mid(1, 2)));
|
||||
|
@ -367,7 +420,7 @@ void Session::dataIn()
|
|||
}
|
||||
else if (bytesAvailable() >= SERVER_HEADER_LEN)
|
||||
{
|
||||
// host header format: [1byte(reply)][2bytes(major)][2bytes(minor)][2bytes(patch)][28bytes(sesId)]
|
||||
// host header format: [1byte(reply)][2bytes(major)][2bytes(minor)][2bytes(tcp_rev)][2bytes(mod_rev)][28bytes(sesId)]
|
||||
|
||||
// reply is an 8bit little endian int the indicates the result of the client header
|
||||
// sent to the host from the isConnected() function.
|
||||
|
@ -377,17 +430,22 @@ void Session::dataIn()
|
|||
// minor = 16bit little endian uint (host ver minor)
|
||||
// patch = 16bit little endian uint (host ver patch)
|
||||
|
||||
quint8 reply = static_cast<quint8>(rdInt(read(1)));
|
||||
// reply 1: client header acceptable, SSL handshake not needed.
|
||||
// reply 2: client header acceptable, SSL handshake needed (STARTTLS).
|
||||
// reply 4: the common name sent by the client header was not found.
|
||||
|
||||
auto reply = static_cast<quint8>(rdInt(read(1)));
|
||||
|
||||
if ((reply == 1) || (reply == 2))
|
||||
{
|
||||
*Shared::servMajor = static_cast<quint16>(rdInt(read(2)));
|
||||
*Shared::servMinor = static_cast<quint16>(rdInt(read(2)));
|
||||
*Shared::servPatch = static_cast<quint16>(rdInt(read(2)));
|
||||
*Shared::tcpRev = static_cast<quint16>(rdInt(read(2)));
|
||||
*Shared::modRev = static_cast<quint16>(rdInt(read(2)));
|
||||
|
||||
cacheTxt(TEXT, "Detected host version: " + verText(*Shared::servMajor, *Shared::servMinor, *Shared::servPatch) + "\n");
|
||||
cacheTxt(TEXT, "Detected host version: " + verText() + "\n");
|
||||
|
||||
if (*Shared::servMajor == 2)
|
||||
if (*Shared::tcpRev == 0)
|
||||
{
|
||||
*Shared::sessionId = read(28);
|
||||
*Shared::connectedToHost = true;
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <QSslCipher>
|
||||
#include <QSslCertificate>
|
||||
#include <QSocketNotifier>
|
||||
#include <QTimer>
|
||||
|
||||
#include "cmd_objs/command.h"
|
||||
#include "cmd_objs/bookmarks.h"
|
||||
|
@ -50,17 +51,20 @@ class Session : public QSslSocket
|
|||
|
||||
private:
|
||||
|
||||
QTimer *progResetDelay;
|
||||
quint32 flags;
|
||||
quint32 dSize;
|
||||
quint16 cmdId;
|
||||
quint16 branId;
|
||||
quint16 hook;
|
||||
quint8 dType;
|
||||
bool activeProg;
|
||||
bool reconnect;
|
||||
|
||||
void cacheTxt(quint8 typeId, QString txt);
|
||||
void dataFromHost(const QByteArray &data);
|
||||
void procAsync(const QByteArray &data);
|
||||
void updateProg(int value);
|
||||
bool isAsync(quint16 id);
|
||||
|
||||
private slots:
|
||||
|
@ -69,6 +73,8 @@ private slots:
|
|||
void isConnected();
|
||||
void isDisconnected();
|
||||
void handShakeDone();
|
||||
void resetProg();
|
||||
void startProg();
|
||||
void sockerr(QAbstractSocket::SocketError err);
|
||||
|
||||
public:
|
||||
|
@ -90,7 +96,7 @@ public slots:
|
|||
void setCmdHook(quint16 cmdId);
|
||||
void idle();
|
||||
void termHostCmd();
|
||||
void haltHostCmd();
|
||||
void yieldHostCmd();
|
||||
void resumeHostCmd();
|
||||
void connectToServ();
|
||||
void disconnectFromServ();
|
||||
|
@ -100,6 +106,8 @@ signals:
|
|||
void hostFinished();
|
||||
void txtInCache();
|
||||
void loopDataIn();
|
||||
void showProg(bool);
|
||||
void setProg(int);
|
||||
void setUserIO(int flgs);
|
||||
void unsetUserIO(int flgs);
|
||||
void hostCmdRemoved(quint16 id);
|
||||
|
|
|
@ -44,7 +44,7 @@ void TextWorker::dumpTxtCache()
|
|||
{
|
||||
*Shared::activeDisp = !Shared::cacheTxt(Shared::TXT_IS_EMPTY);
|
||||
|
||||
if ((typeId == TEXT) || (typeId == PRIV_TEXT))
|
||||
if ((typeId == TEXT) || (typeId == PRIV_TEXT) | (typeId == PROMPT_TEXT))
|
||||
{
|
||||
addMainTxt(txt);
|
||||
|
||||
|
@ -103,8 +103,8 @@ void TextWorker::addBigTxt(const QString &txt)
|
|||
|
||||
void TextWorker::loadSettings()
|
||||
{
|
||||
mainColor = localData->value("text_settings").toObject().value("text_color").toString();
|
||||
errColor = localData->value("text_settings").toObject().value("err_color").toString();
|
||||
mainColor = localData->value("theme").toObject().value("text_color").toString();
|
||||
errColor = localData->value("theme").toObject().value("err_color").toString();
|
||||
}
|
||||
|
||||
TextBody::TextBody(QWidget *parent) : QTextEdit(parent)
|
||||
|
@ -116,7 +116,7 @@ TextBody::TextBody(QWidget *parent) : QTextEdit(parent)
|
|||
setDocument(txtDocument);
|
||||
setReadOnly(true);
|
||||
setWordWrapMode(QTextOption::NoWrap);
|
||||
loadTextSettings(localData, this);
|
||||
loadTheme(localData, this);
|
||||
loadTextBodySettings();
|
||||
}
|
||||
|
||||
|
@ -134,7 +134,7 @@ void TextBody::reload()
|
|||
{
|
||||
clear();
|
||||
|
||||
loadTextSettings(localData, this);
|
||||
loadTheme(localData, this);
|
||||
saveLocalData(localData);
|
||||
loadTextBodySettings();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user