From f943a34e392ced469be800858dfaf687b8e9b09d Mon Sep 17 00:00:00 2001 From: zhangjianjun_code <7844966+zhangjianjun_code@user.noreply.gitee.com> Date: Fri, 30 Oct 2020 11:38:19 +0800 Subject: [PATCH 1/3] 1. Modify the bug of sa export --- conf/app.conf | 16 +++++----- controllers/file.go | 32 +++++++++++--------- models/cve.go | 60 +++++++++++++++++++++++++++++++------- models/issue.go | 2 +- models/modeldb.go | 2 +- taskhandler/createissue.go | 6 ++-- taskhandler/cve.go | 25 +++++++++++++--- taskhandler/excel.go | 34 ++++++++++++--------- 8 files changed, 122 insertions(+), 55 deletions(-) diff --git a/conf/app.conf b/conf/app.conf index 31e3b0d..2f53947 100644 --- a/conf/app.conf +++ b/conf/app.conf @@ -46,7 +46,7 @@ maxsize=204800 [crontab] ymalflag = 2 getymal = 00 00 23 * * * -cveflag = 2 +cveflag = 1 getcve = 00 00 01 * * * oricveflag = 2 oricvecheck = 00 00 05 * * * @@ -57,22 +57,22 @@ createissue = * * 05 * * * test = 0/10 * * * * * gittokenflag = 2 issueoath = * * */20 * * * -genexcelflag = 2 -genexcel = 00 00 04 * * * +genexcelflag = 1 +genexcel = 0 */10 * * * * days = -30 prcnum = 50 -printlogflag = 1 -printlog = 0 */10 * * * * +printlogflag = 2 +printlog = 0 */20 * * * * [gitee] #owner = cve-test -#owner = src-openeuler -#path = test +owner = src-openeuler +path = test #email = 1499273991@qq.com #redirect_uri = http://119.8.126.102:80/v1/issue/oauth/callback # -------jianjun gitee 配置 -------- -owner = cve-test +#owner = cve-test #path = jasper email = 7844966+zhangjianjun_code@user.noreply.gitee.com redirect_uri = http://159.138.2.2:80/v1/issue/oauth/callback diff --git a/controllers/file.go b/controllers/file.go index 44598a4..1fdc2fd 100644 --- a/controllers/file.go +++ b/controllers/file.go @@ -40,20 +40,20 @@ func (f *FileController) DownloadLastExcel() { //DownLoadExcelByFileCode download excel file by code //@router /downloadExcel -func (f *FileController) DownLoadExcelByFileCode() { +func (f *FileController) DownLoadExcelByFileCode() { fd := beego.AppConfig.DefaultString("fileDir", "download") fc := f.GetString("fileCode") - if fc == ""{ + if fc == "" { _ = f.Ctx.Output.Body([]byte("err: fileCode is a required parameter ")) return } er := models.ExportRecord{FileCode: fc} err := er.Read("file_code") if err != nil { - _ = f.Ctx.Output.Body([]byte(fmt.Sprintf("err: %v",err))) + _ = f.Ctx.Output.Body([]byte(fmt.Sprintf("err: %v", err))) return } - if er.FileName == ""{ + if er.FileName == "" { _ = f.Ctx.Output.Body([]byte("err: Can not find excel file by fileCode! ")) return } @@ -75,6 +75,7 @@ func (f *FileController) DownLoadExcelByFileCode() { //TriggerCveData touch off generate cve data excel and get cve package //@router /triggerCveData [get] func (f *FileController) TriggerCveData() { + timeUnix := time.Now().Unix() startTime := f.GetString("startTime") if startTime == "" { f.Ctx.WriteString("Error:start time cannot be empty") @@ -83,15 +84,17 @@ func (f *FileController) TriggerCveData() { //It is time-consuming to generate excel, here is the current limit processing er := models.ExportRecord{} err := er.QueryLast() - if err == nil { - if er.State == 0 { - eng := fmt.Sprintf("There is currently a file being generated, file information: file name %s fileCode=%s; you can use fileCode to download the file.", - er.FileName,er.FileCode) - cha := fmt.Sprintf("\n当前有一个文件正在生成,文件信息:文件名 %s fileCode= %s ;你可以使用fileCode去下载文件。",er.FileName,er.FileCode) - f.Ctx.WriteString(eng+cha) + if err == nil { + if er.State == 0 && (timeUnix-er.CreateTime < 300) { + eng := fmt.Sprintf("There is currently a file being generated, "+ + "file information: file name %s fileCode=%s; you can use fileCode to download the file.", + er.FileName, er.FileCode) + cha := fmt.Sprintf("\n当前有一个文件正在生成,文件信息:文件名 %s fileCode= %s ;"+ + "你可以使用fileCode去下载文件。", er.FileName, er.FileCode) + f.Ctx.WriteString(eng + cha) return } - }else { + } else { logs.Error(err) } rt := regexp.MustCompile(`^(\d{4})-\d{2}-(\d{2})$`) @@ -104,14 +107,15 @@ func (f *FileController) TriggerCveData() { en := fmt.Sprintf("cve与安全公告%v.xlsx", now) fileCode := common.EncryptMd5(en) //call the generate excel task by new thread - go taskhandler.GenerateExcelTrigger(en, startTime,fileCode) - er = models.ExportRecord{FileName: en, FileCode: fileCode, State: 0} + er = models.ExportRecord{FileName: en, FileCode: fileCode, State: 0, CreateTime: timeUnix} err = er.Insert() if err != nil { f.Ctx.WriteString(fmt.Sprintf("error:%v", err)) } else { //return the success notice - f.Ctx.WriteString(fmt.Sprintf("Success:The name of the excel file generated this time is: %s. It takes some time to generate the excel file. "+ + go taskhandler.GenerateExcelTrigger(en, startTime, fileCode) + f.Ctx.WriteString(fmt.Sprintf("Success:The name of the excel file generated this time is: %s. "+ + "It takes some time to generate the excel file. "+ "You can try to call the download file interface and pass in the param fileCode=%s to be downloaded.", en, fileCode)) } } diff --git a/models/cve.go b/models/cve.go index f6f7bee..7de90ad 100644 --- a/models/cve.go +++ b/models/cve.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/astaxie/beego/logs" "github.com/astaxie/beego/orm" + "strings" ) func QueryOriginCveExcel(days string, prcnum int) ([]OriginExcel, int64, error) { @@ -138,8 +139,7 @@ func QueryCveByNum(cveNum, packName, version string) (VulnCenter, bool) { var cve VulnCenter err := o.Raw("select * from cve_vuln_center where cve_num = ? and pack_name = ? and cve_version = ?", cveNum, packName, version).QueryRow(&cve) - if err != nil { - logs.Error(cveNum, packName, version, "cve_vuln_center 查询不到, err: ", err) + if err != nil || cve.CveId == 0 { return cve, false } else { return cve, true @@ -149,7 +149,8 @@ func QueryCveByNum(cveNum, packName, version string) (VulnCenter, bool) { func UpdateCveStatusExportByNum(updatetime, cveNum string, status, isExport int, repoPath string) bool { o := orm.NewOrm() res, err := o.Raw("UPDATE cve_vuln_center SET "+ - "is_export = ?, cve_status = ?, update_time = ? where cve_num = ? and pack_name = ?", isExport, status, updatetime, cveNum, repoPath).Exec() + "is_export = ?, cve_status = ?, update_time = ? where cve_num = ? and pack_name = ?", + isExport, status, updatetime, cveNum, repoPath).Exec() if err == nil { num, _ := res.RowsAffected() if num > 0 { @@ -302,7 +303,8 @@ func InsertScoreRecord(sc *ScoreRecord) (int64, error) { return 0, nil } -func CreateCveRelat(cve *VulnCenter, sec *SecurityNotice, score *Score, op *OpenEulerSA, sc *ScoreRecord) (cveid int64, err error) { +func CreateCveRelat(cve *VulnCenter, sec *SecurityNotice, score *Score, + op *OpenEulerSA, sc *ScoreRecord) (cveid int64, err error) { o := orm.NewOrm() errs := o.Begin() if errs == nil { @@ -571,16 +573,19 @@ func QueryOpenSaById(cveId int64) (OpenEulerSA, error) { func UpdateOriginStatus(updateTime, pakName, version string, cveId int64, status int) bool { o := orm.NewOrm() res, err := o.Raw("UPDATE cve_origin_upstream SET "+ - "cve_status = ?, update_time = ? where cve_id = ? and git_packname = ? and version = ?", status, updateTime, cveId, pakName, version).Exec() + "cve_status = ?, update_time = ? where cve_id = ? and git_packname = ? and version = ?", + status, updateTime, cveId, pakName, version).Exec() if err == nil { num, _ := res.RowsAffected() if num > 0 { - logs.Info("cve_origin_upstream row affected nums: ", num, ",cveId: ", cveId, ",", updateTime, pakName, version) + logs.Info("cve_origin_upstream row affected nums: ", + num, ",cveId: ", cveId, ",", updateTime, pakName, version) return true } return false } else { - logs.Error("更新失败, cve_origin_upstream, ", ",cveId: ", cveId, ",", updateTime, pakName, version, ", err: ", err) + logs.Error("更新失败, cve_origin_upstream, ", ",cveId: ", + cveId, ",", updateTime, pakName, version, ", err: ", err) return false } } @@ -648,6 +653,40 @@ func GetCanExportVulnCenterCount() (count int64) { return res.Total } +func GetCanExportTheme(cveNums, component string) (string, error) { + if cveNums == "" || component == "" { + return "", errors.New("param is empty") + } + s := strings.Split(cveNums, ";\n") + for k, v := range s { + s[k] = "'" + v + "'" + } + cveNums = strings.Join(s, ",") + type tmp = struct { + OpenEulerScore float64 `orm:"column(openeuler_score)"` + Theme string + } + res := make([]tmp,0) + sql := fmt.Sprintf(`SELECT b.openeuler_score,a.theme FROM cve_issue_template b +JOIN cve_security_notice a ON a.cve_id = b.cve_id +WHERE b.cve_num IN (%s) +AND b.owned_component = '%s'`,cveNums,component) + o := orm.NewOrm() + _, err := o.Raw(sql).QueryRows(&res) + if err != nil { + return "", err + } + max := float64(0) + resStr := "" + for _,v :=range res { + if max < v.OpenEulerScore { + max = v.OpenEulerScore + resStr = v.Theme + } + } + return resStr,nil +} + func GetCanExportCveData(page int64, pageSize int) (list []ExcelExport, err error) { sql := `SELECT b.num,c.*,a.owned_component,a.cve_brief, d.sec_id,d.introduction,d.summary,d.theme,d.description,d.influence_component, @@ -670,7 +709,7 @@ ON b.cve_id = e.cve_id } //GetCanExportExcelData Get exportable data -func GetCanExportExcelData(cveNum,issueNum string) (list []ExcelExport, err error) { +func GetCanExportExcelData(cveNum, issueNum string) (list []ExcelExport, err error) { if cveNum == "" { return list, errors.New("cve number can not empty") } @@ -691,12 +730,13 @@ ON b.cve_id = e.cve_id WHERE a.issue_num = ? ` o := orm.NewOrm() - _, err = o.Raw(sql, cveNum, cveNum,issueNum).QueryRows(&list) + _, err = o.Raw(sql, cveNum, cveNum, issueNum).QueryRows(&list) return } func GetCanExportCveDataSameNum(cId string) (list []ExcelExport, err error) { - sql := `SELECT a.cve_id,a.owned_component,a.cve_brief,c.*,d.sec_id,d.introduction,d.summary,d.theme,d.description,d.influence_component, + sql := `SELECT a.cve_id,a.owned_component,a.cve_brief,c.*,d.sec_id, +d.introduction,d.summary,d.theme,d.description,d.influence_component, d.affect_product,d.reference_link,d.affect_status,e.public_date,e.openeuler_sa_num FROM cve_issue_template a LEFT JOIN cve_score c diff --git a/models/issue.go b/models/issue.go index 393a6a2..6120afa 100644 --- a/models/issue.go +++ b/models/issue.go @@ -192,7 +192,7 @@ func ReplacePackageByCveId(pkgList []string,cveId int64) error { delPkgSql := `DELETE FROM cve_package WHERE sec_id = ?` _, err = o.Raw(delPkgSql, sec.SecId).Exec() if err != nil { - return err + logs.Error("delete cve_package error:",err) } pkgData := make([]Package, 0) for _, v := range pkgList { diff --git a/models/modeldb.go b/models/modeldb.go index 92954c2..d925465 100644 --- a/models/modeldb.go +++ b/models/modeldb.go @@ -551,7 +551,7 @@ type ExportRecord struct { FileName string `orm:"unique"` FileCode string State int8 ` description:"0:文件生成中;1 文件可下载;2 文件不可下载"` - CreateTime time.Time `orm:"auto_now_add;type(datetime);column(create_time)"` + CreateTime int64 `orm:"column(create_time)" description:"时间戳"` } type PackageCpe struct { diff --git a/taskhandler/createissue.go b/taskhandler/createissue.go index e6358af..4f1dc7a 100644 --- a/taskhandler/createissue.go +++ b/taskhandler/createissue.go @@ -115,7 +115,7 @@ func CreateIssueToGit(accessToken string, owner string, path string, assignee st } } else { issueType := "CVE和安全问题" - labels := beego.AppConfig.String("labelFixed") + labels := beego.AppConfig.String("labelUnFix") if accessToken != "" && owner != "" && path != "" { url := "https://gitee.com/api/v5/repos/" + owner + "/issues" score := strconv.FormatFloat(sc.NVDScore, 'f', 1, 64) @@ -505,7 +505,7 @@ func CreateSecNoticeData(sec *models.SecurityNotice, iss models.VulnCenter, path sec.CveNum = iss.CveNum opScoreLeve := openEulerScoreProc(opScore) sec.Introduction = "An update for " + path + " is now available for " + branchs + "." - sec.Theme = sec.Introduction + ";\n\n" + "openEuler Security has rated this" + + sec.Theme = sec.Introduction[:len(sec.Introduction) - 1] + ";\n\n" + "openEuler Security has rated this" + " update as having a security impact of " + opScoreLeve + ". A Common Vunlnerability" + " Scoring System(CVSS)base score,which gives a detailed severity rating," + " is available for each vulnerability from the CVElink(s) in the References section." @@ -518,7 +518,7 @@ func CreateIssueLabel(accessToken string, owner string, path string, url := "https://gitee.com/api/v5/repos/" + owner + "/" + path + "/issues/" + issNum + "/labels" body := make(map[string]interface{}) body["access_token"] = accessToken - body["body"] = fmt.Sprintf(`[%s,%s]`, beego.AppConfig.String("labelUnFix"), beego.AppConfig.String("labelFixed")) + body["body"] = fmt.Sprintf(`[%s,%s]`, beego.AppConfig.String("labelUnFix"), beego.AppConfig.String("labelUnFix")) requestBody, _ := json.Marshal(body) logs.Info("create issue label: ", string(requestBody)) resp, err := util.HTTPPost1(url, string(requestBody)) diff --git a/taskhandler/cve.go b/taskhandler/cve.go index 65853ca..c37cca0 100644 --- a/taskhandler/cve.go +++ b/taskhandler/cve.go @@ -945,7 +945,7 @@ func InsertIssueCveGroups(cveData models.GiteOriginIssue, lop models.Loophole, c } sec.ReferenceLink = cveRef + cveData.CveNumber sec.Introduction = "An update for " + lop.Components + " is now available for " + lop.InfProduct + "." - sec.Theme = sec.Introduction + ";\n\n" + "openEuler Security has rated this" + + sec.Theme = sec.Introduction[:len(sec.Introduction)-1] + ";\n\n" + "openEuler Security has rated this" + " update as having a security impact of " + opScoreLeve + ". A Common Vunlnerability" + " Scoring System(CVSS)base score,which gives a detailed severity rating," + " is available for each vulnerability from the CVElink(s) in the References section." @@ -1107,7 +1107,7 @@ func UpdateIssueCveGroups(cveData models.GiteOriginIssue, lop models.Loophole, c opScoreLeve = openEulerScoreProc(opScore) } sec.Introduction = "An update for " + lop.Components + " is now available for " + lop.InfProduct + "." - sec.Theme = sec.Introduction + ";\n\n" + "openEuler Security has rated this" + + sec.Theme = sec.Introduction[:len(sec.Introduction) - 1] + ";\n\n" + "openEuler Security has rated this" + " update as having a security impact of "+ opScoreLeve + ". A Common Vunlnerability" + " Scoring System(CVSS)base score,which gives a detailed severity rating," + " is available for each vulnerability from the CVElink(s) in the References section." @@ -1263,6 +1263,11 @@ func UpdateIssueCveGroups(cveData models.GiteOriginIssue, lop models.Loophole, c if openError == nil { issueTemp.OpenEulerScore = openEulerScore } + issueTemp.NVDVector = lop.CvsVector + nvdScore, nvdError := strconv.ParseFloat(lop.CvsScore, 64) + if nvdError == nil { + issueTemp.NVDScore = nvdScore + } issueTemp.OpenEulerVector = lop.OpVector issueTemp.CveBrief = RemoveSubstring(lop.BriefIntroduction, specCharList) issueTemp.CveAnalysis = lop.Influences @@ -1303,6 +1308,11 @@ func UpdateIssueCveGroups(cveData models.GiteOriginIssue, lop models.Loophole, c issueTemp.OpenEulerScore = openEulerScore } issueTemp.NVDVector = lop.CvsVector + nvdScore, nvdError := strconv.ParseFloat(lop.CvsScore, 64) + if nvdError == nil { + issueTemp.NVDScore = nvdScore + } + issueTemp.NVDVector = lop.CvsVector issueTemp.OpenEulerVector = lop.OpVector issueTemp.CveBrief = RemoveSubstring(lop.BriefIntroduction, specCharList) issueTemp.CveAnalysis = lop.Influences @@ -1524,6 +1534,11 @@ func FilterCveExported() { } func GenerateExcelTask() error { + FilterCveExported() + return nil +} + +func GenerateExcelTask1() error { FilterCveExported() tn := time.Now().Format("2006-01-02") dir := beego.AppConfig.DefaultString("fileDir", "download") @@ -1542,7 +1557,8 @@ func GenerateExcelTask() error { } //GenerateExcelTrigger generate cve&security notice excel file by pr merge and influence package release. func GenerateExcelTrigger(fileName, startTime,fileCode string) { - FilterCveExported() + //FilterCveExported() + logs.Error("start。。。。。") dir := beego.AppConfig.DefaultString("fileDir", "download") err := util.MakeDir(dir) if err != nil { @@ -1551,7 +1567,7 @@ func GenerateExcelTrigger(fileName, startTime,fileCode string) { fr := models.ExportRecord{FileName: fileName} err = fr.Read("file_name") if err != nil { - logs.Error(err) + logs.Error("sddds",err) return } fileName = filepath.Join(dir, fileName) @@ -1574,6 +1590,7 @@ func GenerateExcelTrigger(fileName, startTime,fileCode string) { snPrefix := "openEuler-" + su snSuffix := int64(1001) err = GenerateCveExcelByTrigger(fileName, snPrefix, startTime, snSuffix, true, pkgList) + logs.Error("end....") if err != nil { logs.Error(err) fr.State = 2 diff --git a/taskhandler/excel.go b/taskhandler/excel.go index 7a9d306..95b356e 100644 --- a/taskhandler/excel.go +++ b/taskhandler/excel.go @@ -41,6 +41,7 @@ type CveExcel struct { type IssueAndPkg struct { IssueMap map[int64]models.PullRequestIssue IssuePkg string + Repo string } var fillLock sync.Mutex @@ -401,6 +402,7 @@ func (ec *CveExcel) FillContentTrigger(pkgList []models.ExcelPackage, startTime go ec.handleGiteData(cd) } wgTrigger.Wait() + logs.Error("cve_gen_finish") } func (ec *CveExcel) handleWriteContent(off int64, size int) (err error) { @@ -511,9 +513,7 @@ func (ec *CveExcel) handleWriteContentSync(list []models.ExcelExport) (err error ep.OwnedComponent = ep.OwnedComponent + "\n" + ex.OwnedComponent m[ex.OwnedComponent] = struct{}{} } - } - } fillLock.Lock() ec.setContentRow(ep) @@ -572,6 +572,12 @@ func (ec *CveExcel) setContentRow(v models.ExcelExport) { vd += dSplit[1] } _ = ec.ExcelHandel.SetCellValue(ec.SecNoticeSheetName, rd, vd) + //Get the highest-rated theme + rd = "E" + row + theme, err := models.GetCanExportTheme(vcn, v.OwnedComponent) + if err == nil { + _ = ec.ExcelHandel.SetCellValue(ec.SecNoticeSheetName, rd, theme) + } } cve := []interface{}{v.CveNum, v.CveBrief, v.NVDScore, v.OpenEulerScore, v.NattackVector, v.OattackVector, v.NattackComplexity, v.OattackComplexity, v.NprivilegeRequired, v.OprivilegeRequired, v.NuserInteraction, @@ -729,7 +735,7 @@ func getDateByGite(pkgList []models.ExcelPackage, startTime string, c chan<- []I getPRRelatedAllIssue(token, owner, v.Repo, st, rt, p.Number, repoIssue) } if len(repoIssue) > 0 { - chData = append(chData, IssueAndPkg{IssueMap: repoIssue, IssuePkg: v.Packages}) + chData = append(chData, IssueAndPkg{IssueMap: repoIssue, IssuePkg: v.Packages, Repo: v.Repo}) } } c <- chData @@ -750,7 +756,7 @@ func (ec *CveExcel) handleGiteData(c <-chan []IssueAndPkg) { tpl := models.IssueTemplate{IssueNum: iv.Number, Repo: iv.Repo} err := models.GetIssueTemplateByColName(&tpl, "issue_num", "repo") if err != nil { - logs.Error(err) + logs.Error("----",err) continue } err = models.ReplacePackageByCveId(pkgList, tpl.CveId) @@ -786,7 +792,7 @@ func getRepoAllPR(token, owner, repo string, startTime, releaseTime int64) (prLi q.Add("sort", "created") q.Add("state", "merged") q.Add("per_page", strconv.Itoa(pageSize)) - q.Add("base","openEuler-20.03-LTS") //target branch is openEuler-20.03-LTS + q.Add("base", "openEuler-20.03-LTS") //target branch is openEuler-20.03-LTS for { q.Del("page") q.Add("page", strconv.Itoa(pageCount)) @@ -892,18 +898,18 @@ func isLegallyIssue(i models.HookIssue, startTime int64, releaseTime int64) (pri } tt := strings.Trim(i.Title, " ") regCveNum := regexp.MustCompile(`(?mi)CVE-[\d]{1,}-([\d]{1,})$`) - if tt != "" && regCveNum.Match([]byte(tt)) { + /*if tt != "" && regCveNum.Match([]byte(tt)) { ok = true - } else { - sm := util.RegexpCveNumber.FindAllStringSubmatch(i.Body, -1) - if len(sm) > 0 && len(sm[0]) > 0 { - val := sm[0][1] - tt = util.GetCveNumber(util.TrimString(val)) - if tt != "" && regCveNum.Match([]byte(tt)) { - ok = true - } + } else {*/ + sm := util.RegexpCveNumber.FindAllStringSubmatch(i.Body, -1) + if len(sm) > 0 && len(sm[0]) > 0 { + val := sm[0][1] + tt = util.GetCveNumber(util.TrimString(val)) + if tt != "" && regCveNum.Match([]byte(tt)) { + ok = true } } + //} if ok { pri.Id = i.Id pri.Number = i.Number -- Gitee From 3949921e32062d8232163800ee7d26f4ef9495b3 Mon Sep 17 00:00:00 2001 From: zhangjianjun_code <7844966+zhangjianjun_code@user.noreply.gitee.com> Date: Fri, 30 Oct 2020 14:48:25 +0800 Subject: [PATCH 2/3] 1. Modify configer to start timing tasks; 2. Modify bugs; 3. Verify data --- conf/product_app.conf | 15 +++++++-------- cve-py/controller/timertaskcontroller.py | 8 -------- cve-py/main.py | 2 -- cve-py/newexcels/test.xls | Bin 6656 -> 0 bytes 4 files changed, 7 insertions(+), 18 deletions(-) delete mode 100644 cve-py/newexcels/test.xls diff --git a/conf/product_app.conf b/conf/product_app.conf index 2667c65..4e7f565 100644 --- a/conf/product_app.conf +++ b/conf/product_app.conf @@ -25,7 +25,6 @@ fileDir = "download" rpUrl = "http://119.3.219.20:88/mkb/obs_update_info/openEuler-20.03-LTS.csv" [mysql] -#dbhost = 172.16.1.73 dbhost = "${DB_URI||***}" dbport = 3306 dbuser = "${DB_USER||cve}" @@ -44,20 +43,20 @@ maxlines=50000 maxsize=204800 [crontab] -ymalflag = 2 -getymal = 00 00 01 * * * -cveflag = 2 +ymalflag = 1 +getymal = 00 00 01 * * 1 +cveflag = 1 getcve = 00 00 03 * * * -oricveflag = 2 +oricveflag = 1 oricvecheck = 00 00 05 * * * -getissueflag = 2 +getissueflag = 1 getissue = 00 00 05 * * * -issueflag = 2 +issueflag = 1 createissue = * * 05 * * * test = 0/10 * * * * * gittokenflag = 2 issueoath = * * */20 * * * -genexcelflag = 2 +genexcelflag = 1 genexcel = 00 00 04 * * * days = -30 prcnum = 50 diff --git a/cve-py/controller/timertaskcontroller.py b/cve-py/controller/timertaskcontroller.py index 37264de..9c04eea 100644 --- a/cve-py/controller/timertaskcontroller.py +++ b/cve-py/controller/timertaskcontroller.py @@ -42,11 +42,3 @@ def timertask(): print("Err:", err) -def InitTask(): - """ - 1. Initialize the verification task for the first time; - 2. Shield after verification - """ - taskcontroller.gwcontroller() - taskcontroller.runtabletask() - taskcontroller.runmappeingtask() diff --git a/cve-py/main.py b/cve-py/main.py index 8d12273..966cf7e 100644 --- a/cve-py/main.py +++ b/cve-py/main.py @@ -20,8 +20,6 @@ from controller import timertaskcontroller if __name__ == '__main__': - print("Initialize the verification task for the first time and execute it immediately:") - timertaskcontroller.InitTask() print("The program starts, waiting for the timing task to execute") timertaskcontroller.timertask() diff --git a/cve-py/newexcels/test.xls b/cve-py/newexcels/test.xls deleted file mode 100644 index a7f371ad8fadc9ed3a23cb494ec850371d390000..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6656 zcmeI0Yiv|S6vxlqZrfd<^vScbuI14ur7a+@KwAQd#z-run6L&~TBJc9sbJ)j>jRC7 zi3SqIm>3chH6|5ff+iZ%elYP1(P$viPsN19Z=%su6ubV;xx4Lld+%CkLjvj9{m;xj z_spC#GiT1s-0!|E9z65Of=iM?8zo1E6Jg0q<2#fUMnxh43i>>pNF-dQ2*qi-g+}0C zY`r5nhe7gOpmUxNLLdxg0G(sSG~He!uuTr}J0elpA_vKPQi`z)9)X+*8Pdd0L$s+9D5ur|J1-=^*WJ z*%MC7(62F2`!rGg%aQ#%sUcUk%TYPNufxXvK4xLBjfrxONDt+MNm;L~D%pQsyA##F z0@-hpjj8QAZ)(5a`q%iN!!;8WfLTDNk1aroK?x`YWnea#1LlHxU_Mv?%E6srA&7vx zKor~!D!?MJ7%TxxK_#dH)u0B{f;zAa)B}x04djiWDfzsTd=*#^R)aNQEm#Mp%byuz+GKV4Cfx@MuMx@ zi065U@04xQEnV`MPsP>j-t)&-tVfrhHuqg5*vh6K@voX)bE=UZR&0|vyCj-4u!hoT z&y>Gj#=affcQ1(wMyJARxpiBt90~3qL{z)V{M0DlPl3MkYx)>dw9daDZg;(G9jnY= z&Q;tj%^v-FoRHV()vwIv#`n%kBAcq^MC;k�bFYvsBG2#R$S<`7uU25?qUCF7U20 z>LY%Y*W;b#nUzyUduw&yy1KWZIhw6{HVZ}@8npdNPaH+88L2b2?no0=l#SEu@cnl7(~$E1lM+!=0fr>D2pdlC%S@V0tJ;Y$$D9 zT1cmday40g(4V{&-|XD1Pp!kO z`B0(WEyMByYw{JYclzvPJO|RAEwEbi!}KlBBD6h@B&u%k_`APfZQED$(HkMDt^D-I z26%4){l=y5-TQ&WTPW)t_FkY-ZXZy4PJk3?d^*cZz2^oQWWB%Yop^_|bAyjc8@Kko z+}8K7FDU7IjajWMr~~j1f+yKAdhJ%P-#pyNwl6@}_dQ|_n$vHUZmZeTdw3mE zW2cC&SN{~L9ckuP)~|k|QxS7}6YnBde|Z8ZU(4$A_v7Vl_~DT{r>?7 Date: Fri, 30 Oct 2020 14:51:02 +0800 Subject: [PATCH 3/3] upload excels --- .gitignore | 1 - cve-py/newexcels/20.03-CVE-10-10.xlsx | Bin 0 -> 12859 bytes 2 files changed, 1 deletion(-) create mode 100644 cve-py/newexcels/20.03-CVE-10-10.xlsx diff --git a/.gitignore b/.gitignore index a622d50..bac0496 100644 --- a/.gitignore +++ b/.gitignore @@ -20,4 +20,3 @@ __pycache__ go.sum logs/ lastupdate.tmp -*.xlsx \ No newline at end of file diff --git a/cve-py/newexcels/20.03-CVE-10-10.xlsx b/cve-py/newexcels/20.03-CVE-10-10.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..67c3c08c98677dac89f2f5f3e30f53f8679c1f26 GIT binary patch literal 12859 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