From 7f94254a8ab642e74e11e083563dcb8ca2051098 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=88=98=E6=B4=AA=E6=B4=AA?= <2498601771@qq.com>
Date: Tue, 29 Aug 2023 19:12:49 +0800
Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=AE=9E=E4=BD=93?=
=?UTF-8?q?=E6=90=9C=E7=B4=A2=E6=A1=86=E5=A6=82=E4=B8=8B=E9=97=AE=E9=A2=98?=
=?UTF-8?q?=EF=BC=9A1.=E6=A8=A1=E7=B3=8A=E6=90=9C=E7=B4=A2=E4=B8=8E?=
=?UTF-8?q?=E7=B2=BE=E5=87=86=E6=90=9C=E7=B4=A2=E5=B9=B6=E5=88=97=E6=97=B6?=
=?UTF-8?q?=E6=8A=A5=E9=94=99=EF=BC=8C=E4=BB=A5=E5=8F=8A=E6=90=9C=E7=B4=A2?=
=?UTF-8?q?value=E5=8C=85=E5=90=ABand=E5=AF=BC=E8=87=B4=E6=90=9C=E7=B4=A2?=
=?UTF-8?q?=E5=BC=82=E5=B8=B8=EF=BC=9B2.tag=E6=A8=A1=E5=BC=8F=E6=B8=85?=
=?UTF-8?q?=E9=99=A4=E6=90=9C=E7=B4=A2=E6=9D=A1=E4=BB=B6=E5=90=8E=EF=BC=8C?=
=?UTF-8?q?=E8=BD=ACtext=E6=A8=A1=E5=BC=8F=E5=8F=88=E6=81=A2=E5=A4=8D?=
=?UTF-8?q?=EF=BC=9B3.tag=E6=A8=A1=E5=BC=8F=E4=B8=8Bhas=E5=8F=B3=E6=8B=AC?=
=?UTF-8?q?=E5=8F=B7=E6=98=AF=E5=85=A8=E8=A7=92=EF=BC=9B4.=E7=82=B9?=
=?UTF-8?q?=E5=87=BB=E5=B7=A6=E4=BE=A7tag=E6=9D=A1=E4=BB=B6=E6=97=B6?=
=?UTF-8?q?=EF=BC=8C=E6=90=9C=E7=B4=A2=E8=AF=AD=E5=8F=A5=E5=BA=94=E6=98=AF?=
=?UTF-8?q?has=EF=BC=9B5.tag=E6=A8=A1=E5=BC=8F=E4=B8=8B=EF=BC=8C=E5=A4=9A?=
=?UTF-8?q?=E4=B8=AA=E6=9D=A1=E4=BB=B6=E4=B8=94=E5=85=B6=E4=B8=AD=E4=B8=80?=
=?UTF-8?q?=E4=B8=AA=E4=B8=BA=E5=85=A8=E6=96=87=E6=A3=80=E7=B4=A2=E6=97=B6?=
=?UTF-8?q?=EF=BC=8C=E5=85=A8=E6=96=87=E6=A3=80=E7=B4=A2=E5=9C=A8=E8=AF=B7?=
=?UTF-8?q?=E6=B1=82=E5=8F=82=E6=95=B0=E4=B8=AD=E4=B8=A2=E5=A4=B1=E3=80=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/components/advancedSearch/TagMode.vue | 7 +-
src/components/advancedSearch/meta/parser.js | 11 ++
src/utils/tools.js | 111 +++++++++++++++----
3 files changed, 107 insertions(+), 22 deletions(-)
diff --git a/src/components/advancedSearch/TagMode.vue b/src/components/advancedSearch/TagMode.vue
index 65ca98dd..2debfcad 100644
--- a/src/components/advancedSearch/TagMode.vue
+++ b/src/components/advancedSearch/TagMode.vue
@@ -31,7 +31,7 @@
{{meta.column.label}}
- {{ meta.operator.value.toUpperCase() }}
+ {{ meta.operator.value }}
{{meta.operator.value}}
@@ -44,7 +44,7 @@
{{meta.value.label}}
- )
+ )
@@ -446,6 +446,9 @@ export default {
},
cleanMetaList () {
this.metaList = []
+ const routeQuery = this.$route.query
+ delete routeQuery.q
+ this.reloadUrl(routeQuery, 'cleanOldParams')
}
},
mounted () {
diff --git a/src/components/advancedSearch/meta/parser.js b/src/components/advancedSearch/meta/parser.js
index ca890c5f..e609f8c0 100644
--- a/src/components/advancedSearch/meta/parser.js
+++ b/src/components/advancedSearch/meta/parser.js
@@ -3,6 +3,7 @@ import Token, { types } from './token'
import ParserError, { errorTypes, errorDesc } from '@/components/advancedSearch/meta/error'
import _ from 'lodash'
import { columnList } from '@/utils/static-data'
+import { getEntityTypeByValue } from '@/utils/tools'
const strReg = {
all: /^[\da-zA-Z\s.'> {
+ if (item.column.type === 'fullText') {
+ item.operator.value = '='
+ item.value.value = item.column.label
+ item.value.label = item.column.label
+ item.column.label = getEntityTypeByValue(item.column.label)
+ item.column.type = 'string'
+ }
+ })
// 长度为1时,即模糊搜索,例如搜索框值为1.1.1.1,则直接返回1.1.1.1
// 如果为IP='1.1.1.1'的情况,则从metaList拼接成IP='1.1.1.1'返回出去
if (metaList && metaList.length === 1) {
diff --git a/src/utils/tools.js b/src/utils/tools.js
index a01b6308..35a8e809 100644
--- a/src/utils/tools.js
+++ b/src/utils/tools.js
@@ -1411,6 +1411,7 @@ export function comparedEntityKey (str) {
// 判断是否包含=或者in
const keyEqual = item.substring(0, item.indexOf('='))
const keyIn = item.substring(0, item.indexOf(' IN '))
+ const keyLike = item.substring(0, item.indexOf(' LIKE '))
let keyHas // 目前只有Tag操作符为has函数,避免以后会增加其他实体使用has,故不单独将has作为tag使用
let objHas
@@ -1421,10 +1422,13 @@ export function comparedEntityKey (str) {
const objEqual = columnList.find(t => t.label.toLowerCase() === keyEqual.toLowerCase())
const objIn = columnList.find(t => t.label.toLowerCase() === keyIn.toLowerCase())
+ const objLike = columnList.find(t => t.label.toLowerCase() === keyLike.toLowerCase())
if (objEqual) {
newQ += objEqual.label + item.substring(item.indexOf('='), item.length) + ' AND '
} else if (objIn) {
newQ += objIn.label + item.substring(item.indexOf(' IN '), item.length) + ' AND '
+ } else if (objLike) {
+ newQ += objLike.label + item.substring(item.indexOf(' LIKE '), item.length) + ' AND '
} else if (objHas) {
newQ += item.substring(item.indexOf(' has'), item.length) + ' AND '
} else {
@@ -1494,9 +1498,51 @@ export const handleEntityTypeByStr = (str) => {
}
// 检查str字段在arr中是否出现,true为出现过
const result = arr.some(item => newStr.includes(item))
- if (result) {
+ if (newStr.indexOf(' and ') > -1) {
+ // 将单引号包裹的and拿出来放到数组tempList里,原来的单引号包裹内容用temp即'it is test keyword{键值}'代替
+ // 再将字符串用and转换为数组,遍历数组,发现值为temp的,获取键值,根据键值获取tempList的值组合起来,
+ // 最后将键值删除,后续再多次测试验证
+ const tempList = []
+ const regex = /'([^']*?)'/g
+ let match
+
+ // 将单引号包裹的and内容集合起来
+ while ((match = regex.exec(str)) !== null) {
+ if (match[1].includes('and')) {
+ tempList.push(match[1])
+ }
+ }
+
+ // 将单引号包裹的and内容用特殊值代替
+ tempList.forEach((item, index) => {
+ const regex = new RegExp(item, 'g')
+ str = str.replace(regex, `it is test keyword${index}`)
+ })
+
+ const noAndList = str.split(' and ')
+ noAndList.forEach((item, index) => {
+ // 发现插入的特殊值,获取键值,根据键值替换成原来内容,删除键值
+ if (item.indexOf('it is test keyword') > -1) {
+ const regex = /\d+/g
+ const result1 = item.match(regex)
+ noAndList[index] = noAndList[index].replace(result1[0], '')
+ noAndList[index] = noAndList[index].replace('it is test keyword', tempList[result1[0]])
+ }
+ })
+
+ const newArr = noAndList
+ newArr.forEach((item, index) => {
+ if (!arr.some(ite => item.includes(ite))) {
+ // item = checkFormatByStr(item)
+ newArr[index] = checkFormatByStr(item)
+ }
+ })
+
+ str = newArr.join(' and ')
return str
- } else {
+ } else if (result) {
+ return str
+ } else if (!result) {
const regex = /^["']|["']$/
// 去除两侧引号,如'1.1.1.1',避免校验时被当作app
if (regex.test(str)) {
@@ -1504,24 +1550,49 @@ export const handleEntityTypeByStr = (str) => {
}
}
- // ipv4校验
- const regexIPv4 = /^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
- // ipv6校验
- const regexIPv6 = /^(?:(?:[0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4}|(?:[0-9A-Fa-f]{1,4}:){1,7}:|(?:[0-9A-Fa-f]{1,4}:){1,6}:[0-9A-Fa-f]{1,4}|(?:[0-9A-Fa-f]{1,4}:){1,5}(?::[0-9A-Fa-f]{1,4}){1,2}|(?:[0-9A-Fa-f]{1,4}:){1,4}(?::[0-9A-Fa-f]{1,4}){1,3}|(?:[0-9A-Fa-f]{1,4}:){1,3}(?::[0-9A-Fa-f]{1,4}){1,4}|(?:[0-9A-Fa-f]{1,4}:){1,2}(?::[0-9A-Fa-f]{1,4}){1,5}|[0-9A-Fa-f]{1,4}:(?:(?::[0-9A-Fa-f]{1,4}){1,6})|:(?:(?::[0-9A-Fa-f]{1,4}){1,7}|:)|fe80:(?::[0-9A-Fa-f]{0,4}){0,4}%\w+|::(?:ffff(?::0{1,4}){0,1}:){0,1}(?:(?:2[0-4]|1\d|[1-9])?\d|25[0-5])\.(?:(?:2[0-4]|1\d|[1-9])?\d|25[0-5])\.(?:(?:2[0-4]|1\d|[1-9])?\d|25[0-5])\.(?:(?:2[0-4]|1\d|[1-9])?\d|25[0-5])|(?:[0-9A-Fa-f]{1,4}:){1,4}:192\.88\.99\.(\d{1,3})|(?:[0-9A-Fa-f]{1,4}:){1,4}:192\.0\.2\.(\d{1,3})|(?:[0-9A-Fa-f]{1,4}:){1,4}:(?:[0-9A-Fa-f]{1,4}:){0,1}192\.0\.0\.(\d{1,3})|ff00:(?::[0-9A-Fa-f]{0,4}){0,4}|(?:[0-9A-Fa-f]{1,4}:){1,4}:255\.255\.255\.255)$/
- // domain校验
- const reg = /^(?=^.{3,255}$)(http(s)?:\/\/)?(www\.)?[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+(:\d+)*(\/\w+\.\w+)*$/
+ return checkFormatByStr(str)
+ }
+}
+/**
+ * 校验字符串格式,如ip、domain、app
+ */
+const checkFormatByStr = (str) => {
+ // ipv4校验
+ const regexIPv4 = /^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
+ // ipv6校验
+ const regexIPv6 = /^(?:(?:[0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4}|(?:[0-9A-Fa-f]{1,4}:){1,7}:|(?:[0-9A-Fa-f]{1,4}:){1,6}:[0-9A-Fa-f]{1,4}|(?:[0-9A-Fa-f]{1,4}:){1,5}(?::[0-9A-Fa-f]{1,4}){1,2}|(?:[0-9A-Fa-f]{1,4}:){1,4}(?::[0-9A-Fa-f]{1,4}){1,3}|(?:[0-9A-Fa-f]{1,4}:){1,3}(?::[0-9A-Fa-f]{1,4}){1,4}|(?:[0-9A-Fa-f]{1,4}:){1,2}(?::[0-9A-Fa-f]{1,4}){1,5}|[0-9A-Fa-f]{1,4}:(?:(?::[0-9A-Fa-f]{1,4}){1,6})|:(?:(?::[0-9A-Fa-f]{1,4}){1,7}|:)|fe80:(?::[0-9A-Fa-f]{0,4}){0,4}%\w+|::(?:ffff(?::0{1,4}){0,1}:){0,1}(?:(?:2[0-4]|1\d|[1-9])?\d|25[0-5])\.(?:(?:2[0-4]|1\d|[1-9])?\d|25[0-5])\.(?:(?:2[0-4]|1\d|[1-9])?\d|25[0-5])\.(?:(?:2[0-4]|1\d|[1-9])?\d|25[0-5])|(?:[0-9A-Fa-f]{1,4}:){1,4}:192\.88\.99\.(\d{1,3})|(?:[0-9A-Fa-f]{1,4}:){1,4}:192\.0\.2\.(\d{1,3})|(?:[0-9A-Fa-f]{1,4}:){1,4}:(?:[0-9A-Fa-f]{1,4}:){0,1}192\.0\.0\.(\d{1,3})|ff00:(?::[0-9A-Fa-f]{0,4}){0,4}|(?:[0-9A-Fa-f]{1,4}:){1,4}:255\.255\.255\.255)$/
+ // domain校验
+ const reg = /^(?=^.{3,255}$)(http(s)?:\/\/)?(www\.)?[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+(:\d+)*(\/\w+\.\w+)*$/
- if (regexIPv4.test(str) || regexIPv6.test(str)) {
- const obj = columnList.find(t => t.label.toLowerCase() === 'ip')
- return `${obj.label}='${str}'`
- } else if (reg.test(str)) {
- // 只写作domain即可,schema字段更改几次,避免后续再更改,直接拿columnList的label进行替换
- const obj = columnList.find(t => t.label.toLowerCase() === 'domain')
- return `${obj.label} LIKE '%${str}'`
- } else {
- const obj = columnList.find(t => t.label.toLowerCase() === 'app')
- return `${obj.label} LIKE '%${str}%'`
- }
+ if (regexIPv4.test(str) || regexIPv6.test(str)) {
+ const obj = columnList.find(t => t.label.toLowerCase() === 'ip')
+ return `${obj.label}='${str}'`
+ } else if (reg.test(str)) {
+ // 只写作domain即可,schema字段更改几次,避免后续再更改,直接拿columnList的label进行替换
+ const obj = columnList.find(t => t.label.toLowerCase() === 'domain')
+ return `${obj.label} LIKE '%${str}'`
+ } else {
+ const obj = columnList.find(t => t.label.toLowerCase() === 'app')
+ return `${obj.label} LIKE '%${str}%'`
+ }
+}
+export const getEntityTypeByValue = (str) => {
+ // ipv4校验
+ const regexIPv4 = /^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
+ // ipv6校验
+ const regexIPv6 = /^(?:(?:[0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4}|(?:[0-9A-Fa-f]{1,4}:){1,7}:|(?:[0-9A-Fa-f]{1,4}:){1,6}:[0-9A-Fa-f]{1,4}|(?:[0-9A-Fa-f]{1,4}:){1,5}(?::[0-9A-Fa-f]{1,4}){1,2}|(?:[0-9A-Fa-f]{1,4}:){1,4}(?::[0-9A-Fa-f]{1,4}){1,3}|(?:[0-9A-Fa-f]{1,4}:){1,3}(?::[0-9A-Fa-f]{1,4}){1,4}|(?:[0-9A-Fa-f]{1,4}:){1,2}(?::[0-9A-Fa-f]{1,4}){1,5}|[0-9A-Fa-f]{1,4}:(?:(?::[0-9A-Fa-f]{1,4}){1,6})|:(?:(?::[0-9A-Fa-f]{1,4}){1,7}|:)|fe80:(?::[0-9A-Fa-f]{0,4}){0,4}%\w+|::(?:ffff(?::0{1,4}){0,1}:){0,1}(?:(?:2[0-4]|1\d|[1-9])?\d|25[0-5])\.(?:(?:2[0-4]|1\d|[1-9])?\d|25[0-5])\.(?:(?:2[0-4]|1\d|[1-9])?\d|25[0-5])\.(?:(?:2[0-4]|1\d|[1-9])?\d|25[0-5])|(?:[0-9A-Fa-f]{1,4}:){1,4}:192\.88\.99\.(\d{1,3})|(?:[0-9A-Fa-f]{1,4}:){1,4}:192\.0\.2\.(\d{1,3})|(?:[0-9A-Fa-f]{1,4}:){1,4}:(?:[0-9A-Fa-f]{1,4}:){0,1}192\.0\.0\.(\d{1,3})|ff00:(?::[0-9A-Fa-f]{0,4}){0,4}|(?:[0-9A-Fa-f]{1,4}:){1,4}:255\.255\.255\.255)$/
+ // domain校验
+ const reg = /^(?=^.{3,255}$)(http(s)?:\/\/)?(www\.)?[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+(:\d+)*(\/\w+\.\w+)*$/
+
+ if (regexIPv4.test(str) || regexIPv6.test(str)) {
+ const obj = columnList.find(t => t.label.toLowerCase() === 'ip')
+ return obj.label
+ } else if (reg.test(str)) {
+ const obj = columnList.find(t => t.label.toLowerCase() === 'domain')
+ return obj.label
+ } else {
+ const obj = columnList.find(t => t.label.toLowerCase() === 'app')
+ return obj.label
}
}
/**
@@ -1620,7 +1691,7 @@ const combineLabel1 = (list) => {
* @param str
*/
const checkStrIncludeAnd = (str) => {
- const arr = str.split(' AND ')
+ const arr = str.split(' and ')
let label = ''
arr.forEach((item, index) => {