Added Windows Build/Install Support

- added a -host_trig command line option that creates a new host
  instance without blocking user input.

- the build/install python scripts will no longer internally build
  platform specific shell scripts; instead, they will now copy the
  necessary templates from the /templates folder.

- modified both build.py and install.py to include windows
  deployment support so this app can now be built/installed on
  windows based host. note: i decided to have it "daemonized" as
  a scheduled task that runs on system start instead of service
  because it is simply easier to do it this way and will not
  involve any 3rd party libraries or apps.

- added the src/applink.c file to the source code since it is
  needed for windows openssl support.

- changed over all references of "endl" to "Qt::endl" to avoid
  depreciation errors/warnings.
This commit is contained in:
Maurice ONeal 2020-07-04 11:37:46 -04:00
parent 5ea1e45eb2
commit f62eb125cf
26 changed files with 686 additions and 312 deletions

2
.gitignore vendored
View File

@ -30,6 +30,8 @@ Makefile*
*build-*
/build
/app_dir
/release
/debug
# Qt unit tests
target_wrapper.*

View File

@ -24,25 +24,33 @@ QT -= gui
QT += network
QT += sql
CONFIG += console
CONFIG -= app_bundle
TARGET = build/mrci
OBJECTS_DIR = build
MOC_DIR = build
RCC_DIR = build
CONFIG += console
win32 {
LIBS += -llibeay32 -lssleay32
LIBS += -llibcrypto -llibssl
TARGET = mrci
DESTDIR_TARGET = build\\windows\\mrci.exe
OBJECTS_DIR = build\\windows
MOC_DIR = build\\windows
RCC_DIR = build\\windows
DESTDIR = build\\windows
} else {
LIBS += -lcrypto -lssl
TARGET = build/linux/mrci
OBJECTS_DIR = build/linux
MOC_DIR = build/linux
RCC_DIR = build/linux
}
SOURCES += src/main.cpp \
src/applink.c \
src/async_funcs.cpp \
src/cmd_object.cpp \
src/cmd_proc.cpp \

202
build.py
View File

@ -20,10 +20,10 @@ def get_qt_path():
try:
return str(subprocess.check_output(["qtpaths", "--binaries-dir"]), 'utf-8').strip()
except CalledProcessError:
print("A call to 'qtpaths' to get the QT installation bin folder failed.")
except:
print("A direct call to 'qtpaths' has failed so automatic retrieval of the QT bin folder is not possible.")
return raw_input("Please enter the QT bin path (leave blank to cancel the build): ")
return input("Please enter the QT bin path (leave blank to cancel the build): ")
def get_qt_from_cli():
for arg in sys.argv:
@ -45,6 +45,59 @@ def get_db_header():
return "src" + os.sep + "db.h"
else:
return current_dir + os.sep + "src" + os.sep + "db.h"
def get_nearest_subdir(path, sub_name):
dir_list = os.listdir(path)
ret = ""
for entry in dir_list:
if sub_name in entry:
ret = entry
break
return ret
def get_maker(qt_path):
ret = ""
if platform.system() == "Linux":
ret = "make"
elif platform.system() == "Windows":
path = os.path.abspath(qt_path + "\\..")
name = os.path.basename(path)
if "mingw" in name:
tools_path = os.path.abspath(qt_path + "\\..\\..\\..\\Tools")
mingw_ver = name[5:7]
mingw_tool_subdir = get_nearest_subdir(tools_path, "mingw" + mingw_ver)
mingw_tool_path = tools_path + "\\" + mingw_tool_subdir + "\\bin"
if not os.environ['PATH'].endswith(";"):
os.environ['PATH'] = os.environ['PATH'] + ";"
os.environ['PATH'] = os.environ['PATH'] + mingw_tool_path
ret = "mingw32-make"
elif "msvc" in name:
print("Warning: this script will assume you already ran the VsDevCmd.bat or vsvars32.bat script files")
print(" for Microsoft Visual Studio. Either way, a call to 'nmake' should be recognizable as ")
print(" a shell command otherwise this script will fail.\n")
ans = input("If that is the case enter 'y' to continue or any other key to cancel the build: ")
if ans == 'y' or ans == 'Y':
ret = "nmake"
else:
exit()
else:
print("The system platform is unknown. Output from platform.system() = " + platform.system())
return ret
def cd():
current_dir = os.path.dirname(__file__)
@ -72,9 +125,9 @@ def linux_build_app_dir(app_ver, app_name, app_target, qt_bin):
os.makedirs("app_dir/linux/lib")
verbose_copy(qt_bin + "/../plugins/sqldrivers/libqsqlite.so", "app_dir/linux/sqldrivers/libqsqlite.so")
verbose_copy("build/" + app_target, "app_dir/linux/" + app_target)
verbose_copy("build/linux/" + app_target, "app_dir/linux/" + app_target)
shutil.copyfile("build/" + app_target, "/tmp/" + app_target)
shutil.copyfile("build/linux/" + app_target, "/tmp/" + app_target)
# copying the executable file from the build folder to
# temp bypasses any -noexe retrictions a linux file
# system may have. there is a chance temp is also
@ -96,45 +149,51 @@ def linux_build_app_dir(app_ver, app_name, app_target, qt_bin):
file_name = os.path.basename(src_file)
verbose_copy(src_file, "app_dir/linux/lib/" + file_name)
with open("app_dir/linux/" + app_target + ".sh", "w") as file:
file.write("#!/bin/sh\n")
file.write("export QTDIR=$install_dir\n")
file.write("export QT_PLUGIN_PATH=$install_dir\n")
file.write("export LD_LIBRARY_PATH=\"$install_dir/lib:\$LD_LIBRARY_PATH\"\n")
file.write("$install_dir/" + app_target + " $1 $2 $3\n")
with open("app_dir/linux/" + app_target + ".service", "w") as file:
file.write("[Unit]\n")
file.write("Description=" + app_name + " Host Daemon\n")
file.write("After=network.target\n\n")
file.write("[Service]\n")
file.write("Type=simple\n")
file.write("User=" + app_target + "\n")
file.write("Restart=on-failure\n")
file.write("RestartSec=5\n")
file.write("TimeoutStopSec=infinity\n")
file.write("ExecStart=/usr/bin/env " + app_target + " -host\n")
file.write("ExecStop=/usr/bin/env " + app_target + " -stop\n\n")
file.write("[Install]\n")
file.write("WantedBy=multi-user.target\n")
with open("app_dir/linux/uninstall.sh", "w") as file:
file.write("#!/bin/sh\n")
file.write("systemctl -q stop " + app_target + "\n")
file.write("systemctl -q disable " + app_target + "\n")
file.write("rm -v /etc/systemd/system/" + app_target + ".service\n")
file.write("rm -v /usr/bin/" + app_target + "\n")
file.write("rm -rv $install_dir\n")
file.write("deluser " + app_target + "\n")
complete(app_ver)
def windows_build_app_dir():
print("Windows support is work in progress. Check for an update at a later time.")
# to do: fill out code for windows support here.
verbose_copy("templates/linux_run_script.sh", "app_dir/linux/" + app_target + ".sh")
verbose_copy("templates/linux_service.service", "app_dir/linux/" + app_target + ".service")
verbose_copy("templates/linux_uninstall.sh", "app_dir/linux/uninstall.sh")
complete(app_ver, app_target)
def windows_build_app_dir(app_ver, app_name, app_target, qt_bin):
if os.path.exists("release"):
os.removedirs("release")
if os.path.exists("debug"):
os.removedirs("debug")
if not os.path.exists("app_dir\\windows"):
os.makedirs("app_dir\\windows")
verbose_copy("build\\windows\\" + app_target + ".exe", "app_dir\\windows\\" + app_target + ".exe")
verbose_copy("templates\\windows_uninstall.bat", "app_dir\\windows\\uninstall.bat")
verbose_copy("templates\\windows_shtask.xml", "app_dir\\windows\\shtask.xml")
os.chdir("app_dir\\windows\\")
result = subprocess.run([qt_bin + "\\" + "windeployqt", app_target + ".exe"])
cd()
if result.returncode == 0:
complete(app_ver, app_target)
def complete(app_ver):
def complete(app_ver, app_target):
if os.path.exists("Makefile"):
os.remove("Makefile")
if os.path.exists("Makefile.Debug"):
os.remove("Makefile.Debug")
if os.path.exists("Makefile.Release"):
os.remove("Makefile.Release")
if os.path.exists("object_script." + app_target + ".Debug"):
os.remove("object_script." + app_target + ".Debug")
if os.path.exists("object_script." + app_target + ".Release"):
os.remove("object_script." + app_target + ".Release")
print("Build complete for version: " + app_ver)
print("You can now run the install.py script to install onto this machine or create an installer.")
@ -147,40 +206,47 @@ def main():
app_name = get_app_name(text)
qt_bin = get_qt_from_cli()
if qt_bin is "":
if qt_bin == "":
qt_bin = get_qt_path()
maker = get_maker(qt_bin)
if qt_bin != "":
print("app_target = " + app_target)
print("app_version = " + app_ver)
print("app_name = " + app_name)
print("qt_bin = " + qt_bin)
cd()
result = subprocess.run([qt_bin + os.sep + "qmake", "-config", "release"])
if result.returncode == 0:
result = subprocess.run(["make"])
print("maker = " + maker + "\n")
if maker == "":
print("Could not find a valid maker/compiler on this platform, unable to continue.")
else:
cd()
if result.returncode == 0:
if not os.path.exists("app_dir"):
os.makedirs("app_dir")
result = subprocess.run([qt_bin + os.sep + "qmake", "-config", "release"])
if result.returncode == 0:
result = subprocess.run([maker])
if result.returncode == 0:
if not os.path.exists("app_dir"):
os.makedirs("app_dir")
with open("app_dir" + os.sep + "info.txt", "w") as info_file:
info_file.write(app_target + "\n")
info_file.write(app_ver + "\n")
info_file.write(app_name + "\n")
if platform.system() == "Linux":
linux_build_app_dir(app_ver, app_name, app_target, qt_bin)
elif platform.system() == "Windows":
windows_build_app_dir(app_ver, app_name, app_target, qt_bin)
with open("app_dir" + os.sep + "info.txt", "w") as info_file:
info_file.write(app_target + "\n")
info_file.write(app_ver + "\n")
info_file.write(app_name + "\n")
if platform.system() == "Linux":
linux_build_app_dir(app_ver, app_name, app_target, qt_bin)
elif platform.system() == "Windows":
windows_build_app_dir()
else:
print("The platform you are running in is not compatible with the app_dir build out procedure.")
print(" output from platform.system() = " + platform.system())
else:
print("The platform you are running in is not compatible with the app_dir build out procedure.")
print(" output from platform.system() = " + platform.system())
if __name__ == "__main__":
main()

