#include "ui/askuser.h"
#include "csr/error.h"
+#define EXCEPTION_GUARD_START return Csr::exceptionGuard([&]() {
+#define EXCEPTION_GUARD_CLOSER(retArg) }, [](int retArg) {
+#define EXCEPTION_GUARD_END });
+
namespace Csr {
+namespace {
+
+RawBuffer exceptionGuard(const std::function<RawBuffer()> &func,
+ const std::function<RawBuffer(int)> &closer)
+{
+ try {
+ return func();
+ } catch (const Exception &e) {
+ ERROR("Exception caught. code: " << e.error() << " message: " << e.what());
+ return closer(e.error());
+ } catch (const std::bad_alloc &) {
+ ERROR("memory alloc failed.");
+ return closer(CSR_ERROR_OUT_OF_MEMORY);
+ } catch (const std::exception &e) {
+ ERROR("std exception: " << e.what());
+ return closer(CSR_ERROR_UNKNOWN);
+ } catch (...) {
+ ERROR("Unknown exception occured in logic");
+ return closer(CSR_ERROR_UNKNOWN);
+ }
+}
+
+} // namespace anonymous
+
Logic::Logic(ThreadPool &pool) :
m_workqueue(pool),
m_cs(new CsLoader(CS_ENGINE_PATH)),
RawBuffer Logic::scanData(const CsContext &context, const RawBuffer &data)
{
+ EXCEPTION_GUARD_START
+
CsEngineContext engineContext(m_cs);
auto &c = engineContext.get();
csre_cs_detected_h result;
- int ret = CSR_ERROR_NONE;
int eret = m_cs->scanData(c, data, &result);
if (eret != CSRE_ERROR_NONE) {
// detected handle is null if it's safe
if (result == nullptr)
- return BinaryQueue::Serialize(ret, CsDetected()).pop();
+ return BinaryQueue::Serialize(CSR_ERROR_NONE, CsDetected()).pop();
auto d = convert(result);
ThrowExc(InternalError, "Invalid severity: " << static_cast<int>(d.severity));
}
- return BinaryQueue::Serialize(ret, d).pop();
+ return BinaryQueue::Serialize(CSR_ERROR_NONE, d).pop();
+
+ EXCEPTION_GUARD_CLOSER(ret)
+
+ return BinaryQueue::Serialize(ret, CsDetected()).pop();
+
+ EXCEPTION_GUARD_END
}
RawBuffer Logic::scanFileHelper(const CsContext &context, const std::string &filepath)
auto &c = engineContext.get();
csre_cs_detected_h result;
- int ret = CSR_ERROR_NONE;
int eret = m_cs->scanFile(c, filepath, &result);
if (eret != CSRE_ERROR_NONE) {
// detected handle is null if it's safe
if (result == nullptr)
- return BinaryQueue::Serialize(ret, CsDetected()).pop();
+ return BinaryQueue::Serialize(CSR_ERROR_NONE, CsDetected()).pop();
auto d = convert(result);
m_db->insertDetectedMalware(d, m_csDataVersion, d.response == CSR_CS_IGNORE);
- return BinaryQueue::Serialize(ret, d).pop();
+ return BinaryQueue::Serialize(CSR_ERROR_NONE, d).pop();
}
RawBuffer Logic::scanFile(const CsContext &context, const std::string &filepath)
{
+ EXCEPTION_GUARD_START
+
DEBUG("Scan request on file: " << filepath);
auto history = m_db->getDetectedMalware(filepath);
DEBUG("file[" << filepath << "] isn't modified since the detected time. "
"history can be used.");
+
if (!context.askUser) {
return BinaryQueue::Serialize(CSR_ERROR_NONE, history).pop();
} else if (history->isIgnored) {
case CSR_CS_REMOVE:
try {
auto file = File::create(filepath);
+
if (!file && !file->remove()) {
ERROR("Failed to remove filepath: " << filepath);
return BinaryQueue::Serialize(CSR_ERROR_REMOVE_FAILED, CsDetected()).pop();
DEBUG("file[" << filepath << "] user response: " << static_cast<int>(history->response));
return BinaryQueue::Serialize(CSR_ERROR_NONE, history).pop();
+
+ EXCEPTION_GUARD_CLOSER(ret)
+
+ return BinaryQueue::Serialize(ret, CsDetected()).pop();
+
+ EXCEPTION_GUARD_END
}
RawBuffer Logic::getScannableFiles(const Credential &cred, const std::string &dir)
{
+ EXCEPTION_GUARD_START
+
auto lastScanTime = m_db->getLastScanTime(dir, m_csDataVersion);
StrSet filesetForClient;
auto filesetForServer = std::make_shared<StrSet>();
+
try {
auto visitor = FsVisitor::create(dir, lastScanTime);
while (auto file = visitor->next()) {
DEBUG("In dir[" << dir << "], Scannable file[" << file->getPath() << "]");
+
if (hasPermToRemove(cred, file->getPath()))
filesetForClient.insert(file->getPath());
else
});
return BinaryQueue::Serialize(CSR_ERROR_NONE, filesetForClient).pop();
+
+ EXCEPTION_GUARD_CLOSER(ret)
+
+ return BinaryQueue::Serialize(ret, StrSet()).pop();
+
+ EXCEPTION_GUARD_END
}
RawBuffer Logic::judgeStatus(const std::string &filepath, csr_cs_action_e action)
{
+ EXCEPTION_GUARD_START
+
auto history = m_db->getDetectedMalware(filepath);
if (!history) {
case CSR_CS_ACTION_REMOVE:
try {
auto file = File::create(filepath);
+
if (!file && !file->remove()) {
ERROR("Failed to remove filepath: " << filepath);
return BinaryQueue::Serialize(CSR_ERROR_REMOVE_FAILED).pop();
}
return BinaryQueue::Serialize(CSR_ERROR_NONE).pop();
+
+ EXCEPTION_GUARD_CLOSER(ret)
+
+ return BinaryQueue::Serialize(ret).pop();
+
+ EXCEPTION_GUARD_END
}
RawBuffer Logic::getDetected(const std::string &filepath)
{
+ EXCEPTION_GUARD_START
+
auto row = m_db->getDetectedMalware(filepath);
if (row)
return BinaryQueue::Serialize(CSR_ERROR_NONE, row).pop();
else
return BinaryQueue::Serialize(CSR_ERROR_NONE, CsDetected()).pop();
+
+ EXCEPTION_GUARD_CLOSER(ret)
+
+ return BinaryQueue::Serialize(ret, CsDetected()).pop();
+
+ EXCEPTION_GUARD_END
}
RawBuffer Logic::getDetectedList(const StrSet &dirSet)
{
+ EXCEPTION_GUARD_START
+
Db::RowShPtrs rows;
std::for_each(dirSet.begin(), dirSet.end(),
[this, &rows](const std::string & dir) {
});
return BinaryQueue::Serialize(CSR_ERROR_NONE, rows).pop();
+
+ EXCEPTION_GUARD_CLOSER(ret)
+
+ return BinaryQueue::Serialize(ret, Db::RowShPtrs()).pop();
+
+ EXCEPTION_GUARD_END
}
// TODO: is this command needed?
RawBuffer Logic::getIgnored(const std::string &filepath)
{
+ EXCEPTION_GUARD_START
+
auto row = m_db->getDetectedMalware(filepath);
if (row && row->isIgnored)
return BinaryQueue::Serialize(CSR_ERROR_NONE, row).pop();
else
return BinaryQueue::Serialize(CSR_ERROR_NONE, CsDetected()).pop();
+
+ EXCEPTION_GUARD_CLOSER(ret)
+
+ return BinaryQueue::Serialize(ret, CsDetected()).pop();
+
+ EXCEPTION_GUARD_END
}
RawBuffer Logic::getIgnoredList(const StrSet &dirSet)
{
+ EXCEPTION_GUARD_START
+
Db::RowShPtrs rows;
std::for_each(dirSet.begin(), dirSet.end(),
[this, &rows](const std::string & dir) {
});
return BinaryQueue::Serialize(CSR_ERROR_NONE, rows).pop();
+
+ EXCEPTION_GUARD_CLOSER(ret)
+
+ return BinaryQueue::Serialize(ret, Db::RowShPtrs()).pop();
+
+ EXCEPTION_GUARD_END
}
RawBuffer Logic::checkUrl(const WpContext &context, const std::string &url)
{
+ EXCEPTION_GUARD_START
+
DEBUG("Logic::checkUrl start");
WpEngineContext engineContext(m_wp);
auto &c = engineContext.get();
csre_wp_check_result_h result;
- int ret = CSR_ERROR_NONE;
int eret = m_wp->checkUrl(c, url.c_str(), &result);
if (eret != CSRE_ERROR_NONE) {
ThrowExc(InternalError, "Invalid level: " << static_cast<int>(wr.riskLevel));
}
- return BinaryQueue::Serialize(ret, wr).pop();
+ return BinaryQueue::Serialize(CSR_ERROR_NONE, wr).pop();
+
+ EXCEPTION_GUARD_CLOSER(ret)
+
+ return BinaryQueue::Serialize(ret, WpResult()).pop();
+
+ EXCEPTION_GUARD_END
}
csr_cs_user_response_e Logic::getUserResponse(const CsContext &c, const CsDetected &d)
}
csr_wp_user_response_e Logic::getUserResponse(const WpContext &c, const std::string &url,
- const WpResult &wr)
+ const WpResult &wr)
{
if (c.askUser == CSR_WP_NOT_ASK_USER)
return CSR_WP_NO_ASK_USER;