diff --git a/build.py b/build.py index 9161f38..93aa67d 100644 --- a/build.py +++ b/build.py @@ -125,6 +125,8 @@ 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(qt_bin + "/../plugins/sqldrivers/libqsqlodbc.so", "app_dir/linux/sqldrivers/libqsqlodbc.so") + verbose_copy(qt_bin + "/../plugins/sqldrivers/libqsqlpsql.so", "app_dir/linux/sqldrivers/libqsqlpsql.so") verbose_copy("build/linux/" + app_target, "app_dir/linux/" + app_target) shutil.copyfile("build/linux/" + app_target, "/tmp/" + app_target) diff --git a/docs/protocol.md b/docs/protocol.md index f20853e..53f8a34 100644 --- a/docs/protocol.md +++ b/docs/protocol.md @@ -58,18 +58,21 @@ Any increments to the Major resets the Minor to 0. Any 3rd party client applicat ### 1.4 Client Header ### ``` -[tag][appName][padding] +[tag][appName][mod_instructions][padding] tag - 4bytes - 0x4D, 0x52, 0x43, 0x49 (MRCI) -appName - 134bytes - UTF16LE string (padded with 0x00) -padding - 272bytes - padding of 0x00 bytes reserved for future expansion +appName - 32bytes - UTF8 string (padded with 0x00) +modInst - 128bytes - UTF8 string (padded with 0x00) +padding - 128bytes - string of (0x00) ``` notes: -* The **tag** is just a fixed ascii string "MRCI" that indicates to the host that the client is indeed attempting to use the MRCI protocol. +* **tag** is just a fixed ascii string "MRCI" that indicates to the host that the client is indeed attempting to use the MRCI protocol. -* 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. This string is accessable to all modules so the commands themselves can be made aware of what app the user is currently using. +* **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. This string is accessable to all modules so the commands themselves can be made aware of what app the user is currently using. + +* **modInst** is an additional set of command lines that can be passed onto to all module processes when they are intialized. This can be used by certain clients that want to intruct certain modules that might be installed in the host to do certain actions during intialization. This remains constant for as long as the session is active and cannot be changed at any point. ### 1.5 Host Header ### diff --git a/docs/type_ids.md b/docs/type_ids.md index cee2ed3..7e81a4a 100644 --- a/docs/type_ids.md +++ b/docs/type_ids.md @@ -42,7 +42,7 @@ enum TypeID : quint8 ```TEXT``` This is text that can be displayed directly to the user, passed as command line arguments to be processed or used to carry text data within other data types. -format: ```[UTF-16LE_string] (no BOM)``` +format: ```[UTF-8_string] (no BOM)``` ```GEN_FILE``` This is a file transfer type id that can be used to transfer any file type (music, photos, documents, etc...). It operates in its own protocol of sorts. The 1st GEN_FILE frame received by the host or client is TEXT parameters similar to what you see in terminal command lines with at least one of the arguments listed below. The next set of GEN_FILE frames received by the host or client is then the binary data that needs to be written to an open file or streamed until the limit defined in -len is meet. @@ -77,7 +77,7 @@ This id can be treated exactly like TEXT except this tells the client that the c 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. +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 recommended to honor those line breaks. ```IDLE``` 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. @@ -97,13 +97,13 @@ enum RetCode : quint16 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. + be any format that the module itself decides it to 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. +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 will only tell it to stop what it is currently doing. This will also terminate any commands in a prompt state. ```KILL_CMD``` 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. @@ -143,12 +143,12 @@ This is a data structure that carries information about a file system object (fi 2. bytes[1-8] - creation time in msec since Epoch UTC (64bit little endian uint) 3. bytes[9-16] - modification time in msec since Epoch UTC (64bit little endian uint) 4. bytes[17-24] - file size (64bit little endian uint) - 5. bytes[25-n] - file name (UTF16-LE string, 16bit terminated) - 6. bytes[n-n] - symmlink target if it is a symmlink (UTF16-LE string, 16bit terminated) + 5. bytes[25-n] - file name (UTF8 string, NULL terminated) + 6. bytes[n-n] - symmlink target if it is a symmlink (UTF8 string, NULL terminated) notes: - 1. 16bit terminated UTF-16LE strings are basically - terminated by 2 bytes of 0x00. + 1. NULL terminated UTF-8 strings are basically tailed + by a single 0x00 byte to indicate the end-of-string. 2. the symmlink target is empty if not a symmlink but the terminator should still be present. @@ -169,11 +169,11 @@ This carry some user account and session information about a peer client connect ``` format: - 1. bytes[0-27] 28bytes - session id (224bit hash) - 2. bytes[28-59] 32bytes - user id (256bit hash) - 3. bytes[60-107] 48bytes - user name (TEXT - padded with 0x00) - 4. bytes[108-241] 134bytes - app name (TEXT - padded with 0x00) - 5. bytes[242-305] 64bytes - disp name (TEXT - padded with 0x00) + 1. bytes[0-27] 28bytes - session id (224bit hash) + 2. bytes[28-59] 32bytes - user id (256bit hash) + 3. bytes[60-83] 24bytes - user name (TEXT - padded with 0x00) + 4. bytes[84-115] 32bytes - app name (TEXT - padded with 0x00) + 5. bytes[116-139] 24bytes - disp name (TEXT - padded with 0x00) notes: 1. the session id is unique to the peer's session connection only. it @@ -183,23 +183,23 @@ This carry some user account and session information about a peer client connect even when the user name changes and across all clients logged into the same account. - 3. the display name is the preffered display name of the peer. clients + 3. the display name is the preferred display name of the peer. clients are encouraged to use this rather than the user name when displaying - peer info to the user. if empty, it's ok to just fall back to the user - name. + peer info to the end user. if empty, then it is ok to fall back to + displaying the user name. ``` ```PING_PEERS``` -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. +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 forward the same frame to their own clients and return PEER_INFO frames about themselves to the session that sent the PING_PEERS. ```MY_INFO``` This contains all of the information found in ```PEER_INFO``` for the local session but also includes the following: ``` format: - 1. bytes[306-433] 128bytes - email (TEXT - padded with 0x00) - 2. bytes[434-437] 4bytes - host rank (32bit unsigned int) - 3. bytes[438] 1byte - is email confirmed? (0x00 false, 0x01 true) + 1. bytes[140-203] 64bytes - email (TEXT - padded with 0x00) + 2. bytes[204-207] 4bytes - host rank (32bit unsigned int) + 3. bytes[208] 1byte - is email confirmed? (0x00 false, 0x01 true) ``` ```NEW_CMD``` @@ -207,13 +207,13 @@ This contains information about a new command that was added to the current sess ``` format: - 1. bytes[0-1] 2bytes - 16bit LE unsigned int (command id) - 2. bytes[2] 1byte - 8bit LE unsigned int (genfile type) - 3. bytes[3-130] 128bytes - command name (TEXT - padded with 0x00) - 4. bytes[131-258] 128bytes - library name (TEXT - padded with 0x00) - 5. bytes[259-n] variable - short text (16bit null terminated) - 6. bytes[n-n] variable - io text (16bit null terminated) - 7. bytes[n-n] variable - long text (16bit null terminated) + 1. bytes[0-1] 2bytes - 16bit LE unsigned int (command id) + 2. bytes[2] 1byte - 8bit LE unsigned int (genfile type) + 3. bytes[3-66] 64bytes - command name (TEXT - padded with 0x00) + 4. bytes[67-130] 64bytes - library name (TEXT - padded with 0x00) + 5. bytes[131-n] variable - short text (null terminated) + 6. bytes[n-n] variable - io text (null terminated) + 7. bytes[n-n] variable - long text (null terminated) notes: 1. the genfile type is numerical value of 2, 3 or 0. a value of 2 @@ -288,13 +288,13 @@ This contains public information about a channel member. 2. bytes[8-39] 32bytes - user id (256bit hash) 3. bytes[40] 1byte - is invite? (0x00=false, 0x01=true) 4. bytes[41] 1byte - member's channel privilege level (8bit unsigned int) - 5. bytes[42-n] variable - user name (TEXT - 16bit null terminated) - 6. bytes[n-n] variable - display name (TEXT - 16bit null terminated) - 7. bytes[n-n] variable - channel name (TEXT - 16bit null terminated) + 5. bytes[42-n] variable - user name (TEXT - null terminated) + 6. bytes[n-n] variable - display name (TEXT - null terminated) + 7. bytes[n-n] variable - channel name (TEXT - null terminated) notes: - 1. a 16bit null terminated TEXT formatted string ended with 2 bytes of - (0x00) to indicate the end of the string data. + 1. a null terminated TEXT formatted string ends with a 0x00 to + indicate the end of the string. 2. the member's privilege level can be any of the values discribed in section [4.3](host_features.md). diff --git a/src/applink.c b/src/applink.c index a44add2..e2b4f9a 100644 --- a/src/applink.c +++ b/src/applink.c @@ -7,6 +7,10 @@ * https://www.openssl.org/source/license.html */ +#include + +#ifdef Q_OS_WINDOWS + #define APPLINK_STDIN 1 #define APPLINK_STDOUT 2 #define APPLINK_STDERR 3 @@ -136,3 +140,4 @@ OPENSSL_Applink(void) } #endif #endif +#endif diff --git a/src/async_funcs.cpp b/src/async_funcs.cpp index 3582f57..25ffa2a 100644 --- a/src/async_funcs.cpp +++ b/src/async_funcs.cpp @@ -25,8 +25,8 @@ void Session::acctDeleted(const QByteArray &data) if (memcmp(userId, data.data(), BLKSIZE_USER_ID) == 0) { logout("", true); - asyncToClient(ASYNC_SYS_MSG, toTEXT("\nsystem: your session was forced to logout because your account was deleted.\n"), TEXT); - asyncToClient(ASYNC_USER_DELETED, data, TEXT); + asyncToClient(ASYNC_SYS_MSG, "\nsystem: your session was forced to logout because your account was deleted.\n", TEXT); + asyncToClient(ASYNC_USER_DELETED, data, BYTES); } } } @@ -48,7 +48,7 @@ void Session::acctRenamed(const QByteArray &data) { if (flags & LOGGED_IN) { - // format: [32bytes(user_id)][48bytes(new_user_name)] + // format: [32bytes(user_id)][24bytes(new_user_name)] if (memcmp(userId, data.data(), BLKSIZE_USER_ID) == 0) { @@ -63,7 +63,7 @@ void Session::acctDispChanged(const QByteArray &data) { if (flags & LOGGED_IN) { - // format: [32bytes(user_id)][64bytes(new_disp_name)] + // format: [32bytes(user_id)][24bytes(new_disp_name)] if (memcmp(userId, data.data(), BLKSIZE_USER_ID) == 0) { @@ -325,7 +325,7 @@ void Session::subChannelUpdated(quint16 cmdId, const QByteArray &data) void Session::addModule(const QByteArray &data) { - auto modApp = fromTEXT(data); + auto modApp = QString::fromUtf8(data); if (!modCmdNames.contains(modApp)) { @@ -335,7 +335,7 @@ void Session::addModule(const QByteArray &data) void Session::rmModule(const QByteArray &data) { - auto modApp = fromTEXT(data); + auto modApp = QString::fromUtf8(data); if (modCmdNames.contains(modApp) && (modApp != QCoreApplication::applicationFilePath())) { diff --git a/src/cmd_object.cpp b/src/cmd_object.cpp index 9b2e42a..e5f9aa3 100644 --- a/src/cmd_object.cpp +++ b/src/cmd_object.cpp @@ -197,27 +197,27 @@ void CmdObject::postProc() void CmdObject::mainTxt(const QString &txt) { - emit procOut(toTEXT(txt), TEXT); + emit procOut(txt.toUtf8(), TEXT); } void CmdObject::errTxt(const QString &txt) { - emit procOut(toTEXT(txt), ERR); + emit procOut(txt.toUtf8(), ERR); } void CmdObject::privTxt(const QString &txt) { - emit procOut(toTEXT(txt), PRIV_TEXT); + emit procOut(txt.toUtf8(), PRIV_TEXT); } void CmdObject::bigTxt(const QString &txt) { - emit procOut(toTEXT(txt), BIG_TEXT); + emit procOut(txt.toUtf8(), BIG_TEXT); } void CmdObject::promptTxt(const QString &txt) { - emit procOut(toTEXT(txt), PROMPT_TEXT); + emit procOut(txt.toUtf8(), PROMPT_TEXT); } void CmdObject::async(quint16 asyncId, const QByteArray &data) diff --git a/src/cmd_proc.cpp b/src/cmd_proc.cpp index 0fcd5db..fa582bb 100644 --- a/src/cmd_proc.cpp +++ b/src/cmd_proc.cpp @@ -49,12 +49,12 @@ ModProcess::ModProcess(const QString &app, const QString &memSes, const QString void ModProcess::rdFromStdErr() { - emit dataToClient(toCmdId32(ASYNC_SYS_MSG, 0), toTEXT(readAllStandardError()), ERR); + emit dataToClient(toCmdId32(ASYNC_SYS_MSG, 0), readAllStandardError(), ERR); } void ModProcess::rdFromStdOut() { - emit dataToClient(toCmdId32(ASYNC_SYS_MSG, 0), toTEXT(readAllStandardOutput()), TEXT); + emit dataToClient(toCmdId32(ASYNC_SYS_MSG, 0), readAllStandardOutput(), TEXT); } quint16 ModProcess::genCmdId() @@ -124,11 +124,11 @@ void ModProcess::onDataFromProc(quint8 typeId, const QByteArray &data) { if ((typeId == NEW_CMD) && (flags & SESSION_PARAMS_SET)) { - if (data.size() >= 259) + if (data.size() >= 131) { - // a valid NEW_CMD must have a minimum of 259 bytes. + // a valid NEW_CMD must have a minimum of 131 bytes. - auto cmdName = fromTEXT(data.mid(3, 128)).trimmed().toLower(); + auto cmdName = QString::fromUtf8(data.mid(3, 64)).trimmed().toLower(); if (isCmdLoaded(cmdName)) { @@ -172,7 +172,7 @@ void ModProcess::onDataFromProc(quint8 typeId, const QByteArray &data) modCmdNames->insert(program(), list); } - auto frame = cmdIdBa + data.mid(2, 1) + fixedToTEXT(unique, 128) + data.mid(131); + auto frame = cmdIdBa + data.mid(2, 1) + toFixedTEXT(unique, 64) + data.mid(67); emit dataToClient(toCmdId32(ASYNC_ADD_CMD, 0), frame, NEW_CMD); } @@ -180,7 +180,7 @@ void ModProcess::onDataFromProc(quint8 typeId, const QByteArray &data) } else if (typeId == ERR) { - qDebug() << fromTEXT(data); + qDebug() << QString::fromUtf8(data); } } @@ -267,7 +267,7 @@ void ModProcess::setSessionParams(QHash *uniqueNames, void ModProcess::onFailToStart() { - emit dataToClient(toCmdId32(ASYNC_SYS_MSG, 0), toTEXT("\nerr: A module failed to start so some commands may not have loaded. detailed error information was logged for admin review.\n"), ERR); + emit dataToClient(toCmdId32(ASYNC_SYS_MSG, 0), "\nerr: A module failed to start so some commands may not have loaded. detailed error information was logged for admin review.\n", ERR); emit modProcFinished(); deleteLater(); @@ -307,7 +307,7 @@ bool ModProcess::startProc(const QStringList &args) { fullPipe = ipcServ->fullServerName(); - setArguments(QStringList() << "-pipe_name" << fullPipe << "-mem_ses" << sesMemKey << "-mem_host" << hostMemKey << args); + setArguments(QStringList() << "-pipe_name" << fullPipe << "-mem_ses" << sesMemKey << "-mem_host" << hostMemKey << args << additionalArgs); start(); } else @@ -320,6 +320,11 @@ bool ModProcess::startProc(const QStringList &args) return ret; } +void ModProcess::addArgs(const QString &cmdLine) +{ + additionalArgs = parseArgs(cmdLine.toUtf8(), -1); +} + bool ModProcess::loadPublicCmds() { flags |= LOADING_PUB_CMDS; @@ -434,7 +439,7 @@ void CmdProcess::onReady() void CmdProcess::onFailToStart() { - emit dataToClient(cmdId, toTEXT("err: The command failed to start. error details were logged for admin review.\n"), ERR); + emit dataToClient(cmdId, "err: The command failed to start. error details were logged for admin review.\n", ERR); emit dataToClient(cmdId, wrInt(FAILED_TO_START, 16), IDLE); emit cmdProcFinished(cmdId); @@ -448,7 +453,7 @@ void CmdProcess::onFinished(int exitCode, QProcess::ExitStatus exitStatus) if (!cmdIdle) { - emit dataToClient(cmdId, toTEXT("err: The command has stopped unexpectedly or it has failed to send an IDLE frame before exiting.\n"), ERR); + emit dataToClient(cmdId, "err: The command has stopped unexpectedly or it has failed to send an IDLE frame before exiting.\n", ERR); emit dataToClient(cmdId, wrInt(CRASH, 16), IDLE); } @@ -460,12 +465,12 @@ void CmdProcess::onFinished(int exitCode, QProcess::ExitStatus exitStatus) void CmdProcess::rdFromStdErr() { - emit dataToClient(cmdId, toTEXT(readAllStandardError()), ERR); + emit dataToClient(cmdId, readAllStandardError(), ERR); } void CmdProcess::rdFromStdOut() { - emit dataToClient(cmdId, toTEXT(readAllStandardOutput()), TEXT); + emit dataToClient(cmdId, readAllStandardOutput(), TEXT); } void CmdProcess::dataFromSession(quint32 id, const QByteArray &data, quint8 dType) diff --git a/src/cmd_proc.h b/src/cmd_proc.h index c74bc7b..8b4d2a7 100644 --- a/src/cmd_proc.h +++ b/src/cmd_proc.h @@ -46,6 +46,7 @@ protected: quint32 ipcDataSize; quint32 hostRank; quint32 flags; + QStringList additionalArgs; IdleTimer *idleTimer; QLocalServer *ipcServ; QLocalSocket *ipcSocket; @@ -75,6 +76,7 @@ public: explicit ModProcess(const QString &app, const QString &memSes, const QString &memHos, const QString &pipe, QObject *parent = nullptr); + void addArgs(const QString &cmdLine); void setSessionParams(QHash *uniqueNames, QHash *realNames, QHash *appById, diff --git a/src/commands/acct_recovery.cpp b/src/commands/acct_recovery.cpp index eecb9d6..1908333 100644 --- a/src/commands/acct_recovery.cpp +++ b/src/commands/acct_recovery.cpp @@ -115,7 +115,7 @@ void RecoverAcct::procIn(const QByteArray &binIn, quint8 dType) { if ((flags & MORE_INPUT) && (dType == TEXT)) { - auto pw = fromTEXT(binIn); + auto pw = QString::fromUtf8(binIn); if (inputOk) { @@ -265,9 +265,14 @@ void ResetPwRequest::procIn(const QByteArray &binIn, uchar dType) cmdLine.replace(SUBJECT_SUB, "'" + escapeChars(subject, '\\', '\'') + "'"); cmdLine.replace(MSG_SUB, "'" + escapeChars(body, '\\', '\'') + "'"); - QProcess::startDetached(expandEnvVariables(app), parseArgs(toTEXT(cmdLine), -1)); - - mainTxt("A temporary password was sent to the email address associated with the account. this password will expire in 1hour.\n"); + if (QProcess::startDetached(expandEnvVariables(app), parseArgs(cmdLine.toUtf8(), -1))) + { + mainTxt("A temporary password was sent to the email address associated with the account. this password will expire in 1hour.\n"); + } + else + { + errTxt("err: The host email system has reported an internal error, try again later.\n"); + } } } } @@ -276,7 +281,7 @@ void VerifyEmail::procIn(const QByteArray &binIn, quint8 dType) { if ((flags & MORE_INPUT) && (dType == TEXT)) { - auto txt = fromTEXT(binIn); + auto txt = QString::fromUtf8(binIn); if (txt.isEmpty()) { @@ -343,9 +348,14 @@ void VerifyEmail::procIn(const QByteArray &binIn, quint8 dType) cmdLine.replace(SUBJECT_SUB, "'" + escapeChars(subject, '\\', '\'') + "'"); cmdLine.replace(MSG_SUB, "'" + escapeChars(body, '\\', '\'') + "'"); - QProcess::startDetached(expandEnvVariables(app), parseArgs(toTEXT(cmdLine), -1)); - - privTxt("A confirmation code was sent to your email address: " + email + "\n\n" + "Please enter that code now or leave blank to cancel: "); + if (QProcess::startDetached(expandEnvVariables(app), parseArgs(cmdLine.toUtf8(), -1))) + { + privTxt("A confirmation code was sent to your email address: " + email + "\n\n" + "Please enter that code now or leave blank to cancel: "); + } + else + { + errTxt("err: The host email system has reported an internal error, try again later.\n"); + } } } } @@ -373,7 +383,7 @@ void SetEmailTemplate::procIn(const QByteArray &binIn, quint8 dType) { if ((flags & MORE_INPUT) && (dType == GEN_FILE)) { - bodyText.append(fromTEXT(binIn)); + bodyText.append(QString::fromUtf8(binIn)); dataSent += binIn.size(); diff --git a/src/commands/admin.cpp b/src/commands/admin.cpp index 46f3609..f12b7b1 100644 --- a/src/commands/admin.cpp +++ b/src/commands/admin.cpp @@ -30,7 +30,7 @@ void CloseHost::procIn(const QByteArray &binIn, quint8 dType) { if (flags & MORE_INPUT) { - auto input = fromTEXT(binIn); + auto input = QString::fromUtf8(binIn); if (input == "CLOSE") { @@ -64,7 +64,7 @@ void RestartHost::procIn(const QByteArray &binIn, quint8 dType) { if (flags & MORE_INPUT) { - auto input = fromTEXT(binIn); + auto input = QString::fromUtf8(binIn); if (input == "RESTART") { @@ -127,10 +127,10 @@ void ServSettings::printSettings() 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; + printDatabaseInfo(txtOut); mainTxt(txt); } @@ -178,7 +178,7 @@ void ServSettings::procIn(const QByteArray &binIn, quint8 dType) auto ok = false; - select = fromTEXT(binIn).toInt(&ok); + select = QString::fromUtf8(binIn).toInt(&ok); if ((select == 1) && ok) { @@ -327,7 +327,7 @@ void ServSettings::procIn(const QByteArray &binIn, quint8 dType) } else if (level == 2) { - auto value = fromTEXT(binIn); + auto value = QString::fromUtf8(binIn); if (value.isEmpty()) { diff --git a/src/commands/auth.cpp b/src/commands/auth.cpp index e821cca..3c96a1e 100644 --- a/src/commands/auth.cpp +++ b/src/commands/auth.cpp @@ -115,7 +115,7 @@ void Auth::procIn(const QByteArray &binIn, quint8 dType) { if (flags & MORE_INPUT) { - QString text = fromTEXT(binIn); + auto text = QString::fromUtf8(binIn); if (loginOk) { @@ -174,7 +174,7 @@ void Auth::procIn(const QByteArray &binIn, quint8 dType) } else if (validEmailAddr(text)) { - errTxt("err: Invaild use rname. it looks like an email address.\n"); + errTxt("err: Invaild user name. it looks like an email address.\n"); promptTxt("Enter a new user name (leave blank to cancel): "); } else if (!validUserName(text)) @@ -202,7 +202,7 @@ void Auth::procIn(const QByteArray &binIn, quint8 dType) db.addCondition(COLUMN_USER_ID, uId); db.exec(); - async(ASYNC_USER_RENAMED, uId + fixedToTEXT(text, BLKSIZE_USER_NAME)); + async(ASYNC_USER_RENAMED, uId + toFixedTEXT(text, BLKSIZE_USER_NAME)); uName = text; newUserName = false; diff --git a/src/commands/cast.cpp b/src/commands/cast.cpp index df04d4e..b22ce0c 100644 --- a/src/commands/cast.cpp +++ b/src/commands/cast.cpp @@ -426,11 +426,11 @@ void ListRDonlyFlags::procIn(const QByteArray &binIn, quint8 dType) if (channelAccessLevel(rdFromBlock(userId, BLKSIZE_USER_ID), chOwnerOverride, chId) > REGULAR) { - TableViewer::procIn(toTEXT("-" + QString(COLUMN_CHANNEL_NAME) + " " + chName + " -" + QString(COLUMN_LOWEST_LEVEL) + " " + QString::number(PUBLIC)), dType); + TableViewer::procIn(QString("-" + QString(COLUMN_CHANNEL_NAME) + " " + chName + " -" + QString(COLUMN_LOWEST_LEVEL) + " " + QString::number(PUBLIC)).toUtf8(), dType); } else { - TableViewer::procIn(toTEXT("-" + QString(COLUMN_CHANNEL_NAME) + " " + chName), dType); + TableViewer::procIn(QString("-" + QString(COLUMN_CHANNEL_NAME) + " " + chName).toUtf8(), dType); } } } diff --git a/src/commands/channels.cpp b/src/commands/channels.cpp index 1a1dc90..6c666a8 100644 --- a/src/commands/channels.cpp +++ b/src/commands/channels.cpp @@ -123,7 +123,7 @@ void ListChannels::procIn(const QByteArray &binIn, quint8 dType) } else { - TableViewer::procIn(toTEXT("-" + QString(COLUMN_USERNAME) + " " + rdStringFromBlock(userName, BLKSIZE_USER_NAME)), dType); + TableViewer::procIn(QString("-" + QString(COLUMN_USERNAME) + " " + rdStringFromBlock(userName, BLKSIZE_USER_NAME)).toUtf8(), dType); } } @@ -156,11 +156,11 @@ void ListSubCh::procIn(const QByteArray &binIn, quint8 dType) if (channelAccessLevel(rdFromBlock(userId, BLKSIZE_USER_ID), chOwnerOverride, chId) > REGULAR) { - TableViewer::procIn(toTEXT("-" + QString(COLUMN_CHANNEL_NAME) + " " + chName + " -" + QString(COLUMN_LOWEST_LEVEL) + " " + QString::number(PUBLIC)), dType); + TableViewer::procIn(QString("-" + QString(COLUMN_CHANNEL_NAME) + " " + chName + " -" + QString(COLUMN_LOWEST_LEVEL) + " " + QString::number(PUBLIC)).toUtf8(), dType); } else { - TableViewer::procIn(toTEXT("-" + QString(COLUMN_CHANNEL_NAME) + " " + chName), dType); + TableViewer::procIn(QString("-" + QString(COLUMN_CHANNEL_NAME) + " " + chName).toUtf8(), dType); } } } @@ -194,13 +194,13 @@ void SearchChannels::procIn(const QByteArray &binIn, quint8 dType) { retCode = NO_ERRORS; - TableViewer::procIn(toTEXT("-" + QString(COLUMN_CHANNEL_NAME) + " " + name), dType); + TableViewer::procIn(QString("-" + QString(COLUMN_CHANNEL_NAME) + " " + name).toUtf8(), dType); } else if (!chId.isEmpty()) { retCode = NO_ERRORS; - TableViewer::procIn(toTEXT("-" + QString(COLUMN_CHANNEL_ID) + " " + chId), dType); + TableViewer::procIn(QString("-" + QString(COLUMN_CHANNEL_ID) + " " + chId).toUtf8(), dType); } else { @@ -251,16 +251,16 @@ void ListMembers::procIn(const QByteArray &binIn, quint8 dType) { retCode = NO_ERRORS; - auto argsBa = toTEXT("-" + QString(COLUMN_CHANNEL_NAME) + " " + chName); + auto argsBa = QString("-" + QString(COLUMN_CHANNEL_NAME) + " " + chName).toUtf8(); if (!userFind.isEmpty()) { - argsBa.append(toTEXT(" -" + QString(COLUMN_USERNAME) + " " + userFind)); + argsBa.append(QString(" -" + QString(COLUMN_USERNAME) + " " + userFind).toUtf8()); } if (!dispFind.isEmpty()) { - argsBa.append(toTEXT(" -" + QString(COLUMN_DISPLAY_NAME) + " " + dispFind)); + argsBa.append(QString(" -" + QString(COLUMN_DISPLAY_NAME) + " " + dispFind).toUtf8()); } TableViewer::procIn(argsBa, dType); diff --git a/src/commands/fs.cpp b/src/commands/fs.cpp index ab98355..a8bb5a1 100644 --- a/src/commands/fs.cpp +++ b/src/commands/fs.cpp @@ -24,7 +24,7 @@ QByteArray toFILE_INFO(const QFileInfo &info) // format: [1byte(flags)][8bytes(createTime)][8bytes(modTime)][8bytes(fileSize)] // [TEXT(fileName)][TEXT(symLinkTarget)] - // note: the TEXT strings are 16bit NULL terminated meaning 2 bytes of 0x00 + // note: the TEXT strings are NULL terminated which means 1 byte of 0x00 // indicate the end of the string. // note: the integer data found in flags, modTime, createTime and fileSize @@ -41,14 +41,13 @@ QByteArray toFILE_INFO(const QFileInfo &info) if (info.exists()) flags |= EXISTS; QByteArray ret; - QByteArray strTerm(2, 0); ret.append(flags); ret.append(wrInt(info.birthTime().toMSecsSinceEpoch(), 64)); ret.append(wrInt(info.lastModified().toMSecsSinceEpoch(), 64)); ret.append(wrInt(info.size(), 64)); - ret.append(toTEXT(info.fileName()) + strTerm); - ret.append(toTEXT(info.symLinkTarget()) + strTerm); + ret.append(nullTermTEXT(info.fileName())); + ret.append(nullTermTEXT(info.symLinkTarget())); return ret; } @@ -184,7 +183,7 @@ void DownloadFile::procIn(const QByteArray &binIn, quint8 dType) emit mainTxt("dl_file: " + path + "\n"); emit mainTxt("bytes: " + QString::number(progMax) + "\n"); - emit procOut(toTEXT("-len " + QString::number(progMax)), GEN_FILE); + emit procOut(QString("-len " + QString::number(progMax)).toUtf8(), GEN_FILE); startProgPulse(); } @@ -257,7 +256,7 @@ void UploadFile::procIn(const QByteArray &binIn, quint8 dType) { if (((dType == GEN_FILE) || (dType == TEXT)) && confirm) { - auto ans = fromTEXT(binIn); + auto ans = QString::fromUtf8(binIn); if (noCaseMatch("y", ans)) { @@ -386,7 +385,7 @@ void Delete::procIn(const QByteArray &binIn, uchar dType) { if ((flags & MORE_INPUT) && (dType == TEXT)) { - auto ans = fromTEXT(binIn); + auto ans = QString::fromUtf8(binIn); if (noCaseMatch("y", ans)) { @@ -609,7 +608,7 @@ void Copy::procIn(const QByteArray &binIn, uchar dType) } else if ((dType == TEXT) && (flags & MORE_INPUT)) { - auto ans = fromTEXT(binIn); + auto ans = QString::fromUtf8(binIn); if (noCaseMatch("y", ans)) { @@ -942,7 +941,7 @@ void ChangeDir::procIn(const QByteArray &binIn, quint8 dType) QDir::setCurrent(path); mainTxt(QDir::currentPath() + "\n"); - async(ASYNC_SET_DIR, toTEXT(path)); + async(ASYNC_SET_DIR, path.toUtf8()); } } } diff --git a/src/commands/info.cpp b/src/commands/info.cpp index ee58ad4..a409c16 100644 --- a/src/commands/info.cpp +++ b/src/commands/info.cpp @@ -84,8 +84,8 @@ void ListCommands::onIPCConnected() frame.append(QByteArray(2, 0x00)); frame.append(genType); - frame.append(fixedToTEXT(cmdName, BLKSIZE_CMD_NAME)); - frame.append(fixedToTEXT(libName(), BLKSIZE_LIB_NAME)); + frame.append(toFixedTEXT(cmdName, 64)); + frame.append(toFixedTEXT(libName(), 64)); frame.append(nullTermTEXT(shortText(cmdName))); frame.append(nullTermTEXT(ioText(cmdName))); frame.append(nullTermTEXT(longText(cmdName))); @@ -139,9 +139,9 @@ void MyInfo::procIn(const QByteArray &binIn, quint8 dType) QString txt; QTextStream txtOut(&txt); - QString sesId = rdFromBlock(sessionId, BLKSIZE_SESSION_ID).toHex(); - QString ip = rdStringFromBlock(clientIp, BLKSIZE_CLIENT_IP); - QString app = rdStringFromBlock(appName, BLKSIZE_APP_NAME); + auto sesId = rdFromBlock(sessionId, BLKSIZE_SESSION_ID).toHex(); + auto ip = rdStringFromBlock(clientIp, BLKSIZE_CLIENT_IP); + auto app = rdStringFromBlock(appName, BLKSIZE_APP_NAME); txtOut << "Session id: " << sesId << Qt::endl; txtOut << "IP Address: " << ip << Qt::endl; @@ -149,7 +149,7 @@ void MyInfo::procIn(const QByteArray &binIn, quint8 dType) if (!isEmptyBlock(userId, BLKSIZE_USER_ID)) { - QByteArray uId = rdFromBlock(userId, BLKSIZE_USER_ID); + auto uId = rdFromBlock(userId, BLKSIZE_USER_ID); Query db(this); diff --git a/src/commands/mods.cpp b/src/commands/mods.cpp index 6420cf5..2362c03 100644 --- a/src/commands/mods.cpp +++ b/src/commands/mods.cpp @@ -71,7 +71,7 @@ void AddMod::procIn(const QByteArray &binIn, quint8 dType) db.addColumn(COLUMN_MOD_MAIN, path); db.exec(); - async(ASYNC_ENABLE_MOD, toTEXT(path)); + async(ASYNC_ENABLE_MOD, path.toUtf8()); } } } @@ -107,7 +107,7 @@ void DelMod::procIn(const QByteArray &binIn, quint8 dType) db.addCondition(COLUMN_MOD_MAIN, path); db.exec(); - async(ASYNC_DISABLE_MOD, toTEXT(path)); + async(ASYNC_DISABLE_MOD, path.toUtf8()); } } } diff --git a/src/commands/table_viewer.cpp b/src/commands/table_viewer.cpp index aa54130..aa7f71e 100644 --- a/src/commands/table_viewer.cpp +++ b/src/commands/table_viewer.cpp @@ -210,7 +210,7 @@ void TableViewer::procIn(const QByteArray &binIn, quint8 dType) { if (flags & MORE_INPUT) { - auto text = fromTEXT(binIn).toLower(); + auto text = QString::fromUtf8(binIn).toLower(); if (text == "y") { diff --git a/src/commands/users.cpp b/src/commands/users.cpp index 2fb1652..eecd98a 100644 --- a/src/commands/users.cpp +++ b/src/commands/users.cpp @@ -133,7 +133,7 @@ void CreateUser::procIn(const QByteArray &binIn, quint8 dType) { if (flags & MORE_INPUT) { - auto password = fromTEXT(binIn); + auto password = QString::fromUtf8(binIn); QString errMsg; @@ -242,7 +242,7 @@ void RemoveUser::procIn(const QByteArray &binIn, quint8 dType) { if (flags & MORE_INPUT) { - auto ans = fromTEXT(binIn); + auto ans = QString::fromUtf8(binIn); if (noCaseMatch("y", ans)) { @@ -376,7 +376,7 @@ void ChangePassword::procIn(const QByteArray &binIn, quint8 dType) { if (flags & MORE_INPUT) { - auto password = fromTEXT(binIn); + auto password = QString::fromUtf8(binIn); QString errMsg; @@ -440,7 +440,7 @@ void ChangeUsername::procIn(const QByteArray &binIn, quint8 dType) retCode = NO_ERRORS; auto uId = rdFromBlock(userId, BLKSIZE_USER_ID); - auto newNameBa = fixedToTEXT(newName, BLKSIZE_USER_NAME); + auto newNameBa = toFixedTEXT(newName, BLKSIZE_USER_NAME); Query db(this); @@ -478,7 +478,7 @@ void ChangeDispName::procIn(const QByteArray &binIn, quint8 dType) Query db(this); auto uId = rdFromBlock(userId, BLKSIZE_USER_ID); - auto newNameBa = fixedToTEXT(name, BLKSIZE_DISP_NAME); + auto newNameBa = toFixedTEXT(name, BLKSIZE_DISP_NAME); db.setType(Query::UPDATE, TABLE_USERS); db.addColumn(COLUMN_DISPLAY_NAME, name); diff --git a/src/common.cpp b/src/common.cpp index a66e56e..69f51f0 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -99,30 +99,14 @@ quint16 toCmdId16(quint32 id) return ret; } -QByteArray toTEXT(const QString &txt) +QByteArray toFixedTEXT(const QString &txt, int len) { - QByteArray ret = QTextCodec::codecForName(TXT_CODEC)->fromUnicode(txt); - - return ret.mid(2); // removes BOM. -} - -QByteArray fixedToTEXT(const QString &txt, int len) -{ - return toTEXT(txt).leftJustified(len, 0, true); + return txt.toUtf8().leftJustified(len, 0, true); } QByteArray nullTermTEXT(const QString &txt) { - return toTEXT(txt) + QByteArray(2, 0x00); -} - -QString fromTEXT(const QByteArray &txt) -{ - QByteArray ba = txt; - - ba.replace(QByteArray(2, 0x00), QByteArray()); - - return QTextCodec::codecForName(TXT_CODEC)->toUnicode(ba); + return txt.toUtf8() + QByteArray(1, 0x00); } bool noCaseMatch(const QString &strA, const QString &strB) @@ -132,7 +116,7 @@ bool noCaseMatch(const QString &strA, const QString &strB) bool containsNewLine(const QString &str) { - bool ret = false; + auto ret = false; for (auto&& chr : str) { @@ -147,7 +131,7 @@ bool containsNewLine(const QString &str) bool validSubId(const QString &num) { - bool ret = false; + auto ret = false; if (isInt(num)) { @@ -159,9 +143,9 @@ bool validSubId(const QString &num) bool validUserName(const QString &uName) { - bool ret = false; + auto ret = false; - if ((uName.size() >= 2) && ((uName.size() * 2) <= BLKSIZE_USER_NAME)) + if ((uName.size() >= 2) && (uName.size() <= BLKSIZE_USER_NAME)) { ret = !uName.contains(' ') && !containsNewLine(uName); } @@ -169,25 +153,12 @@ bool validUserName(const QString &uName) return ret; } -bool validCommonName(const QString &name) -{ - bool ret = false; - - if ((name.size() >= 1) && (name.size() <= 136)) - { - ret = !name.contains(' ') && !containsNewLine(name); - } - - return ret; -} - bool validEmailAddr(const QString &email) { - bool ret = false; + auto ret = false; + auto spEmail = email.split('@'); - QStringList spEmail = email.split('@'); - - if ((spEmail.size() == 2) && (email.size() >= 4) && (email.size() <= 64)) + if ((spEmail.size() == 2) && (email.size() >= 4) && (email.size() <= BLKSIZE_EMAIL_ADDR)) { if (!email.contains(' ') && !containsNewLine(email)) { @@ -212,7 +183,7 @@ bool validCommandName(const QString &name) bool validDispName(const QString &name) { - return ((name.size() * 2) <= BLKSIZE_DISP_NAME) && !containsNewLine(name); + return (name.size() <= BLKSIZE_DISP_NAME) && !containsNewLine(name); } bool validChName(const QString &name) @@ -248,11 +219,12 @@ bool validLevel(const QString &num, bool includePub) bool validModPath(const QString &modPath) { - bool ret = true; - QString forbidden = "|*:\"?<>"; + auto ret = !modPath.isEmpty(); - if ((modPath.size() > 512) || modPath.isEmpty()) + if (ret) { + static const QString forbidden = "|*:\"?<>"; + for (auto&& chr : forbidden) { if (modPath.contains(chr)) @@ -584,6 +556,27 @@ void containsActiveCh(const char *subChs, char *actBlock) } } +void printDatabaseInfo(QTextStream &txt) +{ + auto json = getDbSettings(); + auto driver = json["driver"].toString(); + + txt << "Database Parameters --" << Qt::endl << Qt::endl; + txt << "Driver: " << driver << Qt::endl; + + if (driver == "QSQLITE") + { + txt << "File: " << sqlDataPath() << Qt::endl; + } + else + { + txt << "Host: " << json["host_name"].toString() << Qt::endl; + txt << "User: " << json["user_name"].toString() << Qt::endl; + } + + txt << Qt::endl; +} + QString defaultPw() { Query db; @@ -854,16 +847,17 @@ QStringList parseArgs(const QByteArray &data, int maxArgs, int *pos) { QStringList ret; QString arg; - QString line = fromTEXT(data); - bool inDQuotes = false; - bool inSQuotes = false; - bool escaped = false; + + auto line = QString::fromUtf8(data); + auto inDQuotes = false; + auto inSQuotes = false; + auto escaped = false; if (pos != nullptr) *pos = 0; for (int i = 0; i < line.size(); ++i) { - if (pos != nullptr) *pos += (TXT_CODEC_BITS / 8); + if (pos != nullptr) *pos += 1; if ((line[i] == '\'') && !inDQuotes && !escaped) { @@ -990,9 +984,10 @@ void IdleTimer::attach(QIODevice *dev, int msec) connect(dev, SIGNAL(bytesWritten(qint64)), this, SLOT(detectWrite(qint64))); } -ShellIPC::ShellIPC(const QStringList &args, QObject *parent) : QLocalSocket(parent) +ShellIPC::ShellIPC(const QStringList &args, bool supressErr, QObject *parent) : QLocalSocket(parent) { arguments = args; + holdErrs = supressErr; connect(this, SIGNAL(connected()), this, SLOT(hostConnected())); connect(this, SIGNAL(disconnected()), this, SIGNAL(closeInstance())); @@ -1001,17 +996,23 @@ ShellIPC::ShellIPC(const QStringList &args, QObject *parent) : QLocalSocket(pare bool ShellIPC::connectToHost() { - connectToServer(HOST_CONTROL_PIPE); + auto pipeInfo = QFileInfo(QDir::tempPath() + "/" + HOST_CONTROL_PIPE); - if (!waitForConnected()) + if (!pipeInfo.exists()) { - if (QFileInfo(QDir::tempPath() + "/" + HOST_CONTROL_PIPE).exists()) + if (!holdErrs) { - QTextStream(stdout) << "" << Qt::endl << "Permission denied." << Qt::endl << Qt::endl; + QTextStream(stdout) << "" << Qt::endl << "A host instance is not running." << Qt::endl << Qt::endl; } - else + } + else + { + connectToServer(HOST_CONTROL_PIPE); + + if (!waitForConnected() && !holdErrs) { - QTextStream(stdout) << "" << Qt::endl << "Host instance not running." << Qt::endl << Qt::endl; + QTextStream(stdout) << "" << Qt::endl << "err: Failed to connect to the host instance control pipe." << Qt::endl; + QTextStream(stdout) << "err: Reason - " << errorString() << Qt::endl; } } @@ -1020,12 +1021,12 @@ bool ShellIPC::connectToHost() void ShellIPC::hostConnected() { - write(toTEXT(arguments.join(' '))); + write(arguments.join(' ').toUtf8()); } void ShellIPC::dataIn() { - QTextStream(stdout) << fromTEXT(readAll()); + QTextStream(stdout) << QString::fromUtf8(readAll()); emit closeInstance(); } diff --git a/src/common.h b/src/common.h index f5e27cb..77ba31e 100644 --- a/src/common.h +++ b/src/common.h @@ -72,21 +72,12 @@ #include "shell.h" #include "mem_share.h" -#define FRAME_HEADER_SIZE 8 -#define MAX_FRAME_BITS 24 -#define IMPORT_REV 3 -#define LOCAL_BUFFSIZE 16777215 -#define CLIENT_INIT_TIME 5000 -#define IPC_PREP_TIME 1000 -#define IPC_CONNECT_DELAY 500 -#define CLIENT_HEADER_LEN 410 -#define SERVER_HEADER_LEN 35 -#define EXE_CRASH_LIMIT 5 -#define EXE_DEBUG_INFO_SIZE 512 -#define SERVER_HEADER_TAG "MRCI" -#define HOST_CONTROL_PIPE "MRCI_HOST_CONTROL" -#define TXT_CODEC "UTF-16LE" -#define TXT_CODEC_BITS 16 +#define FRAME_HEADER_SIZE 8 +#define MAX_FRAME_BITS 24 +#define LOCAL_BUFFSIZE 16777215 +#define CLIENT_HEADER_LEN 292 +#define SERVER_HEADER_TAG "MRCI" +#define HOST_CONTROL_PIPE "MRCI_HOST_CONTROL" enum AsyncCommands : quint16 { @@ -231,12 +222,12 @@ enum ChannelMemberLevel : quint8 class Session; -QByteArray toTEXT(const QString &txt); -QByteArray fixedToTEXT(const QString &txt, int len); +QByteArray toFixedTEXT(const QString &txt, int len); QByteArray nullTermTEXT(const QString &txt); QByteArray rdFileContents(const QString &path, QTextStream &msg); quint32 toCmdId32(quint16 cmdId, quint16 branchId); quint16 toCmdId16(quint32 id); +void printDatabaseInfo(QTextStream &txt); void serializeThread(QThread *thr); void mkPath(const QString &path); void listDir(QList > &list, const QString &srcPath, const QString &dstPath); @@ -249,7 +240,6 @@ bool validUserName(const QString &uName); bool validEmailAddr(const QString &email); bool validPassword(const QString &pw); bool validCommandName(const QString &name); -bool validCommonName(const QString &name); bool validDispName(const QString &name); bool validChName(const QString &name); bool validLevel(const QString &num, bool includePub); @@ -277,7 +267,6 @@ bool isChOwner(const QByteArray &uId); int channelAccessLevel(const QByteArray &uId, quint64 chId); int channelAccessLevel(const QByteArray &uId, const char *override, quint64 chId); int maxSubChannels(); -QString fromTEXT(const QByteArray &txt); QString getUserNameForEmail(const QString &email); QString getEmailForUser(const QByteArray &uId); QString getDispName(const QByteArray &uId); @@ -330,6 +319,7 @@ class ShellIPC : public QLocalSocket private: QStringList arguments; + bool holdErrs; private slots: @@ -340,7 +330,7 @@ public: bool connectToHost(); - explicit ShellIPC(const QStringList &args, QObject *parent = nullptr); + explicit ShellIPC(const QStringList &args, bool supressErr = false, QObject *parent = nullptr); signals: diff --git a/src/db.cpp b/src/db.cpp index d3dd3d7..c6add87 100644 --- a/src/db.cpp +++ b/src/db.cpp @@ -116,7 +116,7 @@ QChar genSpecialChar() int inRange(int pos, int min, int max) { - int ret = pos; + auto ret = pos; if (pos < min) ret = min; if (pos > max) ret = max; @@ -128,7 +128,7 @@ void moveCharLeft(int pos, QString &str) { pos = inRange(pos, 0, str.size() - 1); - QChar chr = str[pos]; + auto chr = str[pos]; str.remove(pos, 1); @@ -140,7 +140,7 @@ void moveCharRight(int pos, QString &str) { pos = inRange(pos, 0, str.size() - 1); - QChar chr = str[pos]; + auto chr = str[pos]; str.remove(pos, 1); @@ -152,7 +152,7 @@ QString genPw() { QString ret; - QList seq = genSequence(2, 5, 4); + auto seq = genSequence(2, 5, 4); for (int i = 0; i < seq[0]; ++i) { @@ -176,7 +176,7 @@ QString genPw() seq = genSequence(0, ret.size() - 1, 10); - bool toggle = false; + auto toggle = false; for (int i : seq) { @@ -220,7 +220,7 @@ QByteArray rootUserId() db.addColumn(COLUMN_ROOT_USER); db.exec(); - QByteArray id = db.getData(COLUMN_ROOT_USER).toByteArray(); + auto id = db.getData(COLUMN_ROOT_USER).toByteArray(); if (id.isEmpty()) { @@ -235,12 +235,59 @@ QByteArray rootUserId() return id; } +QJsonObject getDbSettings(bool defaults) +{ + QJsonObject ret; + + QFile file(DEFAULT_DB_JSON_FILE); + + if (file.exists() && !defaults) + { + if (file.open(QFile::ReadOnly)) + { + ret = QJsonDocument::fromJson(file.readAll()).object(); + } + else + { + ret = getDbSettings(true); + } + } + else + { + ret.insert("driver", "QSQLITE"); + ret.insert("host_name", "localhost"); + ret.insert("user_name", QSysInfo::machineHostName()); + ret.insert("password", QString(QSysInfo::machineUniqueId().toHex())); + + if (file.open(QFile::WriteOnly | QFile::Truncate)) + { + file.write(QJsonDocument(ret).toJson()); + } + } + + file.close(); + + return ret; +} + +void saveDbSettings(const QJsonObject &obj) +{ + QFile file(DEFAULT_DB_JSON_FILE); + + if (file.open(QFile::WriteOnly | QFile::Truncate)) + { + file.write(QJsonDocument(obj).toJson()); + } + + file.close(); +} + bool createUser(const QString &userName, const QString &email, const QString &dispName, const QString &password) { - bool ret = false; + auto ret = false; + auto newUId = genUniqueHash(); - Query db; - QByteArray newUId = genUniqueHash(); + Query db; db.setType(Query::PUSH, TABLE_USERS); db.addColumn(COLUMN_USERNAME, userName); @@ -264,7 +311,7 @@ bool createUser(const QString &userName, const QString &email, const QString &di bool createTempPw(const QByteArray &uId, const QString &password) { - bool ret = false; + auto ret = false; Query db; @@ -282,8 +329,8 @@ bool createTempPw(const QByteArray &uId, const QString &password) bool updatePassword(const QByteArray &uId, const QString &password, const QString &table, bool requireNewPass) { - bool ret = false; - QByteArray salt = getSalt(uId, table); + auto ret = false; + auto salt = getSalt(uId, table); if (!salt.isEmpty()) { @@ -291,7 +338,7 @@ bool updatePassword(const QByteArray &uId, const QString &password, const QStrin QCryptographicHash hasher(QCryptographicHash::Keccak_512); - hasher.addData(QTextCodec::codecForName("UTF-16LE")->fromUnicode(password) + salt); + hasher.addData(password.toUtf8() + salt); db.setType(Query::UPDATE, table); db.addColumn(COLUMN_HASH, hasher.result()); @@ -306,8 +353,8 @@ bool updatePassword(const QByteArray &uId, const QString &password, const QStrin bool auth(const QByteArray &uId, const QString &password, const QString &table) { - bool ret = false; - QByteArray salt = getSalt(uId, table); + auto ret = false; + auto salt = getSalt(uId, table); if (!salt.isEmpty()) { @@ -354,15 +401,28 @@ Query::Query(QObject *parent) : QObject(parent) if (!QSqlDatabase::contains(getConnectionName())) { - QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", getConnectionName()); + auto settings = getDbSettings(); + auto driver = settings["driver"].toString(); + auto db = QSqlDatabase::addDatabase(driver, getConnectionName()); - db.setConnectOptions("ISC_DPB_LC_CTYPE=UTF16LE"); - db.setDatabaseName(sqlDataPath()); + db.setConnectOptions("ISC_DPB_LC_CTYPE=UTF8"); + + if (driver == "QSQLITE") + { + db.setDatabaseName(sqlDataPath()); + } + else + { + db.setDatabaseName(APP_NAME); + db.setUserName(settings["user_name"].toString()); + db.setHostName(settings["host_name"].toString()); + db.setPassword(settings["password"].toString()); + } if (db.open()) { enableForeignKeys(true); - setTextEncoding("UTF16LE"); + setTextEncoding("UTF8"); } else { @@ -386,19 +446,6 @@ QString Query::errDetail() 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." << Qt::endl; - } - - if (!info.isWritable()) - { - txtOut << " writable: database path doesn't have write permissions." << Qt::endl; - } return ret; } @@ -752,7 +799,7 @@ void Query::addForeign(const QString &column, const QString &refTable, const QSt { if ((columnsAsPassed.contains(column)) && ((type == CREATE_TABLE) || (type == ALTER_TABLE))) { - QString str = "FOREIGN KEY (" + column + ") REFERENCES " + refTable + " (" + refColum + ")"; + auto str = "FOREIGN KEY (" + column + ") REFERENCES " + refTable + " (" + refColum + ")"; switch (onDel) { @@ -778,7 +825,7 @@ void Query::addForeign(const QString &column, const QString &refTable, const QSt void Query::preExec() { - QString columnsStr = QStringList(columnList).join(", "); + auto columnsStr = QStringList(columnList).join(", "); qStr.replace("%columns%", columnsStr); data.clear(); @@ -806,14 +853,14 @@ void Query::preExec() bool Query::createRedirect() { - bool ret = false; + auto ret = false; if ((type == CREATE_TABLE) && (tables().contains(table))) { ret = true; - QStringList existingColumns = columnsInTable(table); - QStringList newColumns = columnsAsPassed; + auto existingColumns = columnsInTable(table); + auto newColumns = columnsAsPassed; for (int i = 0; (i < newColumns.size()) && queryOk; ++i) { @@ -895,7 +942,7 @@ QVariant Query::getData(const QString &column, int row) if ((row < data.size()) && (row >= 0)) { - int index = columnsAsPassed.indexOf(column); + auto index = columnsAsPassed.indexOf(column); if (index != -1) { @@ -908,7 +955,7 @@ QVariant Query::getData(const QString &column, int row) int Query::rows() { - int ret = 0; + auto ret = 0; if ((type == PULL) || (type == INNER_JOIN_PULL)) { diff --git a/src/db.h b/src/db.h index 1216af2..e529dbc 100644 --- a/src/db.h +++ b/src/db.h @@ -33,11 +33,13 @@ #include #include #include +#include +#include #include "shell.h" #define APP_NAME "MRCI" -#define APP_VER "3.5.1.0" +#define APP_VER "4.0.2.0" #define APP_TARGET "mrci" #ifdef Q_OS_WIN @@ -68,6 +70,7 @@ #define DEFAULT_PUB_KEY_NAME "cert.pem" #define DEFAULT_PRIV_KEY_NAME "priv.pem" #define DEFAULT_DB_FILE "data.db" +#define DEFAULT_DB_JSON_FILE "db_settings.json" #define DEFAULT_ROOT_USER "root" #define DEFAULT_CONFIRM_SUBJECT "Email Verification" #define DEFAULT_TEMP_PW_SUBJECT "Password Reset" @@ -159,25 +162,27 @@ Date requested: %date%." #define COLUMN_DEFAULT_PASS "default_password" #define COLUMN_ROOT_USER "root_user" -QString genPw(); -QList genSequence(int min, int max, int len); -QChar genLetter(); -QChar genNum(); -QChar genSpecialChar(); -int inRange(int pos, int min, int max); -QString sqlDataPath(); -QString columnType(const QString &column); -quint32 initHostRank(); -QByteArray getSalt(const QByteArray &uId, const QString &table); -QByteArray genUniqueHash(); -QByteArray rootUserId(); -bool createUser(const QString &userName, const QString &email, const QString &dispName, const QString &password); -bool createTempPw(const QByteArray &uId, const QString &password); -bool updatePassword(const QByteArray &uId, const QString &password, const QString &table, bool requireNewPass = false); -bool auth(const QByteArray &uId, const QString &password, const QString &table); -void cleanupDbConnection(); -void moveCharLeft(int pos, QString &str); -void moveCharRight(int pos, QString &str); +QString genPw(); +QList genSequence(int min, int max, int len); +QChar genLetter(); +QChar genNum(); +QChar genSpecialChar(); +int inRange(int pos, int min, int max); +QString sqlDataPath(); +QString columnType(const QString &column); +quint32 initHostRank(); +QByteArray getSalt(const QByteArray &uId, const QString &table); +QByteArray genUniqueHash(); +QByteArray rootUserId(); +QJsonObject getDbSettings(bool defaults = false); +bool createUser(const QString &userName, const QString &email, const QString &dispName, const QString &password); +bool createTempPw(const QByteArray &uId, const QString &password); +bool updatePassword(const QByteArray &uId, const QString &password, const QString &table, bool requireNewPass = false); +bool auth(const QByteArray &uId, const QString &password, const QString &table); +void cleanupDbConnection(); +void saveDbSettings(const QJsonObject &obj); +void moveCharLeft(int pos, QString &str); +void moveCharRight(int pos, QString &str); class Query : public QObject { diff --git a/src/db_setup.cpp b/src/db_setup.cpp index 05f8c96..73095e6 100644 --- a/src/db_setup.cpp +++ b/src/db_setup.cpp @@ -18,7 +18,7 @@ bool setupDb(QString *errMsg) { - bool ret = true; + auto ret = true; errMsg->clear(); @@ -110,7 +110,7 @@ bool setupDb(QString *errMsg) if (query.createExecuted()) { - QByteArray uId = genUniqueHash(); + auto uId = genUniqueHash(); query.setType(Query::PUSH, TABLE_USERS); query.addColumn(COLUMN_USERNAME, DEFAULT_ROOT_USER); @@ -234,7 +234,7 @@ bool setupDb(QString *errMsg) randPw = genPw(); } - QByteArray rootUId = rootUserId(); + auto rootUId = rootUserId(); if (query.createExecuted()) { diff --git a/src/main.cpp b/src/main.cpp index 53be6af..9a6af0e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -73,6 +73,7 @@ void showHelp() 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 << " -ls_sql_drvs : list all available SQL drivers that the host currently supports." << 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; @@ -81,9 +82,9 @@ void showHelp() 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; + txtOut << "run_cmd - this argument is used by the host itself along with the internal module arguments to run the" << Qt::endl; + txtOut << " internal command names passed by it. this is not ment to be run directly by human input. the" << Qt::endl; + txtOut << " 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) @@ -94,10 +95,10 @@ void soeDueToDbErr(int *retCode, const QString *errMsg) QTextStream(stderr) << " what happened: " << Qt::endl << *errMsg << Qt::endl << Qt::endl; } -int shellToHost(const QStringList &args, QCoreApplication &app) +int shellToHost(const QStringList &args, bool holdErrs, QCoreApplication &app) { auto ret = 0; - auto *ipc = new ShellIPC(args, &app); + auto *ipc = new ShellIPC(args, holdErrs, &app); QObject::connect(ipc, SIGNAL(closeInstance()), &app, SLOT(quit())); @@ -135,12 +136,49 @@ int main(int argc, char *argv[]) qInstallMessageHandler(msgHandler); - //args.append("-host"); // debug + // args.append("-ls_sql_drvs"); // debug - if (args.contains("-help", Qt::CaseInsensitive) || args.size() == 1) + if (args.contains("-run_cmd", Qt::CaseInsensitive) || + args.contains("-public_cmds", Qt::CaseInsensitive) || + args.contains("-exempt_cmds", Qt::CaseInsensitive) || + args.contains("-user_cmds", Qt::CaseInsensitive)) + { + // security note: it is critical that the above internal arguments are checked + // first. external clients have the ability to pass additional + // args and those args come through here. it can be a security + // threat if an external arg is a powerful arg like "reset_root" + // and it ends up getting processed unintentionally by this + // function. + + if (setupDb(&err)) + { + auto *mod = new Module(&app); + + if (mod->start(args)) + { + ret = QCoreApplication::exec(); + } + } + else + { + soeDueToDbErr(&ret, &err); + } + } + else if (args.contains("-help", Qt::CaseInsensitive) || args.size() == 1) { showHelp(); } + else if (args.contains("-ls_sql_drvs", Qt::CaseInsensitive)) + { + QTextStream(stdout) << "" << Qt::endl; + + for (auto driver : QSqlDatabase::drivers()) + { + QTextStream(stdout) << driver << Qt::endl; + } + + QTextStream(stdout) << "" << Qt::endl; + } else if (args.contains("-about", Qt::CaseInsensitive)) { QTextStream(stdout) << "" << Qt::endl << APP_NAME << " v" << QCoreApplication::applicationVersion() << Qt::endl << Qt::endl; @@ -152,11 +190,24 @@ int main(int argc, char *argv[]) args.contains("-status", Qt::CaseInsensitive) || args.contains("-load_ssl", Qt::CaseInsensitive)) { - ret = shellToHost(args, app); + ret = shellToHost(args, false, app); } else if (setupDb(&err)) { - if (args.contains("-addr", Qt::CaseInsensitive)) + if (args.contains("-host", Qt::CaseInsensitive)) + { + auto *serv = new TCPServer(&app); + + if (serv->start()) + { + ret = QCoreApplication::exec(); + } + } + else if (args.contains("-host_trig", Qt::CaseInsensitive)) + { + QProcess::startDetached(QCoreApplication::applicationFilePath(), QStringList() << "-host"); + } + else if (args.contains("-addr", Qt::CaseInsensitive)) { auto params = getParam("-addr", args); auto addr = params.split(':'); @@ -186,42 +237,17 @@ int main(int argc, char *argv[]) } else { - ret = 0; - Query db(&app); db.setType(Query::UPDATE, TABLE_SERV_SETTINGS); db.addColumn(COLUMN_IPADDR, addr[0]); db.addColumn(COLUMN_PORT, port); db.exec(); + + ret = shellToHost(args, true, app); } } } - else if (args.contains("-run_cmd", Qt::CaseInsensitive) || - args.contains("-public_cmds", Qt::CaseInsensitive) || - args.contains("-exempt_cmds", Qt::CaseInsensitive) || - args.contains("-user_cmds", Qt::CaseInsensitive)) - { - auto *mod = new Module(&app); - - if (mod->start(args)) - { - ret = QCoreApplication::exec(); - } - } - else if (args.contains("-host", Qt::CaseInsensitive)) - { - auto *serv = new TCPServer(&app); - - if (serv->start()) - { - 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(); diff --git a/src/mem_share.cpp b/src/mem_share.cpp index 18661c3..f4661c0 100644 --- a/src/mem_share.cpp +++ b/src/mem_share.cpp @@ -18,7 +18,8 @@ QString createHostSharedMem(QSharedMemory *mem) { - int len = 0; + auto len = 0; + QString ret; len += BLKSIZE_HOST_LOAD; // hostLoad @@ -39,8 +40,8 @@ QString createHostSharedMem(QSharedMemory *mem) int posOfLikeBlock(const QByteArray &block, const char *blocks, quint32 numOfBlocks, quint32 bytesPerBlock) { - int ret = -1; - quint32 cmpLen = static_cast(block.size()); + auto ret = -1; + auto cmpLen = static_cast(block.size()); if (cmpLen > bytesPerBlock) { @@ -110,7 +111,7 @@ int posOfEmptyBlock(const char *blocks, quint32 numOfBlocks, quint32 bytesPerBlo bool addBlockToBlockset(const char *block, char *blocks, quint32 numOfBlocks, quint32 bytesPerBlock) { - bool ret = false; + auto ret = false; if (posOfBlock(block, blocks, numOfBlocks, bytesPerBlock) == -1) { @@ -180,7 +181,8 @@ bool isEmptyBlock(const char *block, quint32 blockSize) void wrStringToBlock(const QString &str, char *block, quint32 blockSize) { - quint32 strByteSize = static_cast(str.size()) * 2; + auto strBytes = str.toUtf8(); + auto strByteSize = static_cast(strBytes.size()); if (strByteSize > blockSize) { @@ -191,7 +193,7 @@ void wrStringToBlock(const QString &str, char *block, quint32 blockSize) memset(block, 0, blockSize); } - memcpy(block, reinterpret_cast(str.utf16()), strByteSize); + memcpy(block, strBytes.data(), strByteSize); } void wr8BitToBlock(quint8 num, char *block) @@ -290,24 +292,21 @@ quint64 rd64BitFromBlock(const char *block) QString rdStringFromBlock(const char *block, quint32 blockSize) { - QString ret; - quint16 chr; + quint32 len = 0; - for (quint32 i = 0; i < blockSize; i += 2) + for (quint32 i = 0; i < blockSize; i++) { - memcpy(&chr, block + i, 2); - - if (chr == 0) + if (block[i] == 0) { break; } else { - ret.append(QChar(chr)); + len++; } } - return ret; + return QString(QByteArray(block, len)); } QByteArray rdFromBlock(const char *block, quint32 blockSize) @@ -339,8 +338,8 @@ MemShare::MemShare(QObject *parent) : QObject(parent) bool MemShare::createSharedMem(const QByteArray &sesId, const QString &hostKey) { - int len = 0; - bool ret = false; + auto len = 0; + auto ret = false; sharedMem->setKey(sesId.toHex()); hostSharedMem->setNativeKey(hostKey); @@ -433,11 +432,11 @@ void MemShare::setupDataBlocks() QByteArray MemShare::createPeerInfoFrame() { - QByteArray sesId = rdFromBlock(sessionId, BLKSIZE_SESSION_ID); - QByteArray usrId = rdFromBlock(userId, BLKSIZE_USER_ID); - QByteArray uName = rdFromBlock(userName, BLKSIZE_USER_NAME); - QByteArray aName = rdFromBlock(appName, BLKSIZE_APP_NAME); - QByteArray dName = rdFromBlock(displayName, BLKSIZE_DISP_NAME); + auto sesId = rdFromBlock(sessionId, BLKSIZE_SESSION_ID); + auto usrId = rdFromBlock(userId, BLKSIZE_USER_ID); + auto uName = rdFromBlock(userName, BLKSIZE_USER_NAME); + auto aName = rdFromBlock(appName, BLKSIZE_APP_NAME); + auto dName = rdFromBlock(displayName, BLKSIZE_DISP_NAME); return sesId + usrId + uName + aName + dName; } diff --git a/src/mem_share.h b/src/mem_share.h index bac7058..c56780e 100644 --- a/src/mem_share.h +++ b/src/mem_share.h @@ -29,18 +29,16 @@ #define BLKSIZE_CLIENT_IP 78 #define BLKSIZE_SESSION_ID 28 #define BLKSIZE_SUB_CHANNEL 9 -#define BLKSIZE_APP_NAME 134 +#define BLKSIZE_APP_NAME 32 #define BLKSIZE_USER_ID 32 -#define BLKSIZE_USER_NAME 48 -#define BLKSIZE_DISP_NAME 64 +#define BLKSIZE_USER_NAME 24 +#define BLKSIZE_DISP_NAME 24 #define BLKSIZE_CHANNEL_ID 8 #define BLKSIZE_HOST_RANK 4 #define BLKSIZE_ACT_UPDATE 1 #define BLKSIZE_CH_OVERRIDE 1 #define BLKSIZE_HOST_LOAD 4 -#define BLKSIZE_CMD_NAME 128 -#define BLKSIZE_LIB_NAME 128 -#define BLKSIZE_EMAIL_ADDR 128 +#define BLKSIZE_EMAIL_ADDR 64 #define HOST_NON_NATIVE_KEY "MRCI_Host_Shared_Mem_Key" diff --git a/src/session.cpp b/src/session.cpp index 9339c06..143581f 100644 --- a/src/session.cpp +++ b/src/session.cpp @@ -103,7 +103,7 @@ void Session::sesRdy() emit connectPeers(QSharedPointer(payload)); loadCmds(); - asyncToClient(ASYNC_RDY, toTEXT("\nReady!\n\n"), TEXT); + asyncToClient(ASYNC_RDY, QString("\nReady!\n\n").toUtf8(), TEXT); } void Session::addIpAction(const QString &action) @@ -221,6 +221,7 @@ ModProcess *Session::initModProc(const QString &modApp) auto *proc = new ModProcess(modApp, sesMemKey, hostMemKey, pipe, this); proc->setWorkingDirectory(currentDir); + proc->addArgs(modInst); proc->setSessionParams(&cmdUniqueNames, &cmdRealNames, &cmdAppById, &modCmdNames, &cmdIds, rnk); connect(proc, &ModProcess::dataToClient, this, &Session::dataToClient); @@ -292,7 +293,7 @@ void Session::dataToCmd(quint32 cmdId, const QByteArray &data, quint8 typeId) } else { - dataToClient(cmdId, toTEXT("err: No such command id: " + QString::number(cmdId16) + "."), ERR); + dataToClient(cmdId, QString("err: No such command id: " + QString::number(cmdId16) + ".").toUtf8(), ERR); } } @@ -336,16 +337,19 @@ void Session::dataFromClient() { auto clientHeader = tcpSocket->read(CLIENT_HEADER_LEN); - // client header format: [4bytes(tag)][134bytes(appName)][272bytes(padding)] + // client header format: [4bytes(tag)][32bytes(appName)][128bytes(mod_instructions)][128byes(padding)] // tag = 0x4D, 0x52, 0x43, 0x49 (MRCI) - // appName = UTF16LE string (padded with 0x00) - // padding = just a string of 0x00 (reserved for future expansion) + // appName = UTF8 string (padded with 0x00) + // modInst = UTF8 string (padded with 0x00) + // padding = 128 bytes of (0x00) if (clientHeader.startsWith(SERVER_HEADER_TAG)) { wrToBlock(clientHeader.mid(4, BLKSIZE_APP_NAME), appName, BLKSIZE_APP_NAME); + modInst = rdStringFromBlock(clientHeader.data() + 36, 64); + auto ver = QCoreApplication::applicationVersion().split('.'); QByteArray servHeader; @@ -474,7 +478,7 @@ void Session::login(const QByteArray &uId) for (int i = 0; i < db.rows(); ++i) { - QByteArray chId = wrInt(db.getData(COLUMN_CHANNEL_ID, i).toULongLong(), 64); + auto chId = wrInt(db.getData(COLUMN_CHANNEL_ID, i).toULongLong(), 64); addBlockToBlockset(chId.data(), chList, MAX_CHANNELS_PER_USER, BLKSIZE_CHANNEL_ID); } @@ -498,7 +502,7 @@ void Session::sendLocalInfo() db.addCondition(COLUMN_USER_ID, rdFromBlock(userId, BLKSIZE_USER_ID)); db.exec(); - frame.append(fixedToTEXT(db.getData(COLUMN_EMAIL).toString(), BLKSIZE_EMAIL_ADDR)); + frame.append(toFixedTEXT(db.getData(COLUMN_EMAIL).toString(), BLKSIZE_EMAIL_ADDR)); frame.append(rdFromBlock(hostRank, BLKSIZE_HOST_RANK)); if (db.getData(COLUMN_EMAIL_VERIFIED).toBool()) @@ -616,11 +620,11 @@ void Session::privAsyncDataIn(quint16 cmdId, const QByteArray &data) } else if (cmdId == ASYNC_SET_DIR) { - currentDir = fromTEXT(data); + currentDir = QString::fromUtf8(data); } else if (cmdId == ASYNC_DEBUG_TEXT) { - qDebug() << fromTEXT(data); + qDebug() << QString::fromUtf8(data); } sharedMem->unlock(); diff --git a/src/session.h b/src/session.h index 2b173ce..7a36a3c 100644 --- a/src/session.h +++ b/src/session.h @@ -33,6 +33,7 @@ private: QSslSocket *tcpSocket; QList *sslChain; QSslKey *sslKey; + QString modInst; QString currentDir; QHash modCmdNames; QHash > frameQueue; diff --git a/src/tcp_server.cpp b/src/tcp_server.cpp index 9332db7..cc85f18 100644 --- a/src/tcp_server.cpp +++ b/src/tcp_server.cpp @@ -217,11 +217,31 @@ void TCPServer::procPipeIn() { closeServer(); - controlSocket->write(toTEXT("\n")); + controlSocket->write(QString("\n").toUtf8()); } else if (args.contains("-load_ssl", Qt::CaseInsensitive)) { - controlSocket->write(toTEXT(loadSSLData(true))); + controlSocket->write(loadSSLData(true).toUtf8()); + } + else if (args.contains("-addr", Qt::CaseInsensitive)) + { + auto params = getParam("-addr", args); + auto addr = params.split(':'); + + close(); + + QString text; + QTextStream txtOut(&text); + + if (!listen(QHostAddress(addr[0]), addr[1].toUInt())) + { + txtOut << "" << Qt::endl << "err: TCP listen failure on address: " << addr[0] << " port: " << addr[1] << Qt::endl; + txtOut << "err: Reason - " << errorString() << Qt::endl; + } + + txtOut << "" << Qt::endl; + + controlSocket->write(text.toUtf8()); } else if (args.contains("-status", Qt::CaseInsensitive)) { @@ -238,18 +258,17 @@ void TCPServer::procPipeIn() hostSharedMem->lock(); 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; + txtOut << "Host Load: " << rd32BitFromBlock(hostLoad) << "/" << maxSessions << Qt::endl; + txtOut << "Address: " << serverAddress().toString() << Qt::endl; + txtOut << "Port: " << serverPort() << Qt::endl; + txtOut << "Working Path: " << QDir::currentPath() << Qt::endl; + txtOut << "SSL Chain: " << sslCertChain() << Qt::endl; + txtOut << "SSL Private: " << sslPrivKey() << Qt::endl << Qt::endl; + + printDatabaseInfo(txtOut); hostSharedMem->unlock(); - controlSocket->write(toTEXT(text)); + controlSocket->write(text.toUtf8()); } }