mirror of
https://github.com/MountCloud/FireDog.git
synced 2026-10-16 20:20:49 +08:00
1:重构规则引擎,支持多种逻辑运算,支持多种统计运算,支持多种比较运算。
2:重构特征库格式,从json改用yaml(json确实看起来不好看)。 3:更改特征匹配逻辑,将字节匹配与校验匹配结果拆分。 4:编辑器适配新的规则引擎和特征库格式。
This commit is contained in:
+118
-319
@@ -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) {
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
//匹配管家
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -18,8 +18,6 @@ FireDogFeatureInfo::FireDogFeatureInfo(QWidget *parent) :
|
||||
|
||||
|
||||
void FireDogFeatureInfo::init() {
|
||||
|
||||
|
||||
QRegExp hexregx(FEATURE_FORMATE_REG_HEX);
|
||||
this->hexValidator = new QRegExpValidator(hexregx, ui->lineEditContent);
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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":"取消",
|
||||
|
||||
@@ -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
|
||||

|
||||
|
||||
|
||||
# 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 |
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user