View File

@ -16,6 +16,7 @@ Usage: mrci <argument>
-status : display status information about the host instance if it is currently running.
-reset_root : reset the root account password to the default password.
-host : start a new host instance. (this blocks)
-host_trig : start a new host instance. (this does not block)
-default_pw : show the default password.
-public_cmds : run the internal module to list it's public commands. for internal use only.
-exempt_cmds : run the internal module to list it's rank exempt commands. for internal use only.
@ -84,7 +85,7 @@ make
python3
```
Windows support is still work in progress but the following applications will must likely need to be installed:
For Windows support you need to have the following applications installed:
```
OpenSSL
Qt5.12 or newer
@ -112,3 +113,5 @@ If a target linux system supports systemd, the application will be installed as
sudo systemctl start mrci
sudo systemctl stop mrci
```
In a Windows system, a scheduled task will be created to auto start the application in the background when the system starts.

View File

@ -220,7 +220,7 @@ to_client: [type_id(25)][cmd_id(28)][branch_id(0)][size_of_payload][payload(CH_M
```
```ASYNC_RM_CH_MEMBER (29)```
This async command carries a combination of the channel id and the 32byte user id of the channel member that has left or kicked from the channel member list. All sessions that are logged in as a member of the channel forwards the data to the clients as a [BYTES](type_ids.md) frame.
This async command carries a combination of the channel id and the 32byte user id of the channel member that has left or kicked from the channel member list. All sessions that are logged in as a member of the channel forwards the data to the clients as a [BYTES](type_ids.md) frame. This async aommand also sent when a user declines an invite to a channel.
```
from_module: [8bytes(chId)][32bytes(userId)]
to_client: [type_id(14)][cmd_id(29)][branch_id(0)][size_of_payload][payload(64bit_ch_id + 256bit_user_id)]

View File

@ -73,9 +73,13 @@ def make_install_dir(path):
try:
if not os.path.exists(path):
os.makedirs(path)
return True
except:
print("Failed to create the install directory, please make sure you are runnning this script with admin rights.")
return False
def replace_text(text, old_text, new_text, offs):
while(True):
@ -89,7 +93,7 @@ def replace_text(text, old_text, new_text, offs):
return text
def sub_copy_file(src, dst, old_text, new_text, offs):
print("cpy: " + src + " --> " + dst)
print("set: " + dst + " keyword: " + old_text + " to: " + new_text)
text = ""
@ -100,6 +104,11 @@ def sub_copy_file(src, dst, old_text, new_text, offs):
with open(dst, "w") as wr_file:
wr_file.write(text)
def template_to_deploy(src, dst, install_dir, app_name, app_target):
sub_copy_file(src, dst, "$install_dir", install_dir, 0)
sub_copy_file(dst, dst, "$app_name", app_name, 0)
sub_copy_file(dst, dst, "$app_target", app_target, 0)
def verbose_copy(src, dst):
print("cpy: " + src + " --> " + dst)
@ -119,6 +128,17 @@ def verbose_create_symmlink(src, dst):
os.remove(dst)
os.symlink(src, dst)
def conv_utf8_to_utf16(src, dst):
print("cvt: " + dst + " UTF-8 --> UTF-16")
data = bytearray()
with open(src, 'rb') as source_file:
data = source_file.read()
with open(dst, 'w+b') as dest_file:
dest_file.write(data.decode('utf-8').encode('utf-16'))
def local_install(app_target, app_name):
if platform.system() == "Linux":
@ -131,40 +151,71 @@ def local_install(app_target, app_name):
if os.path.exists(install_dir + "/uninstall.sh"):
subprocess.run([install_dir + "/uninstall.sh"])
make_install_dir(install_dir)
if make_install_dir(install_dir):
if not os.path.exists("/var/opt/" + app_target):
os.makedirs("/var/opt/" + app_target)
if not os.path.exists("/var/opt/" + app_target):
os.makedirs("/var/opt/" + app_target)
template_to_deploy("app_dir/linux/" + app_target + ".sh", install_dir + "/" + app_target + ".sh", install_dir, app_name, app_target)
template_to_deploy("app_dir/linux/uninstall.sh", install_dir + "/uninstall.sh", install_dir, app_name, app_target)
template_to_deploy("app_dir/linux/" + app_target + ".service", "/etc/systemd/system/" + app_target + ".service", install_dir, app_name, app_target)
sub_copy_file("app_dir/linux/" + app_target + ".sh", install_dir + "/" + app_target + ".sh", "$install_dir", install_dir, 0)
sub_copy_file("app_dir/linux/uninstall.sh", install_dir + "/uninstall.sh", "$install_dir", install_dir, 0)
verbose_copy("app_dir/linux/" + app_target, install_dir + "/" + app_target)
verbose_copy("app_dir/linux/lib", install_dir + "/lib")
verbose_copy("app_dir/linux/sqldrivers", install_dir + "/sqldrivers")
verbose_copy("app_dir/linux/" + app_target, install_dir + "/" + app_target)
verbose_copy("app_dir/linux/lib", install_dir + "/lib")
verbose_copy("app_dir/linux/sqldrivers", install_dir + "/sqldrivers")
verbose_copy("app_dir/linux/" + app_target + ".service", "/etc/systemd/system/" + app_target + ".service")
verbose_create_symmlink(install_dir + "/" + app_target + ".sh", "/usr/bin/" + app_target)
verbose_create_symmlink(install_dir + "/" + app_target + ".sh", "/usr/bin/" + app_target)
subprocess.run(["useradd", "-r", app_target])
subprocess.run(["chmod", "-R", "755", install_dir])
subprocess.run(["chmod", "755", "/etc/systemd/system/" + app_target + ".service"])
subprocess.run(["chown", "-R", app_target + ":" + app_target, "/var/opt/" + app_target])
subprocess.run(["systemctl", "start", app_target])
subprocess.run(["systemctl", "enable", app_target])
subprocess.run(["useradd", "-r", app_target])
subprocess.run(["chmod", "-R", "755", install_dir])
subprocess.run(["chmod", "755", "/etc/systemd/system/" + app_target + ".service"])
subprocess.run(["chown", "-R", app_target + ":" + app_target, "/var/opt/" + app_target])
subprocess.run(["systemctl", "start", app_target])
subprocess.run(["systemctl", "enable", app_target])
print("Installation finished. If you ever need to uninstall this application, run this command with root rights:")
print(" sh " + install_dir + "/uninstall.sh\n")
print("Installation finished. If you ever need to uninstall this application, run this command with root rights:")
print(" sh " + install_dir + "/uninstall.sh\n")
elif platform.system() == "Windows":
print("Windows support is work progress. Check for an update at a later time.")
# to do: fill ot code for windows support here.
if not os.path.exists("app_dir\\windows"):
print("An app_dir for the Windows platform could not be found.")
else:
install_dir = get_install_dir(app_target, app_name)
if os.path.exists(install_dir + "\\uninstall.bat"):
subprocess.run([install_dir + "\\uninstall.bat"])
if os.path.exists(install_dir):
# this block is here make sure the install_dir is deleted if/when
# the uninstall.bat fails to do so. in my test machine, the .bat
# script will delete install_dir if run directly but not when
# called through subprocess.run() for some reason.
shutil.rmtree(install_dir)
if make_install_dir(install_dir):
verbose_copy("app_dir\\windows", install_dir)
template_to_deploy("app_dir\\windows\\uninstall.bat", install_dir + "\\uninstall.bat", install_dir, app_name, app_target)
template_to_deploy("app_dir\\windows\\shtask.xml", install_dir + "\\shtask.xml", install_dir, app_name, app_target)
sub_copy_file(install_dir + "\\shtask.xml", install_dir + "\\shtask.xml", "UTF-8", "UTF-16", 0)
conv_utf8_to_utf16(install_dir + "\\shtask.xml", install_dir + "\\shtask.xml")
verbose_create_symmlink(install_dir + "\\" + app_target + ".exe", os.environ['WINDIR'] + "\\" + app_target + ".exe")
subprocess.run(["schtasks", "/create", "/xml", install_dir + "\\shtask.xml", "/tn", app_name])
subprocess.run(["schtasks", "/run", "/tn", app_name])
print("Installation finished. If you ever need to uninstall this application, run this batch file with admin rights:")
print(" " + install_dir + "\\uninstall.bat\n")
else:
print("The platform you are running in is not compatible.")
print(" output from platform.system() = " + platform.system())
def dir_tree(path):
ret = []
if os.path.isdir(path):

138
src/applink.c Normal file
View File

@ -0,0 +1,138 @@
/*
* Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#define APPLINK_STDIN 1
#define APPLINK_STDOUT 2
#define APPLINK_STDERR 3
#define APPLINK_FPRINTF 4
#define APPLINK_FGETS 5
#define APPLINK_FREAD 6
#define APPLINK_FWRITE 7
#define APPLINK_FSETMOD 8
#define APPLINK_FEOF 9
#define APPLINK_FCLOSE 10 /* should not be used */
#define APPLINK_FOPEN 11 /* solely for completeness */
#define APPLINK_FSEEK 12
#define APPLINK_FTELL 13
#define APPLINK_FFLUSH 14
#define APPLINK_FERROR 15
#define APPLINK_CLEARERR 16
#define APPLINK_FILENO 17 /* to be used with below */
#define APPLINK_OPEN 18 /* formally can't be used, as flags can vary */
#define APPLINK_READ 19
#define APPLINK_WRITE 20
#define APPLINK_LSEEK 21
#define APPLINK_CLOSE 22
#define APPLINK_MAX 22 /* always same as last macro */
#ifndef APPMACROS_ONLY
# include <stdio.h>
# include <io.h>
# include <fcntl.h>
static void *app_stdin(void)
{
return stdin;
}
static void *app_stdout(void)
{
return stdout;
}
static void *app_stderr(void)
{
return stderr;
}
static int app_feof(FILE *fp)
{
return feof(fp);
}
static int app_ferror(FILE *fp)
{
return ferror(fp);
}
static void app_clearerr(FILE *fp)
{
clearerr(fp);
}
static int app_fileno(FILE *fp)
{
return _fileno(fp);
}
static int app_fsetmod(FILE *fp, char mod)
{
return _setmode(_fileno(fp), mod == 'b' ? _O_BINARY : _O_TEXT);
}
#ifdef __cplusplus
extern "C" {
#endif
__declspec(dllexport)
void **
# if defined(__BORLANDC__)
/*
* __stdcall appears to be the only way to get the name
* decoration right with Borland C. Otherwise it works
* purely incidentally, as we pass no parameters.
*/
__stdcall
# else
__cdecl
# endif
OPENSSL_Applink(void)
{
static int once = 1;
static void *OPENSSL_ApplinkTable[APPLINK_MAX + 1] =
{ (void *)APPLINK_MAX };
if (once) {
OPENSSL_ApplinkTable[APPLINK_STDIN] = (void*) app_stdin;
OPENSSL_ApplinkTable[APPLINK_STDOUT] = (void*) app_stdout;
OPENSSL_ApplinkTable[APPLINK_STDERR] = (void*) app_stderr;
OPENSSL_ApplinkTable[APPLINK_FPRINTF] = (void*) fprintf;
OPENSSL_ApplinkTable[APPLINK_FGETS] = (void*) fgets;
OPENSSL_ApplinkTable[APPLINK_FREAD] = (void*) fread;
OPENSSL_ApplinkTable[APPLINK_FWRITE] = (void*) fwrite;
OPENSSL_ApplinkTable[APPLINK_FSETMOD] = (void*) app_fsetmod;
OPENSSL_ApplinkTable[APPLINK_FEOF] = (void*) app_feof;
OPENSSL_ApplinkTable[APPLINK_FCLOSE] = (void*) fclose;
OPENSSL_ApplinkTable[APPLINK_FOPEN] = (void*) fopen;
OPENSSL_ApplinkTable[APPLINK_FSEEK] = (void*) fseek;
OPENSSL_ApplinkTable[APPLINK_FTELL] = (void*) ftell;
OPENSSL_ApplinkTable[APPLINK_FFLUSH] = (void*) fflush;
OPENSSL_ApplinkTable[APPLINK_FERROR] = (void*) app_ferror;
OPENSSL_ApplinkTable[APPLINK_CLEARERR] = (void*) app_clearerr;
OPENSSL_ApplinkTable[APPLINK_FILENO] = (void*) app_fileno;
OPENSSL_ApplinkTable[APPLINK_OPEN] = (void*) _open;
OPENSSL_ApplinkTable[APPLINK_READ] = (void*) _read;
OPENSSL_ApplinkTable[APPLINK_WRITE] = (void*) _write;
OPENSSL_ApplinkTable[APPLINK_LSEEK] = (void*) _lseek;
OPENSSL_ApplinkTable[APPLINK_CLOSE] = (void*) _close;
once = 0;
}
return OPENSSL_ApplinkTable;
}
#ifdef __cplusplus
}
#endif
#endif

View File

@ -608,9 +608,9 @@ void PreviewEmail::procIn(const QByteArray &binIn, quint8 dType)
QString txt;
QTextStream txtOut(&txt);
txtOut << "-----Subject-------" << endl << endl;
txtOut << subject << endl << endl;
txtOut << "-----Body----------" << endl << endl;
txtOut << "-----Subject-------" << Qt::endl << Qt::endl;
txtOut << subject << Qt::endl << Qt::endl;
txtOut << "-----Body----------" << Qt::endl << Qt::endl;
mainTxt(txt);
bigTxt(body);

View File

@ -117,19 +117,19 @@ void ServSettings::printSettings()
QString txt;
QTextStream txtOut(&txt);
txtOut << "All Sub-Channels Active Update: " << actBool << endl;
txtOut << "Public Registration: " << pubBool << endl;
txtOut << "Automated Password Resets: " << resBool << endl;
txtOut << "Automated Email Verify: " << conBool << endl;
txtOut << "Maximum Sessions: " << db.getData(COLUMN_MAXSESSIONS).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 Host Rank: " << db.getData(COLUMN_INITRANK).toUInt() << endl;
txtOut << "Root User: " << getUserName(rootUserId()) << endl;
txtOut << "Working Path: " << QDir::currentPath() << endl;
txtOut << "Database: " << sqlDataPath() << endl;
txtOut << "Mailer Executable: " << db.getData(COLUMN_MAILERBIN).toString() << endl;
txtOut << "Mailer Command: " << db.getData(COLUMN_MAIL_SEND).toString() << endl << endl;
txtOut << "All Sub-Channels Active Update: " << actBool << Qt::endl;
txtOut << "Public Registration: " << pubBool << Qt::endl;
txtOut << "Automated Password Resets: " << resBool << Qt::endl;
txtOut << "Automated Email Verify: " << conBool << Qt::endl;
txtOut << "Maximum Sessions: " << db.getData(COLUMN_MAXSESSIONS).toUInt() << Qt::endl;
txtOut << "Autolock Threshold: " << db.getData(COLUMN_LOCK_LIMIT).toUInt() << Qt::endl;
txtOut << "Maximum Sub-Channels: " << db.getData(COLUMN_MAX_SUB_CH).toUInt() << Qt::endl;
txtOut << "Initial Host Rank: " << db.getData(COLUMN_INITRANK).toUInt() << Qt::endl;
txtOut << "Root User: " << getUserName(rootUserId()) << Qt::endl;
txtOut << "Working Path: " << QDir::currentPath() << Qt::endl;
txtOut << "Database: " << sqlDataPath() << Qt::endl;
txtOut << "Mailer Executable: " << db.getData(COLUMN_MAILERBIN).toString() << Qt::endl;
txtOut << "Mailer Command: " << db.getData(COLUMN_MAIL_SEND).toString() << Qt::endl << Qt::endl;
mainTxt(txt);
}
@ -141,12 +141,12 @@ void ServSettings::printOptions()
QString txt;
QTextStream txtOut(&txt);
txtOut << "[01] Autolock Threshold [02] Max Sessions" << endl;
txtOut << "[03] Public Registration [04] Initial Rank" << endl;
txtOut << "[05] Mailer Exe [06] Mailer Command" << endl;
txtOut << "[07] Password Resets [08] Email Verify" << endl;
txtOut << "[09] Active Update [10] Max Sub-Channels" << endl;
txtOut << "[11] Set Root User [00] Exit" << endl << endl;
txtOut << "[01] Autolock Threshold [02] Max Sessions" << Qt::endl;
txtOut << "[03] Public Registration [04] Initial Rank" << Qt::endl;
txtOut << "[05] Mailer Exe [06] Mailer Command" << Qt::endl;
txtOut << "[07] Password Resets [08] Email Verify" << Qt::endl;
txtOut << "[09] Active Update [10] Max Sub-Channels" << Qt::endl;
txtOut << "[11] Set Root User [00] Exit" << Qt::endl << Qt::endl;
txtOut << "Select an option: ";
level = 1;
@ -182,125 +182,125 @@ void ServSettings::procIn(const QByteArray &binIn, quint8 dType)
if ((select == 1) && ok)
{
txtOut << "" << endl;
txtOut << "The autolock threshold is an integer value that determines how many" << endl;
txtOut << "failed login attempts can be made before the user account is locked" << endl;
txtOut << "by the host." << endl << endl;
txtOut << "" << Qt::endl;
txtOut << "The autolock threshold is an integer value that determines how many" << Qt::endl;
txtOut << "failed login attempts can be made before the user account is locked" << Qt::endl;
txtOut << "by the host." << Qt::endl << Qt::endl;
txtOut << "Enter a new value (leave blank to cancel): ";
level = 2;
}
else if ((select == 2) && ok)
{
txtOut << "" << endl;
txtOut << "Max sessions is an integar value that determines how many simultaneous" << endl;
txtOut << "clients the host will be allowed to run at once." << endl << endl;
txtOut << "" << Qt::endl;
txtOut << "Max sessions is an integar value that determines how many simultaneous" << Qt::endl;
txtOut << "clients the host will be allowed to run at once." << Qt::endl << Qt::endl;
txtOut << "Enter a new value (leave blank to cancel): ";
level = 2;
}
else if ((select == 3) && ok)
{
txtOut << "" << endl;
txtOut << "Public registration basically allows un-logged in clients to run the" << endl;
txtOut << "add_acct command. doing this allows un-registered users to become" << endl;
txtOut << "registered users without the need to contact an admin." << endl << endl;
txtOut << "[0] Disable" << endl;
txtOut << "[1] Enable" << endl << endl;
txtOut << "" << Qt::endl;
txtOut << "Public registration basically allows un-logged in clients to run the" << Qt::endl;
txtOut << "add_acct command. doing this allows un-registered users to become" << Qt::endl;
txtOut << "registered users without the need to contact an admin." << Qt::endl << Qt::endl;
txtOut << "[0] Disable" << Qt::endl;
txtOut << "[1] Enable" << Qt::endl << Qt::endl;
txtOut << "Select an option (leave blank to cancel): ";
level = 2;
}
else if ((select == 4) && ok)
{
txtOut << "" << endl;
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 << "" << Qt::endl;
txtOut << "The initial host rank is the rank all new user accounts are registered" << Qt::endl;
txtOut << "with when created. the host rank itself is an integer value that" << Qt::endl;
txtOut << "determine what commands each user can or cannot run." << Qt::endl << Qt::endl;
txtOut << "Enter a new value (leave blank to cancel): ";
level = 2;
}
else if ((select == 5) && ok)
{
txtOut << "" << endl;
txtOut << "This is the path to the command line email client executable" << endl;
txtOut << "that the host can utilize to send emails to registered users." << endl << endl;
txtOut << "note: the host assumes the email application already has a" << endl;
txtOut << " configured sender email address/server." << endl << endl;
txtOut << "" << Qt::endl;
txtOut << "This is the path to the command line email client executable" << Qt::endl;
txtOut << "that the host can utilize to send emails to registered users." << Qt::endl << Qt::endl;
txtOut << "note: the host assumes the email application already has a" << Qt::endl;
txtOut << " configured sender email address/server." << Qt::endl << Qt::endl;
txtOut << "Enter a new path (leave blank to cancel): ";
level = 2;
}
else if ((select == 6) && ok)
{
txtOut << "" << endl;
txtOut << "This is the command line that will be used with the email client" << endl;
txtOut << "executable to send emails to registered users. it must contain the" << endl;
txtOut << "keywords " << SUBJECT_SUB << ", " << TARGET_EMAIL_SUB << " and " << MSG_SUB << " to be" << endl;
txtOut << "acceptable. the host will substitute these keywords for actual" << endl;
txtOut << "parameters when calling the email client." << endl << endl;
txtOut << "" << Qt::endl;
txtOut << "This is the command line that will be used with the email client" << Qt::endl;
txtOut << "executable to send emails to registered users. it must contain the" << Qt::endl;
txtOut << "keywords " << SUBJECT_SUB << ", " << TARGET_EMAIL_SUB << " and " << MSG_SUB << " to be" << Qt::endl;
txtOut << "acceptable. the host will substitute these keywords for actual" << Qt::endl;
txtOut << "parameters when calling the email client." << Qt::endl << Qt::endl;
txtOut << "Enter a new command line (leave blank to cancel): ";
level = 2;
}
else if ((select == 7) && ok)
{
txtOut << "" << endl;
txtOut << "This enables automated password resets via email so users can" << endl;
txtOut << "reset their account passwords without the need to contact an" << endl;
txtOut << "admin. this basically tells the host if it is allowed to load" << endl;
txtOut << "the request_pw_reset and recover_acct commands or not." << endl << endl;
txtOut << "[0] Disable" << endl;
txtOut << "[1] Enable" << endl << endl;
txtOut << "" << Qt::endl;
txtOut << "This enables automated password resets via email so users can" << Qt::endl;
txtOut << "reset their account passwords without the need to contact an" << Qt::endl;
txtOut << "admin. this basically tells the host if it is allowed to load" << Qt::endl;
txtOut << "the request_pw_reset and recover_acct commands or not." << Qt::endl << Qt::endl;
txtOut << "[0] Disable" << Qt::endl;
txtOut << "[1] Enable" << Qt::endl << Qt::endl;
txtOut << "Select an option (leave blank to cancel): ";
level = 2;
}
else if ((select == 8) && ok)
{
txtOut << "" << endl;
txtOut << "This enables/disables automated email confirmations. this" << endl;
txtOut << "tells the host if it is allowed to load the verify_email " << endl;
txtOut << "command for any user, regardless of rank." << endl << endl;
txtOut << "[0] Disable" << endl;
txtOut << "[1] Enable" << endl << endl;
txtOut << "" << Qt::endl;
txtOut << "This enables/disables automated email confirmations. this" << Qt::endl;
txtOut << "tells the host if it is allowed to load the verify_email " << Qt::endl;
txtOut << "command for any user, regardless of rank." << Qt::endl << Qt::endl;
txtOut << "[0] Disable" << Qt::endl;
txtOut << "[1] Enable" << Qt::endl << Qt::endl;
txtOut << "Select an option (leave blank to cancel): ";
level = 2;
}
else if ((select == 9) && ok)
{
txtOut << "" << endl;
txtOut << "This option tells the host if all sub-channels should be considered" << endl;
txtOut << "active or not. otherwise, the active flag can be toggled on/off at the" << endl;
txtOut << "sub-channel level. active sub-channels send/receive PEER_INFO or" << endl;
txtOut << "PEER_STAT frames with each other so all peers connected to the" << endl;
txtOut << "sub-channel can be made aware of each other's public information." << endl;
txtOut << "without the active flag, no such frames are transffered." << endl << endl;
txtOut << "[0] Disable" << endl;
txtOut << "[1] Enable" << endl << endl;
txtOut << "" << Qt::endl;
txtOut << "This option tells the host if all sub-channels should be considered" << Qt::endl;
txtOut << "active or not. otherwise, the active flag can be toggled on/off at the" << Qt::endl;
txtOut << "sub-channel level. active sub-channels send/receive PEER_INFO or" << Qt::endl;
txtOut << "PEER_STAT frames with each other so all peers connected to the" << Qt::endl;
txtOut << "sub-channel can be made aware of each other's public information." << Qt::endl;
txtOut << "without the active flag, no such frames are transffered." << Qt::endl << Qt::endl;
txtOut << "[0] Disable" << Qt::endl;
txtOut << "[1] Enable" << Qt::endl << Qt::endl;
txtOut << "Select an option (leave blank to cancel): ";
level = 2;
}
else if ((select == 10) && ok)
{
txtOut << "" << endl;
txtOut << "This option sets the maximum amount of sub-channels each channel can" << endl;
txtOut << "have. the hard maximum is 256 and the minimum is 1." << endl << endl;
txtOut << "" << Qt::endl;
txtOut << "This option sets the maximum amount of sub-channels each channel can" << Qt::endl;
txtOut << "have. the hard maximum is 256 and the minimum is 1." << Qt::endl << Qt::endl;
txtOut << "Enter a new value (leave blank to cancel): ";
level = 2;
}
else if ((select == 11) && ok)
{
txtOut << "" << endl;
txtOut << "Set the root user of the host by the given user name. the root user" << endl;
txtOut << "is an unrestricted user that can do anything on the host. this user" << endl;
txtOut << "however is unable to change rank (1) and cannot get deleted. only" << endl;
txtOut << "the current root user can use this option to appoint an existing" << endl;
txtOut << "user as the new root." << endl << endl;
txtOut << "" << Qt::endl;
txtOut << "Set the root user of the host by the given user name. the root user" << Qt::endl;
txtOut << "is an unrestricted user that can do anything on the host. this user" << Qt::endl;
txtOut << "however is unable to change rank (1) and cannot get deleted. only" << Qt::endl;
txtOut << "the current root user can use this option to appoint an existing" << Qt::endl;
txtOut << "user as the new root." << Qt::endl << Qt::endl;
if (rdFromBlock(userId, BLKSIZE_USER_ID) != rootUserId())
{
@ -308,7 +308,7 @@ void ServSettings::procIn(const QByteArray &binIn, quint8 dType)
}
else
{
txtOut << "You are not the current root user so this option is blocked." << endl;
txtOut << "You are not the current root user so this option is blocked." << Qt::endl;
txtOut << "Press enter to return to the main menu.";
}
@ -320,7 +320,7 @@ void ServSettings::procIn(const QByteArray &binIn, quint8 dType)
}
else
{
txtOut << "" << endl << "Select an option: ";
txtOut << "" << Qt::endl << "Select an option: ";
}
promptTxt(txt);

View File

@ -64,6 +64,7 @@ ListMembers::ListMembers(QObject *parent) : TableViewer(parent)
addTableColumn(TABLE_CH_MEMBERS, COLUMN_CHANNEL_ID);
addTableColumn(TABLE_USERS, COLUMN_USERNAME);
addTableColumn(TABLE_USERS, COLUMN_DISPLAY_NAME);
addTableColumn(TABLE_USERS, COLUMN_USER_ID);
addTableColumn(TABLE_CH_MEMBERS, COLUMN_PENDING_INVITE);
addTableColumn(TABLE_CH_MEMBERS, COLUMN_ACCESS_LEVEL);
addJointColumn(TABLE_USERS, COLUMN_USER_ID);

View File

@ -200,7 +200,7 @@ void UploadFile::onTerminate()
ssMode = false;
flags = 0;
offs = 0;
mode = nullptr;
mode = QFile::OpenModeFlag();
}
void UploadFile::wrToFile(const QByteArray &data)
@ -309,7 +309,7 @@ void UploadFile::procIn(const QByteArray &binIn, quint8 dType)
{
if (argExists("-truncate", args))
{
mode = QFile::ReadWrite | QFile::Truncate;
mode = QFile::WriteOnly;
}
else
{
@ -892,21 +892,21 @@ void FileInfo::procIn(const QByteArray &binIn, quint8 dType)
QTextStream txtOut(&txt);
QStorageInfo storInfo(path);
txtOut << "is_file: " << boolStr(info.isFile()) << endl;
txtOut << "is_dir: " << boolStr(info.isDir()) << endl;
txtOut << "is_symlnk: " << boolStr(info.isSymLink()) << endl << endl;
txtOut << "is_file: " << boolStr(info.isFile()) << Qt::endl;
txtOut << "is_dir: " << boolStr(info.isDir()) << Qt::endl;
txtOut << "is_symlnk: " << boolStr(info.isSymLink()) << Qt::endl << Qt::endl;
txtOut << "can_read: " << boolStr(info.isReadable()) << endl;
txtOut << "can_write: " << boolStr(info.isWritable()) << endl;
txtOut << "can_execute: " << boolStr(info.isExecutable()) << endl << endl;
txtOut << "can_read: " << boolStr(info.isReadable()) << Qt::endl;
txtOut << "can_write: " << boolStr(info.isWritable()) << Qt::endl;
txtOut << "can_execute: " << boolStr(info.isExecutable()) << Qt::endl << Qt::endl;
txtOut << "bytes: " << QString::number(info.size()) << endl << endl;
txtOut << "bytes: " << QString::number(info.size()) << Qt::endl << Qt::endl;
txtOut << "device: " << storInfo.device() << endl << endl;
txtOut << "device: " << storInfo.device() << Qt::endl << Qt::endl;
txtOut << "time_created: " << info.birthTime().toString("MM/dd/yyyy hh:mm:ss AP t") << endl;
txtOut << "last_modified: " << info.lastModified().toString("MM/dd/yyyy hh:mm:ss AP t") << endl;
txtOut << "last_accessed: " << info.lastRead().toString("MM/dd/yyyy hh:mm:ss AP t") << endl;
txtOut << "time_created: " << info.birthTime().toString("MM/dd/yyyy hh:mm:ss AP t") << Qt::endl;
txtOut << "last_modified: " << info.lastModified().toString("MM/dd/yyyy hh:mm:ss AP t") << Qt::endl;
txtOut << "last_accessed: " << info.lastRead().toString("MM/dd/yyyy hh:mm:ss AP t") << Qt::endl;
mainTxt(txt);
}

View File

@ -54,12 +54,12 @@ class UploadFile : public CmdObject
private:
QFile::OpenMode mode;
QFile *file;
qint64 offs;
bool ssMode;
bool confirm;
bool force;
QFile::OpenModeFlag mode;
QFile *file;
qint64 offs;
bool ssMode;
bool confirm;
bool force;
void wrToFile(const QByteArray &data);
void onTerminate();

View File

@ -118,13 +118,13 @@ void HostInfo::procIn(const QByteArray &binIn, quint8 dType)
hostSharedMem->unlock();
txtOut << "Application: " << libName() << endl;
txtOut << "Qt Base: " << QT_VERSION_STR << endl;
txtOut << "Host Name: " << QSysInfo::machineHostName() << endl;
txtOut << "Host OS: " << QSysInfo::prettyProductName() << endl;
txtOut << "Load: " << sesCount << "/" << maxSes << endl;
txtOut << "Listening Addr: " << db.getData(COLUMN_IPADDR).toString() << endl;
txtOut << "Listening Port: " << db.getData(COLUMN_PORT).toUInt() << endl;
txtOut << "Application: " << libName() << Qt::endl;
txtOut << "Qt Base: " << QT_VERSION_STR << Qt::endl;
txtOut << "Host Name: " << QSysInfo::machineHostName() << Qt::endl;
txtOut << "Host OS: " << QSysInfo::prettyProductName() << Qt::endl;
txtOut << "Load: " << sesCount << "/" << maxSes << Qt::endl;
txtOut << "Listening Addr: " << db.getData(COLUMN_IPADDR).toString() << Qt::endl;
txtOut << "Listening Port: " << db.getData(COLUMN_PORT).toUInt() << Qt::endl;
mainTxt(txt);
}
@ -143,9 +143,9 @@ void MyInfo::procIn(const QByteArray &binIn, quint8 dType)
QString ip = rdStringFromBlock(clientIp, BLKSIZE_CLIENT_IP);
QString app = rdStringFromBlock(appName, BLKSIZE_APP_NAME);
txtOut << "Session id: " << sesId << endl;
txtOut << "IP Address: " << ip << endl;
txtOut << "App Name: " << app << endl;
txtOut << "Session id: " << sesId << Qt::endl;
txtOut << "IP Address: " << ip << Qt::endl;
txtOut << "App Name: " << app << Qt::endl;
if (!isEmptyBlock(userId, BLKSIZE_USER_ID))
{
@ -160,14 +160,14 @@ void MyInfo::procIn(const QByteArray &binIn, quint8 dType)
db.addCondition(COLUMN_USER_ID, uId);
db.exec();
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(rd8BitFromBlock(chOwnerOverride)) << endl;
txtOut << "Host Rank: " << rd32BitFromBlock(hostRank) << endl;
txtOut << "User Name: " << rdStringFromBlock(userName, BLKSIZE_USER_NAME) << Qt::endl;
txtOut << "Display Name: " << rdStringFromBlock(displayName, BLKSIZE_DISP_NAME) << Qt::endl;
txtOut << "User id: " << uId.toHex() << Qt::endl;
txtOut << "Email: " << db.getData(COLUMN_EMAIL).toString() << Qt::endl;
txtOut << "Register Date: " << db.getData(COLUMN_TIME).toString() << Qt::endl;
txtOut << "Email Verified: " << boolStr(db.getData(COLUMN_EMAIL_VERIFIED).toBool()) << Qt::endl;
txtOut << "Owner Override: " << boolStr(rd8BitFromBlock(chOwnerOverride)) << Qt::endl;
txtOut << "Host Rank: " << rd32BitFromBlock(hostRank) << Qt::endl;
}
mainTxt(txt);

View File

@ -40,16 +40,16 @@ QByteArray rdFileContents(const QString &path, QTextStream &msg)
if (!ret.isEmpty())
{
msg << "[pass]" << endl;
msg << "[pass]" << Qt::endl;
}
else
{
msg << "[fail] (0 bytes of data was read from the file, is it empty?)" << endl;
msg << "[fail] (0 bytes of data was read from the file, is it empty?)" << Qt::endl;
}
}
else
{
msg << "[fail] (" << file.errorString() << ")" << endl;
msg << "[fail] (" << file.errorString() << ")" << Qt::endl;
}
file.close();
@ -1007,11 +1007,11 @@ bool ShellIPC::connectToHost()
{
if (QFileInfo(QDir::tempPath() + "/" + HOST_CONTROL_PIPE).exists())
{
QTextStream(stdout) << "" << endl << "Permission denied." << endl << endl;
QTextStream(stdout) << "" << Qt::endl << "Permission denied." << Qt::endl << Qt::endl;
}
else
{
QTextStream(stdout) << "" << endl << "Host instance not running." << endl << endl;
QTextStream(stdout) << "" << Qt::endl << "Host instance not running." << Qt::endl << Qt::endl;
}
}

View File

@ -17,9 +17,6 @@
// along with MRCI under the LICENSE.md file. If not, see
// <http://www.gnu.org/licenses/>.
#include <openssl/ssl.h>
#include <openssl/x509.h>
#include <QList>
#include <QObject>
#include <QtEndian>
@ -68,6 +65,9 @@
#include <QtGlobal>
#include <QLibrary>
#include <openssl/ssl.h>
#include <openssl/x509.h>
#include "db.h"
#include "shell.h"
#include "mem_share.h"

View File

@ -384,20 +384,20 @@ QString Query::errDetail()
QTextStream txtOut(&ret);
txtOut << " driver error: " << errTxt << endl;
txtOut << " query: " << qStr << jStr << wStr << limit << endl;
txtOut << " database: " << sqlDataPath() << endl;
txtOut << " driver error: " << errTxt << Qt::endl;
txtOut << " query: " << qStr << jStr << wStr << limit << Qt::endl;
txtOut << " database: " << sqlDataPath() << Qt::endl;
auto info = QFileInfo(QFileInfo(sqlDataPath()).path());
if (!info.isReadable())
{
txtOut << " readable: database path doesn't have read permissions." << endl;
txtOut << " readable: database path doesn't have read permissions." << Qt::endl;
}
if (!info.isWritable())
{
txtOut << " writable: database path doesn't have write permissions." << endl;
txtOut << " writable: database path doesn't have write permissions." << Qt::endl;
}
return ret;

View File

@ -37,7 +37,7 @@
#include "shell.h"
#define APP_NAME "MRCI"
#define APP_VER "3.4.1.0"
#define APP_VER "3.5.1.0"
#define APP_TARGET "mrci"
#ifdef Q_OS_WIN

View File

@ -25,6 +25,19 @@
// along with MRCI under the LICENSE.md file. If not, see
// <http://www.gnu.org/licenses/>.
#ifdef Q_OS_WINDOWS
extern "C"
{
// applink.c was copied from the openssl lib and slightly modified so
// it can be compiled in mingw64.
// per https://www.openssl.org/docs/man1.1.0/man3/OPENSSL_Applink.html
// this file provides a glue between OpenSSL BIO layer and Win32
// compiler run-time environment. without this the app will crash with
// a "no OPENSSL_Applink" error.
#include <src/applink.c>
}
#endif
void msgHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
Q_UNUSED(type)
@ -44,40 +57,41 @@ void showHelp()
{
QTextStream txtOut(stdout);
txtOut << "" << endl << APP_NAME << " v" << QCoreApplication::applicationVersion() << endl << endl;
txtOut << "Usage: " << APP_TARGET << " <argument>" << endl << endl;
txtOut << "<Arguments>" << endl << endl;
txtOut << " -help : display usage information about this application." << endl;
txtOut << " -stop : stop the current host instance if one is currently running." << endl;
txtOut << " -about : display versioning/warranty information about this application." << endl;
txtOut << " -addr : set the listening address and port for TCP clients." << endl;
txtOut << " -status : display status information about the host instance if it is currently running." << endl;
txtOut << " -reset_root : reset the root account password to the default password." << endl;
txtOut << " -host : start a new host instance. (this blocks)" << endl;
txtOut << " -default_pw : show the default password." << endl;
txtOut << " -public_cmds : run the internal module to list it's public commands. for internal use only." << endl;
txtOut << " -exempt_cmds : run the internal module to list it's rank exempt commands. for internal use only." << endl;
txtOut << " -user_cmds : run the internal module to list it's user commands. for internal use only." << endl;
txtOut << " -run_cmd : run an internal module command. for internal use only." << endl;
txtOut << " -load_ssl : re-load the host SSL certificate without stopping the host instance." << endl << endl;
txtOut << "Internal module | -public_cmds, -user_cmds, -exempt_cmds, -run_cmd |:" << endl << endl;
txtOut << " -pipe : the named pipe used to establish a data connection with the session." << endl;
txtOut << " -mem_ses : the shared memory key for the session." << endl;
txtOut << " -mem_host : the shared memory key for the host main process." << endl << endl;
txtOut << "Details:" << endl << endl;
txtOut << "addr - this argument takes a {ip_address:port} string. it will return an error if not formatted correctly" << endl;
txtOut << " examples: 10.102.9.2:35516 or 0.0.0.0:35516." << endl << endl;
txtOut << "run_cmd - this argument is used by the host itself, along side the internal module arguments below to run" << endl;
txtOut << " the internal command names passed by it. this is not ment to be run directly by human input." << endl;
txtOut << " the executable will auto close if it fails to connect to the pipe and/or shared memory segments" << endl << endl;
txtOut << "" << Qt::endl << APP_NAME << " v" << QCoreApplication::applicationVersion() << Qt::endl << Qt::endl;
txtOut << "Usage: " << APP_TARGET << " <argument>" << Qt::endl << Qt::endl;
txtOut << "<Arguments>" << Qt::endl << Qt::endl;
txtOut << " -help : display usage information about this application." << Qt::endl;
txtOut << " -stop : stop the current host instance if one is currently running." << Qt::endl;
txtOut << " -about : display versioning/warranty information about this application." << Qt::endl;
txtOut << " -addr : set the listening address and port for TCP clients." << Qt::endl;
txtOut << " -status : display status information about the host instance if it is currently running." << Qt::endl;
txtOut << " -reset_root : reset the root account password to the default password." << Qt::endl;
txtOut << " -host : start a new host instance. (this blocks)" << Qt::endl;
txtOut << " -host_trig : start a new host instance. (this does not block)" << Qt::endl;
txtOut << " -default_pw : show the default password." << Qt::endl;
txtOut << " -public_cmds : run the internal module to list it's public commands. for internal use only." << Qt::endl;
txtOut << " -exempt_cmds : run the internal module to list it's rank exempt commands. for internal use only." << Qt::endl;
txtOut << " -user_cmds : run the internal module to list it's user commands. for internal use only." << Qt::endl;
txtOut << " -run_cmd : run an internal module command. for internal use only." << Qt::endl;
txtOut << " -load_ssl : re-load the host SSL certificate without stopping the host instance." << Qt::endl << Qt::endl;
txtOut << "Internal module | -public_cmds, -user_cmds, -exempt_cmds, -run_cmd |:" << Qt::endl << Qt::endl;
txtOut << " -pipe : the named pipe used to establish a data connection with the session." << Qt::endl;
txtOut << " -mem_ses : the shared memory key for the session." << Qt::endl;
txtOut << " -mem_host : the shared memory key for the host main process." << Qt::endl << Qt::endl;
txtOut << "Details:" << Qt::endl << Qt::endl;
txtOut << "addr - this argument takes a {ip_address:port} string. it will return an error if not formatted correctly" << Qt::endl;
txtOut << " examples: 10.102.9.2:35516 or 0.0.0.0:35516." << Qt::endl << Qt::endl;
txtOut << "run_cmd - this argument is used by the host itself, along side the internal module arguments below to run" << Qt::endl;
txtOut << " the internal command names passed by it. this is not ment to be run directly by human input." << Qt::endl;
txtOut << " the executable will auto close if it fails to connect to the pipe and/or shared memory segments" << Qt::endl << Qt::endl;
}
void soeDueToDbErr(int *retCode, const QString *errMsg)
{
*retCode = 1;
QTextStream(stderr) << "" << endl << "err: Stop error." << endl;
QTextStream(stderr) << " what happened: " << endl << *errMsg << endl << endl;
QTextStream(stderr) << "" << Qt::endl << "err: Stop error." << Qt::endl;
QTextStream(stderr) << " what happened: " << Qt::endl << *errMsg << Qt::endl << Qt::endl;
}
int shellToHost(const QStringList &args, QCoreApplication &app)
@ -129,10 +143,10 @@ int main(int argc, char *argv[])
}
else if (args.contains("-about", Qt::CaseInsensitive))
{
QTextStream(stdout) << "" << endl << APP_NAME << " v" << QCoreApplication::applicationVersion() << endl << endl;
QTextStream(stdout) << "Based on QT " << QT_VERSION_STR << " " << 8 * QT_POINTER_SIZE << "bit" << endl << endl;
QTextStream(stdout) << "The program is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE" << endl;
QTextStream(stdout) << "WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE." << endl << endl;
QTextStream(stdout) << "" << Qt::endl << APP_NAME << " v" << QCoreApplication::applicationVersion() << Qt::endl << Qt::endl;
QTextStream(stdout) << "Based on QT " << QT_VERSION_STR << " " << 8 * QT_POINTER_SIZE << "bit" << Qt::endl << Qt::endl;
QTextStream(stdout) << "The program is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE" << Qt::endl;
QTextStream(stdout) << "WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE." << Qt::endl << Qt::endl;
}
else if (args.contains("-stop", Qt::CaseInsensitive) ||
args.contains("-status", Qt::CaseInsensitive) ||
@ -151,7 +165,7 @@ int main(int argc, char *argv[])
if (addr.size() != 2)
{
QTextStream(stderr) << "" << endl << "err: Address string parsing error, number of params found: " << addr.size() << endl;
QTextStream(stderr) << "" << Qt::endl << "err: Address string parsing error, number of params found: " << addr.size() << Qt::endl;
}
else
{
@ -160,15 +174,15 @@ int main(int argc, char *argv[])
if (!pOk)
{
QTextStream(stderr) << "" << endl << "err: Invalid port." << endl;
QTextStream(stderr) << "" << Qt::endl << "err: Invalid port." << Qt::endl;
}
else if (port == 0)
{
QTextStream(stderr) << "" << endl << "err: The port cannot be 0." << endl;
QTextStream(stderr) << "" << Qt::endl << "err: The port cannot be 0." << Qt::endl;
}
else if (QHostAddress(addr[0]).isNull())
{
QTextStream(stderr) << "" << endl << "err: Invalid ip address." << endl;
QTextStream(stderr) << "" << Qt::endl << "err: Invalid ip address." << Qt::endl;
}
else
{
@ -204,6 +218,10 @@ int main(int argc, char *argv[])
ret = QCoreApplication::exec();
}
}
else if (args.contains("-host_trig"))
{
QProcess::startDetached(QCoreApplication::applicationFilePath(), QStringList() << "-host");
}
else if (args.contains("-reset_root", Qt::CaseInsensitive))
{
auto uId = rootUserId();
@ -219,8 +237,8 @@ int main(int argc, char *argv[])
}
else if (args.contains("-default_pw", Qt::CaseInsensitive))
{
QTextStream(stdout) << "" << endl << " Root User : " << getUserName(rootUserId()) << endl;
QTextStream(stdout) << " Default Password: " << defaultPw() << endl << endl;
QTextStream(stdout) << "" << Qt::endl << " Root User : " << getUserName(rootUserId()) << Qt::endl;
QTextStream(stdout) << " Default Password: " << defaultPw() << Qt::endl << Qt::endl;
}
}
else

View File

@ -47,22 +47,22 @@ bool genRSAKey(Cert *cert, QTextStream &msg)
}
else
{
msg << "Failed to assign the generated RSA key to a PKEY object." << endl;
msg << "Failed to assign the generated RSA key to a PKEY object." << Qt::endl;
}
}
else
{
msg << "Failed to generate the RSA private key." << endl;
msg << "Failed to generate the RSA private key." << Qt::endl;
}
}
else
{
msg << "Failed to initialize a BIGNUM object needed to generate the RSA key." << endl;
msg << "Failed to initialize a BIGNUM object needed to generate the RSA key." << Qt::endl;
}
}
else
{
msg << "The x509 object did not initialize correctly." << endl;
msg << "The x509 object did not initialize correctly." << Qt::endl;
}
return ret;
@ -77,7 +77,7 @@ bool genX509(Cert *cert, const QString &outsideAddr, QTextStream &msg)
if (!outsideAddr.isEmpty())
{
msg << "x509 gen_wan_ip: " << outsideAddr << endl;
msg << "x509 gen_wan_ip: " << outsideAddr << Qt::endl;
cnNames.append(outsideAddr.toUtf8());
}
@ -86,7 +86,7 @@ bool genX509(Cert *cert, const QString &outsideAddr, QTextStream &msg)
{
if (addr.isGlobal())
{
msg << "x509 gen_lan_ip: " << addr.toString() << endl;
msg << "x509 gen_lan_ip: " << addr.toString() << Qt::endl;
cnNames.append(addr.toString().toUtf8());
}
@ -133,12 +133,12 @@ bool genX509(Cert *cert, const QString &outsideAddr, QTextStream &msg)
}
else
{
msg << "Failed to self-sign the generated x509 cert." << endl;
msg << "Failed to self-sign the generated x509 cert." << Qt::endl;
}
}
else
{
msg << "No usable IP addresses could be found to be used as common names in the self-signed cert." << endl;
msg << "No usable IP addresses could be found to be used as common names in the self-signed cert." << Qt::endl;
}
return ret;
@ -169,7 +169,7 @@ FILE *openFileForWrite(const char *path, QTextStream &msg)
void encodeErr(const char *path, QTextStream &msg)
{
msg << "Failed to encode file '" << path << "' to PEM format." << endl;
msg << "Failed to encode file '" << path << "' to PEM format." << Qt::endl;
}
bool writePrivateKey(const char *path, Cert* cert, QTextStream &msg)

View File

@ -111,18 +111,18 @@ bool TCPServer::start()
if (!createPipe())
{
QTextStream(stderr) << "" << endl << "err: Unable to open a control pipe." << endl;
QTextStream(stderr) << "err: Reason - " << controlPipe->errorString() << endl;
QTextStream(stderr) << "" << Qt::endl << "err: Unable to open a control pipe." << Qt::endl;
QTextStream(stderr) << "err: Reason - " << controlPipe->errorString() << Qt::endl;
}
else if (!listen(QHostAddress(addr), port))
{
QTextStream(stderr) << "" << endl << "err: TCP listen failure on address: " << addr << " port: " << port << endl;
QTextStream(stderr) << "err: Reason - " << errorString() << endl;
QTextStream(stderr) << "" << Qt::endl << "err: TCP listen failure on address: " << addr << " port: " << port << Qt::endl;
QTextStream(stderr) << "err: Reason - " << errorString() << Qt::endl;
}
else if (hostKey.isEmpty())
{
QTextStream(stderr) << "" << endl << "err: Failed to create the host shared memory block." << endl;
QTextStream(stderr) << "err: Reason - " << hostSharedMem->errorString() << endl;
QTextStream(stderr) << "" << Qt::endl << "err: Failed to create the host shared memory block." << Qt::endl;
QTextStream(stderr) << "err: Reason - " << hostSharedMem->errorString() << Qt::endl;
}
else
{
@ -237,16 +237,16 @@ void TCPServer::procPipeIn()
hostSharedMem->lock();
txtOut << "" << endl;
txtOut << "Host Load: " << rd32BitFromBlock(hostLoad) << "/" << maxSessions << endl;
txtOut << "Active Address: " << serverAddress().toString() << endl;
txtOut << "Active Port: " << serverPort() << endl;
txtOut << "Set Address: " << db.getData(COLUMN_IPADDR).toString() << endl;
txtOut << "Set Port: " << db.getData(COLUMN_PORT).toUInt() << endl;
txtOut << "Working Path: " << QDir::currentPath() << endl;
txtOut << "Database: " << sqlDataPath() << endl;
txtOut << "SSL Chain: " << sslCertChain() << endl;
txtOut << "SSL Private: " << sslPrivKey() << endl << endl;
txtOut << "" << Qt::endl;
txtOut << "Host Load: " << rd32BitFromBlock(hostLoad) << "/" << maxSessions << Qt::endl;
txtOut << "Active Address: " << serverAddress().toString() << Qt::endl;
txtOut << "Active Port: " << serverPort() << Qt::endl;
txtOut << "Set Address: " << db.getData(COLUMN_IPADDR).toString() << Qt::endl;
txtOut << "Set Port: " << db.getData(COLUMN_PORT).toUInt() << Qt::endl;
txtOut << "Working Path: " << QDir::currentPath() << Qt::endl;
txtOut << "Database: " << sqlDataPath() << Qt::endl;
txtOut << "SSL Chain: " << sslCertChain() << Qt::endl;
txtOut << "SSL Private: " << sslPrivKey() << Qt::endl << Qt::endl;
hostSharedMem->unlock();
controlSocket->write(toTEXT(text));
@ -330,7 +330,7 @@ void TCPServer::applyPrivKey(const QString &path, QTextStream &msg)
if (key.isNull())
{
msg << "[fail]" << endl;
msg << "[fail]" << Qt::endl;
msg << "Attempting to load the private key with DSA. ";
key = QSslKey(bytes, QSsl::Dsa);
@ -338,7 +338,7 @@ void TCPServer::applyPrivKey(const QString &path, QTextStream &msg)
if (key.isNull())
{
msg << "[fail]" << endl;
msg << "[fail]" << Qt::endl;
msg << "Attempting to load the private key with Elliptic Curve. ";
key = QSslKey(bytes, QSsl::Ec);
@ -346,7 +346,7 @@ void TCPServer::applyPrivKey(const QString &path, QTextStream &msg)
if (key.isNull())
{
msg << "[fail]" << endl;
msg << "[fail]" << Qt::endl;
msg << "Attempting to load the private key with Diffie-Hellman. ";
key = QSslKey(bytes, QSsl::Dh);
@ -354,7 +354,7 @@ void TCPServer::applyPrivKey(const QString &path, QTextStream &msg)
if (key.isNull())
{
msg << "[fail]" << endl;
msg << "[fail]" << Qt::endl;
msg << "Attempting to load the private key as a black box. ";
key = QSslKey(bytes, QSsl::Opaque);
@ -362,11 +362,11 @@ void TCPServer::applyPrivKey(const QString &path, QTextStream &msg)
if (key.isNull())
{
msg << "[fail]" << endl << endl;
msg << "[fail]" << Qt::endl << Qt::endl;
}
else
{
msg << "[pass]" << endl << endl;
msg << "[pass]" << Qt::endl << Qt::endl;
sslKey = key;
}
@ -393,20 +393,20 @@ QString TCPServer::loadSSLData(bool onReload)
auto allCertsExists = true;
auto privKeyExists = QFile::exists(priv);
stream << "Private key: " << priv << endl;
stream << "Private key: " << priv << Qt::endl;
if (!privKeyExists)
{
stream << " ^(the private key does not exists)" << endl;
stream << " ^(the private key does not exists)" << Qt::endl;
}
for (auto cert : chain)
{
stream << "Cert: " << cert << endl;
stream << "Cert: " << cert << Qt::endl;
if (!QFile::exists(cert))
{
stream << " ^(this cert does not exists)" << endl;
stream << " ^(this cert does not exists)" << Qt::endl;
allCertsExists = false;
}
@ -414,22 +414,22 @@ QString TCPServer::loadSSLData(bool onReload)
if (chain.isEmpty())
{
stream << "No cert files are defined in the env." << endl;
stream << "No cert files are defined in the env." << Qt::endl;
allCertsExists = false;
}
stream << endl;
stream << Qt::endl;
if (allCertsExists && privKeyExists)
{
if (onReload && (priv == DEFAULT_PRIV_KEY_NAME) && (sslCertChain() == DEFAULT_PUB_KEY_NAME))
{
stream << "Re-generating self-signed cert." << endl;
stream << "Re-generating self-signed cert." << Qt::endl;
if (genDefaultSSLFiles(wanIP, stream))
{
stream << endl << "complete." << endl << endl;
stream << Qt::endl << "complete." << Qt::endl << Qt::endl;
}
}
@ -438,11 +438,11 @@ QString TCPServer::loadSSLData(bool onReload)
}
else if ((priv == DEFAULT_PRIV_KEY_NAME) && (sslCertChain() == DEFAULT_PUB_KEY_NAME))
{
stream << "Generating self-signed cert." << endl;
stream << "Generating self-signed cert." << Qt::endl;
if (genDefaultSSLFiles(wanIP, stream))
{
stream << endl << "The default self-signed cert files are generated successfully." << endl << endl;
stream << Qt::endl << "The default self-signed cert files are generated successfully." << Qt::endl << Qt::endl;
applyPrivKey(priv, stream);
applyCerts(chain, stream);

View File

@ -16,6 +16,8 @@
// along with MRCI under the LICENSE.md file. If not, see
// <http://www.gnu.org/licenses/>.
#ifdef Q_OS_LINUX
void setupUnixSignalHandlers()
{
struct sigaction hup;
@ -89,3 +91,5 @@ void UnixSignalHandler::handleSigHup()
snHup->setEnabled(true);
}
#endif // Q_OS_LINUX

View File

@ -0,0 +1,5 @@
#!/bin/sh
export QTDIR=$install_dir
export QT_PLUGIN_PATH=$install_dir
export LD_LIBRARY_PATH="$install_dir/lib:\$LD_LIBRARY_PATH"
$install_dir/$app_target $1 $2 $3

View File

@ -0,0 +1,15 @@
[Unit]
Description=$app_name Host Daemon
After=network.target
[Service]
Type=simple
User=$app_target
Restart=on-failure
RestartSec=5
TimeoutStopSec=infinity
ExecStart=/usr/bin/env $app_target -host
ExecStop=/usr/bin/env $app_target -stop
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,8 @@
#!/bin/sh
systemctl -q stop $app_target
systemctl -q disable $app_target
rm -v /etc/systemd/system/$app_target.service
rm -v /usr/bin/$app_target
rm -rv $install_dir
deluser $app_target
echo "Uninstallation Complete"

View File

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
<RegistrationInfo>
<Date>2020-07-03T11:47:38.6011458</Date>
<Author>Zii-Projects</Author>
<URI>\$app_name</URI>
</RegistrationInfo>
<Triggers>
<BootTrigger>
<Enabled>true</Enabled>
</BootTrigger>
</Triggers>
<Principals>
<Principal id="Author">
<UserId>SYSTEM</UserId>
<RunLevel>HighestAvailable</RunLevel>
</Principal>
</Principals>
<Settings>
<MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
<StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
<AllowHardTerminate>true</AllowHardTerminate>
<StartWhenAvailable>true</StartWhenAvailable>
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
<IdleSettings>
<StopOnIdleEnd>true</StopOnIdleEnd>
<RestartOnIdle>false</RestartOnIdle>
</IdleSettings>
<AllowStartOnDemand>true</AllowStartOnDemand>
<Enabled>true</Enabled>
<Hidden>true</Hidden>
<RunOnlyIfIdle>false</RunOnlyIfIdle>
<DisallowStartOnRemoteAppSession>false</DisallowStartOnRemoteAppSession>
<UseUnifiedSchedulingEngine>true</UseUnifiedSchedulingEngine>
<WakeToRun>false</WakeToRun>
<ExecutionTimeLimit>PT0S</ExecutionTimeLimit>
<Priority>7</Priority>
<RestartOnFailure>
<Interval>PT5M</Interval>
<Count>3</Count>
</RestartOnFailure>
</Settings>
<Actions Context="Author">
<Exec>
<Command>"$install_dir\$app_target.exe"</Command>
<Arguments>-host</Arguments>
</Exec>
</Actions>
</Task>

View File

@ -0,0 +1,5 @@
$app_target -stop
schtasks /delete /f /tn $app_name
del /f "%windir%\$app_target.exe"
rd /q /s "$install_dir"
echo "Uninstallation Complete"