2023-05-30 23:04:03 +00:00
|
|
|
|
module daster;
|
|
|
|
|
|
|
|
|
|
import vibe.vibe;
|
|
|
|
|
import singlog;
|
|
|
|
|
import readconf;
|
|
|
|
|
|
|
|
|
|
import core.stdc.stdlib : exit, EXIT_SUCCESS, EXIT_FAILURE;
|
|
|
|
|
import std.stdio: writefln;
|
|
|
|
|
import std.getopt;
|
|
|
|
|
import std.file;
|
|
|
|
|
import std.path;
|
|
|
|
|
import std.algorithm;
|
|
|
|
|
import std.array;
|
|
|
|
|
|
|
|
|
|
import verinfo;
|
|
|
|
|
import pgdb;
|
|
|
|
|
import structures;
|
|
|
|
|
|
|
|
|
|
import requests.listsgroups;
|
|
|
|
|
import requests.groupnumbers;
|
2023-05-31 22:10:08 +00:00
|
|
|
|
import requests.editnumber;
|
2023-06-01 21:36:21 +00:00
|
|
|
|
import requests.updatenumber;
|
|
|
|
|
import requests.addnumber;
|
|
|
|
|
import requests.delnumber;
|
|
|
|
|
import requests.writenumber;
|
2023-06-02 23:28:18 +00:00
|
|
|
|
import requests.smsnumbers;
|
|
|
|
|
import requests.listsms;
|
|
|
|
|
import requests.viewsms;
|
|
|
|
|
import requests.delsms;
|
2023-05-30 23:04:03 +00:00
|
|
|
|
|
|
|
|
|
static ServerInfo serverInfo;
|
|
|
|
|
|
|
|
|
|
private void showVersion() {
|
|
|
|
|
writefln("daster версия %s, собрано %s", getDasterVersion(), __DATE__);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int main(string[] args) {
|
|
|
|
|
log.level(log.INFORMATION);
|
|
|
|
|
log.output(log.SYSLOG);
|
|
|
|
|
|
|
|
|
|
bool flagVersion;
|
|
|
|
|
string flagSettings;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
auto opt = getopt(
|
|
|
|
|
args,
|
|
|
|
|
config.bundling,
|
|
|
|
|
config.caseSensitive,
|
|
|
|
|
"settings|s",
|
|
|
|
|
"<файл> Путь к файлу конфигурации settings.conf",
|
|
|
|
|
&flagSettings,
|
|
|
|
|
"version|v",
|
|
|
|
|
"Текущая версия программы",
|
|
|
|
|
&flagVersion
|
|
|
|
|
);
|
|
|
|
|
if (opt.helpWanted) {
|
|
|
|
|
showVersion();
|
|
|
|
|
defaultGetoptPrinter(
|
|
|
|
|
"Использование: daster [ОПЦИИ]...\n",
|
|
|
|
|
opt.options
|
|
|
|
|
);
|
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
if (flagVersion) {
|
|
|
|
|
showVersion();
|
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
} catch (GetOptException e) {
|
|
|
|
|
showVersion();
|
|
|
|
|
log.c(e.msg);
|
|
|
|
|
log.i("Попробуйте 'daster -h' для дополнительной информации");
|
|
|
|
|
log.i("https://git.zhirov.kz/alexander/daster");
|
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!flagSettings.length)
|
|
|
|
|
flagSettings = "./settings.conf";
|
|
|
|
|
|
|
|
|
|
if (!flagSettings.exists) {
|
|
|
|
|
log.c("Файл конфигурации не найден: " ~ flagSettings);
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rc.read(flagSettings);
|
|
|
|
|
rcAsteriskDB();
|
|
|
|
|
auto webHost = rcWebHost();
|
|
|
|
|
|
|
|
|
|
serverInfo = ServerInfo(webHost.title);
|
|
|
|
|
|
|
|
|
|
if (webHost.loglevel != -1) log.level(webHost.loglevel);
|
|
|
|
|
if (webHost.logoutput) log.output(webHost.logoutput);
|
|
|
|
|
if (webHost.logfile.length) log.file(webHost.logfile);
|
|
|
|
|
|
|
|
|
|
auto router = new URLRouter;
|
|
|
|
|
router.post("/", &postReq);
|
|
|
|
|
router.get("/", &getReq);
|
|
|
|
|
router.get("*", serveStaticFiles(buildPath(webHost.data, "public")));
|
|
|
|
|
router.get("*", serveStaticFiles(buildPath(webHost.data, "images")));
|
|
|
|
|
router.get("*", serveStaticFiles(buildPath(webHost.data, "js")));
|
|
|
|
|
router.get("*", serveStaticFiles(buildPath(webHost.data, "jq")));
|
|
|
|
|
|
|
|
|
|
auto memorySessionStore = new MemorySessionStore;
|
|
|
|
|
|
|
|
|
|
auto settingsHTTP = new HTTPServerSettings;
|
|
|
|
|
auto settingsHTTPS = new HTTPServerSettings;
|
|
|
|
|
|
|
|
|
|
if (webHost.http) {
|
|
|
|
|
settingsHTTP.sessionStore = memorySessionStore;
|
|
|
|
|
settingsHTTP.port = webHost.http;
|
|
|
|
|
settingsHTTP.bindAddresses = ["::1"] ~ webHost.addresses;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (webHost.https) {
|
|
|
|
|
settingsHTTPS.sessionStore = memorySessionStore;
|
|
|
|
|
settingsHTTPS.port = webHost.https;
|
|
|
|
|
settingsHTTPS.bindAddresses = ["::1"] ~ webHost.addresses;
|
|
|
|
|
settingsHTTPS.tlsContext = createTLSContext(TLSContextKind.server);
|
|
|
|
|
settingsHTTPS.tlsContext.useCertificateChainFile(webHost.cert);
|
|
|
|
|
settingsHTTPS.tlsContext.usePrivateKeyFile(webHost.key);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
startWebServer(webHost, settingsHTTP, settingsHTTPS, router);
|
|
|
|
|
|
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void startWebServer(WebHost wh, HTTPServerSettings http, HTTPServerSettings https, URLRouter router)
|
|
|
|
|
{
|
|
|
|
|
if (wh.http && wh.https) {
|
|
|
|
|
auto listenerHTTP = listenHTTP(http, router);
|
|
|
|
|
auto listenerHTTPS = listenHTTP(https, router);
|
|
|
|
|
scope (exit) { listenerHTTP.stopListening(); }
|
|
|
|
|
scope (exit) { listenerHTTPS.stopListening(); }
|
|
|
|
|
runApplication();
|
|
|
|
|
} else if (wh.http) {
|
|
|
|
|
auto listenerHTTP = listenHTTP(http, router);
|
|
|
|
|
scope (exit) { listenerHTTP.stopListening(); }
|
|
|
|
|
runApplication();
|
|
|
|
|
} else if (wh.https) {
|
|
|
|
|
auto listenerHTTPS = listenHTTP(https, router);
|
|
|
|
|
scope (exit) { listenerHTTPS.stopListening(); }
|
|
|
|
|
runApplication();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void getReq(HTTPServerRequest req, HTTPServerResponse res) {
|
|
|
|
|
// if (req.session) {
|
|
|
|
|
// auto user = req.session.get!UserData("userData");
|
|
|
|
|
// if (user.loggedIn) {
|
|
|
|
|
// renderMainPage(req, res);
|
|
|
|
|
// return;
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// render!("index.dt", serverInfo)(res);
|
|
|
|
|
renderMainPage(req, res);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void renderMainPage(HTTPServerRequest req, HTTPServerResponse res) {
|
|
|
|
|
render!("index.dt", serverInfo)(res);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void postReq(HTTPServerRequest req, HTTPServerResponse res) {
|
|
|
|
|
if (req.method != HTTPMethod.POST) return;
|
|
|
|
|
|
|
|
|
|
auto jsr = req.json;
|
|
|
|
|
string query = jsr["query"].get!string;
|
|
|
|
|
|
|
|
|
|
if (query.empty) return;
|
|
|
|
|
|
|
|
|
|
// if (query != "authorization" && !checkAuth(req)) {
|
|
|
|
|
// res.send(
|
|
|
|
|
// true,
|
|
|
|
|
// "Сессия не существует. Перезагрузите страницу"
|
|
|
|
|
// );
|
|
|
|
|
// return;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
switch (query) {
|
|
|
|
|
case "listsgroups":
|
2023-05-31 22:10:08 +00:00
|
|
|
|
listsGroups(req, res);
|
2023-05-30 23:04:03 +00:00
|
|
|
|
break;
|
|
|
|
|
case "groupnumbers":
|
2023-05-31 22:10:08 +00:00
|
|
|
|
groupNumbers(req, res);
|
2023-05-30 23:04:03 +00:00
|
|
|
|
break;
|
|
|
|
|
// case "authorization":
|
|
|
|
|
// authorization(req, res);
|
|
|
|
|
// break;
|
|
|
|
|
// case "logout":
|
|
|
|
|
// logout(req, res);
|
|
|
|
|
// break;
|
2023-06-01 21:36:21 +00:00
|
|
|
|
case "addnumber":
|
|
|
|
|
addNumber(req, res);
|
|
|
|
|
break;
|
|
|
|
|
case "writenumber":
|
|
|
|
|
writeNumber(req, res);
|
|
|
|
|
break;
|
2023-05-31 22:10:08 +00:00
|
|
|
|
case "editnumber":
|
|
|
|
|
editNumber(req, res);
|
|
|
|
|
break;
|
2023-06-01 21:36:21 +00:00
|
|
|
|
case "updatenumber":
|
|
|
|
|
updateNumber(req, res);
|
|
|
|
|
break;
|
|
|
|
|
case "delnumber":
|
|
|
|
|
delNumber(req, res);
|
|
|
|
|
break;
|
2023-06-02 23:28:18 +00:00
|
|
|
|
case "smsnumbers":
|
|
|
|
|
smsNumbers(req, res);
|
|
|
|
|
break;
|
|
|
|
|
case "listsms":
|
|
|
|
|
listSMS(req, res);
|
|
|
|
|
break;
|
|
|
|
|
case "viewsms":
|
|
|
|
|
viewSMS(req, res);
|
|
|
|
|
break;
|
|
|
|
|
case "delsms":
|
|
|
|
|
delSMS(req, res);
|
|
|
|
|
break;
|
2023-05-30 23:04:03 +00:00
|
|
|
|
default:
|
|
|
|
|
res.redirect("/");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void rcAsteriskDB() {
|
|
|
|
|
ConfigSection asteriskDB;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
asteriskDB = rc[]["daster-db"];
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.c("В конфигурационном файле не верны настройки daster-db");
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (asteriskDB["host"].empty) {
|
|
|
|
|
log.c("В конфигурационном файле не верны настройки daster-db.host");
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (asteriskDB["port"].empty) {
|
|
|
|
|
log.c("В конфигурационном файле не верны настройки daster-db.port");
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (asteriskDB["dbname"].empty) {
|
|
|
|
|
log.c("В конфигурационном файле не верны настройки daster-db.dbname");
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (asteriskDB["user"].empty) {
|
|
|
|
|
log.c("В конфигурационном файле не верны настройки daster-db.user");
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
pgsql(
|
|
|
|
|
"hostaddr=" ~ asteriskDB["host"] ~
|
|
|
|
|
" port=" ~ asteriskDB["port"] ~
|
|
|
|
|
" dbname=" ~ asteriskDB["dbname"] ~
|
|
|
|
|
" user=" ~ asteriskDB["user"] ~
|
|
|
|
|
" password=" ~ asteriskDB["password"]
|
|
|
|
|
);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.c(e);
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WebHost rcWebHost() {
|
|
|
|
|
WebHost wh;
|
|
|
|
|
ConfigSection webHost;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
webHost = rc[]["web-host"];
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.c("В конфигурационном файле не верны настройки web-host");
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (webHost["addresses"].empty) {
|
|
|
|
|
log.c("В конфигурационном файле не верны настройки web-host.addresses");
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
wh.addresses = webHost["addresses"].to!string.split(',').map!(a => a.strip).array;
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.c("В конфигурационном файле не верны настройки web-host.addresses");
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (webHost["http"].empty && webHost["https"].empty) {
|
|
|
|
|
log.c("В конфигурационном файле не верны настройки web-host.[http|https]:
|
|
|
|
|
должен быть указан хотя бы один протокол");
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!webHost["http"].empty) {
|
|
|
|
|
try {
|
|
|
|
|
wh.http = webHost["http"].to!ushort;
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.c("В конфигурационном файле не верны настройки web-host.http");
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!webHost["https"].empty) {
|
|
|
|
|
try {
|
|
|
|
|
wh.https = webHost["https"].to!ushort;
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.c("В конфигурационном файле не верны настройки web-host.https");
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!webHost["https"].empty) {
|
|
|
|
|
if (webHost["cert"].empty || webHost["key"].empty) {
|
|
|
|
|
log.c("В конфигурационном файле не верны настройки web-host.[cert|key]:
|
|
|
|
|
необходимо указать сертификат и ключ для использования https протокола"
|
|
|
|
|
);
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
wh.cert = webHost["cert"];
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.c("В конфигурационном файле не верны настройки web-host.cert");
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
wh.key = webHost["key"];
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.c("В конфигурационном файле не верны настройки web-host.key");
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!webHost["data"].empty) {
|
|
|
|
|
string data;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
data = webHost["data"];
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.c("В конфигурационном файле не верны настройки web-host.data");
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (data.exists) {
|
|
|
|
|
if (!buildPath(data, "public").exists) {
|
|
|
|
|
log.c("В конфигурационном файле не верны настройки web-host.data - каталог не существует: public");
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
if (!buildPath(data, "js").exists) {
|
|
|
|
|
log.c("В конфигурационном файле не верны настройки web-host.data - каталог не существует: js");
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
if (!buildPath(data, "images").exists) {
|
|
|
|
|
log.c("В конфигурационном файле не верны настройки web-host.data - каталог не существует: images");
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
log.c("В конфигурационном файле не верны настройки web-host.data - каталог не существует: " ~ data);
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wh.data = data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!webHost["title"].empty) {
|
|
|
|
|
try {
|
|
|
|
|
wh.title = webHost["title"];
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.w("Заголовок не был установлен - web-host.title");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!webHost["loglevel"].empty) {
|
|
|
|
|
try {
|
|
|
|
|
wh.loglevel = webHost["loglevel"].to!int;
|
|
|
|
|
if (wh.loglevel < 0 || wh.loglevel > 6)
|
|
|
|
|
throw new Exception("несуществующий уровень");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.c("В конфигурационном файле не верны настройки web-host.loglevel: " ~ e.msg);
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!webHost["logoutput"].empty) {
|
|
|
|
|
try {
|
|
|
|
|
wh.logoutput = webHost["logoutput"]
|
|
|
|
|
.to!string.split(',')
|
|
|
|
|
.map!((a) {
|
|
|
|
|
auto flag = a.strip.to!int;
|
|
|
|
|
|
|
|
|
|
if ([1, 2, 4].canFind(flag))
|
|
|
|
|
return flag;
|
|
|
|
|
|
|
|
|
|
log.c("В конфигурационном файле не верны настройки web-host.logoutput");
|
|
|
|
|
exit(1);
|
|
|
|
|
})
|
|
|
|
|
.fold!((a, b) => a | b);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.c("В конфигурационном файле не верны настройки web-host.logoutput");
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (wh.logoutput & 4) {
|
|
|
|
|
if (webHost["logfile"].empty) {
|
|
|
|
|
log.c("В конфигурационном файле не верны настройки web-host.logfile");
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
wh.logfile = webHost["logfile"];
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.c("В конфигурационном файле не верны настройки web-host.logfile");
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return wh;
|
|
|
|
|
}
|