2019-09-06 23:43:07 -04:00
|
|
|
#include "common.h"
|
|
|
|
|
|
|
|
|
|
// This file is part of MRCI.
|
|
|
|
|
|
|
|
|
|
// MRCI is free software: you can redistribute it and/or modify
|
|
|
|
|
// it under the terms of the GNU General Public License as published by
|
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
// (at your option) any later version.
|
|
|
|
|
|
|
|
|
|
// MRCI is distributed in the hope that it will be useful,
|
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
// GNU General Public License for more details.
|
|
|
|
|
|
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
|
// along with MRCI under the LICENSE.md file. If not, see
|
|
|
|
|
// <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
2020-04-21 12:04:36 -04:00
|
|
|
QString sslCertChain()
|
|
|
|
|
{
|
|
|
|
|
return expandEnvVariables(qEnvironmentVariable(ENV_PUB_KEY, DEFAULT_PUB_KEY_NAME));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString sslPrivKey()
|
|
|
|
|
{
|
|
|
|
|
return expandEnvVariables(qEnvironmentVariable(ENV_PRIV_KEY, DEFAULT_PRIV_KEY_NAME));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QByteArray rdFileContents(const QString &path, QTextStream &msg)
|
|
|
|
|
{
|
|
|
|
|
QByteArray ret;
|
|
|
|
|
|
|
|
|
|
msg << "Reading file contents: '" << path << "' ";
|
|
|
|
|
|
|
|
|
|
QFile file(path);
|
|
|
|
|
|
|
|
|
|
if (file.open(QFile::ReadOnly))
|
|
|
|
|
{
|
|
|
|
|
ret = file.readAll();
|
|
|
|
|
|
|
|
|
|
if (!ret.isEmpty())
|
|
|
|
|
{
|
2020-07-04 11:37:46 -04:00
|
|
|
msg << "[pass]" << Qt::endl;
|
2020-04-21 12:04:36 -04:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2020-07-04 11:37:46 -04:00
|
|
|
msg << "[fail] (0 bytes of data was read from the file, is it empty?)" << Qt::endl;
|
2020-04-21 12:04:36 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2020-07-04 11:37:46 -04:00
|
|
|
msg << "[fail] (" << file.errorString() << ")" << Qt::endl;
|
2020-04-21 12:04:36 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
file.close();
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-06 23:43:07 -04:00
|
|
|
QString boolStr(bool state)
|
|
|
|
|
{
|
|
|
|
|
QString ret;
|
|
|
|
|
|
|
|
|
|
if (state) ret = "true";
|
|
|
|
|
else ret = "false";
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString genSerialNumber()
|
|
|
|
|
{
|
2019-11-08 22:06:09 -05:00
|
|
|
Serial::serialIndex++;
|
|
|
|
|
|
|
|
|
|
return QString::number(QDateTime::currentDateTime().toMSecsSinceEpoch()) + "-" + QString::number(Serial::serialIndex);
|
2019-09-06 23:43:07 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void serializeThread(QThread *thr)
|
|
|
|
|
{
|
|
|
|
|
thr->setObjectName(genSerialNumber());
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
quint32 toCmdId32(quint16 cmdId, quint16 branchId)
|
2019-09-06 23:43:07 -04:00
|
|
|
{
|
2019-11-08 22:06:09 -05:00
|
|
|
quint32 ret = 0;
|
|
|
|
|
quint32 *dst = &ret;
|
2019-09-06 23:43:07 -04:00
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
memcpy(dst, &cmdId, 2);
|
|
|
|
|
memcpy(dst + 2, &branchId, 2);
|
2019-09-06 23:43:07 -04:00
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
quint16 toCmdId16(quint32 id)
|
2019-09-06 23:43:07 -04:00
|
|
|
{
|
2019-11-08 22:06:09 -05:00
|
|
|
quint16 ret = 0;
|
2019-09-06 23:43:07 -04:00
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
memcpy(&ret, &id, 2);
|
2019-09-06 23:43:07 -04:00
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-09 12:21:33 -04:00
|
|
|
QByteArray toFixedTEXT(const QString &txt, int len)
|
2019-09-06 23:43:07 -04:00
|
|
|
{
|
2020-08-09 12:21:33 -04:00
|
|
|
return txt.toUtf8().leftJustified(len, 0, true);
|
2019-09-06 23:43:07 -04:00
|
|
|
}
|
|
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
QByteArray nullTermTEXT(const QString &txt)
|
2019-09-06 23:43:07 -04:00
|
|
|
{
|
2020-08-09 12:21:33 -04:00
|
|
|
return txt.toUtf8() + QByteArray(1, 0x00);
|
2019-09-06 23:43:07 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool noCaseMatch(const QString &strA, const QString &strB)
|
|
|
|
|
{
|
|
|
|
|
return strA.toLower() == strB.toLower();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool containsNewLine(const QString &str)
|
|
|
|
|
{
|
2020-08-09 12:21:33 -04:00
|
|
|
auto ret = false;
|
2019-09-06 23:43:07 -04:00
|
|
|
|
|
|
|
|
for (auto&& chr : str)
|
|
|
|
|
{
|
|
|
|
|
if (chr.category() == QChar::Other_Control)
|
|
|
|
|
{
|
|
|
|
|
ret = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool validSubId(const QString &num)
|
|
|
|
|
{
|
2020-08-09 12:21:33 -04:00
|
|
|
auto ret = false;
|
2019-09-06 23:43:07 -04:00
|
|
|
|
|
|
|
|
if (isInt(num))
|
|
|
|
|
{
|
|
|
|
|
ret = (num.toInt() >= 0) && (num.toInt() <= 255);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool validUserName(const QString &uName)
|
|
|
|
|
{
|
2020-08-09 12:21:33 -04:00
|
|
|
auto ret = false;
|
2019-09-06 23:43:07 -04:00
|
|
|
|
2020-08-09 12:21:33 -04:00
|
|
|
if ((uName.size() >= 2) && (uName.size() <= BLKSIZE_USER_NAME))
|
2019-09-06 23:43:07 -04:00
|
|
|
{
|
|
|
|
|
ret = !uName.contains(' ') && !containsNewLine(uName);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool validEmailAddr(const QString &email)
|
|
|
|
|
{
|
2020-08-09 12:21:33 -04:00
|
|
|
auto ret = false;
|
|
|
|
|
auto spEmail = email.split('@');
|
2019-09-06 23:43:07 -04:00
|
|
|
|
2020-08-09 12:21:33 -04:00
|
|
|
if ((spEmail.size() == 2) && (email.size() >= 4) && (email.size() <= BLKSIZE_EMAIL_ADDR))
|
2019-09-06 23:43:07 -04:00
|
|
|
{
|
|
|
|
|
if (!email.contains(' ') && !containsNewLine(email))
|
|
|
|
|
{
|
|
|
|
|
ret = (spEmail[1].split('.').size() > 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool validCommandName(const QString &name)
|
|
|
|
|
{
|
2019-11-08 22:06:09 -05:00
|
|
|
bool ret = false;
|
2019-09-06 23:43:07 -04:00
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
if ((name.size() >= 1) && (name.size() <= 64))
|
2019-09-06 23:43:07 -04:00
|
|
|
{
|
2019-11-08 22:06:09 -05:00
|
|
|
ret = !name.contains(' ') && !containsNewLine(name);
|
2019-09-06 23:43:07 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool validDispName(const QString &name)
|
|
|
|
|
{
|
2020-08-09 12:21:33 -04:00
|
|
|
return (name.size() <= BLKSIZE_DISP_NAME) && !containsNewLine(name);
|
2019-09-06 23:43:07 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool validChName(const QString &name)
|
|
|
|
|
{
|
|
|
|
|
bool ret = false;
|
|
|
|
|
|
|
|
|
|
if ((name.size() >= 4) && (name.size() <= 32))
|
|
|
|
|
{
|
|
|
|
|
ret = !name.contains(' ') && !containsNewLine(name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool validLevel(const QString &num, bool includePub)
|
|
|
|
|
{
|
|
|
|
|
bool ret = false;
|
|
|
|
|
|
|
|
|
|
if (isInt(num))
|
|
|
|
|
{
|
|
|
|
|
if (includePub)
|
|
|
|
|
{
|
|
|
|
|
ret = (num.toInt() >= 1) && (num.toInt() <= PUBLIC);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ret = (num.toInt() >= 1) && (num.toInt() <= REGULAR);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
bool validModPath(const QString &modPath)
|
|
|
|
|
{
|
2020-08-09 12:21:33 -04:00
|
|
|
auto ret = !modPath.isEmpty();
|
2019-11-08 22:06:09 -05:00
|
|
|
|
2020-08-09 12:21:33 -04:00
|
|
|
if (ret)
|
2019-11-08 22:06:09 -05:00
|
|
|
{
|
2020-08-09 12:21:33 -04:00
|
|
|
static const QString forbidden = "|*:\"?<>";
|
|
|
|
|
|
2019-11-16 13:08:02 -05:00
|
|
|
for (auto&& chr : forbidden)
|
2019-11-08 22:06:09 -05:00
|
|
|
{
|
2019-11-16 13:08:02 -05:00
|
|
|
if (modPath.contains(chr))
|
|
|
|
|
{
|
|
|
|
|
ret = false;
|
2019-11-08 22:06:09 -05:00
|
|
|
|
2019-11-16 13:08:02 -05:00
|
|
|
break;
|
|
|
|
|
}
|
2019-11-08 22:06:09 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-29 12:29:01 -05:00
|
|
|
bool acceptablePw(const QString &pw, const QString &uName, const QString &dispName, const QString &email, QString *errMsg)
|
|
|
|
|
{
|
|
|
|
|
auto ret = validPassword(pw);
|
|
|
|
|
|
|
|
|
|
if (!ret)
|
|
|
|
|
{
|
|
|
|
|
*errMsg = "err: Invalid password. it must be between 8-200 chars long containing numbers, mixed case letters and special chars.\n";
|
|
|
|
|
}
|
|
|
|
|
else if (ret && !email.isEmpty())
|
|
|
|
|
{
|
|
|
|
|
if (pw.contains(email, Qt::CaseInsensitive))
|
|
|
|
|
{
|
|
|
|
|
*errMsg = "err: Invalid password. it contains your email address.\n"; ret = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (ret && !uName.isEmpty())
|
|
|
|
|
{
|
|
|
|
|
if (pw.contains(uName, Qt::CaseInsensitive))
|
|
|
|
|
{
|
|
|
|
|
*errMsg = "err: Invalid password. it contains your user name.\n"; ret = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (ret && !dispName.isEmpty())
|
|
|
|
|
{
|
|
|
|
|
if (pw.contains(dispName, Qt::CaseInsensitive))
|
|
|
|
|
{
|
|
|
|
|
*errMsg = "err: Invalid password. it contains your display name.\n"; ret = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool acceptablePw(const QString &pw, const QByteArray &uId, QString *errMsg)
|
|
|
|
|
{
|
|
|
|
|
auto ret = false;
|
|
|
|
|
|
|
|
|
|
if (auth(uId, pw, TABLE_USERS))
|
|
|
|
|
{
|
|
|
|
|
*errMsg = "err: Invaild password. you cannot re-use your old password.\n";
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
Query db;
|
|
|
|
|
|
|
|
|
|
db.setType(Query::PULL, TABLE_USERS);
|
|
|
|
|
db.addColumn(COLUMN_EMAIL);
|
|
|
|
|
db.addColumn(COLUMN_USERNAME);
|
|
|
|
|
db.addColumn(COLUMN_DISPLAY_NAME);
|
|
|
|
|
db.addCondition(COLUMN_USER_ID, uId);
|
|
|
|
|
db.exec();
|
|
|
|
|
|
|
|
|
|
auto email = db.getData(COLUMN_EMAIL).toString();
|
|
|
|
|
auto uName = db.getData(COLUMN_USERNAME).toString();
|
|
|
|
|
auto dName = db.getData(COLUMN_DISPLAY_NAME).toString();
|
|
|
|
|
|
|
|
|
|
ret = acceptablePw(pw, uName, dName, email, errMsg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-06 23:43:07 -04:00
|
|
|
bool validPassword(const QString &pw)
|
|
|
|
|
{
|
|
|
|
|
bool ret = false;
|
|
|
|
|
|
|
|
|
|
if ((pw.size() >= 8) && (pw.size() <= 200))
|
|
|
|
|
{
|
|
|
|
|
bool letters = false;
|
|
|
|
|
bool numbers = false;
|
|
|
|
|
bool upper = false;
|
|
|
|
|
bool lower = false;
|
|
|
|
|
bool special = false;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < pw.size(); ++i)
|
|
|
|
|
{
|
|
|
|
|
if (pw[i].isLetter()) {letters = true; break;}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 0; (i < pw.size()) && letters; ++i)
|
|
|
|
|
{
|
|
|
|
|
if (pw[i].isNumber()) {numbers = true; break;}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 0; (i < pw.size()) && numbers; ++i)
|
|
|
|
|
{
|
|
|
|
|
if (pw[i].isUpper()) {upper = true; break;}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 0; (i < pw.size()) && upper; ++i)
|
|
|
|
|
{
|
|
|
|
|
if (pw[i].isLower()) {lower = true; break;}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 0; (i < pw.size()) && lower; ++i)
|
|
|
|
|
{
|
|
|
|
|
if (pw[i].isSymbol() || pw[i].isPunct()) {special = true; break;}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret = (letters && numbers && upper && lower && special);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool matchedFsObjTypes(const QString &pathA, const QString &pathB)
|
|
|
|
|
{
|
|
|
|
|
QFileInfo infoA(pathA);
|
|
|
|
|
QFileInfo infoB(pathB);
|
|
|
|
|
|
|
|
|
|
bool ret = false;
|
|
|
|
|
|
|
|
|
|
if (infoA.isSymLink()) ret = infoB.isSymLink();
|
|
|
|
|
else if (infoA.isFile()) ret = infoB.isFile();
|
|
|
|
|
else ret = infoB.isDir();
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool matchedVolume(const QString &pathA, const QString &pathB)
|
|
|
|
|
{
|
|
|
|
|
QFileInfo infoA(pathA);
|
|
|
|
|
QFileInfo infoB(pathB);
|
|
|
|
|
|
|
|
|
|
QStorageInfo storA(infoA.absolutePath());
|
|
|
|
|
QStorageInfo storB(infoB.absolutePath());
|
|
|
|
|
|
|
|
|
|
return storA.device() == storB.device();
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
bool userExists(const QString &uName, QByteArray *uId, QString *email)
|
2019-09-06 23:43:07 -04:00
|
|
|
{
|
|
|
|
|
Query db;
|
|
|
|
|
|
|
|
|
|
db.setType(Query::PULL, TABLE_USERS);
|
2019-11-08 22:06:09 -05:00
|
|
|
db.addColumn(COLUMN_USER_ID);
|
|
|
|
|
db.addColumn(COLUMN_EMAIL);
|
2019-09-06 23:43:07 -04:00
|
|
|
db.addCondition(COLUMN_USERNAME, uName);
|
|
|
|
|
db.exec();
|
|
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
if (db.rows() && (uId != nullptr))
|
|
|
|
|
{
|
|
|
|
|
*uId = db.getData(COLUMN_USER_ID).toByteArray();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (db.rows() && (email != nullptr))
|
|
|
|
|
{
|
|
|
|
|
*email = db.getData(COLUMN_EMAIL).toString();
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-06 23:43:07 -04:00
|
|
|
return db.rows();
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
bool recoverPWExists(const QByteArray &uId)
|
2019-09-06 23:43:07 -04:00
|
|
|
{
|
|
|
|
|
Query db;
|
|
|
|
|
|
|
|
|
|
db.setType(Query::PULL, TABLE_PW_RECOVERY);
|
2019-11-08 22:06:09 -05:00
|
|
|
db.addColumn(COLUMN_USER_ID);
|
|
|
|
|
db.addCondition(COLUMN_USER_ID, uId);
|
2019-09-06 23:43:07 -04:00
|
|
|
db.exec();
|
|
|
|
|
|
|
|
|
|
return db.rows();
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
bool emailExists(const QString &email, QByteArray *uId)
|
2019-09-06 23:43:07 -04:00
|
|
|
{
|
|
|
|
|
Query db;
|
|
|
|
|
|
|
|
|
|
db.setType(Query::PULL, TABLE_USERS);
|
2019-11-08 22:06:09 -05:00
|
|
|
db.addColumn(COLUMN_USER_ID);
|
2019-09-06 23:43:07 -04:00
|
|
|
db.addCondition(COLUMN_EMAIL, email);
|
|
|
|
|
db.exec();
|
|
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
if (db.rows() && (uId != nullptr))
|
|
|
|
|
{
|
|
|
|
|
*uId = db.getData(COLUMN_USER_ID).toByteArray();
|
|
|
|
|
}
|
2019-09-06 23:43:07 -04:00
|
|
|
|
|
|
|
|
return db.rows();
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
bool modExists(const QString &modPath)
|
2019-09-06 23:43:07 -04:00
|
|
|
{
|
|
|
|
|
Query db;
|
|
|
|
|
|
|
|
|
|
db.setType(Query::PULL, TABLE_MODULES);
|
2019-11-08 22:06:09 -05:00
|
|
|
db.addColumn(COLUMN_MOD_MAIN);
|
|
|
|
|
db.addCondition(COLUMN_MOD_MAIN, modPath);
|
2019-09-06 23:43:07 -04:00
|
|
|
db.exec();
|
|
|
|
|
|
|
|
|
|
return db.rows();
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-01 11:34:13 -04:00
|
|
|
bool rdOnlyFlagExists(quint64 chId, quint8 subId, quint32 level)
|
2019-09-06 23:43:07 -04:00
|
|
|
{
|
|
|
|
|
Query db;
|
|
|
|
|
|
|
|
|
|
db.setType(Query::PULL, TABLE_RDONLY_CAST);
|
|
|
|
|
db.addColumn(COLUMN_ACCESS_LEVEL);
|
|
|
|
|
db.addCondition(COLUMN_SUB_CH_ID, subId);
|
2020-04-01 11:34:13 -04:00
|
|
|
db.addCondition(COLUMN_CHANNEL_ID, chId);
|
2019-09-06 23:43:07 -04:00
|
|
|
db.addCondition(COLUMN_ACCESS_LEVEL, level);
|
|
|
|
|
db.exec();
|
|
|
|
|
|
|
|
|
|
return db.rows();
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
bool isLocked(const QByteArray &uId)
|
2019-09-06 23:43:07 -04:00
|
|
|
{
|
|
|
|
|
Query db;
|
|
|
|
|
|
|
|
|
|
db.setType(Query::PULL, TABLE_USERS);
|
|
|
|
|
db.addColumn(COLUMN_LOCKED);
|
2019-11-08 22:06:09 -05:00
|
|
|
db.addCondition(COLUMN_USER_ID, uId);
|
2019-09-06 23:43:07 -04:00
|
|
|
db.exec();
|
|
|
|
|
|
|
|
|
|
return db.getData(COLUMN_LOCKED).toBool();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool isBool(const QString &str)
|
|
|
|
|
{
|
|
|
|
|
bool ret = false;
|
|
|
|
|
int binary = str.toInt(&ret);
|
|
|
|
|
|
|
|
|
|
if (ret)
|
|
|
|
|
{
|
|
|
|
|
ret = (binary == 1) || (binary == 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool isInt(const QString &str)
|
|
|
|
|
{
|
|
|
|
|
bool ret;
|
|
|
|
|
|
|
|
|
|
str.toULongLong(&ret);
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-08 14:58:51 -04:00
|
|
|
bool matchAnyCh(const char *chsA, const char *chsB)
|
2019-09-06 23:43:07 -04:00
|
|
|
{
|
|
|
|
|
bool ret = false;
|
|
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
for (int i = 0; i < MAX_OPEN_SUB_CHANNELS; i += BLKSIZE_SUB_CHANNEL)
|
2019-09-06 23:43:07 -04:00
|
|
|
{
|
2020-03-08 14:58:51 -04:00
|
|
|
if (!isEmptyBlock(chsA + i, BLKSIZE_SUB_CHANNEL))
|
2019-09-06 23:43:07 -04:00
|
|
|
{
|
2020-03-08 14:58:51 -04:00
|
|
|
if (posOfBlock(chsA + i, chsB, MAX_OPEN_SUB_CHANNELS, BLKSIZE_SUB_CHANNEL) != -1)
|
|
|
|
|
{
|
|
|
|
|
ret = true;
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
2019-09-06 23:43:07 -04:00
|
|
|
|
2020-03-08 14:58:51 -04:00
|
|
|
bool fullMatchChs(const char *openChs, const char *comp)
|
|
|
|
|
{
|
|
|
|
|
bool ret = true;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < MAX_OPEN_SUB_CHANNELS; i += BLKSIZE_SUB_CHANNEL)
|
|
|
|
|
{
|
|
|
|
|
if (!isEmptyBlock(comp + i, BLKSIZE_SUB_CHANNEL))
|
|
|
|
|
{
|
|
|
|
|
if (posOfBlock(comp + i, openChs, MAX_OPEN_SUB_CHANNELS, BLKSIZE_SUB_CHANNEL) == -1)
|
|
|
|
|
{
|
|
|
|
|
ret = false;
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
2019-09-06 23:43:07 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
void containsActiveCh(const char *subChs, char *actBlock)
|
2019-09-06 23:43:07 -04:00
|
|
|
{
|
2019-11-08 22:06:09 -05:00
|
|
|
if (globalActiveFlag())
|
2019-09-06 23:43:07 -04:00
|
|
|
{
|
2019-11-08 22:06:09 -05:00
|
|
|
wr8BitToBlock(1, actBlock);
|
2019-09-06 23:43:07 -04:00
|
|
|
}
|
2019-11-08 22:06:09 -05:00
|
|
|
else
|
2019-09-06 23:43:07 -04:00
|
|
|
{
|
2019-11-08 22:06:09 -05:00
|
|
|
wr8BitToBlock(0, actBlock);
|
2019-09-06 23:43:07 -04:00
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
Query db;
|
2019-09-06 23:43:07 -04:00
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
for (int i = 0; i < MAX_OPEN_SUB_CHANNELS; i += BLKSIZE_SUB_CHANNEL)
|
2019-09-06 23:43:07 -04:00
|
|
|
{
|
2019-11-08 22:06:09 -05:00
|
|
|
quint64 chId = rd64BitFromBlock(subChs + i);
|
|
|
|
|
quint8 subId = rd8BitFromBlock(subChs + (i + 8));
|
2019-09-06 23:43:07 -04:00
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
db.setType(Query::PULL, TABLE_SUB_CHANNELS);
|
|
|
|
|
db.addColumn(COLUMN_CHANNEL_ID);
|
|
|
|
|
db.addCondition(COLUMN_CHANNEL_ID, chId);
|
|
|
|
|
db.addCondition(COLUMN_SUB_CH_ID, subId);
|
|
|
|
|
db.addCondition(COLUMN_ACTIVE_UPDATE, true);
|
|
|
|
|
db.exec();
|
|
|
|
|
|
|
|
|
|
if (db.rows())
|
|
|
|
|
{
|
|
|
|
|
wr8BitToBlock(1, actBlock);
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
2019-09-06 23:43:07 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-09 12:21:33 -04:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
QString defaultPw()
|
2019-09-06 23:43:07 -04:00
|
|
|
{
|
|
|
|
|
Query db;
|
|
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
db.setType(Query::PULL, TABLE_SERV_SETTINGS);
|
|
|
|
|
db.addColumn(COLUMN_DEFAULT_PASS);
|
2019-09-06 23:43:07 -04:00
|
|
|
db.exec();
|
|
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
return db.getData(COLUMN_DEFAULT_PASS).toString();
|
2019-09-06 23:43:07 -04:00
|
|
|
}
|
|
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
bool channelExists(const QString &chName, quint64 *chId)
|
2019-09-06 23:43:07 -04:00
|
|
|
{
|
|
|
|
|
Query db;
|
|
|
|
|
|
|
|
|
|
db.setType(Query::PULL, TABLE_CHANNELS);
|
2019-11-08 22:06:09 -05:00
|
|
|
db.addColumn(COLUMN_CHANNEL_ID);
|
2019-09-06 23:43:07 -04:00
|
|
|
db.addCondition(COLUMN_CHANNEL_NAME, chName);
|
|
|
|
|
db.exec();
|
|
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
if (db.rows() && (chId != nullptr))
|
|
|
|
|
{
|
|
|
|
|
*chId = db.getData(COLUMN_CHANNEL_ID).toULongLong();
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-06 23:43:07 -04:00
|
|
|
return db.rows();
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
bool channelSubExists(quint64 chId, const QString &sub, quint8 *subId)
|
2019-09-06 23:43:07 -04:00
|
|
|
{
|
|
|
|
|
Query db;
|
|
|
|
|
|
|
|
|
|
db.setType(Query::PULL, TABLE_SUB_CHANNELS);
|
|
|
|
|
db.addColumn(COLUMN_SUB_CH_ID);
|
|
|
|
|
db.addCondition(COLUMN_CHANNEL_ID, chId);
|
|
|
|
|
db.addCondition(COLUMN_SUB_CH_NAME, sub);
|
|
|
|
|
db.exec();
|
|
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
if (db.rows() && (subId != nullptr))
|
|
|
|
|
{
|
|
|
|
|
*subId = static_cast<quint8>(db.getData(COLUMN_SUB_CH_ID).toUInt());
|
|
|
|
|
}
|
2019-09-06 23:43:07 -04:00
|
|
|
|
|
|
|
|
return db.rows();
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
bool inviteExists(const QByteArray &uId, quint64 chId)
|
2019-09-06 23:43:07 -04:00
|
|
|
{
|
|
|
|
|
Query db;
|
|
|
|
|
|
|
|
|
|
db.setType(Query::PULL, TABLE_CH_MEMBERS);
|
2019-11-08 22:06:09 -05:00
|
|
|
db.addColumn(COLUMN_CHANNEL_ID);
|
|
|
|
|
db.addCondition(COLUMN_CHANNEL_ID, chId);
|
|
|
|
|
db.addCondition(COLUMN_USER_ID, uId);
|
|
|
|
|
db.addCondition(COLUMN_PENDING_INVITE, true);
|
2019-09-06 23:43:07 -04:00
|
|
|
db.exec();
|
|
|
|
|
|
|
|
|
|
return db.rows();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool globalActiveFlag()
|
|
|
|
|
{
|
|
|
|
|
Query db;
|
|
|
|
|
|
|
|
|
|
db.setType(Query::PULL, TABLE_SERV_SETTINGS);
|
|
|
|
|
db.addColumn(COLUMN_ACTIVE_UPDATE);
|
|
|
|
|
db.exec();
|
|
|
|
|
|
|
|
|
|
return db.getData(COLUMN_ACTIVE_UPDATE).toBool();
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
bool genSubId(quint64 chId, quint8 *newId)
|
2019-09-06 23:43:07 -04:00
|
|
|
{
|
|
|
|
|
bool ret = false;
|
|
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
Query db;
|
|
|
|
|
|
|
|
|
|
db.setType(Query::PULL, TABLE_SUB_CHANNELS);
|
|
|
|
|
db.addColumn(COLUMN_SUB_CH_ID);
|
|
|
|
|
db.addCondition(COLUMN_CHANNEL_ID, chId);
|
|
|
|
|
db.exec();
|
|
|
|
|
|
|
|
|
|
if (db.rows() < maxSubChannels())
|
2019-09-06 23:43:07 -04:00
|
|
|
{
|
2019-11-08 22:06:09 -05:00
|
|
|
QList<quint8> subList;
|
2019-09-06 23:43:07 -04:00
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
for (int i = 0; i < db.rows(); ++i)
|
2019-09-06 23:43:07 -04:00
|
|
|
{
|
2019-11-08 22:06:09 -05:00
|
|
|
subList.append(static_cast<quint8>(db.getData(COLUMN_SUB_CH_ID, i).toUInt()));
|
2019-09-06 23:43:07 -04:00
|
|
|
}
|
|
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
ret = true;
|
|
|
|
|
*newId = 0;
|
2019-09-06 23:43:07 -04:00
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
while (subList.contains(*newId)) *newId += 1;
|
2019-09-06 23:43:07 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
bool isChOwner(const QByteArray &uId)
|
2019-09-06 23:43:07 -04:00
|
|
|
{
|
|
|
|
|
Query db;
|
|
|
|
|
|
|
|
|
|
db.setType(Query::PULL, TABLE_CH_MEMBERS);
|
2019-11-08 22:06:09 -05:00
|
|
|
db.addColumn(COLUMN_USER_ID);
|
|
|
|
|
db.addCondition(COLUMN_USER_ID, uId);
|
2019-09-06 23:43:07 -04:00
|
|
|
db.addCondition(COLUMN_PENDING_INVITE, false);
|
|
|
|
|
db.addCondition(COLUMN_ACCESS_LEVEL, OWNER);
|
|
|
|
|
db.exec();
|
|
|
|
|
|
|
|
|
|
return db.rows();
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
int maxSubChannels()
|
2019-09-06 23:43:07 -04:00
|
|
|
{
|
|
|
|
|
Query db;
|
|
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
db.setType(Query::PULL, TABLE_SERV_SETTINGS);
|
|
|
|
|
db.addColumn(COLUMN_MAX_SUB_CH);
|
2019-09-06 23:43:07 -04:00
|
|
|
db.exec();
|
|
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
return db.getData(COLUMN_MAX_SUB_CH).toInt();
|
2019-09-06 23:43:07 -04:00
|
|
|
}
|
|
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
int channelAccessLevel(const QByteArray &uId, const char *override, quint64 chId)
|
2019-09-06 23:43:07 -04:00
|
|
|
{
|
2019-11-08 22:06:09 -05:00
|
|
|
if (rd8BitFromBlock(override) == 1)
|
2019-09-06 23:43:07 -04:00
|
|
|
{
|
|
|
|
|
return OWNER;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2019-11-08 22:06:09 -05:00
|
|
|
return channelAccessLevel(uId, chId);
|
2019-09-06 23:43:07 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
int channelAccessLevel(const QByteArray &uId, quint64 chId)
|
2019-09-06 23:43:07 -04:00
|
|
|
{
|
|
|
|
|
Query db;
|
|
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
db.setType(Query::PULL, TABLE_CH_MEMBERS);
|
|
|
|
|
db.addColumn(COLUMN_ACCESS_LEVEL);
|
2019-09-06 23:43:07 -04:00
|
|
|
db.addCondition(COLUMN_CHANNEL_ID, chId);
|
2019-11-08 22:06:09 -05:00
|
|
|
db.addCondition(COLUMN_USER_ID, uId);
|
|
|
|
|
db.addCondition(COLUMN_PENDING_INVITE, false);
|
2019-09-06 23:43:07 -04:00
|
|
|
db.exec();
|
|
|
|
|
|
|
|
|
|
if (db.rows())
|
|
|
|
|
{
|
2019-11-08 22:06:09 -05:00
|
|
|
return db.getData(COLUMN_ACCESS_LEVEL).toInt();
|
2019-09-06 23:43:07 -04:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2019-11-08 22:06:09 -05:00
|
|
|
return PUBLIC;
|
2019-09-06 23:43:07 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void listDir(QList<QPair<QString, QString> > &list, const QString &srcPath, const QString &dstPath)
|
|
|
|
|
{
|
|
|
|
|
QDir dir(srcPath);
|
|
|
|
|
|
|
|
|
|
dir.setFilter(QDir::AllEntries | QDir::Hidden | QDir::NoDotAndDotDot);
|
|
|
|
|
dir.setSorting(QDir::DirsFirst);
|
|
|
|
|
|
|
|
|
|
QStringList ls = dir.entryList();
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < ls.size(); ++i)
|
|
|
|
|
{
|
|
|
|
|
QPair<QString,QString> srcToDst(srcPath + "/" + ls[i], dstPath + "/" + ls[i]);
|
|
|
|
|
|
|
|
|
|
list.append(srcToDst);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
QString getUserNameForEmail(const QString &email)
|
2019-09-06 23:43:07 -04:00
|
|
|
{
|
|
|
|
|
Query db;
|
|
|
|
|
|
|
|
|
|
db.setType(Query::PULL, TABLE_USERS);
|
2019-11-08 22:06:09 -05:00
|
|
|
db.addColumn(COLUMN_USERNAME);
|
|
|
|
|
db.addCondition(COLUMN_EMAIL, email);
|
2019-09-06 23:43:07 -04:00
|
|
|
db.exec();
|
|
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
return db.getData(COLUMN_USERNAME).toString();
|
2019-09-06 23:43:07 -04:00
|
|
|
}
|
|
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
QString getDispName(const QByteArray &uId)
|
2019-09-06 23:43:07 -04:00
|
|
|
{
|
|
|
|
|
Query db;
|
|
|
|
|
|
|
|
|
|
db.setType(Query::PULL, TABLE_USERS);
|
2019-11-08 22:06:09 -05:00
|
|
|
db.addColumn(COLUMN_DISPLAY_NAME);
|
|
|
|
|
db.addCondition(COLUMN_USER_ID, uId);
|
2019-09-06 23:43:07 -04:00
|
|
|
db.exec();
|
|
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
return db.getData(COLUMN_DISPLAY_NAME).toString();
|
2019-09-06 23:43:07 -04:00
|
|
|
}
|
|
|
|
|
|
2020-01-29 12:29:01 -05:00
|
|
|
QString getUserName(const QByteArray &uId)
|
|
|
|
|
{
|
|
|
|
|
Query db;
|
|
|
|
|
|
|
|
|
|
db.setType(Query::PULL, TABLE_USERS);
|
|
|
|
|
db.addColumn(COLUMN_USERNAME);
|
|
|
|
|
db.addCondition(COLUMN_USER_ID, uId);
|
|
|
|
|
db.exec();
|
|
|
|
|
|
|
|
|
|
return db.getData(COLUMN_USERNAME).toString();
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
QString getEmailForUser(const QByteArray &uId)
|
2019-09-06 23:43:07 -04:00
|
|
|
{
|
|
|
|
|
Query db;
|
|
|
|
|
|
|
|
|
|
db.setType(Query::PULL, TABLE_USERS);
|
|
|
|
|
db.addColumn(COLUMN_EMAIL);
|
2019-11-08 22:06:09 -05:00
|
|
|
db.addCondition(COLUMN_USER_ID, uId);
|
2019-09-06 23:43:07 -04:00
|
|
|
db.exec();
|
|
|
|
|
|
|
|
|
|
return db.getData(COLUMN_EMAIL).toString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString escapeChars(const QString &str, const QChar &escapeChr, const QChar &chr)
|
|
|
|
|
{
|
|
|
|
|
QString ret;
|
|
|
|
|
bool escaped = false;
|
|
|
|
|
|
|
|
|
|
if (escapeChr == chr)
|
|
|
|
|
{
|
|
|
|
|
ret = str;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
for (auto&& strChr : str)
|
|
|
|
|
{
|
|
|
|
|
if ((strChr == chr) && !escaped)
|
|
|
|
|
{
|
|
|
|
|
ret.append(escapeChr);
|
|
|
|
|
ret.append(strChr);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
escaped = false;
|
|
|
|
|
|
|
|
|
|
if (strChr == escapeChr)
|
|
|
|
|
{
|
|
|
|
|
escaped = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret.append(strChr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void mkPath(const QString &path)
|
|
|
|
|
{
|
|
|
|
|
if (!QDir().exists(path))
|
|
|
|
|
{
|
|
|
|
|
QDir().mkpath(path);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QStringList parseArgs(const QByteArray &data, int maxArgs, int *pos)
|
|
|
|
|
{
|
|
|
|
|
QStringList ret;
|
|
|
|
|
QString arg;
|
2020-08-09 12:21:33 -04:00
|
|
|
|
|
|
|
|
auto line = QString::fromUtf8(data);
|
|
|
|
|
auto inDQuotes = false;
|
|
|
|
|
auto inSQuotes = false;
|
|
|
|
|
auto escaped = false;
|
2019-09-06 23:43:07 -04:00
|
|
|
|
|
|
|
|
if (pos != nullptr) *pos = 0;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < line.size(); ++i)
|
|
|
|
|
{
|
2020-08-09 12:21:33 -04:00
|
|
|
if (pos != nullptr) *pos += 1;
|
2019-09-06 23:43:07 -04:00
|
|
|
|
|
|
|
|
if ((line[i] == '\'') && !inDQuotes && !escaped)
|
|
|
|
|
{
|
|
|
|
|
// single quote '
|
|
|
|
|
|
|
|
|
|
inSQuotes = !inSQuotes;
|
|
|
|
|
}
|
|
|
|
|
else if ((line[i] == '\"') && !inSQuotes && !escaped)
|
|
|
|
|
{
|
|
|
|
|
// double quote "
|
|
|
|
|
|
|
|
|
|
inDQuotes = !inDQuotes;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
escaped = false;
|
|
|
|
|
|
|
|
|
|
if (line[i].isSpace() && !inDQuotes && !inSQuotes)
|
|
|
|
|
{
|
|
|
|
|
// space
|
|
|
|
|
|
|
|
|
|
if (!arg.isEmpty())
|
|
|
|
|
{
|
|
|
|
|
ret.append(arg);
|
|
|
|
|
arg.clear();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if ((line[i] == '\\') && ((i + 1) < line.size()))
|
|
|
|
|
{
|
|
|
|
|
if ((line[i + 1] == '\'') || (line[i + 1] == '\"'))
|
|
|
|
|
{
|
|
|
|
|
escaped = true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
arg.append(line[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
arg.append(line[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((ret.size() >= maxArgs) && (maxArgs != -1))
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!arg.isEmpty() && !inDQuotes && !inSQuotes)
|
|
|
|
|
{
|
|
|
|
|
ret.append(arg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString getParam(const QString &key, const QStringList &args)
|
|
|
|
|
{
|
|
|
|
|
// this can be used by command objects to pick out parameters
|
|
|
|
|
// from a command line that are pointed by a name identifier
|
|
|
|
|
// example: -i /etc/some_file, this function should pick out
|
|
|
|
|
// "/etc/some_file" from args if "-i" is passed into key.
|
|
|
|
|
|
|
|
|
|
QString ret;
|
|
|
|
|
|
|
|
|
|
int pos = args.indexOf(QRegExp(key, Qt::CaseInsensitive));
|
|
|
|
|
|
|
|
|
|
if (pos != -1)
|
|
|
|
|
{
|
|
|
|
|
// key found.
|
|
|
|
|
|
|
|
|
|
if ((pos + 1) <= (args.size() - 1))
|
|
|
|
|
{
|
|
|
|
|
// check ahead to make sure pos + 1 will not go out
|
|
|
|
|
// of range.
|
|
|
|
|
|
|
|
|
|
if (!args[pos + 1].startsWith("-"))
|
|
|
|
|
{
|
|
|
|
|
// the "-" used throughout this application
|
|
|
|
|
// indicates an argument so the above 'if'
|
|
|
|
|
// statement will check to make sure it does
|
|
|
|
|
// not return another argument as a parameter
|
|
|
|
|
// in case a back-to-back "-arg -arg" is
|
|
|
|
|
// present.
|
|
|
|
|
|
|
|
|
|
ret = args[pos + 1];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool argExists(const QString &key, const QStringList &args)
|
|
|
|
|
{
|
|
|
|
|
return args.contains(key, Qt::CaseInsensitive);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SessionCarrier::SessionCarrier(Session *session) : QObject()
|
|
|
|
|
{
|
|
|
|
|
sessionObj = session;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
IdleTimer::IdleTimer(QObject *parent) : QTimer(parent)
|
2019-09-06 23:43:07 -04:00
|
|
|
{
|
2019-11-08 22:06:09 -05:00
|
|
|
setSingleShot(true);
|
2019-09-06 23:43:07 -04:00
|
|
|
}
|
|
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
void IdleTimer::detectWrite(qint64)
|
2019-09-06 23:43:07 -04:00
|
|
|
{
|
2019-11-08 22:06:09 -05:00
|
|
|
start();
|
2019-09-06 23:43:07 -04:00
|
|
|
}
|
|
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
void IdleTimer::attach(QIODevice *dev, int msec)
|
2019-09-06 23:43:07 -04:00
|
|
|
{
|
2019-11-08 22:06:09 -05:00
|
|
|
setInterval(msec);
|
2019-09-06 23:43:07 -04:00
|
|
|
|
2019-11-08 22:06:09 -05:00
|
|
|
connect(dev, SIGNAL(readyRead()), this, SLOT(start()));
|
|
|
|
|
connect(dev, SIGNAL(bytesWritten(qint64)), this, SLOT(detectWrite(qint64)));
|
2019-09-06 23:43:07 -04:00
|
|
|
}
|
|
|
|
|
|
2020-08-09 12:21:33 -04:00
|
|
|
ShellIPC::ShellIPC(const QStringList &args, bool supressErr, QObject *parent) : QLocalSocket(parent)
|
2019-09-06 23:43:07 -04:00
|
|
|
{
|
|
|
|
|
arguments = args;
|
2020-08-09 12:21:33 -04:00
|
|
|
holdErrs = supressErr;
|
2019-09-06 23:43:07 -04:00
|
|
|
|
|
|
|
|
connect(this, SIGNAL(connected()), this, SLOT(hostConnected()));
|
|
|
|
|
connect(this, SIGNAL(disconnected()), this, SIGNAL(closeInstance()));
|
|
|
|
|
connect(this, SIGNAL(readyRead()), this, SLOT(dataIn()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ShellIPC::connectToHost()
|
|
|
|
|
{
|
2020-08-09 12:21:33 -04:00
|
|
|
auto pipeInfo = QFileInfo(QDir::tempPath() + "/" + HOST_CONTROL_PIPE);
|
2019-09-06 23:43:07 -04:00
|
|
|
|
2020-08-09 12:21:33 -04:00
|
|
|
if (!pipeInfo.exists())
|
2019-09-06 23:43:07 -04:00
|
|
|
{
|
2020-08-09 12:21:33 -04:00
|
|
|
if (!holdErrs)
|
2020-01-29 12:29:01 -05:00
|
|
|
{
|
2020-08-09 12:21:33 -04:00
|
|
|
QTextStream(stdout) << "" << Qt::endl << "A host instance is not running." << Qt::endl << Qt::endl;
|
2020-01-29 12:29:01 -05:00
|
|
|
}
|
2020-08-09 12:21:33 -04:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
connectToServer(HOST_CONTROL_PIPE);
|
|
|
|
|
|
|
|
|
|
if (!waitForConnected() && !holdErrs)
|
2020-01-29 12:29:01 -05:00
|
|
|
{
|
2020-08-09 12:21:33 -04:00
|
|
|
QTextStream(stdout) << "" << Qt::endl << "err: Failed to connect to the host instance control pipe." << Qt::endl;
|
|
|
|
|
QTextStream(stdout) << "err: Reason - " << errorString() << Qt::endl;
|
2020-01-29 12:29:01 -05:00
|
|
|
}
|
2019-09-06 23:43:07 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return state() == QLocalSocket::ConnectedState;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ShellIPC::hostConnected()
|
|
|
|
|
{
|
2020-08-09 12:21:33 -04:00
|
|
|
write(arguments.join(' ').toUtf8());
|
2019-09-06 23:43:07 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ShellIPC::dataIn()
|
|
|
|
|
{
|
2020-08-09 12:21:33 -04:00
|
|
|
QTextStream(stdout) << QString::fromUtf8(readAll());
|
2019-09-06 23:43:07 -04:00
|
|
|
|
|
|
|
|
emit closeInstance();
|
|
|
|
|
}
|
2019-11-08 22:06:09 -05:00
|
|
|
|
|
|
|
|
quint64 Serial::serialIndex = 0;
|