diff --git a/cve-agency-manager/controllers/live.go b/cve-agency-manager/controllers/live.go
index 951bc7c2b3af37e206ae8b8e4387eefd13f3fd0e..1c77344bcbf5f4ef1ba1aac13c2b46a5cb90281d 100644
--- a/cve-agency-manager/controllers/live.go
+++ b/cve-agency-manager/controllers/live.go
@@ -15,7 +15,7 @@ func (c *TriggerHeartbeatreadController) RetCveData(resp map[string]interface{})
// @Title Heartbeatreadiness
// @Description Heartbeatreadiness
-// @Param body body models.Heartbeatreadiness true "body for Heartbeatreadiness content"
+// @Param body body models.Heartbeatreadiness true
// @Success 200 {int} models.Id
// @Failure 403 body is empty
// @router / [get]
@@ -38,7 +38,7 @@ func (c *TriggerHeartbeatLiveController) RetCveData(resp map[string]interface{})
// @Title HeartbeatLive check
// @Description get HeartbeatLive
-// @Param nil
+// @Param body body models.Heartbeatreadiness true
// @Success 200 {int}
// @Failure 403 :status is err
// @router / [get]
diff --git a/cve-agency-manager/controllers/object.go b/cve-agency-manager/controllers/object.go
index d05eaf6f437be50215ed03c9022ae1f053ebf23b..ee28d544312a0ad121b7f4435e14f55eada3a6e1 100644
--- a/cve-agency-manager/controllers/object.go
+++ b/cve-agency-manager/controllers/object.go
@@ -1,9 +1,8 @@
package controllers
import (
- "cve-agency-service/models"
+ "cve-agency-manager/models"
"encoding/json"
-
"github.com/astaxie/beego"
)
diff --git a/cve-agency-manager/controllers/track.go b/cve-agency-manager/controllers/track.go
index 63d2e1f7af135f52954e44ad1393661ea945c72b..c85e1630d4ea0a9c6c071bde9d02f31b7c60eb22 100644
--- a/cve-agency-manager/controllers/track.go
+++ b/cve-agency-manager/controllers/track.go
@@ -1,7 +1,7 @@
package controllers
import (
- "cve-agency-service/common"
+ "cve-agency-manager/common"
"encoding/json"
"os/exec"
@@ -24,11 +24,13 @@ type CveReqPramData struct {
PackVersion string `json:"packVersion"`
IssueNumber string `json:"issueNumber"`
AffectBranch string `json:"affectBranch"`
+ CveUrl string `json:"cveUrl"`
+ PatchUrl string `json:"patchUrl"`
}
// @Title TriggerTrack
// @Description Trigger Track
-// @Param body body models.TriggerTrack true "body for TriggerTrack content"
+// @Param body body models.TriggerTrack true
// @Success 200 {int} models.Id
// @Failure 403 body is empty
// @router / [post]
@@ -45,7 +47,12 @@ func (c *TriggerTrackController) Post() {
logs.Info("trigger track request parameters: ", string(c.Ctx.Input.RequestBody))
// Call python script
pythonFile := beego.AppConfig.String("python_conf::python_file")
- args := []string{pythonFile, "comment", "-c", cvePram.CveNum, "-r", cvePram.PackName, "-i", cvePram.IssueNumber}
+ args := []string{}
+ if len(cvePram.CveUrl) > 1 || len(cvePram.PatchUrl) > 1 {
+ args = []string{pythonFile, "feedback", "-c", cvePram.CveNum, "-p", cvePram.CveUrl, "-u", cvePram.PatchUrl}
+ } else {
+ args = []string{pythonFile, "comment", "-c", cvePram.CveNum, "-r", cvePram.PackName, "-i", cvePram.IssueNumber}
+ }
//args := []string{pythonFile}
out, err := exec.Command("python3", args...).Output()
if err != nil {
diff --git a/cve-agency-manager/controllers/user.go b/cve-agency-manager/controllers/user.go
index afd18fd816f5e0669cb8ebe4610a476a391a668f..b473a659719fba4dc8921c0300e4fc0446550b53 100644
--- a/cve-agency-manager/controllers/user.go
+++ b/cve-agency-manager/controllers/user.go
@@ -1,9 +1,8 @@
package controllers
import (
- "cve-agency-service/models"
+ "cve-agency-manager/models"
"encoding/json"
-
"github.com/astaxie/beego"
)
diff --git a/cve-agency-manager/cve_tracking/core/platform/bugzila.py b/cve-agency-manager/cve_tracking/core/platform/bugzila.py
new file mode 100644
index 0000000000000000000000000000000000000000..81852a2427deca60a1a764789849e3b6f7194edd
--- /dev/null
+++ b/cve-agency-manager/cve_tracking/core/platform/bugzila.py
@@ -0,0 +1,42 @@
+#!/usr/bin/python3
+# ******************************************************************************
+# Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved.
+# licensed under the Mulan PSL v2.
+# You can use this software according to the terms and conditions of the Mulan PSL v2.
+# You may obtain a copy of Mulan PSL v2 at:
+# http://license.coscl.org.cn/MulanPSL2
+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+# PURPOSE.
+# See the Mulan PSL v2 for more details.
+# ******************************************************************************/
+import json
+from json import JSONDecodeError
+
+from constant import Constant
+from core.platform.cve_platform import CvePlatform
+from logger import logger
+
+
+class Bugzilla(CvePlatform):
+ """
+ cve refer to the URL bugzilla to find the patch implementation class
+ """
+
+ def __init__(self, cve_num, base_url=Constant.BUGZILLA_BASE_URL):
+ super(Bugzilla, self).__init__(cve_num, base_url)
+
+ @staticmethod
+ def format_text(text):
+ """
+ Rewrite the formatted web page to get the content method
+ :param text: content of web page
+ :return: formatted content
+ """
+ try:
+ text_dict = json.loads(text)
+ return json.dumps(text_dict, indent=4)
+ except JSONDecodeError as e:
+ logger.error(f'The format of the content obtained by bugzilla website is incorrect, '
+ f'content is {text}, message is {e.msg}')
+ return None
diff --git a/cve-agency-manager/cve_tracking/core/platform/debian.py b/cve-agency-manager/cve_tracking/core/platform/debian.py
new file mode 100644
index 0000000000000000000000000000000000000000..a50d2807475a65bc45868eae91dad6f06d1db2b2
--- /dev/null
+++ b/cve-agency-manager/cve_tracking/core/platform/debian.py
@@ -0,0 +1,23 @@
+#!/usr/bin/python3
+# ******************************************************************************
+# Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved.
+# licensed under the Mulan PSL v2.
+# You can use this software according to the terms and conditions of the Mulan PSL v2.
+# You may obtain a copy of Mulan PSL v2 at:
+# http://license.coscl.org.cn/MulanPSL2
+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+# PURPOSE.
+# See the Mulan PSL v2 for more details.
+# ******************************************************************************/
+from constant import Constant
+from core.platform.cve_platform import CvePlatform
+
+
+class Debian(CvePlatform):
+ """
+ cve refer to the URL debian to find the patch implementation class
+ """
+
+ def __init__(self, cve_num, base_url=Constant.DEBIAN_BASE_URL):
+ super(Debian, self).__init__(cve_num, base_url)
diff --git a/cve-agency-manager/cve_tracking/core/platform/nvd.py b/cve-agency-manager/cve_tracking/core/platform/nvd.py
new file mode 100644
index 0000000000000000000000000000000000000000..98a5efc26ec19663a5b4d918a691cd4d4bf681d7
--- /dev/null
+++ b/cve-agency-manager/cve_tracking/core/platform/nvd.py
@@ -0,0 +1,23 @@
+#!/usr/bin/python3
+# ******************************************************************************
+# Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved.
+# licensed under the Mulan PSL v2.
+# You can use this software according to the terms and conditions of the Mulan PSL v2.
+# You may obtain a copy of Mulan PSL v2 at:
+# http://license.coscl.org.cn/MulanPSL2
+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+# PURPOSE.
+# See the Mulan PSL v2 for more details.
+# ******************************************************************************/
+from constant import Constant
+from core.platform.cve_platform import CvePlatform
+
+
+class Nvd(CvePlatform):
+ """
+ cve refer to the URL nvd to find the patch implementation class
+ """
+
+ def __init__(self, cve_num, base_url=Constant.NVD_BASE_URL):
+ super(Nvd, self).__init__(cve_num, base_url)
diff --git a/cve-agency-manager/cve_tracking/core/platform/suse.py b/cve-agency-manager/cve_tracking/core/platform/suse.py
new file mode 100644
index 0000000000000000000000000000000000000000..f5d6a5e3777bd54863ec1062266e45ead7279cb2
--- /dev/null
+++ b/cve-agency-manager/cve_tracking/core/platform/suse.py
@@ -0,0 +1,23 @@
+#!/usr/bin/python3
+# ******************************************************************************
+# Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved.
+# licensed under the Mulan PSL v2.
+# You can use this software according to the terms and conditions of the Mulan PSL v2.
+# You may obtain a copy of Mulan PSL v2 at:
+# http://license.coscl.org.cn/MulanPSL2
+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+# PURPOSE.
+# See the Mulan PSL v2 for more details.
+# ******************************************************************************/
+from constant import Constant
+from core.platform import CvePlatform
+
+
+class Suse(CvePlatform):
+ """
+ cve refer to the URL suse to find the patch implementation class
+ """
+
+ def __init__(self, cve_num, base_url=Constant.SUSE_BASE_URL):
+ super(Suse, self).__init__(cve_num, base_url)
diff --git a/cve-agency-manager/cve_tracking/core/platform/ubuntu.py b/cve-agency-manager/cve_tracking/core/platform/ubuntu.py
new file mode 100644
index 0000000000000000000000000000000000000000..d3446bb3bd10af80e30465eb2a1b1b67cf42fa50
--- /dev/null
+++ b/cve-agency-manager/cve_tracking/core/platform/ubuntu.py
@@ -0,0 +1,23 @@
+#!/usr/bin/python3
+# ******************************************************************************
+# Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved.
+# licensed under the Mulan PSL v2.
+# You can use this software according to the terms and conditions of the Mulan PSL v2.
+# You may obtain a copy of Mulan PSL v2 at:
+# http://license.coscl.org.cn/MulanPSL2
+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+# PURPOSE.
+# See the Mulan PSL v2 for more details.
+# ******************************************************************************/
+from constant import Constant
+from core.platform.cve_platform import CvePlatform
+
+
+class Ubuntu(CvePlatform):
+ """
+ cve refer to the URL ubuntu to find the patch implementation class
+ """
+
+ def __init__(self, cve_num, base_url=Constant.UBUNTU_BASE_URL):
+ super(Ubuntu, self).__init__(cve_num, base_url)
diff --git a/cve-agency-manager/cve_tracking/setup.py b/cve-agency-manager/cve_tracking/setup.py
new file mode 100644
index 0000000000000000000000000000000000000000..5ae0bfceb2d7be2adfdedb02f31b7dca332af059
--- /dev/null
+++ b/cve-agency-manager/cve_tracking/setup.py
@@ -0,0 +1,27 @@
+#!/usr/bin/python3
+# ******************************************************************************
+# Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved.
+# licensed under the Mulan PSL v2.
+# You can use this software according to the terms and conditions of the Mulan PSL v2.
+# You may obtain a copy of Mulan PSL v2 at:
+# http://license.coscl.org.cn/MulanPSL2
+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+# PURPOSE.
+# See the Mulan PSL v2 for more details.
+# ******************************************************************************/
+from setuptools import setup, find_packages
+
+
+setup(
+ name='automatic-cve',
+ version='0.0.1',
+ packages=find_packages("src"),
+ package_dir={"": "src"},
+ install_requires=['requests (==2.21.0)',
+ 'retrying(==1.3.3)'],
+ license='Automatic acquisition of CVE',
+ long_description=open('README.md', encoding='utf-8').read(),
+ author='gongzt',
+ zip_safe=False
+)
diff --git a/cve-agency-manager/cve_tracking/src/__init__.py b/cve-agency-manager/cve_tracking/src/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..6851032853d1af6ec5065266cf9d86c2bd1c0b3c
--- /dev/null
+++ b/cve-agency-manager/cve_tracking/src/__init__.py
@@ -0,0 +1,12 @@
+#!/usr/bin/python3
+# ******************************************************************************
+# Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved.
+# licensed under the Mulan PSL v2.
+# You can use this software according to the terms and conditions of the Mulan PSL v2.
+# You may obtain a copy of Mulan PSL v2 at:
+# http://license.coscl.org.cn/MulanPSL2
+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+# PURPOSE.
+# See the Mulan PSL v2 for more details.
+# ******************************************************************************/
diff --git a/cve-agency-manager/cve_tracking/src/cve.py b/cve-agency-manager/cve_tracking/src/cve.py
new file mode 100644
index 0000000000000000000000000000000000000000..dd4654e3841d8646bf764244560662276d3444d4
--- /dev/null
+++ b/cve-agency-manager/cve_tracking/src/cve.py
@@ -0,0 +1,17 @@
+#!/usr/bin/python3
+# ******************************************************************************
+# Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved.
+# licensed under the Mulan PSL v2.
+# You can use this software according to the terms and conditions of the Mulan PSL v2.
+# You may obtain a copy of Mulan PSL v2 at:
+# http://license.coscl.org.cn/MulanPSL2
+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+# PURPOSE.
+# See the Mulan PSL v2 for more details.
+# ******************************************************************************/
+import sys
+from cve.cli import main
+
+
+main(sys.argv[1:], exit_code=True)
diff --git a/cve-agency-manager/cve_tracking/src/cve/__init__.py b/cve-agency-manager/cve_tracking/src/cve/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..0bd4560a08f201568445a22ffcdf8bbe9765df76
--- /dev/null
+++ b/cve-agency-manager/cve_tracking/src/cve/__init__.py
@@ -0,0 +1,16 @@
+#!/usr/bin/python3
+# ******************************************************************************
+# Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved.
+# licensed under the Mulan PSL v2.
+# You can use this software according to the terms and conditions of the Mulan PSL v2.
+# You may obtain a copy of Mulan PSL v2 at:
+# http://license.coscl.org.cn/MulanPSL2
+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+# PURPOSE.
+# See the Mulan PSL v2 for more details.
+# ******************************************************************************/
+
+from .cli import main
+
+__version__ = "0.0.1"
diff --git a/cve-agency-manager/cve_tracking/src/cve/apply.py b/cve-agency-manager/cve_tracking/src/cve/apply.py
new file mode 100644
index 0000000000000000000000000000000000000000..fede6084986c42e3aeea87c76a9251ef80d6e68f
--- /dev/null
+++ b/cve-agency-manager/cve_tracking/src/cve/apply.py
@@ -0,0 +1,146 @@
+#!/usr/bin/python3
+# ******************************************************************************
+# Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved.
+# licensed under the Mulan PSL v2.
+# You can use this software according to the terms and conditions of the Mulan PSL v2.
+# You may obtain a copy of Mulan PSL v2 at:
+# http://license.coscl.org.cn/MulanPSL2
+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+# PURPOSE.
+# See the Mulan PSL v2 for more details.
+# ******************************************************************************/
+import os
+import subprocess
+from .gitee import Gitee
+from .logger import logger
+
+CURRENT_PATCH = os.path.realpath(os.path.dirname(__file__))
+CLEAR = "clear"
+
+
+def apply_patch(patches_path, branches):
+ """
+ Call the script to test compile
+ :param patches_path: path of cve_patches
+ :param branches: branch of source code
+ :return: apply result
+ """
+ shell_file = os.path.join(os.path.dirname(CURRENT_PATCH), "shell/start.sh")
+ try:
+ branch_str = "master"
+ if isinstance(branches, list) and branches:
+ branch_str = " ".join(str(branch) for branch in branches)
+ if isinstance(branches, str) and branches:
+ branch_str = branches
+
+ output = subprocess.check_output(
+ [shell_file, patches_path, branch_str],
+ stderr=subprocess.STDOUT,
+ shell=False,
+ )
+ result = output.decode("utf-8")
+ except subprocess.CalledProcessError:
+ result = "All branch apply failed"
+
+ # _clear_env(shell_file)
+ return result
+
+
+def _clear_env(shell_file):
+ """
+ Clear tmp path and file
+ :param shell_file: shell
+ :return: None
+ """
+ try:
+ subprocess.run([shell_file, CLEAR], stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ shell=False)
+ except subprocess.CalledProcessError:
+ return
+
+
+def row(func):
+ """
+ Combine the rows of the table
+ """
+
+ def wrapper(*args, **kwargs):
+ cols = func(*args, **kwargs)
+ return "
" + "".join([str(col) for col in cols]) + "
"
+
+ return wrapper
+
+
+class Col:
+ """
+ Generates a cell for a row in Table
+ """
+
+ def __init__(self, val, span=0, header=False) -> None:
+ self._val = val
+ self._span = span
+ self.header = header
+
+ def __str__(self) -> str:
+ row_span = ""
+ if self._span:
+ row_span = f' rowspan="{self._span}" '
+ if self.header:
+ return "" + self._val + " | "
+
+ return "" + self._val + " | "
+
+
+class AutoComment:
+ """
+ Automatically submit the content of comments
+ """
+
+ def __init__(self, header=None) -> None:
+ self._gitee = Gitee()
+ self._line_feed = "\n"
+ self._header = header or ["Patchs URL", "Branch", "Apply Result"]
+
+ @row
+ def _row(self, cols, spans=None, header=False):
+ tds = [Col(val=col, header=header) for col in cols]
+ if spans:
+ tds.insert(0, Col(val=spans[0], span=spans[1]))
+
+ return tds
+
+ def _create_table(self, header, body: dict):
+ rows = [self._row(cols=header, header=True)]
+ for index, key in enumerate(body["apply_result"]):
+ row_val = [key, body["apply_result"][key]]
+ if index == 0:
+ rows.append(
+ self._row(
+ cols=row_val,
+ spans=(self._line_feed.join(body["urls"]), len(body)),
+ )
+ )
+ continue
+ rows.append(self._row(cols=row_val))
+
+ return "" + self._line_feed.join(rows) + "
"
+
+ def comment(self, number, body, repo, owner="src-openeuler", table=True):
+ """Comments on PR"""
+ comments = self._gitee.get_issue_comments(repo=repo, number=number, owner=owner)
+ if comments:
+ for comment in comments:
+ if all([header in comment.get("body", "") for header in self._header]):
+ logger.info(
+ "Issue %s in repository %s already has a fixed comment content ."
+ % (number, repo)
+ )
+ return
+ if table:
+ body = self._create_table(header=self._header, body=body)
+ body += self._line_feed * 2 + "> 说明:补丁链接和应用结果仅供初步排查参考,实际应用请人工再次确认。"
+ self._gitee.create_issue_comment(
+ repo=repo, number=number, body=body, owner=owner
+ )
diff --git a/cve-agency-manager/cve_tracking/src/cve/bugzilla.py b/cve-agency-manager/cve_tracking/src/cve/bugzilla.py
new file mode 100644
index 0000000000000000000000000000000000000000..c6fc3276722807e4a93feefced4a1b5bd807a7c9
--- /dev/null
+++ b/cve-agency-manager/cve_tracking/src/cve/bugzilla.py
@@ -0,0 +1,66 @@
+#!/usr/bin/python3
+# ******************************************************************************
+# Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved.
+# licensed under the Mulan PSL v2.
+# You can use this software according to the terms and conditions of the Mulan PSL v2.
+# You may obtain a copy of Mulan PSL v2 at:
+# http://license.coscl.org.cn/MulanPSL2
+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+# PURPOSE.
+# See the Mulan PSL v2 for more details.
+# ******************************************************************************/
+
+
+class Api:
+ """
+ bugzilla api
+ """
+
+ def __init__(self, base_url):
+ self.host = base_url
+
+ def _parse_query_param(self, params):
+ """
+ Parse the request parameters of the query
+ """
+ try:
+ query_str = []
+ for key, value in params.items():
+ query_str.append("{key}={value}".format(key=key, value=value))
+ return "&".join(query_str)
+ except AttributeError:
+ return query_str
+
+ def get_bug(self, fields, **kwargs):
+ """
+ To get information about a particular bug using its ID or alias
+
+ You can also use Search Bugs to return more than one bug at a time
+ by specifying bug IDs as the search terms
+
+ """
+
+ if isinstance(fields, (str, int)):
+ rest_api = '/rest/bug/{}'.format(fields)
+ if isinstance(fields, dict):
+ rest_api = "/rest/bug?{query_param}".format(
+ query_param=self._parse_query_param(params=fields))
+
+ return self.host + rest_api
+
+ def get_comments(self, fields, is_comment_id=False, **kwargs):
+ """
+ To get all comments for a particular bug using the bug ID or alias
+
+ To get a specific comment based on the comment ID
+
+ """
+ if is_comment_id:
+ rest_api = '/rest/bug/comment/{comment_id}'.format(
+ comment_id=fields)
+ else:
+ rest_api = '/rest/bug/{id_or_alias}/comment'.format(
+ id_or_alias=fields)
+
+ return self.host + rest_api
diff --git a/cve-agency-manager/cve_tracking/src/cve/cli.py b/cve-agency-manager/cve_tracking/src/cve/cli.py
new file mode 100644
index 0000000000000000000000000000000000000000..7e74f413cf37c455e46a54ca11ca1ca2e111a9a3
--- /dev/null
+++ b/cve-agency-manager/cve_tracking/src/cve/cli.py
@@ -0,0 +1,103 @@
+#!/usr/bin/python3
+# ******************************************************************************
+# Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved.
+# licensed under the Mulan PSL v2.
+# You can use this software according to the terms and conditions of the Mulan PSL v2.
+# You may obtain a copy of Mulan PSL v2 at:
+# http://license.coscl.org.cn/MulanPSL2
+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+# PURPOSE.
+# See the Mulan PSL v2 for more details.
+# ******************************************************************************/
+import sys
+from argparse import ArgumentParser
+from .engine import crawler
+from .settings import DEFAULT_SAVE_PATH
+
+
+def register_parser(parser):
+ """
+ Register command line arguments
+ """
+ parser.add_argument(
+ "-cve", help="The version number of CVE", default=None, action="store"
+ )
+ parser.add_argument(
+ "-name", help="Name of the affected package", default=None, action="store"
+ )
+
+ parser.add_argument(
+ "-v",
+ nargs="*",
+ default=["0.0.0"],
+ help="The version number of the affected package",
+ )
+
+ parser.add_argument(
+ "-o",
+ help="The path to output the CVE result",
+ default=DEFAULT_SAVE_PATH,
+ action="store",
+ )
+
+ parser.add_argument(
+ "-f", help="CVE file path for batch operation", default=None, action="store"
+ )
+
+ parser.add_argument(
+ "-cmd",
+ help="Whether a shell script to validate the patch needs to be executed",
+ default=False,
+ action="store_true",
+ )
+
+ parser.add_argument(
+ "-branch",
+ nargs="*",
+ default=["master"],
+ help="A list of branches currently affected by CVE",
+ )
+ parser.add_argument(
+ "-issue",
+ help="Issue id",
+ default=None,
+ action="store",
+ )
+
+ parser.set_defaults(func=crawler.run)
+
+ return parser
+
+
+def _run(args, option_parser=ArgumentParser):
+ parser = register_parser(
+ parser=option_parser(description="CVE vulnerability repair management")
+ )
+ if not args:
+ print(parser.parse_args(["-h"]))
+ return 0
+ if ("-cve" not in args or "-name" not in args) and "-f" not in args:
+ print("Both the cve number and package name are required, please enter them")
+ return 0
+ try:
+ parser_args = parser.parse_args(args=args)
+ parser_args.func(parser_args)
+ except Exception as e:
+ return 1
+ else:
+ return 0
+
+
+def main(args, exit_code=False):
+ """
+ CVE gets command-line entry
+ """
+ errcode = _run(args)
+ if exit_code:
+ sys.exit(errcode)
+ return errcode
+
+
+if __name__ == "__main__":
+ main(sys.argv[1:], exit_code=True)
diff --git a/cve-agency-manager/cve_tracking/src/cve/engine.py b/cve-agency-manager/cve_tracking/src/cve/engine.py
new file mode 100644
index 0000000000000000000000000000000000000000..c9fdbeec0650fd044126dd7d78e273bc2d3d5a13
--- /dev/null
+++ b/cve-agency-manager/cve_tracking/src/cve/engine.py
@@ -0,0 +1,381 @@
+#!/usr/bin/python3
+import os
+import csv
+import re
+import shutil
+import signal
+import time
+from concurrent.futures import ThreadPoolExecutor
+from queue import Queue
+from collections import deque
+from threading import Thread
+from typing import Iterable
+import requests
+
+from .apply import apply_patch
+from .logger import logger
+from .httprequest import RemoteService
+from .plantform import Ubuntu, Nvd, Debian, Bugzilla, Crawl
+from .pipe import RequestRepeat, RequestsUrl, SavePipe, FileHandle
+from .settings import (
+ INTERNAL_SERVER,
+ ENABLE_PLANTFORM,
+ MAX_WORKERS,
+ MAX_QUEUE,
+ RECORD_FILE,
+)
+from .apply import AutoComment
+
+
+class Cardiac:
+ """
+ The engine center
+ """
+
+ download_queue = Queue(maxsize=MAX_QUEUE)
+ save_queue = Queue(maxsize=MAX_QUEUE)
+ engine_queue = Queue(maxsize=MAX_QUEUE)
+ pool = ThreadPoolExecutor(max_workers=MAX_WORKERS)
+ download_thread = deque(maxlen=MAX_QUEUE)
+ plantform = [Bugzilla, Debian, Ubuntu, Nvd]
+
+ def __init__(self) -> None:
+ self._active = True
+ self.cve_infos = list()
+ self._request_fingerprint = RequestRepeat()
+
+ def _consume(self, cve, obj):
+ if not issubclass(obj, Crawl):
+ raise RuntimeError("")
+
+ crawl = obj(**cve)
+ return RequestsUrl(
+ url=crawl.start_url, crawl=crawl, callback=crawl.parse, start=True
+ )
+
+ def _record_base_info(self, cve):
+ text = "CVE Information : {cve}".format(cve=str(cve))
+ return SavePipe(text=text, crawl=Crawl(**cve))
+
+ def _req_flow(self):
+ """
+ Sign up for various platforms
+ Returns:
+
+ """
+ for cve in self.cve_infos:
+ for plantform in self.plantform:
+ if plantform.__name__ not in ENABLE_PLANTFORM:
+ continue
+ yield self._consume(cve, obj=plantform)
+
+ yield self._record_base_info(cve)
+
+ def _internal_server(self, reuqest, pkg, commitid):
+ first_char = pkg.lower()[0]
+ success = False
+ response = reuqest.request(
+ url=INTERNAL_SERVER,
+ method="post",
+ json={
+ "git_repo": f"upstream/{first_char}/{pkg}/{pkg}.git",
+ "git_command": ["git-show", commitid, "--pretty=email"],
+ },
+ max_retry=1,
+ )
+ if response.text and response.status_code == requests.codes["ok"]:
+ success = True
+ return success, response
+
+ def _downloader(self, req_flow):
+ """
+ downloader
+ Returns:
+
+ """
+ request = RemoteService()
+
+ def _github(request, response=None, success=False):
+ if not success:
+ response = request.request(url=req_flow.url, method="get", timeout=15)
+
+ if response.status_code != requests.codes["ok"]:
+ self._download_failed(request=req_flow)
+ return
+
+ callback = req_flow.callback(response)
+ if isinstance(callback, Iterable):
+ self._iterback(callback)
+
+ if hasattr(req_flow, "is_patch") and getattr(req_flow, "is_patch"):
+ success, response = self._internal_server(
+ request,
+ req_flow.crawl.pkg,
+ req_flow.url.split("/")[-1].replace(".patch", ""),
+ )
+ _github(request, response=response, success=success)
+ else:
+ _github(request)
+
+ def _download_failed(self, request):
+ if hasattr(request, "start") and getattr(request, "start"):
+ logger.warning("Start page %s failed to open" % request.url)
+ return
+ text = "File download failed:%s" % request.url
+ logger.error(text)
+ self.engine_queue.put(SavePipe(text=text, crawl=request.crawl))
+
+ def _iterback(self, callback):
+ while self._active:
+ try:
+ self.engine_queue.put(callback.send(None))
+ except StopIteration:
+ break
+
+ def download(self):
+ """
+ downloader
+ """
+ while self._active:
+ request_flow = self.download_queue.get()
+ if not request_flow:
+ break
+ if self._request_fingerprint.request_seen(request_flow):
+ continue
+ future = self.pool.submit(self._downloader, request_flow)
+ self.download_thread.append(future)
+
+ def save_pipe(self):
+ """
+ Save data pipe
+ """
+
+ while self._active:
+ save_handle = self.save_queue.get()
+ if not save_handle:
+ break
+
+ callback = save_handle.save_process(save_handle.crawl)
+ if isinstance(callback, Iterable):
+ self._iterback(callback)
+
+ def clear(self, queues):
+ """Clear the stack of messages"""
+ if not isinstance(queues, (list, tuple, set)):
+ return
+ for _queue in queues:
+ if not isinstance(_queue, Queue):
+ continue
+ _queue.queue.clear()
+
+ def stop(self):
+ """
+ Stop the service
+ """
+
+ self._active = False
+ self.download_queue.put_nowait(None)
+ self.engine_queue.put_nowait(None)
+ self.save_queue.put_nowait(None)
+ return not self._active
+
+ def _read_csvfile(self, file, out_path, return_content=False):
+ """
+ Read the CSV file
+ Args:
+ file: CSV file
+
+ Returns:
+
+ """
+ if not os.path.exists(file) or not os.path.isfile(file):
+ logger.info("file not found:{}".format(file))
+ return
+ csv_contents = []
+ try:
+ csv_data = csv.reader(open(file, encoding="utf-8"))
+ for cveinfo in csv_data:
+ if len(cveinfo) != 3:
+ continue
+ cve, pkg, versions = cveinfo
+ versions = re.sub("\[|\]", "", versions).split(",")
+ self._set_cve(cve=cve, pkg=pkg, versions=versions, out_path=out_path)
+ csv_contents.append([pkg, cve])
+ except csv.Error as error:
+ logger.error(error)
+
+ if return_content:
+ return csv_contents
+
+ def _set_cve(self, cve, pkg, versions, out_path):
+ if isinstance(versions, str):
+ versions = [versions]
+ self.cve_infos.append(
+ {"cve": cve, "pkg": pkg, "versions": versions, "out_path": out_path}
+ )
+
+ def start(self, args):
+ """
+ Start the service
+ """
+ # Get information such as CVE
+ if args.f:
+ self._read_csvfile(file=args.f, out_path=args.o)
+ if args.cve:
+ self._set_cve(cve=args.cve, pkg=args.name, versions=args.v, out_path=args.o)
+
+ if not self.cve_infos:
+ logger.info("There is no CVE information queried this time")
+ self.stop()
+
+ req_flow = self._req_flow()
+ while self._active:
+ try:
+ flow = next(req_flow)
+ self.engine_queue.put(flow)
+ except StopIteration:
+ break
+
+ def scheduler(self):
+ """
+ Task scheduler
+ """
+ while self._active:
+ task = self.engine_queue.get()
+ if not task:
+ break
+ if isinstance(task, RequestsUrl):
+ self.download_queue.put(task)
+
+ if isinstance(task, SavePipe):
+ self.save_queue.put(task)
+
+
+class CrawlerProcess:
+ """
+ The process of data crawling
+ """
+
+ def __init__(self) -> None:
+ self.engine = Cardiac()
+ self._thread_container = [self._downloader, self._scheduler, self._save_pipe]
+ self.end_signal = False
+ self._interval = 6
+
+ @property
+ def finish(self):
+ """Task queue consumption completed"""
+ return all(
+ [
+ self.engine.download_queue.empty(),
+ self.engine.save_queue.empty(),
+ self.engine.engine_queue.empty(),
+ ]
+ )
+
+ def _heartbeat(self):
+ """
+ Heartbeat mechanism
+ Returns:
+
+ """
+ while True:
+ time.sleep(self._interval)
+ while len(self.engine.download_thread) > 0:
+ thread = self.engine.download_thread.popleft()
+ if not thread.done() and not self.end_signal:
+ self.engine.download_thread.append(thread)
+ if self.end_signal or self.finish:
+ self.end_signal = True
+ self.engine.clear(
+ queues=[
+ self.engine.download_queue,
+ self.engine.save_queue,
+ self.engine.engine_queue,
+ ]
+ )
+ self.engine.stop()
+ break
+
+ def _stop(self, signum, frame):
+ print("\nIt's in the process of closing .....")
+ self.end_signal = True
+ self._interval = 0
+ self.engine.download_thread.clear()
+
+ @property
+ def _downloader(self):
+ return Thread(target=self.engine.download)
+
+ @property
+ def _scheduler(self):
+ return Thread(target=self.engine.scheduler)
+
+ @property
+ def _save_pipe(self):
+ return Thread(target=self.engine.save_pipe)
+
+ def _extract_info(self, args):
+ file_handle = FileHandle(
+ folder=args.o,
+ branch=args.branch,
+ cve=args.cve,
+ pkg=args.name,
+ csv_file=args.f,
+ read_csv=self.engine._read_csvfile,
+ )
+ apply_result = None
+ if args.cmd:
+ apply_result = apply_patch(args.o, args.branch)
+
+ file_handle.format_text(apply_result=apply_result)
+ if args.issue:
+ path = os.path.join(args.o, args.name + "-" + args.cve, RECORD_FILE)
+ self._comment(
+ file_handle,
+ path,
+ args.issue,
+ args.name,
+ cmd=args.cmd,
+ branch=args.branch,
+ cve=args.cve,
+ )
+
+ def _comment(self, file_handle, path, issue, repo, **kwargs):
+ auto_comment = AutoComment()
+
+ body = file_handle.extract_text(path)
+ if not kwargs["cmd"]:
+ body["apply_result"] = {branch: "Not apply" for branch in kwargs["branch"]}
+ if kwargs["cmd"] and not body["apply_result"]:
+ body["apply_result"] = {
+ branch: "Apply failed" for branch in kwargs["branch"]
+ }
+
+ if not body.get("urls"):
+ logger.warning(
+ "%s has not found a valid patch file yet ." % kwargs.get("cve", "")
+ )
+ return
+ auto_comment.comment(number=issue, body=body, repo=repo)
+
+ def run(self, args):
+ """
+ Entrance to program execution
+ """
+ # Clears all files in the specified path
+ if os.path.exists(args.o):
+ shutil.rmtree(args.o)
+ signal.signal(signal.SIGINT, self._stop)
+ # Start Multiple Tasks
+ while self._thread_container:
+ task = self._thread_container.pop()
+ task.start()
+
+ self.engine.start(args)
+ self._heartbeat()
+ if self.end_signal:
+ self._extract_info(args)
+
+
+crawler = CrawlerProcess()
diff --git a/cve-agency-manager/cve_tracking/src/cve/gitee.py b/cve-agency-manager/cve_tracking/src/cve/gitee.py
new file mode 100644
index 0000000000000000000000000000000000000000..68aa6b921b1f0b43651795e51c870df7235a10a7
--- /dev/null
+++ b/cve-agency-manager/cve_tracking/src/cve/gitee.py
@@ -0,0 +1,469 @@
+#!/usr/bin/python3
+# ******************************************************************************
+# Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved.
+# licensed under the Mulan PSL v2.
+# You can use this software according to the terms and conditions of the Mulan PSL v2.
+# You may obtain a copy of Mulan PSL v2 at:
+# http://license.coscl.org.cn/MulanPSL2
+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+# PURPOSE.
+# See the Mulan PSL v2 for more details.
+# ******************************************************************************/
+"""
+This is a helper script for working with gitee.com
+"""
+import sys
+import os
+import json
+import base64
+import urllib
+import urllib.request
+import urllib.parse
+import urllib.error
+from datetime import datetime
+from fake_useragent import UserAgent
+import yaml
+from .logger import logger
+from .settings import GITEE_AUTH
+
+
+class Gitee:
+ """
+ Gitee is a helper class to abstract gitee.com api
+ """
+
+ user_agent = UserAgent(
+ path=os.path.join(os.path.dirname(__file__), "user-agent.json")
+ )
+
+ def __init__(self):
+ self.token = {"access_token": os.getenv(GITEE_AUTH["token"]), "user": os.getenv(GITEE_AUTH["account"])}
+
+ self.headers = {"User-Agent": self.user_agent.random}
+ self.src_openeuler_url = "https://gitee.com/src-openeuler/{repo}/raw/{br}/"
+ self.advisor_url = "https://gitee.com/openeuler/openEuler-Advisor/raw/master/"
+ self.time_format = "%Y-%m-%dT%H:%M:%S%z"
+
+ def post_gitee(self, url, values, headers=None):
+ """
+ POST into gitee API
+ """
+ if headers is None:
+ headers = self.headers.copy()
+ data = urllib.parse.urlencode(values).encode("utf-8")
+ req = urllib.request.Request(
+ url=url, data=data, headers=headers, method="POST")
+ try:
+ result = urllib.request.urlopen(req)
+ return result.read().decode("utf-8")
+ except urllib.error.HTTPError as err:
+ logger.warning(
+ "reuqest url: %s status code: %s headers: %s "
+ % (url, str(err.code), str(err.headers))
+ )
+ return False
+
+ def fork_repo(self, repo, owner="src-openeuler"):
+ """
+ Fork repository in gitee
+ """
+ url_template = "https://gitee.com/api/v5/repos/{owner}/{repo}/forks"
+ url = url_template.format(owner=owner, repo=repo)
+ values = {}
+ values["access_token"] = self.token["access_token"]
+ return self.post_gitee(url, values)
+
+ def create_issue(
+ self,
+ repo,
+ version="",
+ branch="master",
+ owner="src-openeuler",
+ title=None,
+ body=None,
+ ):
+ """
+ Create issue in gitee
+ """
+ title = title or "Upgrade {pkg} to {ver} in {br}".format(
+ pkg=repo, ver=version, br=branch
+ )
+ body = (
+ body
+ or """This issue is automatically created by openEuler-Advisor.
+ Please check the correspond PR is accepted before close it.
+ Thanks.
+ Yours openEuler-Advisor."""
+ )
+ return self._post_issue(repo, title, body, owner=owner)
+
+ def create_issue_comment(self, repo, owner, number, body):
+ """
+ create issue comment
+ """
+ url_template = (
+ "https://gitee.com/api/v5/repos/{owner}/{repo}/issues/{number}/comments"
+ )
+ url = url_template.format(owner=owner, repo=repo, number=number)
+ values = {}
+ values["access_token"] = self.token["access_token"]
+ values["body"] = body
+ return self.post_gitee(url, values)
+
+ def get_reviewers(self, repo, owner="src-openeuler"):
+ """
+ Get reviewers of pkg
+ """
+ url_template = "https://gitee.com/api/v5/repos/{owner}/{pkg}/collaborators"
+ url = url_template.format(owner=owner, pkg=repo)
+ return self.get_gitee_dict(url)
+
+ def create_pr(
+ self,
+ repo,
+ version="",
+ issue=None,
+ title=None,
+ branch="master",
+ owner="src-openeuler",
+ body=None,
+ ):
+ """
+ Create PR in gitee
+ """
+ # assignees = ""
+ # reviewer_info = self.get_reviewers(repo)
+ # if reviewer_info:
+ # reviewer_list = json.loads(reviewer_info)
+ # assignees = ",".join(reviewer["login"]
+ # for reviewer in reviewer_list)
+ url_template = "https://gitee.com/api/v5/repos/{owner}/{pkg}/pulls"
+ url = url_template.format(owner=owner, pkg=repo)
+ values = {}
+ values["access_token"] = self.token["access_token"]
+ values["title"] = title or "Upgrade {pkg} to {ver}".format(
+ pkg=repo, ver=version
+ )
+ values["head"] = "{hd}:{br}".format(hd=self.token["user"], br=branch)
+ values["base"] = branch
+ # values["assignees"] = assignees
+ if issue:
+ values["issue"] = issue
+ values["body"] = (
+ body
+ or """This is a automatically created PR by openEuler-Advisor.
+ Please be noted that it's not throughly tested.
+ Review carefully before accept this PR.
+ Thanks.
+ Yours openEuler-Advisor."""
+ )
+ return self.post_gitee(url, values)
+
+ def create_pr_comment(self, repo, number, body, owner="src-openeuler"):
+ """
+ Post comment to the given specific PR
+ """
+ url_template = (
+ "https://gitee.com/api/v5/repos/{owner}/{repo}/pulls/{number}/comments"
+ )
+ url = url_template.format(owner=owner, repo=repo, number=number)
+ values = {}
+ values["access_token"] = self.token["access_token"]
+ values["body"] = body
+ return self.post_gitee(url, values)
+
+ def get_gitee(self, url, headers=None):
+ """
+ GET from gitee api
+ """
+ if headers is None:
+ req = urllib.request.Request(url=url, headers=self.headers)
+ else:
+ req = urllib.request.Request(url=url, headers=headers)
+ try:
+ result = urllib.request.urlopen(req)
+ return result.read().decode("utf-8")
+ except urllib.error.HTTPError as e:
+ logger.warning(
+ "reuqest url: %s status code: %s messages: %s "
+ % (url, str(e.code), str(e.reason))
+ )
+ return None
+ except urllib.error.URLError as e:
+ logger.warning("reuqest url: %s messages: %s " %
+ (url, str(e.reason)))
+ return None
+
+ def get_pr(self, repo, num, owner="src-openeuler"):
+ """
+ Get detailed information of the given specific PR
+ """
+ url_template = "https://gitee.com/api/v5/repos/{owner}/{repo}/pulls/{number}"
+ url = url_template.format(owner=owner, repo=repo, number=num)
+ return self.get_gitee_json(url)
+
+ def get_gitee_json(self, url):
+ """
+ Get and load gitee json response
+ """
+ json_resp = []
+ headers = self.headers.copy()
+ headers["Content-Type"] = "application/json;charset=UTF-8"
+ resp = self.get_gitee(url, headers)
+ if resp:
+ json_resp = json.loads(resp)
+ return json_resp
+
+ def get_branch_info(self, branch):
+ """
+ Get upgrade branch info
+ """
+ upgrade_branches_url = (
+ self.advisor_url + "advisors/helper/upgrade_branches.yaml"
+ )
+ resp = self.get_gitee(upgrade_branches_url)
+ if not resp:
+ print("ERROR: upgrade_branches.yaml may not exist.")
+ sys.exit(1)
+ branches_info = yaml.load(resp, Loader=yaml.Loader)
+ for br_info in branches_info["branches"]:
+ if branch == br_info["name"]:
+ return br_info
+ print("WARNING: Don't support branch: {} in auto-upgrade.".format(branch))
+ sys.exit(1)
+
+ def get_spec_exception(self, repo):
+ """
+ Get well known spec file exception
+ """
+ specfile_exception_url = (
+ self.advisor_url + "advisors/helper/specfile_exceptions.yaml"
+ )
+ resp = self.get_gitee(specfile_exception_url)
+ if not resp:
+ print("ERROR: specfile_exceptions.yaml may not exist.")
+ sys.exit(1)
+ excpt_list = yaml.load(resp, Loader=yaml.Loader)
+ if repo in excpt_list:
+ return excpt_list[repo]
+ return None
+
+ def get_version_exception(self):
+ """
+ Get version recommend exceptions
+ """
+ version_exception_url = (
+ self.advisor_url + "advisors/helper/version_exceptions.yaml"
+ )
+ resp = self.get_gitee(version_exception_url)
+ if not resp:
+ print("ERROR: version_exceptions.yaml may not exist.")
+ sys.exit(1)
+ excpt = yaml.load(resp, Loader=yaml.Loader)
+ return excpt
+
+ def get_spec(self, pkg, branch="master"):
+ """
+ Get openeuler spec file for specific package
+ """
+ specurl = self.src_openeuler_url + "{repo}.spec"
+ specurl = specurl.format(repo=pkg, br=branch)
+ excpt = self.get_spec_exception(pkg)
+ if excpt:
+ specurl = urllib.parse.urljoin(
+ specurl, os.path.join(excpt["dir"], excpt["file"])
+ )
+ resp = self.get_gitee(specurl)
+ return resp
+
+ def get_yaml(self, pkg):
+ """
+ Get upstream yaml metadata for specific package
+ """
+ yamlurl = self.advisor_url + "upstream-info/{}.yaml".format(pkg)
+ resp = self.get_gitee(yamlurl)
+ if not resp:
+ yamlurl = self.src_openeuler_url + "{repo}.yaml"
+ yamlurl = yamlurl.format(repo=pkg, br="master")
+ resp = self.get_gitee(yamlurl)
+ if not resp:
+ print(
+ "WARNING: {}.yaml can't be found in upstream-info and repo.".format(
+ pkg
+ )
+ )
+ return resp
+
+ def get_community(self, repo):
+ """
+ Get yaml data from community repo
+ """
+ yamlurl = (
+ "https://gitee.com/api/v5/repos/openeuler/community/contents/"
+ "repository/{repo}.yaml".format(repo=repo)
+ )
+ resp = self.get_gitee_json(yamlurl)
+ resp_str = base64.b64decode(resp["content"])
+ return resp_str
+
+ def get_issues(self, pkg, prj="src-openeuler"):
+ """
+ List all open issues of pkg
+ """
+ issues_url = "https://gitee.com/api/v5/repos/{prj}/{pkg}/issues?".format(
+ prj=prj, pkg=pkg
+ )
+ parameters = "state=open&sort=created&direction=desc&page=1&per_page=20"
+ return self.get_gitee_json(issues_url + parameters)
+
+ def get_issue_comments(self, repo, number, owner="src-openeuler"):
+ """
+ Get comments of specific issue
+ """
+ issues_url = "https://gitee.com/api/v5/repos/{owner}/{repo}/issues/{number}/comments?page=1&per_page=50&order=asc".format(
+ repo=repo, owner=owner, number=number
+ )
+ return self.get_gitee_json(issues_url)
+
+ def get_issue_merged_branches(self, issue_id, repo, owner="src-openeuler"):
+ """
+ Get merged branches of specific issue
+ """
+ issues_url = "https://gitee.com/api/v5/repos/{owner}/issues/{number}/pull_requests?".format(
+ owner=owner, number=issue_id
+ )
+
+ param = "&repo={}".format(repo)
+ return self.get_gitee_dict(issues_url, param)
+
+ def _post_issue(self, pkg, title, body, owner="src-openeuler"):
+ """
+ Post new issue
+ """
+ issues_url = "https://gitee.com/api/v5/repos/{owner}/issues".format(
+ owner=owner)
+ parameters = {}
+ parameters["access_token"] = self.token["access_token"]
+ parameters["repo"] = pkg
+ parameters["title"] = title
+ parameters["body"] = body
+ return self.post_gitee(issues_url, parameters)
+
+ def post_issue_comment(self, pkg, number, comment, prj="src-openeuler"):
+ """
+ Post comment of issue
+ """
+ issues_url = (
+ "https://gitee.com/api/v5/repos/{prj}/{pkg}/issues/{number}/"
+ "comments".format(prj=prj, pkg=pkg, number=number)
+ )
+ parameters = {}
+ parameters["access_token"] = self.token["access_token"]
+ parameters["body"] = comment
+ self.post_gitee(issues_url, parameters)
+
+ def get_gitee_datetime(self, time_string):
+ """
+ Get datetime of gitee
+ """
+ result = datetime.strptime(time_string, self.time_format)
+ return result.replace(tzinfo=None)
+
+ def get_gitee_dict(self, url, param=""):
+ url += param
+ token_param = "access_token={}".format(self.token["access_token"])
+ separator = "?"
+ if param:
+ separator = "&"
+ url += separator + token_param
+ return self.get_gitee_json(url)
+
+ def get_contributors(self, repo, owner):
+ """
+ Get contributors of owner/repo
+ """
+ url_template = "https://gitee.com/api/v5/repos/{owner}/{repo}/contributors"
+ url = url_template.format(owner=owner, repo=repo)
+ return self.get_gitee_dict(url)
+
+ def get_branches(self, repo, owner):
+ """
+ Get branches of owner/repo
+ """
+ url_template = "https://gitee.com/api/v5/repos/{owner}/{repo}/branches"
+ url = url_template.format(owner=owner, repo=repo)
+ return self.get_gitee_dict(url)
+
+ def get_commits(
+ self, repo, owner, sha="", author="", since="", until="", page=1, per_page=20
+ ):
+ """
+ Get commits of owner/repo
+ """
+ url_template = "https://gitee.com/api/v5/repos/{owner}/{repo}/commits"
+ url = url_template.format(owner=owner, repo=repo)
+ param = "?page={}&per_page={}".format(page, per_page)
+ if sha:
+ param += "&sha={}".format(sha)
+ if author:
+ param += "&author={}".format(author)
+ if since:
+ param += "&since={}".format(since)
+ if until:
+ param += "&until={}".format(until)
+ return self.get_gitee_dict(url, param)
+
+ def get_one_commit(self, repo, sha, owner):
+ """
+ Get one commit of owner/repo
+ """
+ url_template = "https://gitee.com/api/v5/repos/{owner}/{repo}/commits/{sha}"
+ url = url_template.format(owner=owner, repo=repo, sha=sha)
+ return self.get_gitee_dict(url)
+
+ def get_pr_list(
+ self, repo, owner, head="", base="", state="all", page=1, per_page=20
+ ):
+ """
+ Get PR list of owner/repo
+ """
+ url_template = "https://gitee.com/api/v5/repos/{owner}/{repo}/pulls"
+ url = url_template.format(owner=owner, repo=repo)
+ param = "?state={}&sort=created&direction=desc&page={}&per_page={}".format(
+ state, page, per_page
+ )
+ if head:
+ param += "&head={}".format(head)
+ if base:
+ param += "&base={}".format(base)
+ return self.get_gitee_dict(url, param)
+
+ def get_pr_comments(self, repo, number, owner, page=1, per_page=20):
+ """
+ Get PR comments of owner/repo
+ """
+ url_template = (
+ "https://gitee.com/api/v5/repos/{owner}/{repo}/pulls/{number}/comments"
+ )
+ url = url_template.format(owner=owner, repo=repo, number=number)
+ param = "?page={}&per_page={}".format(page, per_page)
+ return self.get_gitee_dict(url, param)
+
+ def get_repos(self, org, repo_type, page=1, per_page=20):
+ """
+ Get repos of org
+ """
+ url_template = "https://gitee.com/api/v5/orgs/{org}/repos"
+ url = url_template.format(org=org)
+ param = "?type={}&page={}&per_page={}".format(
+ repo_type, page, per_page)
+ return self.get_gitee_dict(url, param)
+
+ def get_repo(self, repo, owner):
+ """
+ Get repo
+ """
+ url_template = "https://gitee.com/api/v5/repos/{owner}/{repo}"
+ url = url_template.format(owner=owner, repo=repo)
+ return self.get_gitee(url)
diff --git a/cve-agency-manager/cve_tracking/src/cve/httprequest.py b/cve-agency-manager/cve_tracking/src/cve/httprequest.py
new file mode 100644
index 0000000000000000000000000000000000000000..cc948f663172edbd2211f57806fc7086a4a3fe8f
--- /dev/null
+++ b/cve-agency-manager/cve_tracking/src/cve/httprequest.py
@@ -0,0 +1,212 @@
+#!/usr/bin/python3
+# ******************************************************************************
+# Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved.
+# licensed under the Mulan PSL v2.
+# You can use this software according to the terms and conditions of the Mulan PSL v2.
+# You may obtain a copy of Mulan PSL v2 at:
+# http://license.coscl.org.cn/MulanPSL2
+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+# PURPOSE.
+# See the Mulan PSL v2 for more details.
+# ******************************************************************************/
+import os
+import re
+from functools import wraps
+import requests
+from fake_useragent import UserAgent
+from requests.exceptions import RequestException, HTTPError
+from retrying import retry
+
+
+class RemoteService:
+ """
+ HTTP request service
+
+ Attributes:
+ _max_delay:Maximum interval time
+ _retry:Retry count
+ _body:Request body
+ _response:Response info
+ _request_error: request error
+ """
+
+ user_agent = UserAgent(
+ path=os.path.join(os.path.dirname(__file__), "user-agent.json")
+ )
+ url_regex = re.compile(
+ r"http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+"
+ )
+
+ def __init__(self, max_delay=1000):
+ self._retry = 3
+ if not isinstance(max_delay, int):
+ raise TypeError("Max_delay is the number of milliseconds of the integer ")
+ self._max_delay = max_delay
+ self._body = None
+ self._response = None
+ self._request_error = None
+ self._query_param = (
+ "params",
+ "data",
+ "cookies",
+ "files",
+ "auth",
+ "timeout",
+ "allow_redirects",
+ "proxies",
+ "hooks",
+ "stream",
+ "verify",
+ "cert",
+ "json",
+ )
+ self._headers = {"User-Agent": self.user_agent.random}
+
+ @property
+ def response(self):
+ return self._response
+
+ @property
+ def status_code(self):
+ """
+ Description: status code of the response
+ """
+ if self._response is None:
+ return requests.codes["internal_server_error"]
+ return self._response.status_code
+
+ @property
+ def content(self):
+ """
+ Description: original content of the response
+ """
+ return self._response.content if self._response else None
+
+ @property
+ def text(self):
+ """
+ Description: content of the decoded response
+ """
+ return self._response.content.decode("utf-8") if self._response else None
+
+ @property
+ def errors(self):
+ """
+ Description: The error message content of the request
+ """
+ return self._request_error
+
+ def _redirected(self, response):
+ if not response:
+ raise HTTPError("No address after redirect")
+ url = re.findall(self.url_regex, response)
+ if not url:
+ raise HTTPError("Incorrect redirect address")
+ return url[0]
+
+ def _dispatch(self, method, url, **kwargs):
+ """
+ Description: Request remote services in different ways
+
+ Args:
+ method: request method, GET、 POST 、PUT 、DELETE
+ url:Remote request address
+ kwargs:parameters associated with the request
+ """
+
+ @retry(stop_max_attempt_number=self._retry, stop_max_delay=self._max_delay)
+ def http(url):
+ response = method(url, **kwargs)
+ if response.status_code == requests.codes["found"]:
+ url = self._redirected(response.text)
+ response = http(url)
+
+ if response.status_code != requests.codes["ok"]:
+ _msg = (
+ "There is an exception with the remote service [%s],"
+ "Please try again later.The HTTP error code is:%s"
+ % (url, str(response.status_code))
+ )
+ raise HTTPError(_msg)
+ return response
+
+ method = getattr(self, method, None)
+ if method is None:
+ raise RequestException(
+ "Request mode error, temporarily only support POST, GET"
+ )
+ try:
+ self._response = http(url)
+ except RequestException as error:
+ raise RequestException(str(error)) from error
+
+ def request(self, url, method, body=None, max_retry=3, **kwargs):
+ """
+ Description: Request a remote http service
+
+ Args:
+ url: http service address
+ method: mode of request ,only GET、 POST、 DELETE、 PUT is supported
+ body: Request body content
+ max_retry: The number of times the request failed to retry
+ kwargs: Request the relevant parameters
+ """
+ if not isinstance(max_retry, int):
+ raise TypeError("MAX_RETRY must be an integer greater than zero ")
+ self._retry = max_retry
+ self._body = body
+ try:
+ self._dispatch(method=method, url=url, **kwargs)
+ except RequestException as error:
+ self._request_error = str(error)
+ self._response = requests.Response()
+
+ return self._response
+
+ def get(self, url, **kwargs):
+ """
+ Description: HTTP get request method
+
+ Args:
+ kwargs: requests parameters
+ url: requested remote address
+ """
+ query_param = {key: kwargs.get(key, None) for key in self._query_param}
+
+ response = requests.get(url=url, headers=self._headers, **query_param)
+ return response
+
+ def post(self, url, **kwargs):
+ """
+ Description: HTTP post request method
+
+ Args:
+ kwargs: requests parameters
+ url: requested remote address
+ """
+ data = kwargs.get("data") or self._body
+ query_param = {key: kwargs.get(key, None) for key in self._query_param}
+ if data:
+ query_param["data"] = data
+ response = requests.post(url=url, headers=self._headers, **query_param)
+ return response
+
+
+def get(func):
+ """
+ A decorator for HTTP GET requests
+ """
+
+ @wraps(func)
+ def _wrapper(*args, **kwargs):
+ rest_api = func(*args, **kwargs)
+ _remote = RemoteService()
+ _remote.request(url=rest_api, method="get", **kwargs)
+ if _remote.status_code == requests.codes["ok"]:
+ response = (requests.codes["ok"], _remote.text)
+ else:
+ response = (_remote.status_code, _remote.errors)
+ return response
+
+ return _wrapper
diff --git a/cve-agency-manager/cve_tracking/src/cve/logger.py b/cve-agency-manager/cve_tracking/src/cve/logger.py
new file mode 100644
index 0000000000000000000000000000000000000000..22b2137b1b4551d4cb3f057e594ca291f955fad6
--- /dev/null
+++ b/cve-agency-manager/cve_tracking/src/cve/logger.py
@@ -0,0 +1,113 @@
+#!/usr/bin/python3
+# ******************************************************************************
+# Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved.
+# licensed under the Mulan PSL v2.
+# You can use this software according to the terms and conditions of the Mulan PSL v2.
+# You may obtain a copy of Mulan PSL v2 at:
+# http://license.coscl.org.cn/MulanPSL2
+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+# PURPOSE.
+# See the Mulan PSL v2 for more details.
+# ******************************************************************************/
+"""
+Logging related
+"""
+import logging
+import os
+import pathlib
+import pprint
+from concurrent_log_handler import ConcurrentRotatingFileHandler
+from .settings import LOG_DIR
+
+
+def get_spider_looger_str(website, pkg, versions, cve, patch_urls, other_urls):
+ """return logger str
+
+ Args:
+ website (str): to spider web name
+ pkg (str): pkg name
+ versions (list): versions
+ cve (str): cve id
+ patch_urls (list): patch urls
+ other_urls (list): other urls
+
+ Returns:
+ str: logger str
+ """
+ if patch_urls or other_urls:
+ logger_info = (
+ f"{website} result:\npkg_name:{pkg}\nversions:{pprint.pformat(versions)}\nCVE: {cve}\n"
+ f"get patch urls: {pprint.pformat(patch_urls)}\nget other urls {pprint.pformat(other_urls)}"
+ )
+ else:
+ logger_info = f"{website} result: No information available"
+ return logger_info
+
+
+class Log(object):
+ """
+ operation log of the system
+ """
+
+ def __init__(self, name=__name__, path=None):
+ self.__current_rotating_file_handler = None
+ if not path:
+ path = os.path.dirname(__file__)
+ self.__path = os.path.join(path, "log_info.log")
+
+ if not os.path.exists(self.__path):
+ try:
+ os.makedirs(os.path.split(self.__path)[0])
+ except FileExistsError:
+ pathlib.Path(self.__path).touch(mode=0o644)
+ self.__max_bytes = 30000000
+ self.__backup_count = 2
+ self.__level = "INFO"
+ self.__logger = logging.getLogger(name)
+ self.__logger.setLevel(self.__level)
+
+ def __init_handler(self):
+ self.__current_rotating_file_handler = ConcurrentRotatingFileHandler(
+ filename=self.__path,
+ mode="a",
+ maxBytes=self.__max_bytes,
+ backupCount=self.__backup_count,
+ encoding="utf-8",
+ use_gzip=True,
+ )
+ self.__set_formatter()
+ self.__set_handler()
+
+ def __set_formatter(self):
+ formatter = logging.Formatter(
+ "%(asctime)s-%(filename)s-[line:%(lineno)d]"
+ "-%(levelname)s-[ log details ]: %(message)s",
+ datefmt="%a, %d %b %Y %H:%M:%S",
+ )
+ self.__current_rotating_file_handler.setFormatter(formatter)
+
+ def __set_handler(self):
+ self.__current_rotating_file_handler.setLevel(self.__level)
+ self.__logger.addHandler(self.__current_rotating_file_handler)
+
+ @property
+ def logger(self):
+ """
+ Gets the logger property
+ """
+ if not self.__current_rotating_file_handler:
+ self.__init_handler()
+ return self.__logger
+
+ @property
+ def file_handler(self):
+ """
+ The file handle to the log
+ """
+ if not self.__current_rotating_file_handler:
+ self.__init_handler()
+ return self.__current_rotating_file_handler
+
+
+logger = Log(__name__, path=LOG_DIR).logger
diff --git a/cve-agency-manager/cve_tracking/src/cve/pipe.py b/cve-agency-manager/cve_tracking/src/cve/pipe.py
new file mode 100644
index 0000000000000000000000000000000000000000..872acfb379edd217bdc62719cfbe904322fa5ee1
--- /dev/null
+++ b/cve-agency-manager/cve_tracking/src/cve/pipe.py
@@ -0,0 +1,371 @@
+#!/usr/bin/python3
+import os
+import re
+import hashlib
+import shutil
+import ast
+import pprint
+from .logger import logger
+from .settings import DEFAULT_SAVE_PATH, RECORD_FILE
+
+URL_REGEX = re.compile(
+ r"http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+"
+)
+
+
+class FileHandle:
+ """
+ File handle
+ """
+
+ def __init__(
+ self, folder, branch=None, cve=None, pkg=None, csv_file=None, read_csv=None
+ ) -> None:
+ if read_csv and not callable(read_csv):
+ raise ValueError(
+ "The read_csv parameter is a function that can be called to read CSV files"
+ )
+ self.read_csv = read_csv or self._read_csv
+ self.folder = folder
+ self.cve = cve
+ self.pkg = pkg
+ self.cve_file = csv_file
+ self.branches = branch
+ self._apply = "All branch apply failed"
+
+ def _read_csv(self, **kwargs):
+ raise NotImplementedError
+
+ @staticmethod
+ def copy(source_path, target_path):
+ """
+ Copy the files in the directory to each version folder
+ Args:
+ source_path: source path
+ target_path: target path
+ Returns:
+ folder: folder path
+
+ """
+ os.makedirs(target_path, exist_ok=True)
+ files_num = sum([os.path.isfile(listx) for listx in os.listdir(target_path)])
+ files = os.listdir(source_path)
+ for index, file in enumerate(files, start=1):
+ try:
+ mv_file_name = file.split("_")[0] + "_{num}.patch".format(
+ num=files_num + index
+ )
+ shutil.copyfile(
+ os.path.join(source_path, file),
+ os.path.join(target_path, mv_file_name),
+ )
+ except shutil.Error:
+ logger.warning(
+ "The file '%s' of the same name exists in the folder : %s"
+ % (file, os.path.join(target_path, mv_file_name))
+ )
+
+ def _parse_text(self, path):
+ """
+ parse text content
+ Args:
+ root: root
+ cve_folder: cve_folder
+
+ Returns:
+ repair_content: repair_content
+ """
+ with open(path, "r", encoding="utf-8") as file:
+ suspected_spatch = []
+ not_found_patch = []
+ download_failed = []
+ finds = []
+ find_path = {}
+ for line in file.readlines():
+ if "cve information" in line.lower():
+ cve_info = line.replace("CVE Information : ", "")
+ cve_dict = ast.literal_eval(cve_info)
+ if "Uncertain" in line:
+ suspected_spatch.append(line.split(":")[1].split("\n")[0])
+ if "no patch information" in line:
+ not_found_patch.append(line.split(" result:")[0])
+ if "File download failed" in line:
+ download_failed.append(line.split("failed:")[1].split("\n")[0])
+ if "find patch information" in line:
+ find = line.split(":")[1].split("\n")[0]
+ if find not in finds:
+ finds.append(find)
+ find_path[line.split("in ")[1].split(":")[0]] = finds
+ repair_content = {
+ "pkg_name": cve_dict.get("pkg"),
+ "cve": cve_dict.get("cve"),
+ "versions": cve_dict.get("versions"),
+ "Not found patch": ["Platform", list(set(not_found_patch))],
+ "Seen patch files": ["Platform Patchs", find_path],
+ "Download failed": ["Download Patchs URl", list(set(download_failed))],
+ "Suspected Patchs URL": [
+ "Suspected Patchs URL",
+ list(set(suspected_spatch)),
+ ],
+ }
+ return repair_content
+
+ def _write_text_body(self, heard, patch_content, file):
+ """
+ write_text_body
+ Args:
+ heard: heard
+ patch_content: patch_content
+ file: file
+ """
+ file.write("=" * 20 + heard + "=" * 20 + "\n")
+ if not patch_content[1]:
+ file.write("There is no information" + "\n\n")
+ return
+ if isinstance(patch_content[1], dict):
+ for platform, patchs in patch_content[1].items():
+ seen_patch = patch_content[0].split(" ")
+ for patch in patchs:
+ file.write(
+ seen_patch[0]
+ + " "
+ + platform
+ + " "
+ + seen_patch[1]
+ + ": "
+ + patch
+ + "\n\n"
+ )
+ else:
+ for val in patch_content[1]:
+ file.write(patch_content[0] + ": " + val + "\n\n")
+
+ def _wirte_text_format(self, repair_content, path, apply_result, pkg):
+ """
+ wirte text format
+ Args:
+ repair_content: repair_content
+ root: root
+ cve_folder: cve_folder
+ """
+
+ pkg_name = repair_content.get("pkg_name")
+ cve = repair_content.get("cve")
+ versions = repair_content.get("versions")
+
+ with open(path, "w", encoding="utf-8") as file:
+ file.write(
+ f"package name: {pkg_name}\n\nCVE number: {cve}\n\nversions: {pprint.pformat(versions)}\n\n"
+ )
+ for heard, patch_content in repair_content.items():
+ if heard not in ["pkg_name", "cve", "versions"]:
+ self._write_text_body(heard, patch_content, file)
+
+ # apply results of patch
+ if apply_result:
+ for apply_info in self._write_apply_result(pkg, apply_result):
+ file.write(apply_info)
+
+ def _write_apply_result(self, pkg_name, apply_result):
+
+ add_content = list("=" * 20 + "Apply Result" + "=" * 20 + "\n")
+ if apply_result == self._apply:
+ add_content.append(apply_result)
+ else:
+ for branch in self.branches:
+ for result in apply_result.split("\n"):
+ if re.match(
+ f"^\[INFO\] {pkg_name}.*{branch}.*successfully$", result
+ ):
+ add_content.append(f"Apply result: {branch} : apply success")
+ if re.match(f"^\[ERROR\] {pkg_name}.*{branch}.*failed", result):
+ add_content.append(f"Apply result: {branch} : apply failed")
+
+ return add_content
+
+ def _overwrite_text(self, folder, pkg_name, cve_num, apply_result):
+ """
+ write content
+ Args:
+ args: parameter
+ pkg_name: pkg_name
+ cve_num: cve_num
+ apply_result: apply patch result
+ """
+ file_path = os.path.join(folder, pkg_name + "-" + cve_num, RECORD_FILE)
+ if not os.path.exists(file_path):
+ logger.error("The specified file does not exist : %s" % file_path)
+ return
+ try:
+
+ format_text = self._parse_text(file_path)
+ self._wirte_text_format(format_text, file_path, apply_result, pkg_name)
+ except IOError as error:
+ logger.error(error)
+
+ def format_text(self, apply_result=None):
+ """
+ Format the contents recorded in the file to present the process in a uniform format
+ Args:
+ args : parameter
+ """
+ cve_infos = []
+ if self.cve_file:
+ try:
+ cve_infos.extend(
+ self.read_csv(
+ os.path.join(self.cve_file),
+ out_path=self.folder,
+ return_content=True,
+ )
+ )
+ except TypeError:
+ raise ValueError(
+ "The return value of the read_csv function must be iterable"
+ )
+ if all([self.pkg, self.cve]):
+ cve_infos.append([self.pkg, self.cve])
+
+ # Traversal process the searched patch information
+ for cve in cve_infos:
+ pkg_name, cve_num = cve
+ self._overwrite_text(self.folder, pkg_name, cve_num, apply_result)
+
+ def extract_text(self, path):
+ """
+ Extracting the comment content from the text
+ """
+ patchs = list()
+ apply_result = []
+ with open(path, "r", encoding="utf-8") as file:
+ lines = file.readlines()
+ for index, line in enumerate(lines, start=1):
+ if all([p in line for p in ("Platform", "Patchs")]):
+ patchs.extend(re.findall(URL_REGEX, line))
+ if "Apply Result" in line:
+ apply_result = lines[index:]
+ break
+ if self._apply in apply_result:
+ apply_result = [branch + ":" + self._apply for branch in self.branches]
+
+ return {
+ "urls": list(set(patchs)),
+ "apply_result": dict([tuple(apply.split(":")) for apply in apply_result]),
+ }
+
+
+class RequestsUrl:
+ """
+ File download save method
+ """
+
+ def __init__(self, url, crawl, callback=None, **kwargs) -> None:
+ self.crawl = crawl
+ self.url = url
+ self.callback = callback or self._wget
+ self.__dict__.update(**kwargs)
+
+ def _wget(self, response, **kwargs):
+ """
+ Send the request
+ Args:
+ response: response
+ **kwargs:
+
+ Returns:
+
+ """
+ folder = self.crawl.folder or DEFAULT_SAVE_PATH
+ tmp_path = os.path.join(folder, "tmp-folder")
+ try:
+ os.makedirs(tmp_path, exist_ok=True)
+ with open(
+ os.path.join(
+ tmp_path,
+ self.crawl.cve
+ + "_{r}.patch".format(
+ r=hashlib.sha1(self.url.encode()).hexdigest()
+ ),
+ ),
+ "w",
+ encoding="utf-8",
+ ) as file:
+ file.write(response.text)
+ except IOError as error:
+ logger.error(error)
+ else:
+ folders = self.crawl.create_folders(self.crawl.versions)
+ if isinstance(folders, str):
+ folders = [folders]
+
+ for target_folder in folders:
+ FileHandle.copy(tmp_path, target_folder)
+ finally:
+ if os.path.exists(tmp_path):
+ shutil.rmtree(tmp_path)
+
+
+class RequestRepeat:
+ """
+ Request address duplicate determination
+ """
+
+ def __init__(self) -> None:
+ self._fingerprints = set()
+
+ def _to_bytes(self, text, encoding="utf-8"):
+ if isinstance(text, bytes):
+ return text
+ return text.encode(encoding)
+
+ def _request_figerprint(self, request):
+ hash_fp = hashlib.sha1()
+ hash_fp.update(self._to_bytes(request.crawl.cve))
+ hash_fp.update(self._to_bytes(request.url))
+ return hash_fp.hexdigest()
+
+ def request_seen(self, request):
+ """
+ Check if the URL has already been processed
+ """
+ hash_fp = self._request_figerprint(request=request)
+ if hash_fp in self._fingerprints:
+ return True
+ self._fingerprints.add(hash_fp)
+
+ return False
+
+
+class SavePipe:
+ """
+ Data storage pipeline
+ """
+
+ def __init__(self, crawl, **kwargs) -> None:
+ """
+ Initialize the class
+ Args:
+ crawl:
+ **kwargs: crawl
+ """
+ self.crawl = crawl
+ self.__dict__.update(**kwargs)
+
+ def save_process(self, crawl):
+ """
+ Data storage pipeline
+ Args:
+ crawl: crawl
+
+ Returns:
+
+ """
+ path = os.path.join(crawl.folder, RECORD_FILE)
+ try:
+ os.makedirs(crawl.folder, exist_ok=True)
+ if not hasattr(self, "text") or not self.text:
+ return
+ with open(path, "a", encoding="utf-8") as file:
+ file.write(getattr(self, "text", "") + "\n")
+ except IOError as error:
+ logger.error(error)
diff --git a/cve-agency-manager/cve_tracking/src/cve/plantform.py b/cve-agency-manager/cve_tracking/src/cve/plantform.py
new file mode 100644
index 0000000000000000000000000000000000000000..9767226729f8151594ba33ae560049b7a2c63adb
--- /dev/null
+++ b/cve-agency-manager/cve_tracking/src/cve/plantform.py
@@ -0,0 +1,596 @@
+#!/usr/bin/python3
+import json
+import re
+import os
+import pprint
+from bs4 import BeautifulSoup
+import requests
+from .bugzilla import Api
+from .settings import DEFAULT_SAVE_PATH
+from .logger import logger, get_spider_looger_str
+from .pipe import SavePipe, RequestsUrl
+
+
+URL_REGEX = re.compile(
+ r"http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+"
+)
+VERSION_REGEX = r"(\d+[.-]?)+([.-]?[A-Za-z0-9]*)*"
+
+__all__ = ["Crawl", "Nvd", "Debian", "Ubuntu", "Bugzilla"]
+
+
+class Crawl:
+ """
+ CVE platform base class
+ """
+
+ def __init__(self, cve, pkg, versions, out_path, **kwargs) -> None:
+ self.cve = cve
+ self.pkg = pkg
+ self.versions = versions
+ self.fix_versions = None
+ self._folder = out_path
+ self.__dict__.update(**kwargs)
+
+ def parse(self, response, **kwargs):
+ """
+ All enabled entrances
+ Args:
+ response: response
+ **kwargs: kwargs
+
+ Returns:
+ None
+ """
+ raise NotImplementedError(
+ f"{self.__class__.__name__}.parse callback is not defined"
+ )
+
+ @staticmethod
+ def _re_escape(name: str):
+ """escape str
+
+ Args:
+ name (str): pkgname
+
+ Returns:
+ str: escape new pkg name
+ """
+ if "+" in name:
+ name = name.replace("+", "\+")
+ if "^" in name:
+ name = name.replace("^", "\^")
+ if "$" in name:
+ name = name.replace("$", "\$")
+ if "." in name:
+ name = name.replace(".", "\.")
+ if "|" in name:
+ name = name.replace("|", "\|")
+ if "-" in name:
+ name = name.replace("-", "\-")
+ return name
+
+ @property
+ def folder(self):
+ """
+ The CVE folder in the specified directory
+ """
+ folder = getattr(self, "_folder", DEFAULT_SAVE_PATH)
+ if hasattr(self, "pkg") and hasattr(self, "cve"):
+ folder = os.path.join(folder, self.pkg + "-" + self.cve)
+ return folder
+
+ def _create_folder(self, version, folder=None):
+ """
+ Create a folder Path
+ Args:
+ version: version
+ folder: The folder defaults to None
+
+ Returns:
+ path: folder path
+ """
+ if not folder:
+ folder = self.folder
+
+ path = os.path.join(folder, str(version))
+ os.makedirs(os.path.dirname(path), exist_ok=True)
+ return path
+
+ def create_folders(self, versions):
+ """
+ Creating Folder Collection
+ Args:
+ versions: Multiple versions
+
+ Returns:
+ folder: folder path
+ """
+ if not versions:
+ return self.folder
+
+ for version in versions:
+ return self._create_folder(version)
+
+ def git(self, func):
+ """
+ git
+ """
+ git_regex = "^http[s]?://git.({pkg_name}|.*).(org|net)(.*{pkg_name}([0-9]+)?(.git)?/commit.*|(/gitweb)?/\?p={pkg_name}([0-9]+)?.git;a=commit.*)".format(
+ pkg_name=Crawl._re_escape(self.pkg)
+ )
+
+ def wrap(*args, **kwargs):
+ url = kwargs.get("url", "")
+ if re.match(git_regex, url, flags=re.IGNORECASE):
+ url = re.sub("commit|commitdiff|commitdiff_plain", "patch", url)
+ return url
+ if re.match(
+ "^https://git.*raw/([0-9a-z]*$|.*\.patch$)", url, flags=re.IGNORECASE
+ ):
+ return url
+
+ return func(*args, **kwargs)
+
+ return wrap
+
+ def github(self, func):
+ """
+ github
+ """
+ github_regex = "^http[s]?://github.com.*{pkg_name}(.*)?/commit.*".format(
+ pkg_name=Crawl._re_escape(self.pkg)
+ )
+
+ def wrap(*args, **kwargs):
+ url = kwargs.get("url", "")
+ if re.match(github_regex, url, flags=re.IGNORECASE):
+ url = re.sub("\s+(.*)|\?.*", "", url)
+ return url + ".patch"
+ return func(*args, **kwargs)
+
+ return wrap
+
+ def gitlab(self, func):
+ """
+ gitlab
+ """
+ gitlab_regex = (
+ "^http[s]?://gitlab(.*.org|.com).*{pkg_name}([0-9]+)?(/-)?/commit.*".format(
+ pkg_name=Crawl._re_escape(self.pkg)
+ )
+ )
+
+ def wrap(*args, **kwargs):
+ url = kwargs.get("url", "")
+ if re.match(gitlab_regex, url, flags=re.IGNORECASE):
+ url = re.sub("\s+(.*)|\?.*", "", url)
+ return url + ".patch"
+ return func(*args, **kwargs)
+
+ return wrap
+
+ def match(self, url):
+ """
+ match url
+ """
+
+ @self.github
+ @self.git
+ @self.gitlab
+ def _match_url(url):
+ return None
+
+ return _match_url(url=url)
+
+
+class Versions:
+ """
+ Version number processing
+ """
+
+ separator = (".", "-")
+ _connector = "&"
+
+ def _order(self, version, separator=None):
+ """
+ Version of the cutting
+ Args:
+ version: version
+ separator: separator
+
+ Returns:
+
+ """
+ if not separator:
+ separator = self._connector
+ return tuple([int(v) for v in version.split(separator) if v.isdigit()])
+
+ def _similar(self, text, compare_text):
+ """
+ Similarity comparison
+ Args:
+ text: text
+ compare_text: compare_text
+
+ Returns:
+
+ """
+ _text = text if len(text) < len(compare_text) else compare_text
+ weight = 0
+ for index, _ in enumerate(_text):
+ if text[index] != compare_text[index]:
+ weight = index
+ break
+ return weight / len(text) * 1.0 * 100
+
+ def similarity(self, text, compare_queue):
+ """
+ Compare the similarity of two strings
+ """
+ if isinstance(compare_queue, str):
+ return self._similar(text, compare_queue)
+ ratio = [self._similar(text, compare_text) for compare_text in compare_queue]
+ return ratio
+
+ def match_version(self, pkg_name, fix_text):
+ """
+ Match the version number of the software from the repaired text
+ """
+ versions = list()
+ for pkg_info in fix_text.split(","):
+ if pkg_name.lower() in pkg_info.lower():
+ _v = re.search(VERSION_REGEX, pkg_info)
+ versions.append(_v.group())
+ return versions
+
+ def lgt(self, version, compare_version):
+ """
+ Returns true if the size of the compared version is greater
+ than that of the compared version, or false otherwise
+
+ """
+ for separator in self.separator:
+ version = self._connector.join([v for v in version.split(separator)])
+ compare_version = self._connector.join(
+ [v for v in compare_version.split(separator)]
+ )
+ version = self._order(version)
+ compare_version = self._order(compare_version)
+ return version >= compare_version
+
+
+class Nvd(Crawl):
+ """
+ nvd plantform
+ """
+
+ nvd_host = "https://nvd.nist.gov"
+
+ def __init__(self, cve, pkg, versions, out_path=DEFAULT_SAVE_PATH):
+ super(Nvd, self).__init__(
+ cve=cve, pkg=pkg, versions=versions, out_path=out_path
+ )
+ self.start_url = self.nvd_host + "/vuln/detail/" + cve
+
+ def get_urls(self, resp_str, pkg):
+ """
+ Gets the URL of patch
+ Args:
+ resp_str: resp_str
+ pkg: pkg
+
+ Returns:
+
+ """
+ patch_urls = set()
+ other_urls = set()
+ pkg = Crawl._re_escape(pkg)
+
+ soup = BeautifulSoup(resp_str, "html.parser")
+ urls = [
+ res.text
+ for res in soup.find_all(
+ name="td", attrs={"data-testid": re.compile("vuln-hyperlinks-link-\d+")}
+ )
+ ]
+ for url in urls:
+ seen_url = self.match(url=url)
+ if seen_url:
+ patch_urls.add(seen_url)
+ else:
+ other_urls.add(url)
+
+ logger_str = get_spider_looger_str(
+ "Nvd", self.pkg, self.versions, self.cve, patch_urls, other_urls
+ )
+ logger.info(logger_str)
+
+ return patch_urls, other_urls
+
+ def parse(self, response, **kwargs):
+ """
+ Parse response data
+ Args:
+ response: response
+ **kwargs:
+
+ Returns:
+
+ """
+ patch_urls, other_urls = self.get_urls(response.text, self.pkg)
+ if not patch_urls:
+ if not other_urls:
+ text = "NVD result:There is no patch information and it has not been repaired"
+ yield SavePipe(crawl=self, text=text)
+ else:
+ for other_url in other_urls:
+ text = "Uncertain patch information in Nvd:%s" % other_url
+ yield SavePipe(crawl=self, text=text)
+ else:
+ for url in patch_urls:
+ text = "find patch information in Nvd:%s" % url
+ yield SavePipe(crawl=self, text=text)
+ yield RequestsUrl(url=url, crawl=self, is_patch=True)
+
+
+class Debian(Crawl):
+ """
+ Get the PR address in the Debian website
+ """
+
+ def __init__(self, cve, versions, pkg, out_path=DEFAULT_SAVE_PATH):
+ """
+ Initialize attribute
+ Args:
+ cve_num: cve number
+ """
+ super(Debian, self).__init__(
+ cve=cve, pkg=pkg, versions=versions, out_path=out_path
+ )
+ self.start_url = "https://security-tracker.debian.org/tracker/" + self.cve
+
+ def parse(self, response, **kwargs):
+ """
+ Parse response data
+ Args:
+ response: response
+ **kwargs:
+
+ Returns:
+
+ """
+
+ patch_urls = []
+ other_urls = []
+ soup = BeautifulSoup(response.text, "html.parser")
+ pre = soup.pre
+
+ if pre:
+ links = pre.find_all("a")
+ for link in links:
+ _url = link.get("href")
+ seen_url = self.match(url=_url)
+ if seen_url:
+ patch_urls.append(seen_url)
+ else:
+ other_urls.append(_url)
+ logger_str = get_spider_looger_str(
+ "Debian", self.pkg, self.versions, self.cve, patch_urls, other_urls
+ )
+ logger.info(logger_str)
+ for url in other_urls:
+ text = "Uncertain patch information in Debian:%s" % url
+ yield SavePipe(crawl=self, text=text)
+ for patch_url in patch_urls:
+ yield RequestsUrl(url=patch_url, crawl=self, is_patch=True)
+ text = "find patch information in Debian:%s" % patch_url
+ yield SavePipe(crawl=self, text=text)
+ if not any([other_urls, patch_urls]):
+ text = "Debian result:There is no patch information and it has not been repaired"
+ yield SavePipe(crawl=self, text=text)
+
+
+class Ubuntu(Crawl):
+ """
+ Get the PR address in the Ubuntu website
+ """
+
+ def __init__(self, cve, versions, pkg, out_path=DEFAULT_SAVE_PATH):
+ """
+ Initialize attribute
+ Args:
+ cve: cve number
+ """
+ super(Ubuntu, self).__init__(
+ cve=cve, pkg=pkg, versions=versions, out_path=out_path
+ )
+ self.start_url = "https://ubuntu.com/security/" + self.cve
+
+ def parse(self, response, **kwargs):
+ """
+ Parse the webpage and extract the url
+ Args:
+ response:webpage
+ Returns:
+
+ """
+
+ git_list, other_list = [], []
+ try:
+ soup = BeautifulSoup(response.text, "lxml")
+ content = soup.find(colspan="2")
+ for url in content.find_all("a"):
+ patch_url = url.get("href")
+ seen_url = self.match(url=patch_url)
+ if seen_url:
+ git_list.append(seen_url)
+ else:
+ other_list.append(patch_url)
+
+ logger_str = get_spider_looger_str(
+ "Ubuntu", self.pkg, self.versions, self.cve, git_list, other_list
+ )
+ logger.info(logger_str)
+
+ for patch in git_list:
+ yield RequestsUrl(url=patch, crawl=self, is_patch=True)
+ text = "find patch information in Ubuntu:%s" % patch
+ yield SavePipe(crawl=self, text=text)
+ for url in other_list:
+ text = "Uncertain patch information in Ubuntu:%s" % url
+ yield SavePipe(crawl=self, text=text)
+ except:
+ logger.info(
+ "Ubuntu result:There is no patch information and it has not been repaired"
+ )
+ yield SavePipe(
+ crawl=self,
+ text="Ubuntu result:There is no patch information and it has not been repaired",
+ )
+
+
+class Bugzilla(Crawl):
+ """
+ Bug fix
+ """
+
+ bugzilla_api = Api(base_url="https://bugzilla.redhat.com")
+
+ def __init__(self, cve, pkg, versions, out_path=DEFAULT_SAVE_PATH):
+ self._v = Versions()
+ super(Bugzilla, self).__init__(
+ cve=cve, pkg=pkg, versions=versions, out_path=out_path
+ )
+ self.start_url = self.bugzilla_api.get_bug(fields=dict(alias=self.cve))
+
+ @staticmethod
+ def load_json(content):
+ """
+ Loading JSON data
+
+ Args:
+ content: The JSON content returned by the HTTP request
+ """
+ if not content:
+ return dict()
+ try:
+ json_data = json.loads(content)
+ except json.JSONDecodeError:
+ json_data = dict()
+ return json_data
+
+ def _extract_fixed_in_version(self, bugs_info):
+ """
+ extract fixed in version
+
+ Args:
+ bugs_info: Description of CVE information
+ pkg_name: The package name of the fix
+ """
+ fixed_in_versions = []
+ for bug in bugs_info.get("bugs", []):
+ fixed_in_versions.extend(
+ self._v.match_version(self.pkg, bug.get("cf_fixed_in", ""))
+ )
+
+ return fixed_in_versions
+
+ def _get_comments(self):
+ """
+ Get CVE comment information
+
+ """
+ status_code, response = self.bugzilla_api.get_comments(fields=self.cve)
+ comments = dict()
+ if status_code == requests.codes["ok"]:
+ comments = Bugzilla.load_json(response)
+ return comments
+
+ def _filter_patch_remote(self, remote_url):
+ """
+ Filter out the patch pack path in GitHub based on the existing policy
+
+ Args:
+ remote_url:The remote address
+ """
+ if isinstance(remote_url, str):
+ remote_url = [remote_url]
+ patch_urls = list()
+
+ for url in remote_url:
+ seen_url = self.match(url=url)
+ if seen_url:
+ patch_urls.append(seen_url)
+
+ return patch_urls
+
+ def contrast_version(self, fix_versions, warehouse_versions):
+ """
+ Fix or affect version alignment
+ """
+ _fix_version = list()
+ for _version in warehouse_versions:
+ version_similarity = self._v.similarity(_version, fix_versions)
+ compared_version = fix_versions[
+ version_similarity.index(max(version_similarity))
+ ]
+ if self._v.lgt(_version, compared_version):
+ _fix_version.append(_version)
+
+ return _fix_version
+
+ def _extract_url(self, comments):
+ """
+ Extracting comment information
+ Args:
+ comments:
+
+ Returns:
+
+ """
+ pulls = []
+ for _, comment in comments["bugs"].items():
+ for comment_info in comment["comments"]:
+ pulls.extend(re.findall(URL_REGEX, comment_info["text"]))
+ return pulls
+
+ def parse_comments(self, response, **kwargs):
+ """
+ Parse the bug comment content
+ """
+ comments = Bugzilla.load_json(response.text)
+ if not comments:
+ logger.info("Bugzilla result:{} has no comment".format(self.cve))
+ yield SavePipe(
+ crawl=self,
+ text="Bugzilla result:There is no patch information and it has not been repaired",
+ )
+
+ patchs = self._filter_patch_remote(remote_url=self._extract_url(comments))
+ if patchs:
+ logger.info(f"Bugzilla result: found patch urls :{pprint.pformat(patchs)}")
+ for patch in patchs:
+ text = "find patch information in Bugzilla:%s" % patch
+ yield SavePipe(crawl=self, text=text)
+ yield RequestsUrl(url=patch, crawl=self, is_patch=True)
+ else:
+ logger.info("Bugzilla result:{} is not fixed yet".format(self.cve))
+ yield SavePipe(
+ crawl=self,
+ text="Bugzilla result:no patch information in Bugzilla and it has not been fixed yet",
+ )
+
+ def parse(self, response, **kwargs):
+ """
+ Get the bug information for parsing
+ """
+ self.fix_versions = self._extract_fixed_in_version(
+ bugs_info=Bugzilla.load_json(response.text)
+ )
+
+ yield RequestsUrl(
+ url=self.bugzilla_api.get_comments(fields=self.cve),
+ crawl=self,
+ callback=self.parse_comments,
+ )
diff --git a/cve-agency-manager/cve_tracking/src/cve/settings.py b/cve-agency-manager/cve_tracking/src/cve/settings.py
new file mode 100644
index 0000000000000000000000000000000000000000..a9468cd2d2bd69b06f8c3b66bffb1d92557e0cda
--- /dev/null
+++ b/cve-agency-manager/cve_tracking/src/cve/settings.py
@@ -0,0 +1,38 @@
+#!/usr/bin/python3
+# ******************************************************************************
+# Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved.
+# licensed under the Mulan PSL v2.
+# You can use this software according to the terms and conditions of the Mulan PSL v2.
+# You may obtain a copy of Mulan PSL v2 at:
+# http://license.coscl.org.cn/MulanPSL2
+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+# PURPOSE.
+# See the Mulan PSL v2 for more details.
+# ******************************************************************************/
+
+
+# The default path to save CVE information
+DEFAULT_SAVE_PATH = "/tmp/cve_tracking/match_cve"
+
+# The save path of the log file
+LOG_DIR = "/tmp/cve_tracking/cve-log"
+
+# Internal source package information request address
+INTERNAL_SERVER = "http://124.160.11.57:8100/git_command"
+
+# Enable patch lookup platform
+ENABLE_PLANTFORM = ["Bugzilla", "Debian", "Ubuntu", "Nvd"]
+
+# The maximum number of threads allowed to live at the same time in the downloaded thread pool
+MAX_WORKERS = 16
+
+# Maximum number in the queue
+MAX_QUEUE = 100
+
+# The name of the file after platform information integration, which records the important information for finding CVE patch
+
+RECORD_FILE = "repair-verdict.txt"
+
+# Code cloud related API authorization operations, You need to set a global environment variable on the server, where you specify the name of the environment variable
+GITEE_AUTH = {"token": "gitee_token", "account": "gitee_account"}
diff --git a/cve-agency-manager/cve_tracking/src/cve/user-agent.json b/cve-agency-manager/cve_tracking/src/cve/user-agent.json
new file mode 100644
index 0000000000000000000000000000000000000000..92352d50af2c83cc0fa6040f692c7fe2acd041a5
--- /dev/null
+++ b/cve-agency-manager/cve_tracking/src/cve/user-agent.json
@@ -0,0 +1,1251 @@
+{
+ "browsers": {
+ "chrome": [
+ "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36",
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.1 Safari/537.36",
+ "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.0 Safari/537.36",
+ "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.0 Safari/537.36",
+ "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2226.0 Safari/537.36",
+ "Mozilla/5.0 (Windows NT 6.4; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2225.0 Safari/537.36",
+ "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2225.0 Safari/537.36",
+ "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2224.3 Safari/537.36",
+ "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.93 Safari/537.36",
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36",
+ "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2049.0 Safari/537.36",
+ "Mozilla/5.0 (Windows NT 4.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2049.0 Safari/537.36",
+ "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.67 Safari/537.36",
+ "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.67 Safari/537.36",
+ "Mozilla/5.0 (X11; OpenBSD i386) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36",
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1944.0 Safari/537.36",
+ "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.3319.102 Safari/537.36",
+ "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.2309.372 Safari/537.36",
+ "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.2117.157 Safari/537.36",
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Safari/537.36",
+ "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1866.237 Safari/537.36",
+ "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.137 Safari/4E423F",
+ "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36 Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B334b Safari/531.21.10",
+ "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.517 Safari/537.36",
+ "Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1667.0 Safari/537.36",
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1664.3 Safari/537.36",
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1664.3 Safari/537.36",
+ "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.16 Safari/537.36",
+ "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1623.0 Safari/537.36",
+ "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.17 Safari/537.36",
+ "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.62 Safari/537.36",
+ "Mozilla/5.0 (X11; CrOS i686 4319.74.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.57 Safari/537.36",
+ "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.2 Safari/537.36",
+ "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1468.0 Safari/537.36",
+ "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1467.0 Safari/537.36",
+ "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1464.0 Safari/537.36",
+ "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1500.55 Safari/537.36",
+ "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.93 Safari/537.36",
+ "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.93 Safari/537.36",
+ "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.93 Safari/537.36",
+ "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.93 Safari/537.36",
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.93 Safari/537.36",
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.93 Safari/537.36",
+ "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.90 Safari/537.36",
+ "Mozilla/5.0 (X11; NetBSD) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36",
+ "Mozilla/5.0 (X11; CrOS i686 3912.101.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36",
+ "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.60 Safari/537.17",
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1309.0 Safari/537.17",
+ "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.15 (KHTML, like Gecko) Chrome/24.0.1295.0 Safari/537.15",
+ "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.14 (KHTML, like Gecko) Chrome/24.0.1292.0 Safari/537.14"
+ ],
+ "opera": [
+ "Opera/9.80 (X11; Linux i686; Ubuntu/14.10) Presto/2.12.388 Version/12.16",
+ "Opera/9.80 (Windows NT 6.0) Presto/2.12.388 Version/12.14",
+ "Mozilla/5.0 (Windows NT 6.0; rv:2.0) Gecko/20100101 Firefox/4.0 Opera 12.14",
+ "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0) Opera 12.14",
+ "Opera/12.80 (Windows NT 5.1; U; en) Presto/2.10.289 Version/12.02",
+ "Opera/9.80 (Windows NT 6.1; U; es-ES) Presto/2.9.181 Version/12.00",
+ "Opera/9.80 (Windows NT 5.1; U; zh-sg) Presto/2.9.181 Version/12.00",
+ "Opera/12.0(Windows NT 5.2;U;en)Presto/22.9.168 Version/12.00",
+ "Opera/12.0(Windows NT 5.1;U;en)Presto/22.9.168 Version/12.00",
+ "Mozilla/5.0 (Windows NT 5.1) Gecko/20100101 Firefox/14.0 Opera/12.0",
+ "Opera/9.80 (Windows NT 6.1; WOW64; U; pt) Presto/2.10.229 Version/11.62",
+ "Opera/9.80 (Windows NT 6.0; U; pl) Presto/2.10.229 Version/11.62",
+ "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; fr) Presto/2.9.168 Version/11.52",
+ "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; de) Presto/2.9.168 Version/11.52",
+ "Opera/9.80 (Windows NT 5.1; U; en) Presto/2.9.168 Version/11.51",
+ "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; de) Opera 11.51",
+ "Opera/9.80 (X11; Linux x86_64; U; fr) Presto/2.9.168 Version/11.50",
+ "Opera/9.80 (X11; Linux i686; U; hu) Presto/2.9.168 Version/11.50",
+ "Opera/9.80 (X11; Linux i686; U; ru) Presto/2.8.131 Version/11.11",
+ "Opera/9.80 (X11; Linux i686; U; es-ES) Presto/2.8.131 Version/11.11",
+ "Mozilla/5.0 (Windows NT 5.1; U; en; rv:1.8.1) Gecko/20061208 Firefox/5.0 Opera 11.11",
+ "Opera/9.80 (X11; Linux x86_64; U; bg) Presto/2.8.131 Version/11.10",
+ "Opera/9.80 (Windows NT 6.0; U; en) Presto/2.8.99 Version/11.10",
+ "Opera/9.80 (Windows NT 5.1; U; zh-tw) Presto/2.8.131 Version/11.10",
+ "Opera/9.80 (Windows NT 6.1; Opera Tablet/15165; U; en) Presto/2.8.149 Version/11.1",
+ "Opera/9.80 (X11; Linux x86_64; U; Ubuntu/10.10 (maverick); pl) Presto/2.7.62 Version/11.01",
+ "Opera/9.80 (X11; Linux i686; U; ja) Presto/2.7.62 Version/11.01",
+ "Opera/9.80 (X11; Linux i686; U; fr) Presto/2.7.62 Version/11.01",
+ "Opera/9.80 (Windows NT 6.1; U; zh-tw) Presto/2.7.62 Version/11.01",
+ "Opera/9.80 (Windows NT 6.1; U; zh-cn) Presto/2.7.62 Version/11.01",
+ "Opera/9.80 (Windows NT 6.1; U; sv) Presto/2.7.62 Version/11.01",
+ "Opera/9.80 (Windows NT 6.1; U; en-US) Presto/2.7.62 Version/11.01",
+ "Opera/9.80 (Windows NT 6.1; U; cs) Presto/2.7.62 Version/11.01",
+ "Opera/9.80 (Windows NT 6.0; U; pl) Presto/2.7.62 Version/11.01",
+ "Opera/9.80 (Windows NT 5.2; U; ru) Presto/2.7.62 Version/11.01",
+ "Opera/9.80 (Windows NT 5.1; U;) Presto/2.7.62 Version/11.01",
+ "Opera/9.80 (Windows NT 5.1; U; cs) Presto/2.7.62 Version/11.01",
+ "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.13) Gecko/20101213 Opera/9.80 (Windows NT 6.1; U; zh-tw) Presto/2.7.62 Version/11.01",
+ "Mozilla/5.0 (Windows NT 6.1; U; nl; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 Opera 11.01",
+ "Mozilla/5.0 (Windows NT 6.1; U; de; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 Opera 11.01",
+ "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; de) Opera 11.01",
+ "Opera/9.80 (X11; Linux x86_64; U; pl) Presto/2.7.62 Version/11.00",
+ "Opera/9.80 (X11; Linux i686; U; it) Presto/2.7.62 Version/11.00",
+ "Opera/9.80 (Windows NT 6.1; U; zh-cn) Presto/2.6.37 Version/11.00",
+ "Opera/9.80 (Windows NT 6.1; U; pl) Presto/2.7.62 Version/11.00",
+ "Opera/9.80 (Windows NT 6.1; U; ko) Presto/2.7.62 Version/11.00",
+ "Opera/9.80 (Windows NT 6.1; U; fi) Presto/2.7.62 Version/11.00",
+ "Opera/9.80 (Windows NT 6.1; U; en-GB) Presto/2.7.62 Version/11.00",
+ "Opera/9.80 (Windows NT 6.1 x64; U; en) Presto/2.7.62 Version/11.00",
+ "Opera/9.80 (Windows NT 6.0; U; en) Presto/2.7.39 Version/11.00"
+ ],
+ "firefox": [
+ "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1",
+ "Mozilla/5.0 (Windows NT 6.3; rv:36.0) Gecko/20100101 Firefox/36.0",
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10; rv:33.0) Gecko/20100101 Firefox/33.0",
+ "Mozilla/5.0 (X11; Linux i586; rv:31.0) Gecko/20100101 Firefox/31.0",
+ "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:31.0) Gecko/20130401 Firefox/31.0",
+ "Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0",
+ "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20120101 Firefox/29.0",
+ "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/29.0",
+ "Mozilla/5.0 (X11; OpenBSD amd64; rv:28.0) Gecko/20100101 Firefox/28.0",
+ "Mozilla/5.0 (X11; Linux x86_64; rv:28.0) Gecko/20100101 Firefox/28.0",
+ "Mozilla/5.0 (Windows NT 6.1; rv:27.3) Gecko/20130101 Firefox/27.3",
+ "Mozilla/5.0 (Windows NT 6.2; Win64; x64; rv:27.0) Gecko/20121011 Firefox/27.0",
+ "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/25.0",
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:25.0) Gecko/20100101 Firefox/25.0",
+ "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0",
+ "Mozilla/5.0 (Windows NT 6.0; WOW64; rv:24.0) Gecko/20100101 Firefox/24.0",
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:24.0) Gecko/20100101 Firefox/24.0",
+ "Mozilla/5.0 (Windows NT 6.2; rv:22.0) Gecko/20130405 Firefox/23.0",
+ "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20130406 Firefox/23.0",
+ "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:23.0) Gecko/20131011 Firefox/23.0",
+ "Mozilla/5.0 (Windows NT 6.2; rv:22.0) Gecko/20130405 Firefox/22.0",
+ "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:22.0) Gecko/20130328 Firefox/22.0",
+ "Mozilla/5.0 (Windows NT 6.1; rv:22.0) Gecko/20130405 Firefox/22.0",
+ "Mozilla/5.0 (Microsoft Windows NT 6.2.9200.0); rv:22.0) Gecko/20130405 Firefox/22.0",
+ "Mozilla/5.0 (Windows NT 6.2; Win64; x64; rv:16.0.1) Gecko/20121011 Firefox/21.0.1",
+ "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:16.0.1) Gecko/20121011 Firefox/21.0.1",
+ "Mozilla/5.0 (Windows NT 6.2; Win64; x64; rv:21.0.0) Gecko/20121011 Firefox/21.0.0",
+ "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:21.0) Gecko/20130331 Firefox/21.0",
+ "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:21.0) Gecko/20100101 Firefox/21.0",
+ "Mozilla/5.0 (X11; Linux i686; rv:21.0) Gecko/20100101 Firefox/21.0",
+ "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:21.0) Gecko/20130514 Firefox/21.0",
+ "Mozilla/5.0 (Windows NT 6.2; rv:21.0) Gecko/20130326 Firefox/21.0",
+ "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:21.0) Gecko/20130401 Firefox/21.0",
+ "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:21.0) Gecko/20130331 Firefox/21.0",
+ "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:21.0) Gecko/20130330 Firefox/21.0",
+ "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:21.0) Gecko/20100101 Firefox/21.0",
+ "Mozilla/5.0 (Windows NT 6.1; rv:21.0) Gecko/20130401 Firefox/21.0",
+ "Mozilla/5.0 (Windows NT 6.1; rv:21.0) Gecko/20130328 Firefox/21.0",
+ "Mozilla/5.0 (Windows NT 6.1; rv:21.0) Gecko/20100101 Firefox/21.0",
+ "Mozilla/5.0 (Windows NT 5.1; rv:21.0) Gecko/20130401 Firefox/21.0",
+ "Mozilla/5.0 (Windows NT 5.1; rv:21.0) Gecko/20130331 Firefox/21.0",
+ "Mozilla/5.0 (Windows NT 5.1; rv:21.0) Gecko/20100101 Firefox/21.0",
+ "Mozilla/5.0 (Windows NT 5.0; rv:21.0) Gecko/20100101 Firefox/21.0",
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:21.0) Gecko/20100101 Firefox/21.0",
+ "Mozilla/5.0 (Windows NT 6.2; Win64; x64;) Gecko/20100101 Firefox/20.0",
+ "Mozilla/5.0 (Windows x86; rv:19.0) Gecko/20100101 Firefox/19.0",
+ "Mozilla/5.0 (Windows NT 6.1; rv:6.0) Gecko/20100101 Firefox/19.0",
+ "Mozilla/5.0 (Windows NT 6.1; rv:14.0) Gecko/20100101 Firefox/18.0.1",
+ "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0",
+ "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:17.0) Gecko/20100101 Firefox/17.0.6"
+ ],
+ "internetexplorer": [
+ "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) like Gecko",
+ "Mozilla/5.0 (compatible, MSIE 11, Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko",
+ "Mozilla/5.0 (compatible; MSIE 10.6; Windows NT 6.1; Trident/5.0; InfoPath.2; SLCC1; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET CLR 2.0.50727) 3gpp-gba UNTRUSTED/1.0",
+ "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 7.0; InfoPath.3; .NET CLR 3.1.40767; Trident/6.0; en-IN)",
+ "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)",
+ "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)",
+ "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/5.0)",
+ "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/4.0; InfoPath.2; SV1; .NET CLR 2.0.50727; WOW64)",
+ "Mozilla/5.0 (compatible; MSIE 10.0; Macintosh; Intel Mac OS X 10_7_3; Trident/6.0)",
+ "Mozilla/4.0 (Compatible; MSIE 8.0; Windows NT 5.2; Trident/6.0)",
+ "Mozilla/4.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/5.0)",
+ "Mozilla/1.22 (compatible; MSIE 10.0; Windows 3.1)",
+ "Mozilla/5.0 (Windows; U; MSIE 9.0; WIndows NT 9.0; en-US))",
+ "Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)",
+ "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 7.1; Trident/5.0)",
+ "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; Media Center PC 6.0; InfoPath.3; MS-RTC LM 8; Zune 4.7)",
+ "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; Media Center PC 6.0; InfoPath.3; MS-RTC LM 8; Zune 4.7",
+ "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; Zune 4.0; InfoPath.3; MS-RTC LM 8; .NET4.0C; .NET4.0E)",
+ "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; chromeframe/12.0.742.112)",
+ "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)",
+ "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)",
+ "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 2.0.50727; SLCC2; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; Zune 4.0; Tablet PC 2.0; InfoPath.3; .NET4.0C; .NET4.0E)",
+ "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0",
+ "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; yie8)",
+ "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.2; .NET CLR 1.1.4322; .NET4.0C; Tablet PC 2.0)",
+ "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; FunWebProducts)",
+ "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; chromeframe/13.0.782.215)",
+ "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; chromeframe/11.0.696.57)",
+ "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0) chromeframe/10.0.648.205",
+ "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/4.0; GTB7.4; InfoPath.1; SV1; .NET CLR 2.8.52393; WOW64; en-US)",
+ "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0; Trident/5.0; chromeframe/11.0.696.57)",
+ "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0; Trident/4.0; GTB7.4; InfoPath.3; SV1; .NET CLR 3.1.76908; WOW64; en-US)",
+ "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; GTB7.4; InfoPath.2; SV1; .NET CLR 3.3.69573; WOW64; en-US)",
+ "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)",
+ "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; InfoPath.1; SV1; .NET CLR 3.8.36217; WOW64; en-US)",
+ "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; .NET CLR 2.7.58687; SLCC2; Media Center PC 5.0; Zune 3.4; Tablet PC 3.6; InfoPath.3)",
+ "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; Media Center PC 4.0; SLCC1; .NET CLR 3.0.04320)",
+ "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; SLCC1; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET CLR 1.1.4322)",
+ "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; InfoPath.2; SLCC1; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET CLR 2.0.50727)",
+ "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
+ "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 5.1; SLCC1; .NET CLR 1.1.4322)",
+ "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 5.0; Trident/4.0; InfoPath.1; SV1; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET CLR 3.0.04506.30)",
+ "Mozilla/5.0 (compatible; MSIE 7.0; Windows NT 5.0; Trident/4.0; FBSMTWB; .NET CLR 2.0.34861; .NET CLR 3.0.3746.3218; .NET CLR 3.5.33652; msn OptimizedIE8;ENUS)",
+ "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.2; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)",
+ "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; Media Center PC 6.0; InfoPath.2; MS-RTC LM 8)",
+ "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; Media Center PC 6.0; InfoPath.2; MS-RTC LM 8",
+ "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; Media Center PC 6.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C)",
+ "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; InfoPath.3; .NET4.0C; .NET4.0E; .NET CLR 3.5.30729; .NET CLR 3.0.30729; MS-RTC LM 8)",
+ "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; InfoPath.2)",
+ "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; Zune 3.0)"
+ ],
+ "safari": [
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/7046A194A",
+ "Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5355d Safari/8536.25",
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.13+ (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2",
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/534.55.3 (KHTML, like Gecko) Version/5.1.3 Safari/534.53.10",
+ "Mozilla/5.0 (iPad; CPU OS 5_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko ) Version/5.1 Mobile/9B176 Safari/7534.48.3",
+ "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; de-at) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/5.0.5 Safari/533.21.1",
+ "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7; da-dk) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/5.0.5 Safari/533.21.1",
+ "Mozilla/5.0 (Windows; U; Windows NT 6.1; tr-TR) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27",
+ "Mozilla/5.0 (Windows; U; Windows NT 6.1; ko-KR) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27",
+ "Mozilla/5.0 (Windows; U; Windows NT 6.1; fr-FR) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27",
+ "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27",
+ "Mozilla/5.0 (Windows; U; Windows NT 6.1; cs-CZ) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27",
+ "Mozilla/5.0 (Windows; U; Windows NT 6.0; ja-JP) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27",
+ "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27",
+ "Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10_5_8; zh-cn) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27",
+ "Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10_5_8; ja-jp) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27",
+ "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7; ja-jp) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27",
+ "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; zh-cn) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27",
+ "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; sv-se) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27",
+ "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; ko-kr) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27",
+ "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; ja-jp) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27",
+ "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; it-it) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27",
+ "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; fr-fr) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27",
+ "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; es-es) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27",
+ "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; en-us) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27",
+ "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; en-gb) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27",
+ "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; de-de) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27",
+ "Mozilla/5.0 (Windows; U; Windows NT 6.1; sv-SE) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4",
+ "Mozilla/5.0 (Windows; U; Windows NT 6.1; ja-JP) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4",
+ "Mozilla/5.0 (Windows; U; Windows NT 6.1; de-DE) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4",
+ "Mozilla/5.0 (Windows; U; Windows NT 6.0; hu-HU) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4",
+ "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4",
+ "Mozilla/5.0 (Windows; U; Windows NT 6.0; de-DE) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4",
+ "Mozilla/5.0 (Windows; U; Windows NT 5.1; ru-RU) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4",
+ "Mozilla/5.0 (Windows; U; Windows NT 5.1; ja-JP) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4",
+ "Mozilla/5.0 (Windows; U; Windows NT 5.1; it-IT) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4",
+ "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4",
+ "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7; en-us) AppleWebKit/534.16+ (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4",
+ "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; fr-ch) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4",
+ "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_5; de-de) AppleWebKit/534.15+ (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4",
+ "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_5; ar) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4",
+ "Mozilla/5.0 (Android 2.2; Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4",
+ "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-HK) AppleWebKit/533.18.1 (KHTML, like Gecko) Version/5.0.2 Safari/533.18.5",
+ "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.2 Safari/533.18.5",
+ "Mozilla/5.0 (Windows; U; Windows NT 6.0; tr-TR) AppleWebKit/533.18.1 (KHTML, like Gecko) Version/5.0.2 Safari/533.18.5",
+ "Mozilla/5.0 (Windows; U; Windows NT 6.0; nb-NO) AppleWebKit/533.18.1 (KHTML, like Gecko) Version/5.0.2 Safari/533.18.5",
+ "Mozilla/5.0 (Windows; U; Windows NT 6.0; fr-FR) AppleWebKit/533.18.1 (KHTML, like Gecko) Version/5.0.2 Safari/533.18.5",
+ "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-TW) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.2 Safari/533.18.5",
+ "Mozilla/5.0 (Windows; U; Windows NT 5.1; ru-RU) AppleWebKit/533.18.1 (KHTML, like Gecko) Version/5.0.2 Safari/533.18.5",
+ "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; zh-cn) AppleWebKit/533.18.1 (KHTML, like Gecko) Version/5.0.2 Safari/533.18.5"
+ ]
+ },
+ "randomize": {
+ "344": "chrome",
+ "819": "firefox",
+ "346": "chrome",
+ "347": "chrome",
+ "340": "chrome",
+ "341": "chrome",
+ "342": "chrome",
+ "343": "chrome",
+ "810": "internetexplorer",
+ "811": "internetexplorer",
+ "812": "internetexplorer",
+ "813": "firefox",
+ "348": "chrome",
+ "349": "chrome",
+ "816": "firefox",
+ "817": "firefox",
+ "737": "chrome",
+ "719": "chrome",
+ "718": "chrome",
+ "717": "chrome",
+ "716": "chrome",
+ "715": "chrome",
+ "714": "chrome",
+ "713": "chrome",
+ "712": "chrome",
+ "711": "chrome",
+ "710": "chrome",
+ "421": "chrome",
+ "129": "chrome",
+ "420": "chrome",
+ "423": "chrome",
+ "422": "chrome",
+ "425": "chrome",
+ "619": "chrome",
+ "424": "chrome",
+ "427": "chrome",
+ "298": "chrome",
+ "299": "chrome",
+ "296": "chrome",
+ "297": "chrome",
+ "294": "chrome",
+ "295": "chrome",
+ "292": "chrome",
+ "293": "chrome",
+ "290": "chrome",
+ "291": "chrome",
+ "591": "chrome",
+ "590": "chrome",
+ "593": "chrome",
+ "592": "chrome",
+ "595": "chrome",
+ "594": "chrome",
+ "597": "chrome",
+ "596": "chrome",
+ "195": "chrome",
+ "194": "chrome",
+ "197": "chrome",
+ "196": "chrome",
+ "191": "chrome",
+ "190": "chrome",
+ "193": "chrome",
+ "192": "chrome",
+ "270": "chrome",
+ "271": "chrome",
+ "272": "chrome",
+ "273": "chrome",
+ "274": "chrome",
+ "275": "chrome",
+ "276": "chrome",
+ "277": "chrome",
+ "278": "chrome",
+ "279": "chrome",
+ "569": "chrome",
+ "497": "chrome",
+ "524": "chrome",
+ "525": "chrome",
+ "526": "chrome",
+ "527": "chrome",
+ "520": "chrome",
+ "521": "chrome",
+ "522": "chrome",
+ "523": "chrome",
+ "528": "chrome",
+ "529": "chrome",
+ "449": "chrome",
+ "448": "chrome",
+ "345": "chrome",
+ "443": "chrome",
+ "442": "chrome",
+ "441": "chrome",
+ "440": "chrome",
+ "447": "chrome",
+ "446": "chrome",
+ "445": "chrome",
+ "444": "chrome",
+ "47": "chrome",
+ "108": "chrome",
+ "109": "chrome",
+ "102": "chrome",
+ "103": "chrome",
+ "100": "chrome",
+ "101": "chrome",
+ "106": "chrome",
+ "107": "chrome",
+ "104": "chrome",
+ "105": "chrome",
+ "902": "firefox",
+ "903": "firefox",
+ "39": "chrome",
+ "38": "chrome",
+ "906": "firefox",
+ "907": "firefox",
+ "904": "firefox",
+ "905": "firefox",
+ "33": "chrome",
+ "32": "chrome",
+ "31": "chrome",
+ "30": "chrome",
+ "37": "chrome",
+ "36": "chrome",
+ "35": "chrome",
+ "34": "chrome",
+ "641": "chrome",
+ "640": "chrome",
+ "643": "chrome",
+ "642": "chrome",
+ "645": "chrome",
+ "644": "chrome",
+ "438": "chrome",
+ "439": "chrome",
+ "436": "chrome",
+ "437": "chrome",
+ "434": "chrome",
+ "435": "chrome",
+ "432": "chrome",
+ "433": "chrome",
+ "430": "chrome",
+ "431": "chrome",
+ "826": "firefox",
+ "339": "chrome",
+ "338": "chrome",
+ "335": "chrome",
+ "334": "chrome",
+ "337": "chrome",
+ "336": "chrome",
+ "331": "chrome",
+ "330": "chrome",
+ "333": "chrome",
+ "332": "chrome",
+ "559": "chrome",
+ "745": "chrome",
+ "854": "firefox",
+ "818": "firefox",
+ "856": "firefox",
+ "857": "firefox",
+ "850": "firefox",
+ "851": "firefox",
+ "852": "firefox",
+ "0": "chrome",
+ "858": "firefox",
+ "859": "firefox",
+ "748": "chrome",
+ "6": "chrome",
+ "43": "chrome",
+ "99": "chrome",
+ "98": "chrome",
+ "91": "chrome",
+ "90": "chrome",
+ "93": "chrome",
+ "92": "chrome",
+ "95": "chrome",
+ "94": "chrome",
+ "97": "chrome",
+ "96": "chrome",
+ "814": "firefox",
+ "815": "firefox",
+ "153": "chrome",
+ "740": "chrome",
+ "741": "chrome",
+ "742": "chrome",
+ "743": "chrome",
+ "744": "chrome",
+ "558": "chrome",
+ "746": "chrome",
+ "747": "chrome",
+ "555": "chrome",
+ "554": "chrome",
+ "557": "chrome",
+ "556": "chrome",
+ "551": "chrome",
+ "550": "chrome",
+ "553": "chrome",
+ "552": "chrome",
+ "238": "chrome",
+ "239": "chrome",
+ "234": "chrome",
+ "235": "chrome",
+ "236": "chrome",
+ "237": "chrome",
+ "230": "chrome",
+ "231": "chrome",
+ "232": "chrome",
+ "233": "chrome",
+ "1": "chrome",
+ "155": "chrome",
+ "146": "chrome",
+ "147": "chrome",
+ "618": "chrome",
+ "145": "chrome",
+ "142": "chrome",
+ "143": "chrome",
+ "140": "chrome",
+ "141": "chrome",
+ "612": "chrome",
+ "613": "chrome",
+ "610": "chrome",
+ "611": "chrome",
+ "616": "chrome",
+ "617": "chrome",
+ "148": "chrome",
+ "149": "chrome",
+ "46": "chrome",
+ "154": "chrome",
+ "948": "safari",
+ "949": "safari",
+ "946": "safari",
+ "947": "safari",
+ "944": "safari",
+ "945": "safari",
+ "942": "safari",
+ "943": "safari",
+ "940": "safari",
+ "941": "safari",
+ "689": "chrome",
+ "688": "chrome",
+ "685": "chrome",
+ "684": "chrome",
+ "687": "chrome",
+ "686": "chrome",
+ "681": "chrome",
+ "680": "chrome",
+ "683": "chrome",
+ "682": "chrome",
+ "458": "chrome",
+ "459": "chrome",
+ "133": "chrome",
+ "132": "chrome",
+ "131": "chrome",
+ "130": "chrome",
+ "137": "chrome",
+ "136": "chrome",
+ "135": "chrome",
+ "134": "chrome",
+ "494": "chrome",
+ "495": "chrome",
+ "139": "chrome",
+ "138": "chrome",
+ "490": "chrome",
+ "491": "chrome",
+ "492": "chrome",
+ "493": "chrome",
+ "24": "chrome",
+ "25": "chrome",
+ "26": "chrome",
+ "27": "chrome",
+ "20": "chrome",
+ "21": "chrome",
+ "22": "chrome",
+ "23": "chrome",
+ "28": "chrome",
+ "29": "chrome",
+ "820": "firefox",
+ "407": "chrome",
+ "406": "chrome",
+ "405": "chrome",
+ "404": "chrome",
+ "403": "chrome",
+ "402": "chrome",
+ "401": "chrome",
+ "400": "chrome",
+ "933": "firefox",
+ "932": "firefox",
+ "931": "firefox",
+ "930": "firefox",
+ "937": "safari",
+ "452": "chrome",
+ "409": "chrome",
+ "408": "chrome",
+ "453": "chrome",
+ "414": "chrome",
+ "183": "chrome",
+ "415": "chrome",
+ "379": "chrome",
+ "378": "chrome",
+ "228": "chrome",
+ "829": "firefox",
+ "828": "firefox",
+ "371": "chrome",
+ "370": "chrome",
+ "373": "chrome",
+ "372": "chrome",
+ "375": "chrome",
+ "374": "chrome",
+ "377": "chrome",
+ "376": "chrome",
+ "708": "chrome",
+ "709": "chrome",
+ "704": "chrome",
+ "705": "chrome",
+ "706": "chrome",
+ "707": "chrome",
+ "700": "chrome",
+ "144": "chrome",
+ "702": "chrome",
+ "703": "chrome",
+ "393": "chrome",
+ "392": "chrome",
+ "88": "chrome",
+ "89": "chrome",
+ "397": "chrome",
+ "396": "chrome",
+ "395": "chrome",
+ "394": "chrome",
+ "82": "chrome",
+ "83": "chrome",
+ "80": "chrome",
+ "81": "chrome",
+ "86": "chrome",
+ "87": "chrome",
+ "84": "chrome",
+ "85": "chrome",
+ "797": "internetexplorer",
+ "796": "internetexplorer",
+ "795": "internetexplorer",
+ "794": "internetexplorer",
+ "793": "internetexplorer",
+ "792": "internetexplorer",
+ "791": "internetexplorer",
+ "790": "internetexplorer",
+ "749": "chrome",
+ "799": "internetexplorer",
+ "798": "internetexplorer",
+ "7": "chrome",
+ "170": "chrome",
+ "586": "chrome",
+ "587": "chrome",
+ "584": "chrome",
+ "585": "chrome",
+ "582": "chrome",
+ "583": "chrome",
+ "580": "chrome",
+ "581": "chrome",
+ "588": "chrome",
+ "589": "chrome",
+ "245": "chrome",
+ "244": "chrome",
+ "247": "chrome",
+ "246": "chrome",
+ "241": "chrome",
+ "614": "chrome",
+ "243": "chrome",
+ "242": "chrome",
+ "615": "chrome",
+ "249": "chrome",
+ "248": "chrome",
+ "418": "chrome",
+ "419": "chrome",
+ "519": "chrome",
+ "518": "chrome",
+ "511": "chrome",
+ "510": "chrome",
+ "513": "chrome",
+ "512": "chrome",
+ "515": "chrome",
+ "514": "chrome",
+ "517": "chrome",
+ "516": "chrome",
+ "623": "chrome",
+ "622": "chrome",
+ "621": "chrome",
+ "620": "chrome",
+ "627": "chrome",
+ "626": "chrome",
+ "625": "chrome",
+ "624": "chrome",
+ "450": "chrome",
+ "451": "chrome",
+ "629": "chrome",
+ "628": "chrome",
+ "454": "chrome",
+ "455": "chrome",
+ "456": "chrome",
+ "457": "chrome",
+ "179": "chrome",
+ "178": "chrome",
+ "177": "chrome",
+ "199": "chrome",
+ "175": "chrome",
+ "174": "chrome",
+ "173": "chrome",
+ "172": "chrome",
+ "171": "chrome",
+ "198": "chrome",
+ "977": "opera",
+ "182": "chrome",
+ "975": "opera",
+ "974": "opera",
+ "973": "opera",
+ "972": "opera",
+ "971": "opera",
+ "970": "opera",
+ "180": "chrome",
+ "979": "opera",
+ "978": "opera",
+ "656": "chrome",
+ "599": "chrome",
+ "654": "chrome",
+ "181": "chrome",
+ "186": "chrome",
+ "187": "chrome",
+ "184": "chrome",
+ "185": "chrome",
+ "652": "chrome",
+ "188": "chrome",
+ "189": "chrome",
+ "658": "chrome",
+ "653": "chrome",
+ "650": "chrome",
+ "651": "chrome",
+ "11": "chrome",
+ "10": "chrome",
+ "13": "chrome",
+ "12": "chrome",
+ "15": "chrome",
+ "14": "chrome",
+ "17": "chrome",
+ "16": "chrome",
+ "19": "chrome",
+ "18": "chrome",
+ "863": "firefox",
+ "862": "firefox",
+ "865": "firefox",
+ "864": "firefox",
+ "867": "firefox",
+ "866": "firefox",
+ "354": "chrome",
+ "659": "chrome",
+ "44": "chrome",
+ "883": "firefox",
+ "882": "firefox",
+ "881": "firefox",
+ "880": "firefox",
+ "887": "firefox",
+ "886": "firefox",
+ "885": "firefox",
+ "884": "firefox",
+ "889": "firefox",
+ "888": "firefox",
+ "116": "chrome",
+ "45": "chrome",
+ "657": "chrome",
+ "355": "chrome",
+ "322": "chrome",
+ "323": "chrome",
+ "320": "chrome",
+ "321": "chrome",
+ "326": "chrome",
+ "327": "chrome",
+ "324": "chrome",
+ "325": "chrome",
+ "328": "chrome",
+ "329": "chrome",
+ "562": "chrome",
+ "201": "chrome",
+ "200": "chrome",
+ "203": "chrome",
+ "202": "chrome",
+ "205": "chrome",
+ "204": "chrome",
+ "207": "chrome",
+ "206": "chrome",
+ "209": "chrome",
+ "208": "chrome",
+ "779": "internetexplorer",
+ "778": "internetexplorer",
+ "77": "chrome",
+ "76": "chrome",
+ "75": "chrome",
+ "74": "chrome",
+ "73": "chrome",
+ "72": "chrome",
+ "71": "chrome",
+ "70": "chrome",
+ "655": "chrome",
+ "567": "chrome",
+ "79": "chrome",
+ "78": "chrome",
+ "359": "chrome",
+ "358": "chrome",
+ "669": "chrome",
+ "668": "chrome",
+ "667": "chrome",
+ "666": "chrome",
+ "665": "chrome",
+ "664": "chrome",
+ "663": "chrome",
+ "662": "chrome",
+ "661": "chrome",
+ "660": "chrome",
+ "215": "chrome",
+ "692": "chrome",
+ "693": "chrome",
+ "690": "chrome",
+ "691": "chrome",
+ "696": "chrome",
+ "697": "chrome",
+ "694": "chrome",
+ "695": "chrome",
+ "698": "chrome",
+ "699": "chrome",
+ "542": "chrome",
+ "543": "chrome",
+ "540": "chrome",
+ "541": "chrome",
+ "546": "chrome",
+ "547": "chrome",
+ "544": "chrome",
+ "545": "chrome",
+ "8": "chrome",
+ "548": "chrome",
+ "549": "chrome",
+ "598": "chrome",
+ "869": "firefox",
+ "868": "firefox",
+ "120": "chrome",
+ "121": "chrome",
+ "122": "chrome",
+ "123": "chrome",
+ "124": "chrome",
+ "125": "chrome",
+ "126": "chrome",
+ "127": "chrome",
+ "128": "chrome",
+ "2": "chrome",
+ "219": "chrome",
+ "176": "chrome",
+ "214": "chrome",
+ "563": "chrome",
+ "928": "firefox",
+ "929": "firefox",
+ "416": "chrome",
+ "417": "chrome",
+ "410": "chrome",
+ "411": "chrome",
+ "412": "chrome",
+ "413": "chrome",
+ "920": "firefox",
+ "498": "chrome",
+ "922": "firefox",
+ "923": "firefox",
+ "924": "firefox",
+ "925": "firefox",
+ "926": "firefox",
+ "927": "firefox",
+ "319": "chrome",
+ "318": "chrome",
+ "313": "chrome",
+ "312": "chrome",
+ "311": "chrome",
+ "310": "chrome",
+ "317": "chrome",
+ "316": "chrome",
+ "315": "chrome",
+ "314": "chrome",
+ "921": "firefox",
+ "496": "chrome",
+ "832": "firefox",
+ "833": "firefox",
+ "830": "firefox",
+ "831": "firefox",
+ "836": "firefox",
+ "837": "firefox",
+ "834": "firefox",
+ "835": "firefox",
+ "838": "firefox",
+ "839": "firefox",
+ "3": "chrome",
+ "368": "chrome",
+ "369": "chrome",
+ "366": "chrome",
+ "367": "chrome",
+ "364": "chrome",
+ "365": "chrome",
+ "362": "chrome",
+ "363": "chrome",
+ "360": "chrome",
+ "361": "chrome",
+ "218": "chrome",
+ "380": "chrome",
+ "861": "firefox",
+ "382": "chrome",
+ "383": "chrome",
+ "384": "chrome",
+ "385": "chrome",
+ "386": "chrome",
+ "387": "chrome",
+ "388": "chrome",
+ "389": "chrome",
+ "784": "internetexplorer",
+ "785": "internetexplorer",
+ "786": "internetexplorer",
+ "787": "internetexplorer",
+ "780": "internetexplorer",
+ "781": "internetexplorer",
+ "782": "internetexplorer",
+ "381": "chrome",
+ "788": "internetexplorer",
+ "789": "internetexplorer",
+ "860": "firefox",
+ "151": "chrome",
+ "579": "chrome",
+ "578": "chrome",
+ "150": "chrome",
+ "573": "chrome",
+ "572": "chrome",
+ "571": "chrome",
+ "570": "chrome",
+ "577": "chrome",
+ "576": "chrome",
+ "575": "chrome",
+ "574": "chrome",
+ "60": "chrome",
+ "61": "chrome",
+ "62": "chrome",
+ "259": "chrome",
+ "64": "chrome",
+ "65": "chrome",
+ "66": "chrome",
+ "67": "chrome",
+ "68": "chrome",
+ "253": "chrome",
+ "250": "chrome",
+ "251": "chrome",
+ "256": "chrome",
+ "257": "chrome",
+ "254": "chrome",
+ "255": "chrome",
+ "499": "chrome",
+ "157": "chrome",
+ "156": "chrome",
+ "939": "safari",
+ "731": "chrome",
+ "730": "chrome",
+ "733": "chrome",
+ "938": "safari",
+ "735": "chrome",
+ "734": "chrome",
+ "508": "chrome",
+ "736": "chrome",
+ "506": "chrome",
+ "738": "chrome",
+ "504": "chrome",
+ "505": "chrome",
+ "502": "chrome",
+ "503": "chrome",
+ "500": "chrome",
+ "501": "chrome",
+ "630": "chrome",
+ "631": "chrome",
+ "632": "chrome",
+ "633": "chrome",
+ "469": "chrome",
+ "468": "chrome",
+ "636": "chrome",
+ "637": "chrome",
+ "465": "chrome",
+ "464": "chrome",
+ "467": "chrome",
+ "466": "chrome",
+ "461": "chrome",
+ "900": "firefox",
+ "463": "chrome",
+ "462": "chrome",
+ "901": "firefox",
+ "168": "chrome",
+ "169": "chrome",
+ "164": "chrome",
+ "165": "chrome",
+ "166": "chrome",
+ "167": "chrome",
+ "160": "chrome",
+ "161": "chrome",
+ "162": "chrome",
+ "163": "chrome",
+ "964": "safari",
+ "965": "safari",
+ "966": "safari",
+ "967": "safari",
+ "960": "safari",
+ "961": "safari",
+ "962": "safari",
+ "963": "safari",
+ "783": "internetexplorer",
+ "968": "safari",
+ "969": "opera",
+ "936": "firefox",
+ "935": "firefox",
+ "934": "firefox",
+ "908": "firefox",
+ "909": "firefox",
+ "722": "chrome",
+ "426": "chrome",
+ "878": "firefox",
+ "879": "firefox",
+ "876": "firefox",
+ "877": "firefox",
+ "874": "firefox",
+ "875": "firefox",
+ "872": "firefox",
+ "873": "firefox",
+ "870": "firefox",
+ "871": "firefox",
+ "9": "chrome",
+ "890": "firefox",
+ "891": "firefox",
+ "892": "firefox",
+ "893": "firefox",
+ "894": "firefox",
+ "647": "chrome",
+ "896": "firefox",
+ "897": "firefox",
+ "898": "firefox",
+ "899": "firefox",
+ "646": "chrome",
+ "649": "chrome",
+ "648": "chrome",
+ "357": "chrome",
+ "356": "chrome",
+ "809": "internetexplorer",
+ "808": "internetexplorer",
+ "353": "chrome",
+ "352": "chrome",
+ "351": "chrome",
+ "350": "chrome",
+ "803": "internetexplorer",
+ "802": "internetexplorer",
+ "801": "internetexplorer",
+ "800": "internetexplorer",
+ "807": "internetexplorer",
+ "806": "internetexplorer",
+ "805": "internetexplorer",
+ "804": "internetexplorer",
+ "216": "chrome",
+ "217": "chrome",
+ "768": "chrome",
+ "769": "chrome",
+ "212": "chrome",
+ "213": "chrome",
+ "210": "chrome",
+ "211": "chrome",
+ "762": "chrome",
+ "763": "chrome",
+ "760": "chrome",
+ "761": "chrome",
+ "766": "chrome",
+ "767": "chrome",
+ "764": "chrome",
+ "765": "chrome",
+ "40": "chrome",
+ "41": "chrome",
+ "289": "chrome",
+ "288": "chrome",
+ "4": "chrome",
+ "281": "chrome",
+ "280": "chrome",
+ "283": "chrome",
+ "282": "chrome",
+ "285": "chrome",
+ "284": "chrome",
+ "287": "chrome",
+ "286": "chrome",
+ "678": "chrome",
+ "679": "chrome",
+ "674": "chrome",
+ "675": "chrome",
+ "676": "chrome",
+ "677": "chrome",
+ "670": "chrome",
+ "671": "chrome",
+ "672": "chrome",
+ "673": "chrome",
+ "263": "chrome",
+ "262": "chrome",
+ "261": "chrome",
+ "260": "chrome",
+ "267": "chrome",
+ "266": "chrome",
+ "265": "chrome",
+ "264": "chrome",
+ "269": "chrome",
+ "268": "chrome",
+ "59": "chrome",
+ "58": "chrome",
+ "55": "chrome",
+ "54": "chrome",
+ "57": "chrome",
+ "56": "chrome",
+ "51": "chrome",
+ "258": "chrome",
+ "53": "chrome",
+ "52": "chrome",
+ "537": "chrome",
+ "536": "chrome",
+ "535": "chrome",
+ "63": "chrome",
+ "533": "chrome",
+ "532": "chrome",
+ "531": "chrome",
+ "530": "chrome",
+ "152": "chrome",
+ "539": "chrome",
+ "538": "chrome",
+ "775": "internetexplorer",
+ "774": "internetexplorer",
+ "982": "opera",
+ "983": "opera",
+ "980": "opera",
+ "981": "opera",
+ "777": "internetexplorer",
+ "984": "opera",
+ "50": "chrome",
+ "115": "chrome",
+ "252": "chrome",
+ "117": "chrome",
+ "776": "internetexplorer",
+ "111": "chrome",
+ "110": "chrome",
+ "113": "chrome",
+ "69": "chrome",
+ "771": "chrome",
+ "119": "chrome",
+ "118": "chrome",
+ "770": "chrome",
+ "773": "internetexplorer",
+ "772": "internetexplorer",
+ "429": "chrome",
+ "428": "chrome",
+ "534": "chrome",
+ "919": "firefox",
+ "918": "firefox",
+ "915": "firefox",
+ "914": "firefox",
+ "917": "firefox",
+ "916": "firefox",
+ "911": "firefox",
+ "910": "firefox",
+ "913": "firefox",
+ "912": "firefox",
+ "308": "chrome",
+ "309": "chrome",
+ "855": "firefox",
+ "300": "chrome",
+ "301": "chrome",
+ "302": "chrome",
+ "303": "chrome",
+ "304": "chrome",
+ "305": "chrome",
+ "306": "chrome",
+ "307": "chrome",
+ "895": "firefox",
+ "825": "firefox",
+ "824": "firefox",
+ "827": "firefox",
+ "847": "firefox",
+ "846": "firefox",
+ "845": "firefox",
+ "844": "firefox",
+ "843": "firefox",
+ "842": "firefox",
+ "841": "firefox",
+ "840": "firefox",
+ "821": "firefox",
+ "853": "firefox",
+ "849": "firefox",
+ "848": "firefox",
+ "823": "firefox",
+ "822": "firefox",
+ "240": "chrome",
+ "390": "chrome",
+ "732": "chrome",
+ "753": "chrome",
+ "752": "chrome",
+ "751": "chrome",
+ "750": "chrome",
+ "757": "chrome",
+ "756": "chrome",
+ "755": "chrome",
+ "754": "chrome",
+ "560": "chrome",
+ "561": "chrome",
+ "759": "chrome",
+ "758": "chrome",
+ "564": "chrome",
+ "565": "chrome",
+ "566": "chrome",
+ "701": "chrome",
+ "739": "chrome",
+ "229": "chrome",
+ "507": "chrome",
+ "227": "chrome",
+ "226": "chrome",
+ "225": "chrome",
+ "224": "chrome",
+ "223": "chrome",
+ "222": "chrome",
+ "221": "chrome",
+ "220": "chrome",
+ "114": "chrome",
+ "391": "chrome",
+ "726": "chrome",
+ "727": "chrome",
+ "724": "chrome",
+ "725": "chrome",
+ "568": "chrome",
+ "723": "chrome",
+ "720": "chrome",
+ "721": "chrome",
+ "728": "chrome",
+ "729": "chrome",
+ "605": "chrome",
+ "604": "chrome",
+ "607": "chrome",
+ "606": "chrome",
+ "601": "chrome",
+ "600": "chrome",
+ "603": "chrome",
+ "602": "chrome",
+ "159": "chrome",
+ "158": "chrome",
+ "112": "chrome",
+ "609": "chrome",
+ "608": "chrome",
+ "976": "opera",
+ "634": "chrome",
+ "399": "chrome",
+ "635": "chrome",
+ "959": "safari",
+ "958": "safari",
+ "398": "chrome",
+ "48": "chrome",
+ "49": "chrome",
+ "951": "safari",
+ "950": "safari",
+ "953": "safari",
+ "952": "safari",
+ "42": "chrome",
+ "954": "safari",
+ "957": "safari",
+ "956": "safari",
+ "638": "chrome",
+ "5": "chrome",
+ "639": "chrome",
+ "460": "chrome",
+ "489": "chrome",
+ "488": "chrome",
+ "487": "chrome",
+ "486": "chrome",
+ "485": "chrome",
+ "484": "chrome",
+ "483": "chrome",
+ "482": "chrome",
+ "481": "chrome",
+ "480": "chrome",
+ "509": "chrome",
+ "955": "safari",
+ "472": "chrome",
+ "473": "chrome",
+ "470": "chrome",
+ "471": "chrome",
+ "476": "chrome",
+ "477": "chrome",
+ "474": "chrome",
+ "475": "chrome",
+ "478": "chrome",
+ "479": "chrome"
+ }
+}
\ No newline at end of file
diff --git a/cve-agency-manager/cve_tracking/src/shell/__init__.py b/cve-agency-manager/cve_tracking/src/shell/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..3e26da5218904e6406ea988ff828312ffb3f9fe2
--- /dev/null
+++ b/cve-agency-manager/cve_tracking/src/shell/__init__.py
@@ -0,0 +1,12 @@
+#!/usr/bin/python3
+# ******************************************************************************
+# Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved.
+# licensed under the Mulan PSL v2.
+# You can use this software according to the terms and conditions of the Mulan PSL v2.
+# You may obtain a copy of Mulan PSL v2 at:
+# http://license.coscl.org.cn/MulanPSL2
+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+# PURPOSE.
+# See the Mulan PSL v2 for more details.
+# ******************************************************************************/
diff --git a/cve-agency-manager/cve_tracking/src/shell/add_patch.sh b/cve-agency-manager/cve_tracking/src/shell/add_patch.sh
new file mode 100644
index 0000000000000000000000000000000000000000..a0658e75c56c53ea4c3d844b51c158cd681ae1d9
--- /dev/null
+++ b/cve-agency-manager/cve_tracking/src/shell/add_patch.sh
@@ -0,0 +1,212 @@
+#!/bin/bash
+# shellcheck disable=SC2068
+# shellcheck disable=SC2164
+# shellcheck disable=SC2010
+# shellcheck disable=SC2063
+# shellcheck disable=SC2062
+# shellcheck disable=SC2035
+source_path=""
+rpm_name=""
+rpm_branch=""
+patches_path=""
+path_file_name=""
+tmp_path=/tmp/cve_tracking/download_source
+# The rpm package that needs to be installed when compiling
+requires_rpms=""
+spec_file=""
+home_path=$(
+ cd ~
+ pwd -P
+)
+root_build_path=${home_path}/"rpmbuild"
+
+function check_patch() {
+ if [[ -z ${patches_path} ]]; then
+ echo "[ERROR] Input patch is null"
+ exit 1
+ fi
+
+ for patch in ${patches_path[@]}; do
+ if [[ ! -f ${patch} ]]; then
+ echo "[ERROR] ${patch} is not found"
+ exit 1
+ fi
+ done
+}
+
+function check_local() {
+ if [[ ! -d ${source_path} ]]; then
+ echo "[ERROR] The source package path ${source_path} does not exist"
+ exit 1
+ fi
+
+ check_patch
+}
+
+function check_remote() {
+ if [[ -z ${rpm_name} ]] || [[ -z ${rpm_branch} ]]; then
+ echo "[ERROR] Incorrect input,Please use [ /bin/bash add_patch.sh 'name of package' 'branch of package' 'path of patch file']"
+ exit 1
+ fi
+
+ check_patch
+}
+
+function pre_env_download() {
+ if [ ! -d ${tmp_path} ]; then
+ mkdir -p ${tmp_path}
+ echo "[INFO] Create tmp path ${tmp_path}"
+ fi
+ cd ${tmp_path}
+ rm -rf "${rpm_name}"
+}
+
+function pre_env_build() {
+ echo "[INFO] Create root path of rpmbuild"
+ if [[ ! -d ${root_build_path} ]]; then
+ mkdir -p ${root_build_path}/{BUILD,BUILDROOT,RPMS,SPECS,SOURCES,SRPMS}
+ fi
+}
+
+function git_clone() {
+ echo "[INFO] Start to git clone ${rpm_name}"
+ git_status=$(rpm -qa git)
+ if [[ -z ${git_status} ]]; then
+ yum install git -y
+ git_status=$(rpm -qa git)
+ if [[ -z ${git_status} ]]; then
+ echo "[ERROR] Git install failed"
+ exit 1
+ fi
+ fi
+
+ cd ${tmp_path}
+ git clone -b ${rpm_branch} https://gitee.com/src-openeuler/${rpm_name}.git >/dev/null 2>&1
+ rpm_path=$(ls | grep ${rpm_name})
+ if [[ -z ${rpm_path} ]]; then
+ echo "[ERROR] git clone ${rpm_name} failed, please check path ${tmp_path}"
+ exit 1
+ fi
+
+ source_path=${tmp_path}/${rpm_name}
+}
+
+function update_spec() {
+ echo "[INFO] Start to update spec file"
+ cd ${source_path}
+ spec_file=$(ls | grep *.spec | grep -v *.bak)
+ if [[ -z ${spec_file} ]]; then
+ echo "[ERROR] spec file is not found"
+ exit 1
+ fi
+ # backup spec
+ /bin/cp ${spec_file} ${spec_file}.bak
+ # update Release
+ release_version=$(grep "Release:" ${spec_file} | awk -F " " '{print $NF}')
+ new_release=$(expr ${release_version} + 1)
+ sed -i "s/Release:.*${release_version}/Release: ${new_release}/" ${spec_file}
+ # add Patch***
+ last_patch=$(grep "Patch.*:" ${spec_file} | sed -n '$p')
+ if [[ -z ${last_patch} ]]; then
+ source_row=$(grep -n "Source.*:" ${spec_file} | sed -n '$p' | awk -F ':' '{print $1}')
+ sed -ie "${source_row}G;${source_row}a Patch0000: ${path_file_name}" ${spec_file}
+ else
+ last_patch_row=$(grep -n "${last_patch}" ${spec_file} | awk -F ':' '{print $1}')
+ last_patch_num=$(echo ${last_patch} | awk -F ':' '{print $1}' | awk -F 'Patch' '{print $2}')
+ patch_name_len=${#last_patch_num}
+ new_patch_num=$(expr ${last_patch_num} + 1)
+ new_patch_num=$(printf "%0${patch_name_len}d" ${new_patch_num})
+ sed -i "${last_patch_row}a Patch${new_patch_num}: ${path_file_name}" ${spec_file}
+ fi
+ # add changelog
+ change_log_row=$(grep -n '%changelog' ${spec_file} | sed -n '$p' | awk -F ':' '{print $1}')
+ date_now=$(date '+%a %b %d %Y')
+ version=$(grep 'Version:' ${spec_file} | awk -F ' ' '{print $NF}')
+ log_description="- add ${path_file_name}"
+ log_title="* ${date_now} robot - ${version}-${new_release}"
+ sed -i "${change_log_row}G" ${spec_file}
+ sed -i "${change_log_row}a ${log_description}" ${spec_file}
+ sed -i "${change_log_row}a ${log_title}" ${spec_file}
+
+ echo "[INFO] Update spec file success"
+}
+
+function mv_source_file() {
+ echo "[INFO] Copy source file to ${root_build_path}"
+ cd ${source_path}
+ spec_file=$(ls | grep *.spec | grep -v *.bak)
+ /bin/cp ${patches_path} ${source_path}
+ /bin/cp * ${root_build_path}/SOURCES
+ /bin/cp *.spec ${root_build_path}/SPECS
+}
+
+function rpm_build() {
+ echo "[INFO] Start to rpmbuild"
+ rpmbuild_status=$(rpm -qa rpm-build)
+ if [[ -z ${rpmbuild_status} ]]; then
+ yum install rpm-build -y >/dev/null 2>&1
+ rpmbuild_status=$(rpm -qa rpm-build)
+ if [[ -z ${rpmbuild_status} ]]; then
+ echo "[ERROR] Install rpm-build failed"
+ exit 1
+ fi
+ fi
+ rpmbuild -bb ${root_build_path}/SPECS/${spec_file} >./rpmbuild.log 2>&1
+ if [[ $? -eq 0 ]]; then
+ echo "[INFO] build success"
+ exit 0
+ elif [[ -n $(grep "Failed build dependencies" ./rpmbuild.log) ]]; then
+ requires_rpms=$(grep -r "is needed by" ./rpmbuild.log | awk -F " " '{print $1}')
+ echo "${requires_rpms}" >./requires_rpms.log
+ for rpm in ${requires_rpms[@]}; do
+ yum install ${rpm} -y >/dev/null 2>&1
+ if [[ $? -eq 0 ]]; then
+ echo "[INFO] Successfully install dependent package ${rpm}"
+ else
+ echo "[ERROR] Failed to install dependent package ${rpm}"
+ exit 1
+ fi
+ done
+ rpm_build
+ else
+ echo "[ERROR] build failed,log is ${source_path}/rpmbuild.log"
+ exit 1
+ fi
+}
+
+function main() {
+ input_params_length=$#
+ if [[ ${input_params_length} -eq 2 ]]; then
+ source_path=$1
+ patches_path=$2
+ check_local
+ pre_env_build
+ for patch in ${patches_path[@]}; do
+ path_file_name=$(echo "${patch}" | awk -F "/" '{print $NF}' | awk -F "\\" '{print $NF}')
+ update_spec
+ done
+ elif [[ ${input_params_length} -eq 3 ]]; then
+ rpm_name=$1
+ rpm_branch=$2
+ patches_path=$3
+ check_remote
+ pre_env_build
+ pre_env_download
+ git_clone
+ for patch in ${patches_path[@]}; do
+ path_file_name=$(echo "${patch}" | awk -F "/" '{print $NF}' | awk -F "\\" '{print $NF}')
+ update_spec
+ done
+ else
+ echo "[ERROR] Incorrect input,please use:
+ 1、 /bin/bash add_patch.sh 'Source package path' 'Patch file path'
+ 2、 /bin/bash add_patch.sh 'name of package' 'branch of package' 'path of patch file'"
+ exit 1
+ fi
+
+ mv_source_file
+ rpm_build
+}
+
+main "$@"
+exit $?
diff --git a/cve-agency-manager/cve_tracking/src/shell/start.sh b/cve-agency-manager/cve_tracking/src/shell/start.sh
new file mode 100644
index 0000000000000000000000000000000000000000..2209374ac92a8711f34fbaab83616bd2fe55c41a
--- /dev/null
+++ b/cve-agency-manager/cve_tracking/src/shell/start.sh
@@ -0,0 +1,104 @@
+#!/bin/bash
+# shellcheck disable=SC2068
+# shellcheck disable=SC2164
+# shellcheck disable=SC2002
+# shellcheck disable=SC2045
+# shellcheck disable=SC2115
+rpms_path=$1
+clear_cli=$1
+remote_branch=$2
+current_path=$(
+ cd "$(dirname "$0")"
+ pwd
+)
+
+function check() {
+ if [[ ! -d ${rpms_path} ]]; then
+ echo "[ERROR] ${rpms_path} is not exist"
+ exit 1
+ fi
+
+ if [[ -z ${remote_branch} ]]; then
+ echo "[ERROR] The remote branch is not specified"
+ exit 1
+ fi
+}
+
+function install_git() {
+ git_status=$(rpm -qa git)
+ if [[ -z ${git_status} ]]; then
+ yum install git -y
+ git_status=$(rpm -qa git)
+ if [[ -z ${git_status} ]]; then
+ echo "[ERROR] Git install failed"
+ exit 1
+ fi
+ fi
+}
+
+function run() {
+ check
+
+ result_file=${rpms_path}/result.log
+ if [[ -f ${result_file} ]]; then
+ echo "" >"${result_file}"
+ fi
+
+ rpm_cve_path=$(ls "${rpms_path}")
+ IFS=$'\n'
+ for rpm_cve in ${rpm_cve_path[@]}; do
+ if [[ -d ${rpms_path}/${rpm_cve} ]]; then
+ rpm_name=$(echo "${rpm_cve}" | awk -F '-CVE' '{print $1}')
+ patches=$(find "${rpms_path}/${rpm_cve}" -name "*.patch" | sort)
+ if [[ -z ${patches} ]]; then
+ echo "[WARRING] ${rpm_name} not found patch" | tee -a "${result_file}"
+ echo "============================================================="
+ else
+ install_git
+ patch_ids=""
+ new_patches=""
+ for patch in ${patches[@]}; do
+ git_patch_ids=$(cat "${patch}" | git patch-id --stable)
+ if [[ ! ${patch_ids} =~ ${git_patch_ids} ]]; then
+ new_patches="${new_patches} ${patch}"
+ patch_ids="${patch_ids} ${git_patch_ids}"
+ fi
+ done
+ IFS=$' \t\n'
+ for branch in ${remote_branch[@]}; do
+ /bin/bash "${current_path}"/add_patch.sh "${rpm_name}" "${branch}" "${new_patches}"
+ add_patch_result=$?
+ if [[ ${add_patch_result} -eq 0 ]]; then
+ echo "[INFO] ${rpm_name} of ${branch} apply patch ${new_patches} successfully" | tee -a "${result_file}"
+ else
+ echo "[ERROR] ${rpm_name} of ${branch} failed to apply patch ${new_patches}" | tee -a "${result_file}"
+ fi
+ done
+ fi
+ fi
+ echo "============================================================="
+ IFS=$'\n'
+ done
+}
+
+function clear_env() {
+ echo "[INFO] clear env"
+ rm -rf /tmp/cve_tracking/download_source
+ build_root=$(
+ cd ~
+ pwd -P
+ )
+ rpmbuild_path=${build_root}/"rpmbuild"
+
+ if [[ -d ${rpmbuild_path} ]]; then
+ for dir in $(ls ${rpmbuild_path}); do
+ rm -rf ${rpmbuild_path}/${dir}/*
+ done
+ fi
+}
+
+if [[ ${clear_cli} == "clear" ]]; then
+ clear_env
+else
+ run
+fi
diff --git a/cve-agency-manager/cve_tracking/src/test.py b/cve-agency-manager/cve_tracking/src/test.py
new file mode 100644
index 0000000000000000000000000000000000000000..8912cb74bf000bc78d90b131c26462c2916043af
--- /dev/null
+++ b/cve-agency-manager/cve_tracking/src/test.py
@@ -0,0 +1,3 @@
+
+if __name__ == "__main__":
+ print("hess")
\ No newline at end of file
diff --git a/cve-agency-manager/cve_tracking/test/__init__.py b/cve-agency-manager/cve_tracking/test/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..6851032853d1af6ec5065266cf9d86c2bd1c0b3c
--- /dev/null
+++ b/cve-agency-manager/cve_tracking/test/__init__.py
@@ -0,0 +1,12 @@
+#!/usr/bin/python3
+# ******************************************************************************
+# Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved.
+# licensed under the Mulan PSL v2.
+# You can use this software according to the terms and conditions of the Mulan PSL v2.
+# You may obtain a copy of Mulan PSL v2 at:
+# http://license.coscl.org.cn/MulanPSL2
+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+# PURPOSE.
+# See the Mulan PSL v2 for more details.
+# ******************************************************************************/
diff --git a/cve-agency-manager/go.mod b/cve-agency-manager/go.mod
index ac368bff151d12e95610cfe68cf050e5086b80b1..4d63604fc09005b77a0bc28728bb7ccc9650d20f 100644
--- a/cve-agency-manager/go.mod
+++ b/cve-agency-manager/go.mod
@@ -1,10 +1,8 @@
-module cve-agency-service
+module cve-agency-manager
go 1.14
-require github.com/astaxie/beego v1.12.1
-
require (
- github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18 // indirect
- github.com/smartystreets/goconvey v1.6.4
+ github.com/astaxie/beego v1.12.3
+ github.com/smartystreets/goconvey v1.7.2
)
diff --git a/cve-agency-manager/go.sum b/cve-agency-manager/go.sum
index 86f3e92224349a15fb6e2256cca4c71dca5e83f2..6a80d03cf78b8e26dc6928f1f38f09336faee65f 100644
--- a/cve-agency-manager/go.sum
+++ b/cve-agency-manager/go.sum
@@ -1,55 +1,188 @@
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
-github.com/OwnLocal/goes v1.0.0/go.mod h1:8rIFjBGTue3lCU0wplczcUgt9Gxgrkkrw7etMIcn8TM=
-github.com/astaxie/beego v1.12.1 h1:dfpuoxpzLVgclveAXe4PyNKqkzgm5zF4tgF2B3kkM2I=
-github.com/astaxie/beego v1.12.1/go.mod h1:kPBWpSANNbSdIqOc8SUL9h+1oyBMZhROeYsXQDbidWQ=
+github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
+github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
+github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
+github.com/alicebob/miniredis v2.5.0+incompatible/go.mod h1:8HZjEj4yU0dwhYHky+DxYx+6BMjkBbe5ONFIF1MXffk=
+github.com/astaxie/beego v1.12.3 h1:SAQkdD2ePye+v8Gn1r4X6IKZM1wd28EyUOVQ3PDSOOQ=
+github.com/astaxie/beego v1.12.3/go.mod h1:p3qIm0Ryx7zeBHLljmd7omloyca1s4yu1a8kM1FkpIA=
github.com/beego/goyaml2 v0.0.0-20130207012346-5545475820dd/go.mod h1:1b+Y/CofkYwXMUU0OhQqGvsY2Bvgr4j6jfT699wyZKQ=
github.com/beego/x2j v0.0.0-20131220205130-a0352aadc542/go.mod h1:kSeGC/p1AbBiEp5kat81+DSQrZenVBZXklMLaELspWU=
+github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
+github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
+github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
+github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bradfitz/gomemcache v0.0.0-20180710155616-bc664df96737/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60=
github.com/casbin/casbin v1.7.0/go.mod h1:c67qKN6Oum3UF5Q1+BByfFxkwKvhwW57ITjqwtzR1KE=
+github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
+github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80=
-github.com/couchbase/go-couchbase v0.0.0-20181122212707-3e9b6e1258bb/go.mod h1:TWI8EKQMs5u5jLKW/tsb9VwauIrMIxQG1r5fMsswK5U=
-github.com/couchbase/gomemcached v0.0.0-20181122193126-5125a94a666c/go.mod h1:srVSlQLB8iXBVXHgnqemxUXqN6FCvClgCMPCsjBDR7c=
+github.com/couchbase/go-couchbase v0.0.0-20200519150804-63f3cdb75e0d/go.mod h1:TWI8EKQMs5u5jLKW/tsb9VwauIrMIxQG1r5fMsswK5U=
+github.com/couchbase/gomemcached v0.0.0-20200526233749-ec430f949808/go.mod h1:srVSlQLB8iXBVXHgnqemxUXqN6FCvClgCMPCsjBDR7c=
github.com/couchbase/goutils v0.0.0-20180530154633-e865a1461c8a/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs=
github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76/go.mod h1:vYwsqCOLxGiisLwp9rITslkFNpZD5rz43tf41QFkTWY=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
+github.com/elastic/go-elasticsearch/v6 v6.8.5/go.mod h1:UwaDJsD3rWLM5rKNFzv9hgox93HoX8utj1kxD9aFUcI=
+github.com/elazarl/go-bindata-assetfs v1.0.0 h1:G/bYguwHIzWq9ZoyUQqrjTmJbbYn3j3CKKpKinvZLFk=
github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
+github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/glendc/gopher-json v0.0.0-20170414221815-dc4743023d0c/go.mod h1:Gja1A+xZ9BoviGJNA2E9vFkPjjsl+CoJxSXiQM1UXtw=
+github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
+github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
+github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
+github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-redis/redis v6.14.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
-github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
+github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
+github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
+github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
+github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
+github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
+github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
+github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
+github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
+github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
+github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
+github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
+github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
+github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/ledisdb/ledisdb v0.0.0-20200510135210-d35789ec47e6/go.mod h1:n931TsDuKuq+uX4v1fulaMbA/7ZLLhjc85h7chZGBCQ=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
-github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
+github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
+github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
+github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
+github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
+github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
+github.com/pelletier/go-toml v1.0.1/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
+github.com/peterh/liner v1.0.1-0.20171122030339-3681c2a91233/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
-github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18 h1:DAYUYH5869yV94zvCES9F51oYtN5oGlwjxJJz7ZCnik=
-github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg=
-github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw=
-github.com/siddontang/ledisdb v0.0.0-20181029004158-becf5f38d373/go.mod h1:mF1DpOSOUiJRMR+FDqaqu3EBqrybQtrDDszLUZ6oxPg=
+github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
+github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
+github.com/prometheus/client_golang v1.7.0 h1:wCi7urQOGBsYcQROHqpUUX4ct84xp40t9R9JX0FuA/U=
+github.com/prometheus/client_golang v1.7.0/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
+github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
+github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
+github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
+github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc=
+github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
+github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
+github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
+github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8=
+github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
+github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 h1:X+yvsM2yrEktyI+b2qND5gpH8YhURn0k8OCaeRnkINo=
+github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg=
+github.com/siddontang/go v0.0.0-20170517070808-cb568a3e5cc0/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw=
+github.com/siddontang/goredis v0.0.0-20150324035039-760763f78400/go.mod h1:DDcKzU3qCuvj/tPnimWSsZZzvk9qvkvrIL5naVBPh5s=
github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA=
-github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
-github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
+github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
+github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
+github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
+github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
+github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg=
+github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM=
github.com/ssdb/gossdb v0.0.0-20180723034631-88f6b59b84ec/go.mod h1:QBvMkMya+gXctz3kmljlUCu/yB3GZ6oee+dUozsezQE=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/syndtr/goleveldb v0.0.0-20160425020131-cfa635847112/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
github.com/syndtr/goleveldb v0.0.0-20181127023241-353a9fca669c/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
+github.com/ugorji/go v0.0.0-20171122102828-84cb69a8af83/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ=
github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b/go.mod h1:Q12BUT7DqIlHRmgv3RskH+UCM/4eqVMgI0EMmlSpAXc=
+github.com/yuin/gopher-lua v0.0.0-20171031051903-609c9cd26973/go.mod h1:aEV29XrmTYFr3CiRxZeGHpkvbwq+prZduBqMaascyCU=
+golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
+golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 h1:ogLJMz+qpzav7lGMh10LMvAkM/fAoGlaiiHYiFYdm80=
+golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20200117065230-39095c1d176c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
+google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
+google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
+google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
+google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
+google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
+gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
+gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
+gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
diff --git a/cve-agency-manager/main.go b/cve-agency-manager/main.go
index c58fa890e57db38fed99f5cc16205f94b88a04ef..de0651388fe165f51dc904e91fd3d74ae5a44345 100644
--- a/cve-agency-manager/main.go
+++ b/cve-agency-manager/main.go
@@ -1,9 +1,8 @@
package main
import (
- "cve-agency-service/common"
- _ "cve-agency-service/routers"
-
+ "cve-agency-manager/common"
+ _ "cve-agency-manager/routers"
"github.com/astaxie/beego"
)
diff --git a/cve-agency-manager/routers/commentsRouter_controllers.go b/cve-agency-manager/routers/commentsRouter_controllers.go
index c37542d6e3c95e26426f34db99d6961559a562c9..318d81ff372ec56cc6f2b60511f583c6bdc1a72f 100644
--- a/cve-agency-manager/routers/commentsRouter_controllers.go
+++ b/cve-agency-manager/routers/commentsRouter_controllers.go
@@ -7,136 +7,136 @@ import (
func init() {
- beego.GlobalControllerRouter["cve-agency-service/controllers:ObjectController"] = append(beego.GlobalControllerRouter["cve-agency-service/controllers:ObjectController"],
+ beego.GlobalControllerRouter["cve-agency-manager/controllers:ObjectController"] = append(beego.GlobalControllerRouter["cve-agency-manager/controllers:ObjectController"],
beego.ControllerComments{
Method: "Post",
- Router: `/`,
+ Router: "/",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
- beego.GlobalControllerRouter["cve-agency-service/controllers:ObjectController"] = append(beego.GlobalControllerRouter["cve-agency-service/controllers:ObjectController"],
+ beego.GlobalControllerRouter["cve-agency-manager/controllers:ObjectController"] = append(beego.GlobalControllerRouter["cve-agency-manager/controllers:ObjectController"],
beego.ControllerComments{
Method: "GetAll",
- Router: `/`,
+ Router: "/",
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
- beego.GlobalControllerRouter["cve-agency-service/controllers:ObjectController"] = append(beego.GlobalControllerRouter["cve-agency-service/controllers:ObjectController"],
+ beego.GlobalControllerRouter["cve-agency-manager/controllers:ObjectController"] = append(beego.GlobalControllerRouter["cve-agency-manager/controllers:ObjectController"],
beego.ControllerComments{
Method: "Get",
- Router: `/:objectId`,
+ Router: "/:objectId",
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
- beego.GlobalControllerRouter["cve-agency-service/controllers:ObjectController"] = append(beego.GlobalControllerRouter["cve-agency-service/controllers:ObjectController"],
+ beego.GlobalControllerRouter["cve-agency-manager/controllers:ObjectController"] = append(beego.GlobalControllerRouter["cve-agency-manager/controllers:ObjectController"],
beego.ControllerComments{
Method: "Put",
- Router: `/:objectId`,
+ Router: "/:objectId",
AllowHTTPMethods: []string{"put"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
- beego.GlobalControllerRouter["cve-agency-service/controllers:ObjectController"] = append(beego.GlobalControllerRouter["cve-agency-service/controllers:ObjectController"],
+ beego.GlobalControllerRouter["cve-agency-manager/controllers:ObjectController"] = append(beego.GlobalControllerRouter["cve-agency-manager/controllers:ObjectController"],
beego.ControllerComments{
Method: "Delete",
- Router: `/:objectId`,
+ Router: "/:objectId",
AllowHTTPMethods: []string{"delete"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
- beego.GlobalControllerRouter["cve-agency-service/controllers:TriggerTrackController"] = append(beego.GlobalControllerRouter["cve-agency-service/controllers:TriggerTrackController"],
+ beego.GlobalControllerRouter["cve-agency-manager/controllers:TriggerHeartbeatLiveController"] = append(beego.GlobalControllerRouter["cve-agency-manager/controllers:TriggerHeartbeatLiveController"],
beego.ControllerComments{
- Method: "Post",
- Router: `/`,
- AllowHTTPMethods: []string{"post"},
+ Method: "Get",
+ Router: "/",
+ AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
- beego.GlobalControllerRouter["cve-agency-service/controllers:TriggerHeartbeatreadController"] = append(beego.GlobalControllerRouter["cve-agency-service/controllers:TriggerHeartbeatreadController"],
+ beego.GlobalControllerRouter["cve-agency-manager/controllers:TriggerHeartbeatreadController"] = append(beego.GlobalControllerRouter["cve-agency-manager/controllers:TriggerHeartbeatreadController"],
beego.ControllerComments{
Method: "Get",
- Router: `/`,
+ Router: "/",
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
- beego.GlobalControllerRouter["cve-agency-service/controllers:TriggerHeartbeatLiveController"] = append(beego.GlobalControllerRouter["cve-agency-service/controllers:TriggerHeartbeatLiveController"],
+ beego.GlobalControllerRouter["cve-agency-manager/controllers:TriggerTrackController"] = append(beego.GlobalControllerRouter["cve-agency-manager/controllers:TriggerTrackController"],
beego.ControllerComments{
- Method: "Get",
- Router: `/`,
- AllowHTTPMethods: []string{"get"},
+ Method: "Post",
+ Router: "/",
+ AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
- beego.GlobalControllerRouter["cve-agency-service/controllers:UserController"] = append(beego.GlobalControllerRouter["cve-agency-service/controllers:UserController"],
+ beego.GlobalControllerRouter["cve-agency-manager/controllers:UserController"] = append(beego.GlobalControllerRouter["cve-agency-manager/controllers:UserController"],
beego.ControllerComments{
Method: "Post",
- Router: `/`,
+ Router: "/",
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
- beego.GlobalControllerRouter["cve-agency-service/controllers:UserController"] = append(beego.GlobalControllerRouter["cve-agency-service/controllers:UserController"],
+ beego.GlobalControllerRouter["cve-agency-manager/controllers:UserController"] = append(beego.GlobalControllerRouter["cve-agency-manager/controllers:UserController"],
beego.ControllerComments{
Method: "GetAll",
- Router: `/`,
+ Router: "/",
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
- beego.GlobalControllerRouter["cve-agency-service/controllers:UserController"] = append(beego.GlobalControllerRouter["cve-agency-service/controllers:UserController"],
+ beego.GlobalControllerRouter["cve-agency-manager/controllers:UserController"] = append(beego.GlobalControllerRouter["cve-agency-manager/controllers:UserController"],
beego.ControllerComments{
Method: "Get",
- Router: `/:uid`,
+ Router: "/:uid",
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
- beego.GlobalControllerRouter["cve-agency-service/controllers:UserController"] = append(beego.GlobalControllerRouter["cve-agency-service/controllers:UserController"],
+ beego.GlobalControllerRouter["cve-agency-manager/controllers:UserController"] = append(beego.GlobalControllerRouter["cve-agency-manager/controllers:UserController"],
beego.ControllerComments{
Method: "Put",
- Router: `/:uid`,
+ Router: "/:uid",
AllowHTTPMethods: []string{"put"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
- beego.GlobalControllerRouter["cve-agency-service/controllers:UserController"] = append(beego.GlobalControllerRouter["cve-agency-service/controllers:UserController"],
+ beego.GlobalControllerRouter["cve-agency-manager/controllers:UserController"] = append(beego.GlobalControllerRouter["cve-agency-manager/controllers:UserController"],
beego.ControllerComments{
Method: "Delete",
- Router: `/:uid`,
+ Router: "/:uid",
AllowHTTPMethods: []string{"delete"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
- beego.GlobalControllerRouter["cve-agency-service/controllers:UserController"] = append(beego.GlobalControllerRouter["cve-agency-service/controllers:UserController"],
+ beego.GlobalControllerRouter["cve-agency-manager/controllers:UserController"] = append(beego.GlobalControllerRouter["cve-agency-manager/controllers:UserController"],
beego.ControllerComments{
Method: "Login",
- Router: `/login`,
+ Router: "/login",
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
- beego.GlobalControllerRouter["cve-agency-service/controllers:UserController"] = append(beego.GlobalControllerRouter["cve-agency-service/controllers:UserController"],
+ beego.GlobalControllerRouter["cve-agency-manager/controllers:UserController"] = append(beego.GlobalControllerRouter["cve-agency-manager/controllers:UserController"],
beego.ControllerComments{
Method: "Logout",
- Router: `/logout`,
+ Router: "/logout",
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
diff --git a/cve-agency-manager/routers/router.go b/cve-agency-manager/routers/router.go
index ee860644ec4c49ffe9063372953308224feeab56..4f5360f5005ce9b1d92263682be4eda67c604eda 100644
--- a/cve-agency-manager/routers/router.go
+++ b/cve-agency-manager/routers/router.go
@@ -8,7 +8,7 @@
package routers
import (
- "cve-agency-service/controllers"
+ "cve-agency-manager/controllers"
"github.com/astaxie/beego"
)
diff --git a/cve-vulner-manager/conf/app.conf b/cve-vulner-manager/conf/app.conf
index 0b43f65f4834123b551b5946e84a9cc9a9220d50..62188f12219b042941e03df3ad2a9e821f241dcc 100644
--- a/cve-vulner-manager/conf/app.conf
+++ b/cve-vulner-manager/conf/app.conf
@@ -20,6 +20,7 @@ approveCmd = "/approve"
closeCmd = "/close"
errorCmd = "/error"
autoPrCmd = "/find-patch"
+feedBackCmd = "/feedback"
getCveCmd = "/get-cve"
labelFixed = "CVE/FIXED"
labelUnFix = "CVE/UNFIXED"
@@ -243,7 +244,8 @@ download_cvrf_dir = "cvrf/"
upload_updateinfo_dir = "cve-manager-updateinfo/"
[cveagency]
-url = "http://cve-manager-agent.cve-manager-agent.svc.cluster.local/v1/cve/track"
+#url = "http://cve-manager-agent.cve-manager-agent.svc.cluster.local/v1/cve/track"
+url = "http://127.0.0.1:8090/v1/cve/track"
[openlookeng]
#openlookeng_owner = openlookeng
diff --git a/cve-vulner-manager/conf/product_app.conf b/cve-vulner-manager/conf/product_app.conf
index 51a6551025c8035c0854af2febb821f0402321b3..195223dd4812438723a3456892e4480f2a21b105 100644
--- a/cve-vulner-manager/conf/product_app.conf
+++ b/cve-vulner-manager/conf/product_app.conf
@@ -20,6 +20,7 @@ approveCmd = "/approve"
closeCmd = "/close"
errorCmd = "/error"
autoPrCmd = "/find-patch"
+feedBackCmd = "/feedback"
getCveCmd = "/get-cve"
labelFixed = "CVE/FIXED"
labelUnFix = "CVE/UNFIXED"
diff --git a/cve-vulner-manager/controllers/hook.go b/cve-vulner-manager/controllers/hook.go
index 2bbbb071c73aeec8992dac75df26298b63ecc428..48d14605cfc140b7abf1e59a1e01d9043792d579 100644
--- a/cve-vulner-manager/controllers/hook.go
+++ b/cve-vulner-manager/controllers/hook.go
@@ -91,6 +91,11 @@ type HookEventControllers struct {
beego.Controller
}
+type AgencyPrams struct {
+ CveUrl string
+ PatchUrl string
+}
+
//Post handle gitee webhook
// @router / [post]
func (c *HookEventControllers) Post() {
@@ -1566,6 +1571,7 @@ func handleIssueComment(payload models.CommentPayload) {
cmdError := beego.AppConfig.DefaultString("errorCmd", "/error")
cmdAutoPr := beego.AppConfig.String("autoPrCmd")
cmdGetCve := beego.AppConfig.String("getCveCmd")
+ cmdFeedBack := beego.AppConfig.String("feedBackCmd")
if issueNum == "" || cuAccount == "" || cBody == "" {
logs.Error("Data has null values: issueNum, cuAccount, cBody: ", issueNum, cuAccount, cBody)
return
@@ -1587,7 +1593,7 @@ func handleIssueComment(payload models.CommentPayload) {
logs.Error("GetErr: ", err, ",issueTmp: ", issueTmp)
return
}
-
+ agencyPram := AgencyPrams{}
fixed := beego.AppConfig.String("labelFixed")
unfixed := beego.AppConfig.String("labelUnFix")
path := issueTmp.Repo
@@ -1713,7 +1719,16 @@ func handleIssueComment(payload models.CommentPayload) {
}
} else if strings.HasPrefix(cBody, cmdAutoPr) {
if vc.OrganizationID == 1 {
- PostCveAgency(issueTmp)
+ PostCveAgency(issueTmp, agencyPram)
+ }
+ } else if strings.HasPrefix(cBody, cmdFeedBack) {
+ if vc.OrganizationID == 1 {
+ bodyList := strings.Split(cBody, " ")
+ if len(bodyList) > 2 {
+ agencyPram.CveUrl = bodyList[1]
+ agencyPram.PatchUrl = bodyList[2]
+ }
+ PostCveAgency(issueTmp, agencyPram)
}
} else if strings.HasPrefix(cBody, cmdGetCve) {
PostTriggerGetCve(issueTmp, owner, accessToken, cuAccount)
@@ -1730,13 +1745,15 @@ func handleIssueComment(payload models.CommentPayload) {
}
}
-func PostCveAgency(issueTmp models.IssueTemplate) {
+func PostCveAgency(issueTmp models.IssueTemplate, agencyPram AgencyPrams) {
// Trigger third-party data generation
agencyUrl := beego.AppConfig.String("cveagency::url")
agencyReq := make(map[string]interface{}, 0)
agencyReq["CveNum"] = issueTmp.CveNum
agencyReq["PackName"] = issueTmp.OwnedComponent
agencyReq["PackVersion"] = issueTmp.OwnedVersion
+ agencyReq["CveUrl"] = agencyPram.CveUrl
+ agencyReq["PatchUrl"] = agencyPram.PatchUrl
if len(issueTmp.AffectedVersion) > 0 {
versionList := strings.Split(issueTmp.AffectedVersion, ",")
if len(versionList) > 0 {
diff --git a/cve-vulner-manager/taskhandler/cve.go b/cve-vulner-manager/taskhandler/cve.go
index b8801f29cf844a547e71296843c850e16e1be991..83bca0ead36d0b606ca6dcc7b6fc68a6f1efb5b8 100644
--- a/cve-vulner-manager/taskhandler/cve.go
+++ b/cve-vulner-manager/taskhandler/cve.go
@@ -55,6 +55,9 @@ func UpdateExcelCveGroups(cveData models.OriginExcel,
if len(CveRes.RepairTime) < 2 && len(cveData.RepairTime) > 2 {
CveRes.RepairTime = cveData.RepairTime
}
+ if len(goe.Decription) < 1 {
+ goe.Decription = goe.Summary
+ }
//CveRes.PackName = cveData.PackName
CveRes.RepoName = cveData.PackName
CveRes.CveUrl = cveRef + cveData.CveNum
@@ -275,6 +278,9 @@ func InsertCveExcelGroups(cveData models.OriginExcel, cveRef, repoName string, o
sec.Summary = cveData.PackName + " security update"
sec.ReferenceLink = cveRef + cveData.CveNum
specCharList := []string{"\n", "\r", "\t"}
+ if len(goe.Decription) < 1 {
+ goe.Decription = goe.Summary
+ }
if goe.Decription != "" && len(goe.Decription) > 0 {
sec.Description = RemoveSubstring(goe.Decription, specCharList) + "\n\n" +
"Security Fix(es):" + "\n\n" + RemoveSubstring(cveData.CveDesc, specCharList)
@@ -569,6 +575,9 @@ func UpdateCveGroups(cveData models.OriginUpstream, cveRef string, openeulerNum
sec.CveId = CveRes.CveId
sec.Summary = pkList[0] + " security update"
sec.ReferenceLink = cveRef + cveData.CveNum
+ if len(goe.Decription) < 1 {
+ goe.Decription = goe.Summary
+ }
if goe.Decription != "" && len(goe.Decription) > 0 {
sec.Description = goe.Decription + "\n\n" + "Security Fix(es):" + "\n\n" + cveDesc.EnDescription + "(" + CveRes.CveNum + ")"
} else {
@@ -636,6 +645,9 @@ func InsertCveGroups(cveData models.OriginUpstream, cveRef, repoNme string,
sec.Summary = pkList[0] + " security update"
sec.ReferenceLink = cveRef + cveData.CveNum
specCharList := []string{"\n", "\r", "\t"}
+ if len(goe.Decription) < 1 {
+ goe.Decription = goe.Summary
+ }
if goe.Decription != "" && len(goe.Decription) > 0 {
sec.Description = RemoveSubstring(goe.Decription, specCharList) + "\n\n" + "Security Fix(es):" + "\n\n" +
RemoveSubstring(cveDesc.EnDescription, specCharList)
@@ -1439,6 +1451,9 @@ func InsertIssueCveGroups(cveData models.GiteOriginIssue, lop models.Loophole, c
sec.Status = 0
sec.AffectStatus = "Fixed"
sec.Summary = cveData.RepoPath + " security update"
+ if len(goe.Decription) < 1 {
+ goe.Decription = goe.Summary
+ }
sec.Description = RemoveSubstring(goe.Decription, specCharList) + "\n\n" + "Security Fix(es):" + "\n\n" +
RemoveSubstring(lop.BriefIntroduction, specCharList)
if sec.Description != "" && len(sec.Description) > 1 {
@@ -1649,6 +1664,9 @@ func UpdateIssueCveGroups(cveData models.GiteOriginIssue, lop models.Loophole, c
sec.Status = 0
sec.AffectStatus = "Fixed"
sec.Summary = vul.PackName + " security update"
+ if len(goe.Decription) < 1 {
+ goe.Decription = goe.Summary
+ }
sec.Description = RemoveSubstring(goe.Decription, specCharList) + "\n\n" + "Security Fix(es):" + "\n\n" + vul.Description
if sec.Description != "" && len(sec.Description) > 1 {
sec.Description = deleteTailBlank(sec.Description) + "(" + vul.CveNum + ")"