1:重构规则引擎,支持多种逻辑运算,支持多种统计运算,支持多种比较运算。

2:重构特征库格式,从json改用yaml(json确实看起来不好看)。
3:更改特征匹配逻辑,将字节匹配与校验匹配结果拆分。
4:编辑器适配新的规则引擎和特征库格式。
This commit is contained in:
mountcloud
2022-06-30 01:48:43 +08:00
parent fa2576f3d9
commit 3dbac60203
23 changed files with 730 additions and 548 deletions
+118 -319
View File
@@ -26,120 +26,6 @@ FeatureLibrary::~FeatureLibrary() {
}
}
FeatureLibrary* FeatureLibrary::createByJson(string json, int* errorcode) {
FeatureLibrary* result = NULL;
nlohmann::json root;
bool parseStatus = false;
try {
root = json::parse(json);
parseStatus = true;
}
catch (nlohmann::detail::parse_error er) {
parseStatus = false;
}
if (!parseStatus || !root.is_object()|| !root.contains("version") || !root.contains("items")) {
*errorcode = FL_CONTENT_FORMATE_ERROR;
return result;
}
bool validstate = false;
auto schema = json::parse(FIREDOG_FEATURE_LIBRARAY_JSON_SCHEMA);
json_validator validator; // create validator
validator.set_root_schema(schema);
try {
validator.validate(root);
validstate = true;
}
catch (const std::exception& e) {
validstate = false;
}
if (!validstate) {
*errorcode = FL_CONTENT_FORMATE_ERROR;
return result;
}
//get version
string version = root["version"];
//check version
if (version != FIREDOG_FEATURE_LIBRARY_VERSION) {
*errorcode = FL_CONTENT_VERSION_ERROR;
}
result = new FeatureLibrary();
result->version = version;
nlohmann::json items = root["items"];
if (items.is_array()) {
for (int i = 0; i < items.size(); i++) {
nlohmann::json item = items[i];
if (item.is_object()
&& item.contains("author") && item["author"].is_string()
&& item.contains("name") && item["name"].is_string()
&& item.contains("describe") && item["describe"].is_string()
&& item.contains("features") && item["features"].is_array() && item["features"].size() > 0
&& item.contains("rule") && item["rule"].is_object()) {
//ÏÈ¿´¹æÔò
nlohmann::json rulejson = item["rule"];
vector<Rule*> rules = parseRulesByJson(rulejson);
if (rules.size()==0) {
continue;
}
Rule* rule = NULL;
if (rules.size()==1) {
rule = rules.at(0);
}
else {
AndRule* andRule = new AndRule();
andRule->addRules(rules);
}
FeatureLibraryItem* fitem = new FeatureLibraryItem();
fitem->author = item["author"];
fitem->name = item["name"];
fitem->describe = item["describe"];
fitem->rule = rule;
nlohmann::json features = item["features"];
for (int y = 0; y < features.size(); y++) {
nlohmann::json feature = features[y];
if (feature.contains("key") && feature["key"].is_string()
&& (feature.contains("hex") && feature["hex"].is_string()
|| feature.contains("text") && feature["text"].is_string())) {
string fkey = feature["key"];
string fhex = "";
string ftext = "";
if (feature.contains("hex")) {
fhex = feature["hex"];
}
if (feature.contains("text")) {
ftext = feature["text"];
}
Feature* feature = new Feature();
feature->key = fkey;
feature->hex = fhex;
feature->text = ftext;
fitem->features->push_back(feature);
}
}
result->items->push_back(fitem);
}
}
}
return result;
}
FeatureLibrary* FeatureLibrary::createByYaml(std::string yaml, int* errorcode) {
FeatureLibrary* result = NULL;
@@ -243,226 +129,139 @@ FeatureLibrary* FeatureLibrary::createByYaml(std::string yaml, int* errorcode) {
return result;
}
vector<Rule*> FeatureLibrary::parseRulesByJson(nlohmann::json rulejson) {
vector<Rule*> rules;
if (rulejson.is_string()) {
string id = rulejson;
CountRule* countRule = new CountRule(id);
rules.push_back(countRule);
}else if (rulejson.is_object()&&!rulejson.is_array()) {
for (auto ruleiter = rulejson.begin(); ruleiter != rulejson.end(); ruleiter++) {
std::string key = ruleiter.key();
nlohmann::json childrulejson = rulejson[key];
if (key == "$and" || key == "$or" || key == "$not") {
LogicRule* logicRule = NULL;
vector<Rule*> childRules = parseRulesByJson(childrulejson);
if (childRules.size()>0) {
if (key == "$and") {
logicRule = new AndRule();
}
if (key == "$or") {
logicRule = new OrRule();
}
if (key == "$not") {
logicRule = new NotRule();
}
logicRule->addRules(childRules);
rules.push_back(logicRule);
}
}
else if (key == "$int") {
if (childrulejson.is_number()) {
long num = childrulejson;
IntRule* intRule = new IntRule(childrulejson);
rules.push_back(intRule);
}
}
else if (key == "$count") {
vector<string> ids;
long num = 1L;
if (childrulejson.is_string()) {
string id = childrulejson;
ids.push_back(id);
}else if (childrulejson.is_array()) {
int idslen = childrulejson.size();
for (int i = 0; i < idslen; i++) {
nlohmann::json crj = childrulejson[i];
if (crj.is_string()) {
string id = crj;
ids.push_back(id);
}
else if (i == idslen - 1 && crj.is_number()) {
long tempnum = crj;
if (tempnum > 1) {
num = tempnum;
}
}
}
}
if (ids.size() > 0) {
CountRule* countRule = new CountRule(ids);
countRule->setCritical(num);
rules.push_back(countRule);
}
}
else if(key == "$lt"|| key == "$le" || key == "$gt" || key == "$ge") {
Rule* compareRule = NULL;
vector<Rule*> childRules = parseRulesByJson(childrulejson);
if (childRules.size()==2) {
Rule* num1Rule = childRules[0];
Rule* num2Rule = childRules[1];
if (num1Rule != NULL && num1Rule->getBaseType() == RULE_BASE_TYPE_NUMBER
&& num2Rule != NULL && num2Rule->getBaseType() == RULE_BASE_TYPE_NUMBER) {
if (key == "$lt") {
compareRule = new LtRule((NumberRule*)num1Rule, (NumberRule*)num2Rule);
}
if (key == "$le") {
compareRule = new LeRule((NumberRule*)num1Rule, (NumberRule*)num2Rule);
}
if (key == "$gt") {
compareRule = new GtRule((NumberRule*)num1Rule, (NumberRule*)num2Rule);
}
if (key == "$ge") {
compareRule = new GeRule((NumberRule*)num1Rule, (NumberRule*)num2Rule);
}
}
if (compareRule != NULL) {
rules.push_back(compareRule);
}
}
}
}
}
return rules;
}
Rule* FeatureLibrary::parseRuleByJson(nlohmann::json rulejson) {
Rule* rule = NULL;
vector<Rule*> rules = parseRulesByJson(rulejson);
if (rules.size()>0) {
rule = rules.at(0);
}
return rule;
}
FeatureLibraryItem::FeatureLibraryItem() {
features = new vector<Feature*>();
}
std::string FeatureLibrary::toJson(int* state){
json jsonFeatureLibrary;
jsonFeatureLibrary["version"] = FIREDOG_FEATURE_LIBRARY_VERSION;
std::string FeatureLibrary::toYaml(int* state) {
string ymlstr;
ryml::Tree tree;
try {
c4::yml::NodeRef root = tree.rootref();
root |= ryml::MAP;
root["version"] << string(FIREDOG_FEATURE_LIBRARY_VERSION);
if (items != NULL) {
root["items"] |= ryml::SEQ;
for (int i = 0; i < items->size(); i++) {
FeatureLibraryItem* item = items->at(i);
root["items"][i] |= ryml::MAP;
root["items"][i]["name"] << item->name;
root["items"][i]["author"] << item->author;
root["items"][i]["describe"] << item->describe;
if (items!=NULL) {
std::vector<json> jsonItems;
for (int i = 0; i < items->size(); i++) {
json jsonItem;
FeatureLibraryItem* item = items->at(i);
jsonItem["name"] = item->name;
jsonItem["describe"] = item->describe;
jsonItem["author"] = item->author;
std::vector<json> jsonFeatures;
if (item->features != NULL && item->features->size() > 0) {
for (int y = 0; y < item->features->size(); y++) {
Feature* feature = item->features->at(y);
json jsonFeature;
jsonFeature["key"] = feature->key;
if (!feature->hex.empty()) {
jsonFeature["hex"] = feature->hex;
if (item->features != NULL && item->features->size() > 0) {
root["items"][i]["features"] |= ryml::SEQ;;
for (int y = 0; y < item->features->size(); y++) {
Feature* feature = item->features->at(y);
root["items"][i]["features"][y] |= ryml::MAP;
root["items"][i]["features"][y]["key"] << feature->key;
if (!feature->hex.empty()) {
root["items"][i]["features"][y]["hex"] << feature->hex;
}
else {
root["items"][i]["features"][y]["text"] << feature->text;
}
}
else {
jsonFeature["text"] = feature->text;
}
jsonFeatures.push_back(jsonFeature);
}
root["items"][i]["rules"] |= ryml::SEQ;
root["items"][i]["rules"][0] |= ryml::MAP;
c4::yml::NodeRef ymlrules = root["items"][i]["rules"][0];
ruleToYaml(ymlrules, item->rule);
}
else {
*state = FL_CONTENT_EXIST_EMPTY_FEATURES_FAIL;
return "";
}
jsonItem["features"] = jsonFeatures;
bool ruleState = false;
json ruleJson = ruleToJson(item->rule,&ruleState);
if (!ruleState) {
*state = FL_CONTENT_EXIST_RULE_FORMATE_FAIL;
return "";
}
jsonItem["rule"] = ruleJson;
jsonItems.push_back(jsonItem);
}
jsonFeatureLibrary["items"] = jsonItems;
*state = 0;
}
else {
*state = FL_CONTENT_ITEMS_IS_EMPTY;
return "";
catch (...) {
*state = -1;
}
std::string json = jsonFeatureLibrary.dump(4);
*state = NO_ERROR;
return json;
if (*state == 0) {
ymlstr = ryml::emitrs<std::string>(tree);
}
return ymlstr;
}
nlohmann::json FeatureLibrary::ruleToJson(mountcloud::Rule* rule,bool* state) {
json jsonRule;
//if (rule != NULL) {
// if (!rule->id.empty()) {
// jsonRule = rule->id;
// *state = true;
// }
// else if(rule->ands!=NULL&&rule->ands->size()>0){
// vector<json> andsjson;
// for (int i = 0; i < rule->ands->size(); i++) {
// mountcloud::Rule* andRule = rule->ands->at(i);
// bool andRuleState = false;
void FeatureLibrary::ruleToYaml(c4::yml::NodeRef& parentNode, mountcloud::Rule* rule) {
if (rule->getType() == RULE_BASE_TYPE_ALL) {
AllRule* allRule = (AllRule*)rule;
if (allRule->getIds().size() > 0) {
parentNode["$all"] |= ryml::SEQ;
for (int i = 0; i < allRule->getIds().size(); i++) {
parentNode["$all"][i] << allRule->getIds().at(i);
}
}
}
//------------------------------------------------
else if (rule->getBaseType() == RULE_BASE_TYPE_LOGIC) {
c4::yml::NodeRef logicNode;
if (rule->getType() == RULE_TYPE_LOGIC_AND) {
parentNode["$and"] |= ryml::SEQ;
logicNode = parentNode["$and"];
}
else if (rule->getType() == RULE_TYPE_LOGIC_OR) {
parentNode["$or"] |= ryml::SEQ;
logicNode = parentNode["$or"];
}
else if (rule->getType() == RULE_TYPE_LOGIC_NOT) {
parentNode["$not"] |= ryml::SEQ;
logicNode = parentNode["$not"];
}
// json andJson = ruleToJson(andRule, &andRuleState);
// if (!andRuleState) {
// *state = false;
// return jsonRule;
// }
// andsjson.push_back(andJson);
// }
// *state = true;
// jsonRule["$and"] = andsjson;
// }
// else if(rule->ors!=NULL&&rule->ors->size()>0){
// vector<json> orsjson;
// for (int i = 0; i < rule->ors->size(); i++) {
// mountcloud::Rule* orRule = rule->ors->at(i);
// bool orRuleState = false;
LogicRule* logicRule = (LogicRule*)rule;
// json orJson = ruleToJson(orRule, &orRuleState);
// if (!orRuleState) {
// *state = false;
// return jsonRule;
// }
// orsjson.push_back(orJson);
// }
// *state = true;
// jsonRule["$or"] = orsjson;
// }
// else {
// *state = false;
// }
//}
//else {
// *state = false;
//}
return jsonRule;
for (int i = 0; i < logicRule->getRules()->size(); i++) {
Rule* tlr = logicRule->getRules()->at(i);
logicNode[i] |= ryml::MAP;
c4::yml::NodeRef logicChildNode = logicNode[i];
ruleToYaml(logicChildNode, tlr);
}
}
//------------------------------------------------
else if (rule->getType() == RULE_TYPE_NUMBER_INT) {
IntRule* intRule = (IntRule*)rule;
parentNode["$int"] << intRule->getNum();
}
else if (rule->getType() == RULE_TYPE_NUMBER_COUNT) {
CountRule* countRule = (CountRule*)rule;
parentNode["$count"] |= ryml::SEQ;
for (int i = 0; i < countRule->getIds().size(); i++) {
parentNode["$count"][i] << countRule->getIds().at(i);
}
}
//------------------------------------------------
else if (rule->getBaseType() == RULE_BASE_TYPE_COMPARE) {
c4::yml::NodeRef compaerNode;
if (rule->getType() == RULE_TYPE_COMPARE_LT) {
parentNode["$lt"] |= ryml::SEQ;
compaerNode = parentNode["$lt"];
}
else if (rule->getType() == RULE_TYPE_COMPARE_LE) {
parentNode["$lt"] |= ryml::SEQ;
compaerNode = parentNode["$lt"];
}
else if (rule->getType() == RULE_TYPE_COMPARE_GT) {
parentNode["$gt"] |= ryml::SEQ;
compaerNode = parentNode["$gt"];
}
else if (rule->getType() == RULE_TYPE_COMPARE_GE) {
parentNode["$ge"] |= ryml::SEQ;
compaerNode = parentNode["$ge"];
}
CompareRule* compareRule = (CompareRule*)rule;
compaerNode[0] |= ryml::MAP;
compaerNode[1] |= ryml::MAP;
c4::yml::NodeRef num1Node = compaerNode[0];
c4::yml::NodeRef num2Node = compaerNode[1];
ruleToYaml(num1Node, compareRule->getNum1());
ruleToYaml(num2Node, compareRule->getNum2());
}
}
std::vector<mountcloud::Rule*> FeatureLibrary::parseRulesByYaml(c4::yml::NodeRef node) {
+7 -14
View File
@@ -144,10 +144,9 @@ namespace firedog {
class FeatureLibrary {
public:
/// <summary>
/// create by json
/// create by yml
/// </summary>
static FeatureLibrary* createByJson(std::string json, int* errorcode);
static FeatureLibrary* createByYaml(std::string yaml, int* errorcode);
static FeatureLibrary* createByYaml(std::string yaml, int* errorcode);
/// <summary>
/// library version
@@ -161,26 +160,20 @@ namespace firedog {
std::vector<FeatureLibraryItem*>* items = NULL;
/// <summary>
/// to json
/// to yml
/// </summary>
/// <returns></returns>
std::string toJson(int* state);
std::string toYaml(int* state);
FeatureLibrary();
~FeatureLibrary();
private:
static std::vector<mountcloud::Rule*> parseRulesByJson(nlohmann::json rulejson);
static mountcloud::Rule* parseRuleByJson(nlohmann::json rulejson);
static std::vector<mountcloud::Rule*> parseRulesByYaml(c4::yml::NodeRef node);
static mountcloud::Rule* parseRuleByYaml(c4::yml::NodeRef node);
/// <summary>
/// rule to json object
/// </summary>
/// <param name="rule"></param>
/// <returns></returns>
nlohmann::json ruleToJson(mountcloud::Rule* rule,bool* state);
void ruleToYaml(c4::yml::NodeRef& parentNode, mountcloud::Rule* rule);
};
+34 -108
View File
@@ -271,28 +271,14 @@ Matcher::~Matcher() {
}
std::vector <MatcherResult*>* Matcher::matchBytes(const char* bytes, int length) {
std::vector <MatcherResult*>* result = NULL;
void Matcher::matchBytes(const char* bytes, int length) {
for (int i = 0; i < length; i++) {
char byte = bytes[i];
std::vector <MatcherResult*>* tempResult = this->matchByte(byte);
if (tempResult != NULL) {
//匹配到了
if (result == NULL) {
result = new std::vector<MatcherResult*>();
}
result->insert(result->end(), tempResult->begin(), tempResult->end());
//删掉vector的指针
delete tempResult;
}
this->matchByte(byte);
}
return result;
}
std::vector <MatcherResult*>* Matcher::matchByte(const char byte) {
std::vector <MatcherResult*>* result = NULL;
void Matcher::matchByte(const char byte) {
if (matchCache == NULL) {
matchCache = new std::vector<MatcherData*>();
}
@@ -304,16 +290,8 @@ std::vector <MatcherResult*>* Matcher::matchByte(const char byte) {
MatcherData* mbd = matchCache->at(i);
//校验完整字节
std::vector <MatcherResult*>* tempResult = checkMatcherFeature(mbd, byte, tempMatchBytesCache);
if (tempResult !=NULL) {
//匹配到了
if (result==NULL) {
result = new std::vector<MatcherResult*>();
}
result->insert(result->end(), tempResult->begin(), tempResult->end());
//删掉vector的指针
delete tempResult;
}
matcherFeature(mbd, byte, tempMatchBytesCache);
}
this->matchCache->clear();
delete this->matchCache;
@@ -322,90 +300,52 @@ std::vector <MatcherResult*>* Matcher::matchByte(const char byte) {
//step2:find by feature library 然后从特征库中拉取
//校验完整字节
std::vector <MatcherResult*>* tempResult = checkMatcherFeature(this->dataSource->getData(), byte, this->matchCache);
if (tempResult != NULL) {
//匹配到了
if (result == NULL) {
result = new std::vector<MatcherResult*>();
matcherFeature(this->dataSource->getData(), byte, this->matchCache);
}
std::vector <MatcherResult*>* Matcher::check() {
std::vector <MatcherResult*>* result = NULL;
for (std::unordered_map<int, mountcloud::RuleData*>::iterator iter = featureRuleData->begin(); iter != featureRuleData->end(); iter++) {
int featureId = iter->first;
mountcloud::RuleData* ruleData = iter->second;
FeatureLibraryItem* fitem = dataSource->getFeatureLibraryItem(featureId);
Rule* rule = fitem->rule;
if (rule != NULL && rule->check(ruleData)) {
if (result == NULL) {
result = new std::vector<MatcherResult*>();
}
MatcherResult* mr = new MatcherResult();
mr->featureId = featureId;
mr->author = fitem->author;
mr->name = fitem->name;
mr->describe = fitem->describe;
result->push_back(mr);
}
result->insert(result->end(), tempResult->begin(), tempResult->end());
//删掉vector的指针
delete tempResult;
}
return result;
}
std::vector <MatcherResult*>* Matcher::checkMatcherFeature(MatcherData* mbd, char byte, std::vector<MatcherData*>* tempMatchBytesCache) {
std::vector <MatcherResult*>* result = NULL;
void Matcher::matcherFeature(MatcherData* mbd, char byte, std::vector<MatcherData*>* tempMatchBytesCache) {
//高位
const char highPos = StringUtil::byteHigh(byte);
//低位
const char lowPos = StringUtil::byteLow(byte);
//校验完整字节
result = checkMatcherFeatureMap(mbd->fullData, byte, tempMatchBytesCache);
if (result != NULL) {
return result;
}
matcherFeatureMap(mbd->fullData, byte, tempMatchBytesCache);
//校验高位
result = checkMatcherFeatureMap(mbd->highPosData, highPos, tempMatchBytesCache);
if (result != NULL) {
return result;
}
matcherFeatureMap(mbd->highPosData, highPos, tempMatchBytesCache);
//校验低位
result = checkMatcherFeatureMap(mbd->lowPosData, lowPos, tempMatchBytesCache);
if (result != NULL) {
return result;
}
matcherFeatureMap(mbd->lowPosData, lowPos, tempMatchBytesCache);
//校验any
//if (mbd->anyData != NULL) {
// //any 匹配到了
// if (mbd->anyData->features != NULL) {
// result = new std::vector<MatcherResult*>();
// for (int i = 0; i < mbd->anyData->features->size(); i++) {
// MatcherFeature* mf = mbd->anyData->features->at(i);
// int featureId = mf->featureId;
// string featureKey = mf->featureKey;
// RuleData* ruleData = NULL;
// if (featureRuleData == NULL) {
// featureRuleData = new unordered_map<int, mountcloud::RuleData*>();
// }
// if (featureRuleData->find(featureId) == featureRuleData->end()) {
// ruleData = new RuleData();
// }
// else {
// ruleData = featureRuleData->at(featureId);
// }
// ruleData->set(featureKey, true);
// FeatureLibraryItem* fitem = dataSource->getFeatureLibraryItem(featureId);
// Rule* rule = fitem->rule;
// if (rule != NULL && rule->check(ruleData)) {
// MatcherResult* mr = new MatcherResult();
// mr->featureId = featureId;
// mr->author = fitem->author;
// mr->name = fitem->name;
// mr->describe = fitem->describe;
// result->push_back(mr);
// }
// }
// }
// else {
// //any没有匹配到
// tempMatchBytesCache->push_back(mbd->anyData);
// }
//}
return result;
}
std::vector<MatcherResult*>* Matcher::checkMatcherFeatureMap(AvlMap<char, MatcherData*>* map, char byte, std::vector<MatcherData*>* tempMatchBytesCache) {
std::vector<MatcherResult*>* result = NULL;
void Matcher::matcherFeatureMap(AvlMap<char, MatcherData*>* map, char byte, std::vector<MatcherData*>* tempMatchBytesCache) {
if (map==NULL) {
return result;
return;
}
AvlMap<char, MatcherData*>::Iterator mbditer = map->find(byte);
@@ -433,24 +373,10 @@ std::vector<MatcherResult*>* Matcher::checkMatcherFeatureMap(AvlMap<char, Matche
featureRuleData->operator[](featureId) = ruleData;
FeatureLibraryItem* fitem = dataSource->getFeatureLibraryItem(featureId);
Rule* rule = fitem->rule;
if (rule != NULL && rule->check(ruleData)) {
if (result==NULL) {
result = new std::vector<MatcherResult*>();
}
MatcherResult* mr = new MatcherResult();
mr->featureId = featureId;
mr->author = fitem->author;
mr->name = fitem->name;
mr->describe = fitem->describe;
result->push_back(mr);
}
}
}
tempMatchBytesCache->push_back(iterMbd);
}
return result;
}
MatcherData* MatcherDataSource::getData() {
+6 -4
View File
@@ -90,8 +90,10 @@ namespace firedog {
Matcher(MatcherDataSource* dataSource);
~Matcher();
std::vector <MatcherResult*>* matchBytes(const char* bytes, int length);
std::vector <MatcherResult*>* matchByte(const char byte);
void matchBytes(const char* bytes, int length);
void matchByte(const char byte);
std::vector <MatcherResult*>* check();
private:
/// <summary>
/// data source,
@@ -109,8 +111,8 @@ namespace firedog {
std::unordered_map<int, mountcloud::RuleData*>* featureRuleData = NULL;
std::vector<MatcherResult*>* checkMatcherFeature(MatcherData* mbd, char byte, std::vector<MatcherData*>* tempMatchBytesCache);
std::vector<MatcherResult*>* checkMatcherFeatureMap(AvlMap<char, MatcherData*>* map,char byte, std::vector<MatcherData*>* tempMatchBytesCache);
void matcherFeature(MatcherData* mbd, char byte, std::vector<MatcherData*>* tempMatchBytesCache);
void matcherFeatureMap(AvlMap<char, MatcherData*>* map,char byte, std::vector<MatcherData*>* tempMatchBytesCache);
};
}
+11 -2
View File
@@ -118,6 +118,9 @@ bool AndRule::check(RuleData* data) {
}
return true;
}
else {
return true;
}
return true;
}
@@ -135,7 +138,10 @@ bool OrRule::check(RuleData* data) {
}
}
}
return true;
else {
return true;
}
return false;
}
NotRule::NotRule() {
@@ -153,7 +159,10 @@ bool NotRule::check(RuleData* data) {
}
return true;
}
return true;
else {
return true;
}
return false;
}
NumberRule::NumberRule() {
+125 -32
View File
@@ -15,6 +15,8 @@
#include "gui18n.h"
#include "gui18nutil.h"
#include "stringutil.h"
using namespace firedog;
//构造函数
@@ -44,6 +46,9 @@ FireDogEditor::FireDogEditor(QWidget *parent)
//初始化
void FireDogEditor::init() {
QIcon iconFile(":/FireDogEditor/resources/icon.ico");
this->setWindowIcon(iconFile);
QFile qss(":/qss/css/qss.css");
if (qss.open(QIODevice::ReadOnly)) {
QByteArray qssBytes = qss.readAll();
@@ -409,14 +414,14 @@ void FireDogEditor::slots_saveFile() {
QFile file(this->openFilePath);
int state = -1;
std::string json = this->featureLibrary->toJson(&state);
std::string ymlstr = this->featureLibrary->toYaml(&state);
if (state != NO_ERROR) {
QssMessageBox::warn("Save fail,Feature library convert to json fail!.", this, "Warn");
return;
}
QString jsonstr = QString::fromUtf8(QByteArray::fromRawData(json.c_str(), json.size()));
QString jsonstr = QString::fromUtf8(QByteArray::fromRawData(ymlstr.c_str(), ymlstr.size()));
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
{
@@ -457,7 +462,7 @@ void FireDogEditor::slots_saveToFile() {
}
int state = -1;
std::string json = this->featureLibrary->toJson(&state);
std::string ymlstr = this->featureLibrary->toYaml(&state);
if (state != NO_ERROR) {
QString titleStr = Gui18n::GetInstance()->GetConfig("text-message-box-title-warning", "Warning");
@@ -466,7 +471,7 @@ void FireDogEditor::slots_saveToFile() {
return;
}
QString jsonstr = QString::fromUtf8(QByteArray::fromRawData(json.c_str(), json.size()));
QString jsonstr = QString::fromUtf8(QByteArray::fromRawData(ymlstr.c_str(), ymlstr.size()));
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
{
@@ -1005,6 +1010,14 @@ void FireDogEditor::slots_featureLibraryInfoRuleMenuAddEvent() {
bool isOk = this->fireDogFeatureRuleInfoView->updateRule(&rule, &childs, parent);
if (isOk) {
QStandardItem* ruleitem = new QStandardItem(rule);
if (rule=="$lt"||rule=="$le"||rule=="$gt"||rule=="$ge") {
for (int i=0;i<childs.size();i++)
{
QString childStr = childs.at(i);
QStandardItem* childitem = new QStandardItem(childStr);
ruleitem->appendRow(childitem);
}
}
//如果是空的
if (ruleIsEmpty) {
featureLibraryInfoRuleTreeModel->appendRow(ruleitem);
@@ -1018,6 +1031,7 @@ void FireDogEditor::slots_featureLibraryInfoRuleMenuAddEvent() {
QModelIndex index = this->featureLibraryInfoRuleTreeModel->indexFromItem(ruleitem);
ui.treeViewLibraryInfoRules->selectionModel()->setCurrentIndex(index, QItemSelectionModel::Select | QItemSelectionModel::Rows);
ui.treeViewLibraryInfoRules->expand(index);
}
}
@@ -1044,7 +1058,24 @@ void FireDogEditor::slots_featureLibraryInfoRuleMenuEditEvent() {
bool isOk = this->fireDogFeatureRuleInfoView->updateRule(&rule, &childs, parent);
if (isOk) {
bool resultIsCmp = false;
if (rule == "$lt" || rule == "$le" || rule == "$gt" || rule == "$ge") {
resultIsCmp = true;
}
selectItem->setText(rule);
if (resultIsCmp) {
selectItem->removeRows(0, selectItem->rowCount());
for (int i = 0; i < childs.size(); i++)
{
QString childStr = childs.at(i);
QStandardItem* childitem = new QStandardItem(childStr);
selectItem->appendRow(childitem);
}
ui.treeViewLibraryInfoRules->expand(selectItem->index());
}
}
}
@@ -1192,7 +1223,7 @@ mountcloud::Rule* FireDogEditor::itemToRule(QStandardItem* item) {
goto fail;
}
bool isOperation = text == "$and" || text == "$or";
bool isOperation = text == "$and" || text == "$or" || text == "$not";
//根规则只能是逻辑表达式
if (item->parent()==NULL) {
@@ -1210,34 +1241,96 @@ mountcloud::Rule* FireDogEditor::itemToRule(QStandardItem* item) {
}
}
mountcloud::Rule* result = new mountcloud::Rule();
mountcloud::Rule* result = NULL;
// if (isOperation) {
// int childCount = item->rowCount();
// for (int i = 0; i < childCount; i++) {
// QStandardItem* childItem = item->child(i);
// mountcloud::Rule* childRule = itemToRule(childItem);
// if (childRule==NULL) {
// delete result;
// return NULL;
// }
// if(text=="$and"){
// if (result->ands == NULL) {
// result->ands = new std::vector<mountcloud::Rule*>();
// }
// result->ands->push_back(childRule);
// }
// else {
// if (result->ors == NULL) {
// result->ors = new std::vector<mountcloud::Rule*>();
// }
// result->ors->push_back(childRule);
// }
// }
//}
// else {
// result->id = text.toStdString();
// }
if (text == "$and" || text == "$or" || text == "$not") {
mountcloud::LogicRule* logicRule = NULL;
if (text == "$and") {
logicRule = new mountcloud::AndRule();
}
else if (text == "$or") {
logicRule = new mountcloud::OrRule();
}
else {
logicRule = new mountcloud::NotRule();
}
int childCount = item->rowCount();
for (int i = 0; i < childCount; i++) {
QStandardItem* childItem = item->child(i);
mountcloud::Rule* cr = itemToRule(childItem);
if (cr != NULL) {
logicRule->addRule(cr);
}
}
result = logicRule;
}
else if (text.startsWith("$all")) {
QString infostr = text.mid(text.indexOf(":") + 1);
QStringList idsQList = infostr.split(",");
if (idsQList.size() > 0) {
std::vector<std::string> ids;
for (int i = 0; i < idsQList.size(); i++) {
QString id = idsQList.at(i);
ids.push_back(id.toStdString());
}
mountcloud::AllRule* allRule = new mountcloud::AllRule(ids);
result = allRule;
}
}
else if (text.startsWith("$count")) {
QString infostr = text.mid(text.indexOf(":") + 1);
QStringList idsQList = infostr.split(",");
if (idsQList.size() > 0) {
std::vector<std::string> ids;
for (int i = 0; i < idsQList.size(); i++) {
QString id = idsQList.at(i);
ids.push_back(id.toStdString());
}
mountcloud::CountRule* countRule = new mountcloud::CountRule(ids);
result = countRule;
}
}
else if (text.startsWith("$int")) {
QString infostr = text.mid(text.indexOf(":") + 1);
std::string numstr = infostr.toStdString();
if (StringUtil::isNumber(numstr)) {
int num = atoi(numstr.c_str());
mountcloud::IntRule* intRule = new mountcloud::IntRule(num);
result = intRule;
}
}
else if (text == "$lt" || text == "$le" || text == "$gt" || text == "$ge") {
int childCount = item->rowCount();
if (childCount == 2) {
mountcloud::Rule* num1 = itemToRule(item->child(0));
mountcloud::Rule* num2 = itemToRule(item->child(1));
if (num1 != NULL && num1->getBaseType() == RULE_BASE_TYPE_NUMBER
&& num2 != NULL && num2->getBaseType() == RULE_BASE_TYPE_NUMBER) {
mountcloud::NumberRule* numRule1 = (mountcloud::NumberRule*)num1;
mountcloud::NumberRule* numRule2 = (mountcloud::NumberRule*)num2;
mountcloud::CompareRule* compareRule = NULL;
if (text == "$lt") {
compareRule = new mountcloud::LtRule(numRule1, numRule2);
}
else if (text == "$le") {
compareRule = new mountcloud::LeRule(numRule1, numRule2);
}
else if (text == "$gt") {
compareRule = new mountcloud::GtRule(numRule1, numRule2);
}
else if (text == "$ge") {
compareRule = new mountcloud::GeRule(numRule1, numRule2);
}
result = compareRule;
}
}
}
return result;
+1 -1
View File
@@ -17,7 +17,7 @@
#include "Qss/Qss.h"
#define FIREDOG_EDITOR_VERSION "v2.1 DEV"
#define FIREDOG_EDITOR_VERSION "v2.1"
#define EXIT_CODE_REBOOT -123456789
//匹配管家
+6 -5
View File
@@ -19,10 +19,13 @@ HEADERS += ../FireDog/config.h \
../FireDog/matcher.h \
../FireDog/rule/rule.h \
../FireDog/stringutil.h \
../FireDog/yaml/yaml.hpp \
./resource.h \
./FireDogEditor.h \
./FireDogFeatureInfo.h \
./FireDogFeatureRuleInfo.h \
./FireDogSwitchLanguage.h \
./FireDogAbout.h \
./bigdatatableitem.h \
./loadingdialog.h \
./hexeditor.h \
@@ -32,9 +35,7 @@ HEADERS += ../FireDog/config.h \
./partutil.h \
./matchthread.h \
./gui18n.h \
./gui18nutil.h \
./FireDogAbout.h \
./resource.h
./gui18nutil.h
SOURCES += ../FireDog/converter.cpp \
../FireDog/featurelibrary.cpp \
../FireDog/firedog.cpp \
@@ -45,6 +46,7 @@ SOURCES += ../FireDog/converter.cpp \
../FireDog/json/json-schema/string-format-check.cpp \
../FireDog/matcher.cpp \
../FireDog/rule/rule.cpp \
./FireDogAbout.cpp \
./FireDogFeatureInfo.cpp \
./FireDogFeatureRuleInfo.cpp \
./FireDogSwitchLanguage.cpp \
@@ -59,8 +61,7 @@ SOURCES += ../FireDog/converter.cpp \
./partutil.cpp \
./matchthread.cpp \
./gui18n.cpp \
./gui18nutil.cpp \
./FireDogAbout.cpp
./gui18nutil.cpp
FORMS += ./FireDogEditor.ui \
./FireDogFeatureInfo.ui \
./FireDogFeatureRuleInfo.ui \
+1
View File
@@ -2,5 +2,6 @@
<qresource prefix="/FireDogEditor">
<file>resources/loading.gif</file>
<file>resources/loading-new-backgroud.png</file>
<file>resources/icon.ico</file>
</qresource>
</RCC>
+3
View File
@@ -245,6 +245,9 @@
</item>
<item row="9" column="0" colspan="2">
<widget class="QTreeView" name="treeViewLibraryInfoRules">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="headerHidden">
<bool>true</bool>
</property>
-2
View File
@@ -18,8 +18,6 @@ FireDogFeatureInfo::FireDogFeatureInfo(QWidget *parent) :
void FireDogFeatureInfo::init() {
QRegExp hexregx(FEATURE_FORMATE_REG_HEX);
this->hexValidator = new QRegExpValidator(hexregx, ui->lineEditContent);
+155 -21
View File
@@ -25,6 +25,13 @@ void FireDogFeatureRuleInfo::init() {
this->keyValidator = new QRegExpValidator(keyregx, ui->lineEditKey);
ui->lineEditKey->setValidator(keyValidator);
this->num1KeyValidator = new QRegExpValidator(keyregx, ui->lineEditNum1Count);
ui->lineEditNum1Count->setValidator(num1KeyValidator);
this->num2KeyValidator = new QRegExpValidator(keyregx, ui->lineEditNum2Count);
ui->lineEditNum2Count->setValidator(num2KeyValidator);
ui->comboBoxNum1Type->addItem("$count");
ui->comboBoxNum1Type->addItem("$int");
ui->spinBoxNum1Int->setVisible(false);
@@ -54,7 +61,14 @@ void FireDogFeatureRuleInfo::init() {
connect(ui->comboBoxNum2Type, SIGNAL(currentIndexChanged(QString)), this, SLOT(currentIndexChanged(QString)));
//i18n
//Gui18nUtil::SetText(ui->labelType, "feature-rule-info-type");
Gui18nUtil::SetText(ui->groupBoxType, "feature-rule-info-type");
Gui18nUtil::SetText(ui->groupBoxRuleInfo, "feature-rule-info-ruleinfo");
Gui18nUtil::SetText(ui->labelKeyTips, "feature-rule-info-keytips");
Gui18nUtil::SetText(ui->labelCompageTips, "feature-rule-info-keytips");
Gui18nUtil::SetText(ui->labelNumTips, "feature-rule-info-numtips");
Gui18nUtil::SetText(ui->labelKey, "feature-rule-info-key");
Gui18nUtil::SetText(ui->pushButtonSave, "feature-rule-info-save");
Gui18nUtil::SetText(ui->pushButtonCancel, "feature-rule-info-cancel");
@@ -107,14 +121,26 @@ void FireDogFeatureRuleInfo::slots_radioClick() {
void FireDogFeatureRuleInfo::slots_saveClick() {
this->isOk = true;
//if (ui->radioButtonKey->isChecked()){
// if (ui->lineEditKey->text().isEmpty()) {
// QString titleStr = Gui18n::GetInstance()->GetConfig("text-message-box-title-warning", "Warning");
// QString messageStr = Gui18n::GetInstance()->GetConfig("feature-rule-please-enter-key", "Please enter [Key].");
// QssMessageBox::warn(messageStr, this, titleStr);
// return;
// }
//}
//这个函数主要是校验
if (ui->radioButtonAll->isChecked() || ui->radioButtonCount->isChecked()) {
if (ui->lineEditKey->text().isEmpty()) {
QString titleStr = Gui18n::GetInstance()->GetConfig("text-message-box-title-warning", "Warning");
QString messageStr = Gui18n::GetInstance()->GetConfig("feature-rule-please-enter-key", "Please enter [Key].");
QssMessageBox::warn(messageStr, this, titleStr);
return;
}
}
if (ui->radioButtonLt->isChecked() || ui->radioButtonLe->isChecked() ||
ui->radioButtonGt->isChecked() || ui->radioButtonGe->isChecked()) {
if ((ui->comboBoxNum1Type->currentText() == "$count" && ui->lineEditNum1Count->text().isEmpty())
|| (ui->comboBoxNum2Type->currentText() == "$count" && ui->lineEditNum2Count->text().isEmpty())) {
QString titleStr = Gui18n::GetInstance()->GetConfig("text-message-box-title-warning", "Warning");
QString messageStr = Gui18n::GetInstance()->GetConfig("feature-rule-please-enter-key", "Please enter [Key].");
QssMessageBox::warn(messageStr, this, titleStr);
return;
}
}
this->hide();
}
@@ -128,12 +154,6 @@ bool FireDogFeatureRuleInfo::updateRule(QString* rule, QVector<QString>* childs,
this->isOk = false;
setDefaultValue();
// if (isRoot) {
// //ui->radioButtonKey->setEnabled(false);
// }
//else {
// //ui->radioButtonKey->setEnabled(true);
// }
auto getRuleInfoByStr = [](QString& rulestr) {
int index = rulestr.lastIndexOf(":");
@@ -141,6 +161,30 @@ bool FireDogFeatureRuleInfo::updateRule(QString* rule, QVector<QString>* childs,
return infostr;
};
//根据父节点启用禁用状态
if (parent.isEmpty()) {
ui->radioButtonAll->setEnabled(false);
ui->radioButtonCount->setEnabled(false);
ui->radioButtonInt->setEnabled(false);
ui->radioButtonLt->setEnabled(false);
ui->radioButtonLe->setEnabled(false);
ui->radioButtonGt->setEnabled(false);
ui->radioButtonGe->setEnabled(false);
}
else if (parent == "$lt" || parent == "$le" || parent == "$gt" || parent == "$ge") {
ui->radioButtonAnd->setEnabled(false);
ui->radioButtonOr->setEnabled(false);
ui->radioButtonNot->setEnabled(false);
ui->radioButtonAll->setEnabled(false);
ui->radioButtonLt->setEnabled(false);
ui->radioButtonLe->setEnabled(false);
ui->radioButtonGt->setEnabled(false);
ui->radioButtonGe->setEnabled(false);
}
if (!rule->isEmpty()) {
if (*rule == "$and") {
ui->radioButtonAnd->setChecked(true);
@@ -174,7 +218,7 @@ bool FireDogFeatureRuleInfo::updateRule(QString* rule, QVector<QString>* childs,
else if (*rule == "$ge") {
ui->radioButtonGe->setChecked(true);
}
//设置默认值
if (rule->startsWith("$all") || rule->startsWith("$count")) {
QString infostr = getRuleInfoByStr(*rule);
@@ -186,6 +230,14 @@ bool FireDogFeatureRuleInfo::updateRule(QString* rule, QVector<QString>* childs,
ui->spinBoxInt->setValue(intval);
}
else if (*rule == "$lt" || *rule == "$le" || *rule == "$gt" || *rule == "$ge") {
ui->radioButtonAnd->setEnabled(false);
ui->radioButtonOr->setEnabled(false);
ui->radioButtonNot->setEnabled(false);
ui->radioButtonAll->setEnabled(false);
ui->radioButtonCount->setEnabled(false);
ui->radioButtonInt->setEnabled(false);
QString num1 = childs->at(0);
QString num2 = childs->at(1);
@@ -221,18 +273,87 @@ bool FireDogFeatureRuleInfo::updateRule(QString* rule, QVector<QString>* childs,
this->exec();
if (this->isOk) {
if (ui->radioButtonAnd->isChecked()) {
rule->clear();
rule->append("$and");
}
rule->clear();
rule->append("$and");
}
else if (ui->radioButtonOr->isChecked()) {
rule->clear();
rule->append("$or");
}
}
else if (ui->radioButtonNot->isChecked()) {
rule->clear();
rule->append("$not");
}
/////////////////////////////////////////////
else if (ui->radioButtonAll->isChecked()) {
rule->clear();
rule->append("$all:");
rule->append(ui->lineEditKey->text());
}
else if (ui->radioButtonCount->isChecked()) {
rule->clear();
rule->append("$count:");
rule->append(ui->lineEditKey->text());
}
else if (ui->radioButtonInt->isChecked()) {
rule->clear();
rule->append("$int:");
rule->append(QString::number(ui->spinBoxInt->value()));
}
/////////////////////////////////////////////
else if(ui->radioButtonLt->isChecked() || ui->radioButtonLe->isChecked() || ui->radioButtonGt->isChecked() || ui->radioButtonGe->isChecked()){
rule->clear();
if (ui->radioButtonLt->isChecked()) {
rule->append("$lt");
}
else if (ui->radioButtonLe->isChecked()) {
rule->append("$le");
}
else if (ui->radioButtonGt->isChecked()) {
rule->append("$gt");
}
else if (ui->radioButtonGe->isChecked()) {
rule->append("$ge");
}
childs->clear();
QString num1Str = "";
if (ui->comboBoxNum1Type->currentText()=="$count") {
num1Str.append("$count:");
num1Str.append(ui->lineEditNum1Count->text());
}
else {
num1Str.append("$int1:");
num1Str.append(QString::number(ui->spinBoxNum1Int->value()));
}
QString num2Str = "";
if (ui->comboBoxNum2Type->currentText() == "$count") {
num2Str.append("$count:");
num2Str.append(ui->lineEditNum2Count->text());
}
else {
num2Str.append("$int1:");
num2Str.append(QString::number(ui->spinBoxNum2Int->value()));
}
childs->push_back(num1Str);
childs->push_back(num2Str);
}
/*if (ui->radioButtonAnd->isChecked()) {
rule->clear();
rule->append("$and");
}
else if (ui->radioButtonOr->isChecked()) {
rule->clear();
rule->append("$or");
}
else {
rule->clear();
rule->append(ui->lineEditKey->text());
}
}*/
}
return this->isOk;
@@ -279,5 +400,18 @@ void FireDogFeatureRuleInfo::setDefaultValue() {
ui->stackedWidgetRuleInfo->setCurrentIndex(0);
ui->radioButtonAnd->setEnabled(true);
ui->radioButtonOr->setEnabled(true);
ui->radioButtonNot->setEnabled(true);
ui->radioButtonAll->setEnabled(true);
ui->radioButtonCount->setEnabled(true);
ui->radioButtonInt->setEnabled(true);
ui->radioButtonLt->setEnabled(true);
ui->radioButtonLe->setEnabled(true);
ui->radioButtonGt->setEnabled(true);
ui->radioButtonGe->setEnabled(true);
slots_radioClick();
}
+3 -1
View File
@@ -7,7 +7,7 @@
#include "Qss/Qss.h"
#define FEATURE_RULE_FORMATE_REG_KEY "[0-9a-zA-Z]{0,}"
#define FEATURE_RULE_FORMATE_REG_KEY "[0-9a-zA-Z,]{0,}"
namespace Ui {
class FireDogFeatureRuleInfo;
@@ -33,6 +33,8 @@ private:
Ui::FireDogFeatureRuleInfo *ui;
QValidator* keyValidator = NULL;
QValidator* num1KeyValidator = NULL;
QValidator* num2KeyValidator = NULL;
bool isOk = false;
+2 -2
View File
@@ -435,7 +435,7 @@
<string>Separate multiple ids with commas (,).</string>
</property>
</widget>
<widget class="QWidget" name="">
<widget class="QWidget" name="layoutWidget">
<property name="geometry">
<rect>
<x>150</x>
@@ -476,7 +476,7 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="">
<widget class="QWidget" name="layoutWidget">
<property name="geometry">
<rect>
<x>150</x>
+35 -36
View File
@@ -68,9 +68,9 @@ void MatchWorkThread::run() {
while (true)
{
QByteArray bytes = file.read(WORK_READ_FILE_LENGTH);
bool matchState = match(bytes);
match(bytes);
//匹配到了或者文件读完了
if (bytes.size() < WORK_READ_FILE_LENGTH || matchState) {
if (bytes.size() < WORK_READ_FILE_LENGTH) {
break;
}
}
@@ -99,13 +99,42 @@ void MatchWorkThread::run() {
QByteArray bytes = file.read(WORK_READ_FILE_LENGTH);
readlength = readlength + len;
bool matchState = match(bytes);
match(bytes);
//匹配到了或者文件读完了
if (bytes.size() < WORK_READ_FILE_LENGTH || matchState) {
if (bytes.size() < WORK_READ_FILE_LENGTH) {
break;
}
}
}
vector<MatcherResult*>* result = this->nowWork->matcher->check();
if (result != NULL) {
int sourceId = this->nowWork->sourceId;
int workType = this->nowWork->workType;
QString workContent = this->nowWork->content;
for (int i = 0; i < result->size(); i++) {
MatcherResult* mr = result->at(i);
HitFeature hf;
hf.sourceId = sourceId;
hf.featureId = mr->featureId;
hf.workType = workType;
hf.content = workContent;
hf.name = QString::fromStdString(mr->name);
hf.author = QString::fromStdString(mr->author);
hf.describe = QString::fromStdString(mr->describe);
emit hit(hf);
delete mr;
mr = NULL;
}
delete result;
result = NULL;
}
}
this->state = STATE_NO_ERROR;
@@ -116,43 +145,13 @@ void MatchWorkThread::run() {
emit workSuccess(this->id);
}
bool MatchWorkThread::match(QByteArray byteArray) {
void MatchWorkThread::match(QByteArray byteArray) {
Matcher* matcher = this->nowWork->matcher;
bool matchstate = false;
for (int i = 0; i < byteArray.size(); i++) {
char byte = byteArray.at(i);
vector<MatcherResult*>* result = matcher->matchByte(byte);
if (result != NULL) {
int sourceId = this->nowWork->sourceId;
int workType = this->nowWork->workType;
QString workContent = this->nowWork->content;
for (int i = 0; i < result->size(); i++) {
MatcherResult* mr = result->at(i);
HitFeature hf;
hf.sourceId = sourceId;
hf.featureId = mr->featureId;
hf.workType = workType;
hf.content = workContent;
hf.name = QString::fromStdString(mr->name);
hf.author = QString::fromStdString(mr->author);
hf.describe = QString::fromStdString(mr->describe);
emit hit(hf);
delete mr;
mr = NULL;
}
delete result;
result = NULL;
matchstate = true;
}
matcher->matchByte(byte);
}
return matchstate;
}
int MatchWorkThread::getState() {
+1 -1
View File
@@ -68,7 +68,7 @@ private:
int state;
MatchWork* nowWork = NULL;
bool match(QByteArray byteArray);
void match(QByteArray byteArray);
signals:
void nextWork(MatchWorkThread* misson, int* state);
@@ -127,6 +127,9 @@
"feature-rule-window-title":"Feature Rule Editor",
"feature-rule-info-type":"Type",
"feature-rule-info-ruleinfo":"RuleInfo",
"feature-rule-info-keytips":"Separate multiple ids with commas (,).",
"feature-rule-info-numtips":"Only numbers are allowed.",
"feature-rule-info-key":"Key",
"feature-rule-info-save":"Save",
"feature-rule-info-cancel":"Cancel",
@@ -127,6 +127,9 @@
"feature-rule-window-title":"特征规则编辑器",
"feature-rule-info-type":"类型",
"feature-rule-info-ruleinfo":"规则详情",
"feature-rule-info-keytips":"多个id之间用英文“,”逗号分隔。",
"feature-rule-info-numtips":"只能使用数字。",
"feature-rule-info-key":"Key",
"feature-rule-info-save":"保存",
"feature-rule-info-cancel":"取消",
+68
View File
@@ -1,6 +1,8 @@
# FireDog
开源跨平台轻量级病毒特征检测引擎。Open source cross-platform lightweight virus signature detection engine.
在Releases下载最新版本,跟路径有个demo文件夹,可以参考,并且READEME.txt中也有说明。
# 语言 Language
C++ 11
@@ -32,6 +34,28 @@ https://github.com/MountCloud/FireDog/releases
# 更新日志 Update log
# v1.3.1
```
FireDog Version: v1.3.1
FireDog Editor Version: v2.1
Feature Libraray Version: v1.2.1
1:重构规则引擎,支持多种逻辑运算,支持多种统计运算,支持多种比较运算。
2:重构特征库格式,从json改用yaml(json确实看起来不好看)。
3:更改特征匹配逻辑,将字节匹配与校验匹配结果拆分。
4:编辑器适配新的规则引擎和特征库格式。
1: Refactor the rule engine to support multiple logical operations, multiple statistical operations, and multiple comparison operations.
2: Refactor the feature library format and use yaml instead of json (json does not look good).
3: Change the feature matching logic to split the byte matching and check matching results.
4: The editor adapts to the new rule engine and signature library format.
```
## v1.3.1 界面GUI
### 规则配置GUI Rule Configuration GUI
![](images/v1.3.1-rule-gui.png)
# v1.2.1
@@ -77,6 +101,50 @@ Feature Libraray Version: v1.1.0
Support hex, md5, text type detection.
```
# 说明
## 特征说明 Feature Description
```
key:代表这个特征的标识。
hex:hex是以二进制形式进行匹配的二进制数据,允许模糊匹配如:0F ?0 A? ??。
text:以文本形式匹配的关键字。
key: The identifier representing this feature.
hex: hex is binary data that is matched in binary form, allowing fuzzy matching such as: 0F ?0 A? ??.
text: The keyword to match in text form.
```
## 规则说明 Rules Description
```
$and:[规则数组] 并运算,只有子规则结果全部为true(通过)时,结果为true(通过),如果有一条子规则结果为false(不通过),则结果为false(不通过)。
$or:[规则数组] 或运算,有一条子规则结果全部为true(通过)时,结果为true(通过),如果全部子规则结果为false(不通过),则结果为false(不通过)。
$not:[规则数组] 非运算,只有子规则结果全部为false(不通过)时,结果为true(通过),如果有一条子规则结果为true(通过),则结果为false(不通过)。意思就是如果$not的子规则是$lt($count(key1),$int(5))=$not(key1出现次数小于5)=不能(key1出现的次数小于5)=key1出现的次数需要大于5
$all:[字符串数组] 表示一组key必须至少全部出现1次。$all(key1,key2)表示key1和key2必须至少都出现一次。
$count:*数字规则*[字符串数组] 表示统计key出现的次数。$count(key1,key2)就是统计key1和key2出现的次数。
$int:*数字规则*[数字类型] 表示一个数字。$int(1)代表数字1
$lt:*比较规则*,小于比较,使用两个*数字规则*进行比较,数字规则1 < 数字规则2,则为true(通过)。
$le:*比较规则*,小于等于比较,使用两个*数字规则*进行比较,数字规则1 <= 数字规则2,则为true(通过)。
$gt:*比较规则*,大于比较,使用两个*数字规则*进行比较,数字规则1 > 数字规则2,则为true(通过)。
$ge:*比较规则*,大于等于比较,使用两个*数字规则*进行比较,数字规则1 >= 数字规则2,则为true(通过)。
$and: [rule array] Parallel operation, only when the sub-rule results are all true (pass), the result is true (pass), if there is a sub-rule result is false (fail), the result is false (fail) .
$or: [rule array] OR operation, when one sub-rule result is all true (pass), the result is true (pass), if all sub-rule results are false (fail), the result is false (fail) .
$not: [rule array] Non-operation, only when the sub-rule results are all false (fail), the result is true (pass), if there is a sub-rule result is true (pass), the result is false (fail) . It means that if the sub-rule of $not is $lt($count(key1), $int(5)) = $not (the number of occurrences of key1 is less than 5) = cannot (the number of occurrences of key1 is less than 5) = the number of occurrences of key1 needs to be greater than 5
$all: [string array] Indicates that a set of keys must all appear at least once. $all(key1,key2) means that both key1 and key2 must appear at least once.
$count: *Number rule*[String array] Indicates the number of times the key appears. $count(key1,key2) is to count the number of occurrences of key1 and key2.
$int: *Number Rule* [Number Type] Represents a number. $int(1) represents the number 1
$lt: *comparison rule*, less than comparison, use two *number rule* for comparison, number rule 1 < number rule 2, true (pass).
$le: *comparison rule*, less than or equal comparison, use two *number rule* for comparison, number rule 1 <= number rule 2, it is true (pass).
$gt: *comparison rule*, greater than comparison, use two *number rule* for comparison, number rule 1 > number rule 2, it is true (pass).
$ge: *comparison rule*, greater than or equal to comparison, use two *number rule* for comparison, number rule 1 >= number rule 2, it is true (pass).
```
# 使用 Use
## Step 1: download
Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

+63
View File
@@ -0,0 +1,63 @@
本项目为开源项目,MIT开源协议。
https://github.com/MountCloud/FireDog
1:请使用gui打开/demo/demo.fdog来参考
!!!修改完规则记得点击 添加或修改。修改完规则库记得点击顶部菜单->操作->保存或者另存为!!!
2:特征讲解
key:代表这个特征的标识。
hex:hex是以二进制形式进行匹配的二进制数据,允许模糊匹配如:0F ?0 A? ??。
text:以文本形式匹配的关键字。
3:规则
$and:[规则数组] 并运算,只有子规则结果全部为true(通过)时,结果为true(通过),如果有一条子规则结果为false(不通过),则结果为false(不通过)。
$or:[规则数组] 或运算,有一条子规则结果全部为true(通过)时,结果为true(通过),如果全部子规则结果为false(不通过),则结果为false(不通过)。
$not:[规则数组] 非运算,只有子规则结果全部为false(不通过)时,结果为true(通过),如果有一条子规则结果为true(通过),则结果为false(不通过)。意思就是如果$not的子规则是$lt($count(key1),$int(5))=$not(key1出现次数小于5)=不能(key1出现的次数小于5)=key1出现的次数需要大于5
$all:[字符串数组] 表示一组key必须至少全部出现1次。$all(key1,key2)表示key1和key2必须至少都出现一次。
$count:*数字规则*[字符串数组] 表示统计key出现的次数。$count(key1,key2)就是统计key1和key2出现的次数。
$int:*数字规则*[数字类型] 表示一个数字。$int(1)代表数字1
$lt:*比较规则*,小于比较,使用两个*数字规则*进行比较,数字规则1 < 数字规则2,则为true(通过)。
$le:*比较规则*,小于等于比较,使用两个*数字规则*进行比较,数字规则1 <= 数字规则2,则为true(通过)。
$gt:*比较规则*,大于比较,使用两个*数字规则*进行比较,数字规则1 > 数字规则2,则为true(通过)。
$ge:*比较规则*,大于等于比较,使用两个*数字规则*进行比较,数字规则1 >= 数字规则2,则为true(通过)。
4:demo中的规则描述(请勿复制描述的规则,因为引擎不识别注释):
规则库格式是yaml,yaml语法可以自学一下。
规则建议还是别手写,用gui配置减少错误率,而且gui用起来多爽。
特征库讲解:
这个规则结果是:ab至少出现一次,并且c至少出现一次,并且d至少出现一次,并且a至少出现3次($ge是大于等于),
所以aaabcd能被该规则匹配到:
version: 1.2.1 //当前规则引擎版本号
items: //规则集合
- name: test //单条规则名称
author: mountcloud //作者
describe: test new rule engine. //规则描述
features: //特征集合
- key: key1 //特征的key
text: a //text代表文本类型,hex代表二进制类型
- key: key2
text: b
- key: key3
text: c
- key: key4
text: d
- key: key5
hex: 0F ?0 A? ?? //二进制类型允许使用模糊匹配
rules: //规则
- $and: //(规则是第1层)规则是And类型
- $all: //($and的子规则)All是以下key至少全部都出现一次
- key1
- key2
- $and: //(第一层$and的子规则)
- $all: //(第二层$and的子规则)
- key3
- $all:
- key4
- $ge: //(第一层$and的子规则)$ge是大于比较,比较第一个规则要大于第二个规则
- $count: ($ge的子规则)$count是统计key出现的总数
- key1
- $int: 3 ($ge的子规则)$int代表一个固定数字,这里就是 key1出现的次数要大于3
+28
View File
@@ -0,0 +1,28 @@
version: 1.2.1
items:
- name: test
author: mountcloud
describe: test new rule engine.
features:
- key: key1
text: a
- key: key2
text: b
- key: key3
text: c
- key: key4
text: d
rules:
- $and:
- $all:
- key1
- key2
- $and:
- $all:
- key3
- $all:
- key4
- $ge:
- $count:
- key1
- $int: 3
+57
View File
@@ -0,0 +1,57 @@
1:请使用gui打开/demo/demo.fdog来参考
!!!修改完规则记得点击 添加或修改。修改完规则库记得点击顶部菜单->操作->保存或者另存为!!!
2:特征讲解
key:代表这个特征的标识。
hex:hex是以二进制形式进行匹配的二进制数据,允许模糊匹配如:0F ?0 A? ??。
text:以文本形式匹配的关键字。
3:规则
$and:[规则数组] 并运算,只有子规则结果全部为true(通过)时,结果为true(通过),如果有一条子规则结果为false(不通过),则结果为false(不通过)。
$or:[规则数组] 或运算,有一条子规则结果全部为true(通过)时,结果为true(通过),如果全部子规则结果为false(不通过),则结果为false(不通过)。
$not:[规则数组] 非运算,只有子规则结果全部为false(不通过)时,结果为true(通过),如果有一条子规则结果为true(通过),则结果为false(不通过)。意思就是如果$not的子规则是$lt($count(key1),$int(5))=$not(key1出现次数小于5)=不能(key1出现的次数小于5)=key1出现的次数需要大于5
$all:[字符串数组] 表示一组key必须至少全部出现1次。$all(key1,key2)表示key1和key2必须至少都出现一次。
$count:*数字规则*[字符串数组] 表示统计key出现的次数。$count(key1,key2)就是统计key1和key2出现的次数。
$int:*数字规则*[数字类型] 表示一个数字。$int(1)代表数字1
$lt:*比较规则*,小于比较,使用两个*数字规则*进行比较,数字规则1 < 数字规则2,则为true(通过)。
$le:*比较规则*,小于等于比较,使用两个*数字规则*进行比较,数字规则1 <= 数字规则2,则为true(通过)。
$gt:*比较规则*,大于比较,使用两个*数字规则*进行比较,数字规则1 > 数字规则2,则为true(通过)。
$ge:*比较规则*,大于等于比较,使用两个*数字规则*进行比较,数字规则1 >= 数字规则2,则为true(通过)。
4:demo中的规则描述(请勿复制描述的规则,因为引擎不识别注释):
规则库格式是yaml,yaml语法可以自学一下。
规则建议还是别手写,用gui配置减少错误率,而且gui用起来多爽。
特征库讲解:
version: 1.2.1 //当前规则引擎版本号
items: //规则集合
- name: test //单条规则名称
author: mountcloud //作者
describe: test new rule engine. //规则描述
features: //特征集合
- key: key1 //特征的key
text: a //text代表文本类型,hex代表二进制类型
- key: key2
text: b
- key: key3
text: c
- key: key4
text: d
- key: key5
hex: 0F ?0 A? ?? //二进制类型允许使用模糊匹配
rules: //规则
- $and: //(规则是第1层)规则是And类型
- $all: //($and的子规则)All是以下key至少全部都出现一次
- key1
- key2
- $and: //(第一层$and的子规则)
- $all: //(第二层$and的子规则)
- key3
- $all:
- key4
- $ge: //(第一层$and的子规则)$ge是大于比较,比较第一个规则要大于第二个规则
- $count: ($ge的子规则)$count是统计key出现的总数
- key1
- $int: 3 ($ge的子规则)$int代表一个固定数字,这里就是 key1出现的次数要大于3