From 44c421983dd6f41e786f7ac68dd4b2655454f17a Mon Sep 17 00:00:00 2001 From: Georg Spar Date: Thu, 18 Aug 2022 15:01:17 +0200 Subject: [PATCH] zweiter Commit --- DocStract/file.go | 116 -------- DocStract/go.mod | 10 - DocStract/go.sum | 6 - DocStract/helpers.go | 20 -- DocStract/read.go | 64 ---- Testdaten/rtcinfo/220816_rtcinfo.txt | 39 +-- database/database.go | 428 +++++++++++++++++++++++++++ database/go.mod | 5 + database/go.sum | 2 + domain/domain.go | 8 + domain/go.mod | 3 + go.mod | 17 +- go.sum | 27 +- rtcinfo.msg | Bin 162304 -> 0 bytes rtcusertr.go | 187 +++++++++--- 15 files changed, 619 insertions(+), 313 deletions(-) delete mode 100644 DocStract/file.go delete mode 100644 DocStract/go.mod delete mode 100644 DocStract/go.sum delete mode 100644 DocStract/helpers.go delete mode 100644 DocStract/read.go create mode 100644 database/database.go create mode 100644 database/go.mod create mode 100644 database/go.sum create mode 100644 domain/domain.go create mode 100644 domain/go.mod delete mode 100644 rtcinfo.msg diff --git a/DocStract/file.go b/DocStract/file.go deleted file mode 100644 index 3eeb005..0000000 --- a/DocStract/file.go +++ /dev/null @@ -1,116 +0,0 @@ -package docstract - -import ( - "errors" - "io/ioutil" - "strings" -) - -//DocType is a wrapper for the type iota/enum -type DocType int - -const ( - //DocUnkown represents an unknown document type - DocUnkown = iota - - //DocPDF represents a pdf document type - DocPDF - - //DocX represents a microsoft docx document type - DocX - - //DocXLSX represents microsoft excel doc - DocXLSX - - //DocHTML represents an html document type - DocHTML -) - -//DocStract stores the binary data for extracted files, as well as the type and filename metadata -type DocStract struct { - Type DocType - FileName *string - Bytes []byte -} - -//SaveFile saves the file to the path, does not check if it's an unkown filetype only if it has a name -func (d *DocStract) SaveFile(path string) error { - if len(path) > 0 && path[len(path)-1] != '/' { - path += "/" - } - - if d.FileName == nil { - return errors.New("document does not have a filename cannot save") - } - - return ioutil.WriteFile(path+*(d.FileName), d.Bytes, 0644) -} - -//sets name to nil if cannot dertermine name and type to unkown -func (d *DocStract) getName() { - blocks := strings.Split(string(d.Bytes), "\n") - nameBlock := blocks[len(blocks)-1] - - chunks := strings.Split(nameBlock, ".") - - nameChunk := 0 - t := DocUnkown - - switch len(chunks[0]) { - case 0: //pdf - t = DocPDF - nameChunk = 2 - default: //html - switch { - case strings.Contains(chunks[0], "word"): //docx - nameChunk = 8 - t = DocX - break - case strings.Contains(chunks[2], "worksheets"): //xlsx - t = DocXLSX - for i := 3; i < len(chunks); i++ { - if strings.Contains(StripSeperators(chunks[i]), "xlsx") { - nameChunk = i + 1 - break - } - } - break - default: //html - t = DocHTML - } - } - - name := strings.TrimSpace(chunks[nameChunk]) - name = StripSeperators(name) - - switch t { - case DocPDF: - name += ".pdf" - name = name[3:] - d.Type = DocPDF - - case DocX: - name += ".docx" - name = name[3:] - d.Type = DocX - - case DocXLSX: - name += ".xlsx" - head := 0 - for i, b := range d.Bytes { - if i+1 < len(d.Bytes) && b == 'P' && d.Bytes[i+1] == 'K' { - head = i - break - } - } - name = name[3:] - d.Type = DocXLSX - d.Bytes = d.Bytes[head:] - - case DocHTML: - name += ".html" - d.Type = DocHTML - } - - d.FileName = &name -} diff --git a/DocStract/go.mod b/DocStract/go.mod deleted file mode 100644 index b50283f..0000000 --- a/DocStract/go.mod +++ /dev/null @@ -1,10 +0,0 @@ -module AUDIAG/rtcusertr/DocStract - -go 1.18 - -require ( - github.com/pkg/errors v0.9.1 - github.com/richardlehane/mscfb v1.0.4 -) - -require github.com/richardlehane/msoleps v1.0.1 // indirect diff --git a/DocStract/go.sum b/DocStract/go.sum deleted file mode 100644 index 4076a12..0000000 --- a/DocStract/go.sum +++ /dev/null @@ -1,6 +0,0 @@ -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM= -github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk= -github.com/richardlehane/msoleps v1.0.1 h1:RfrALnSNXzmXLbGct/P2b4xkFz4e8Gmj/0Vj9M9xC1o= -github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg= diff --git a/DocStract/helpers.go b/DocStract/helpers.go deleted file mode 100644 index e889aee..0000000 --- a/DocStract/helpers.go +++ /dev/null @@ -1,20 +0,0 @@ -package docstract - -//StripSeperators removes all the random 0 bytes -func StripSeperators(s string) string { - iBytes := []byte(s) - oBytes := []byte{} - - if len(iBytes) >= 3 { - offset := 0 - if iBytes[0] == iBytes[2] && iBytes[0] == byte(0) { - offset = 1 - } - - for i := offset; i < len(iBytes); i += 2 { - oBytes = append(oBytes, iBytes[i]) - } - } - - return string(oBytes) -} diff --git a/DocStract/read.go b/DocStract/read.go deleted file mode 100644 index 7eff446..0000000 --- a/DocStract/read.go +++ /dev/null @@ -1,64 +0,0 @@ -package docstract - -import ( - "bytes" - "strings" - "sync" - - "github.com/pkg/errors" - "github.com/richardlehane/mscfb" -) - -//Extract takes a .msg files binary data and returns an array of attachments and a count of how many files were extracted -func Extract(data []byte) (*[]*DocStract, int, error) { - - reader := bytes.NewReader(data) - - doc, err := mscfb.New(reader) - - if err != nil { - return nil, 0, errors.Wrap(err, "creating reader") - } - - files := []*DocStract{} - - { // Get all the attachments seperated to parse - attachment := false - file := 0 - for entry, err := doc.Next(); err == nil; entry, err = doc.Next() { - - if strings.Contains(entry.Name, "attach") { - files = append(files, &DocStract{}) - attachment = true - continue - } - if attachment && strings.Contains(entry.Name, "properties") { - attachment = false - file++ - continue - } - - if attachment { - buf := make([]byte, entry.Size) - i, _ := entry.Read(buf) - if i > 0 { - files[file].Bytes = append(files[file].Bytes, buf[:i]...) - } - } - } - } - - { //Determine FileType and FileName - wait := sync.WaitGroup{} - for _, doc := range files { - wait.Add(1) - go func(d *DocStract) { - d.getName() - wait.Done() - }(doc) - } - wait.Wait() - } - - return &files, len(files), nil -} diff --git a/Testdaten/rtcinfo/220816_rtcinfo.txt b/Testdaten/rtcinfo/220816_rtcinfo.txt index eaf7453..6321b40 100644 --- a/Testdaten/rtcinfo/220816_rtcinfo.txt +++ b/Testdaten/rtcinfo/220816_rtcinfo.txt @@ -1,4 +1,4 @@ -Von: extern.stefan.renatscher@audi.de +sERVUS Von: extern.stefan.renatscher@audi.de Gesendet: Dienstag, 16. August 2022 22:04 An: Spar, Georg (I/BT-O75); dbjyt0u@islcl011.in.audi.vwg; g6dt7ew@islcl011.in.audi.vwg Betreff: rtcinfo @@ -29,38 +29,11 @@ iclcx638: Laurenje 10 start vred-13.3 ### Format: Master[: allocated client 1 [[allocated client 2] [...]]] cae-lsf-BT: iclcx001 iclcx002 iclcx003 iclcx004 -cae-lsf-ED: iclcx438 iclcx439 iclcx440 iclcx441 iclcx442 iclcx443 iclcx444 iclcx445 iclcx446 iclcx447 iclcx458 -iclcx459 iclcx460 iclcx461 iclcx462 iclcx463 iclcx464 iclcx465 iclcx466 iclcx467 iclcx473 iclcx474 iclcx475 -iclcx476 iclcx477 iclcx498 iclcx509 iclcx510 iclcx511 iclcx512 iclcx513 -cae-lsf-EK: iclcx206 iclcx207 iclcx208 iclcx209 iclcx210 iclcx211 iclcx212 iclcx213 iclcx214 iclcx215 iclcx216 -iclcx217 iclcx218 iclcx219 iclcx220 iclcx221 iclcx222 iclcx223 iclcx224 iclcx225 iclcx226 iclcx227 iclcx228 -iclcx229 iclcx230 iclcx231 iclcx232 iclcx233 iclcx234 iclcx235 iclcx236 iclcx237 iclcx238 iclcx239 iclcx240 -iclcx241 iclcx242 iclcx243 iclcx244 iclcx245 iclcx246 iclcx247 iclcx248 iclcx249 iclcx250 iclcx251 iclcx252 -iclcx253 iclcx254 iclcx255 iclcx256 iclcx257 iclcx258 iclcx259 iclcx260 iclcx261 iclcx262 iclcx263 iclcx264 -iclcx265 iclcx266 iclcx267 iclcx268 iclcx269 iclcx270 iclcx271 iclcx272 iclcx273 iclcx274 iclcx275 iclcx276 -iclcx277 iclcx278 iclcx279 iclcx280 iclcx281 iclcx282 iclcx283 iclcx284 iclcx285 iclcx286 iclcx287 iclcx288 -iclcx289 iclcx290 iclcx291 -cae-lsf-GQ: iclcx292 iclcx293 iclcx294 iclcx295 iclcx296 iclcx297 iclcx298 iclcx299 iclcx300 iclcx301 -iclcx302 iclcx303 iclcx304 iclcx305 iclcx306 iclcx307 iclcx308 iclcx309 iclcx310 iclcx311 iclcx312 iclcx313 -iclcx314 iclcx315 iclcx316 iclcx317 iclcx318 iclcx319 iclcx320 iclcx321 iclcx322 iclcx323 iclcx324 iclcx325 -iclcx326 iclcx327 cae-lsf -cae-lsf-PG: iclcx005 iclcx006 iclcx007 iclcx008 iclcx009 iclcx010 iclcx011 iclcx012 iclcx013 iclcx014 iclcx015 -iclcx016 iclcx017 iclcx018 iclcx019 iclcx020 iclcx021 iclcx022 iclcx023 iclcx024 iclcx025 iclcx026 iclcx027 -iclcx028 iclcx029 iclcx030 iclcx031 iclcx032 iclcx033 iclcx034 iclcx035 iclcx036 iclcx037 iclcx038 iclcx039 -iclcx040 iclcx041 iclcx042 iclcx043 iclcx044 iclcx045 iclcx046 iclcx047 iclcx048 iclcx049 iclcx050 iclcx051 -iclcx052 iclcx054 iclcx055 iclcx056 iclcx057 iclcx058 iclcx060 iclcx061 iclcx062 iclcx063 iclcx064 iclcx065 -iclcx066 iclcx067 iclcx068 iclcx069 iclcx070 iclcx071 iclcx072 iclcx073 iclcx074 iclcx075 iclcx076 iclcx077 -iclcx078 iclcx079 iclcx080 iclcx081 iclcx082 iclcx083 iclcx084 iclcx085 iclcx086 iclcx087 iclcx088 iclcx089 -iclcx090 iclcx091 iclcx092 iclcx093 iclcx094 iclcx095 iclcx096 iclcx097 iclcx098 iclcx099 iclcx100 iclcx101 -iclcx102 iclcx103 iclcx104 iclcx105 iclcx106 iclcx107 iclcx108 iclcx109 iclcx110 iclcx111 iclcx112 iclcx113 -iclcx114 iclcx115 iclcx116 iclcx117 iclcx118 iclcx119 iclcx120 iclcx121 iclcx122 iclcx123 iclcx124 iclcx125 -iclcx126 iclcx127 iclcx128 iclcx129 iclcx130 iclcx131 iclcx132 iclcx133 iclcx134 iclcx135 iclcx136 iclcx137 -iclcx138 iclcx139 iclcx140 iclcx141 iclcx142 iclcx143 iclcx144 iclcx145 iclcx146 iclcx147 iclcx148 iclcx149 -iclcx150 iclcx151 iclcx152 iclcx153 iclcx154 iclcx155 iclcx156 iclcx157 iclcx158 iclcx159 iclcx160 iclcx161 -iclcx162 iclcx163 iclcx164 iclcx165 iclcx166 iclcx167 iclcx168 iclcx169 iclcx170 iclcx171 iclcx172 iclcx173 -iclcx174 iclcx175 iclcx176 iclcx177 iclcx178 iclcx179 iclcx180 iclcx181 iclcx182 iclcx183 iclcx184 iclcx185 -iclcx186 iclcx187 iclcx188 iclcx189 iclcx190 iclcx191 iclcx192 iclcx193 iclcx194 iclcx195 iclcx196 iclcx197 -iclcx198 iclcx199 iclcx200 iclcx201 iclcx202 iclcx203 iclcx204 iclcx205 +cae-lsf-ED: iclcx438 iclcx439 iclcx440 iclcx441 iclcx442 iclcx443 iclcx444 iclcx445 iclcx446 iclcx447 iclcx458 iclcx459 iclcx460 iclcx461 iclcx462 iclcx463 iclcx464 iclcx465 iclcx466 iclcx467 iclcx473 iclcx474 iclcx475 iclcx476 iclcx477 iclcx498 iclcx509 iclcx510 iclcx511 iclcx512 iclcx513 +cae-lsf-EK: iclcx206 iclcx207 iclcx208 iclcx209 iclcx210 iclcx211 iclcx212 iclcx213 iclcx214 iclcx215 iclcx216 iclcx217 iclcx218 iclcx219 iclcx220 iclcx221 iclcx222 iclcx223 iclcx224 iclcx225 iclcx226 iclcx227 iclcx228 iclcx229 iclcx230 iclcx231 iclcx232 iclcx233 iclcx234 iclcx235 iclcx236 iclcx237 iclcx238 iclcx239 iclcx240 iclcx241 iclcx242 iclcx243 iclcx244 iclcx245 iclcx246 iclcx247 iclcx248 iclcx249 iclcx250 iclcx251 iclcx252 iclcx253 iclcx254 iclcx255 iclcx256 iclcx257 iclcx258 iclcx259 iclcx260 iclcx261 iclcx262 iclcx263 iclcx264 iclcx265 iclcx266 iclcx267 iclcx268 iclcx269 iclcx270 iclcx271 iclcx272 iclcx273 iclcx274 iclcx275 iclcx276 iclcx277 iclcx278 iclcx279 iclcx280 iclcx281 iclcx282 iclcx283 iclcx284 iclcx285 iclcx286 iclcx287 iclcx288 iclcx289 iclcx290 iclcx291 +cae-lsf-GQ: iclcx292 iclcx293 iclcx294 iclcx295 iclcx296 iclcx297 iclcx298 iclcx299 iclcx300 iclcx301 iclcx302 iclcx303 iclcx304 iclcx305 iclcx306 iclcx307 iclcx308 iclcx309 iclcx310 iclcx311 iclcx312 iclcx313 iclcx314 iclcx315 iclcx316 iclcx317 iclcx318 iclcx319 iclcx320 iclcx321 iclcx322 iclcx323 iclcx324 iclcx325 iclcx326 iclcx327 +cae-lsf +cae-lsf-PG: iclcx005 iclcx006 iclcx007 iclcx008 iclcx009 iclcx010 iclcx011 iclcx012 iclcx013 iclcx014 iclcx015 iclcx016 iclcx017 iclcx018 iclcx019 iclcx020 iclcx021 iclcx022 iclcx023 iclcx024 iclcx025 iclcx026 iclcx027 iclcx028 iclcx029 iclcx030 iclcx031 iclcx032 iclcx033 iclcx034 iclcx035 iclcx036 iclcx037 iclcx038 iclcx039 iclcx040 iclcx041 iclcx042 iclcx043 iclcx044 iclcx045 iclcx046 iclcx047 iclcx048 iclcx049 iclcx050 iclcx051 iclcx052 iclcx054 iclcx055 iclcx056 iclcx057 iclcx058 iclcx060 iclcx061 iclcx062 iclcx063 iclcx064 iclcx065 iclcx066 iclcx067 iclcx068 iclcx069 iclcx070 iclcx071 iclcx072 iclcx073 iclcx074 iclcx075 iclcx076 iclcx077 iclcx078 iclcx079 iclcx080 iclcx081 iclcx082 iclcx083 iclcx084 iclcx085 iclcx086 iclcx087 iclcx088 iclcx089 iclcx090 iclcx091 iclcx092 iclcx093 iclcx094 iclcx095 iclcx096 iclcx097 iclcx098 iclcx099 iclcx100 iclcx101 iclcx102 iclcx103 iclcx104 iclcx105 iclcx106 iclcx107 iclcx108 iclcx109 iclcx110 iclcx111 iclcx112 iclcx113 iclcx114 iclcx115 iclcx116 iclcx117 iclcx118 iclcx119 iclcx120 iclcx121 iclcx122 iclcx123 iclcx124 iclcx125 iclcx126 iclcx127 iclcx128 iclcx129 iclcx130 iclcx131 iclcx132 iclcx133 iclcx134 iclcx135 iclcx136 iclcx137 iclcx138 iclcx139 iclcx140 iclcx141 iclcx142 iclcx143 iclcx144 iclcx145 iclcx146 iclcx147 iclcx148 iclcx149 iclcx150 iclcx151 iclcx152 iclcx153 iclcx154 iclcx155 iclcx156 iclcx157 iclcx158 iclcx159 iclcx160 iclcx161 iclcx162 iclcx163 iclcx164 iclcx165 iclcx166 iclcx167 iclcx168 iclcx169 iclcx170 iclcx171 iclcx172 iclcx173 iclcx174 iclcx175 iclcx176 iclcx177 iclcx178 iclcx179 iclcx180 iclcx181 iclcx182 iclcx183 iclcx184 iclcx185 iclcx186 iclcx187 iclcx188 iclcx189 iclcx190 iclcx191 iclcx192 iclcx193 iclcx194 iclcx195 iclcx196 iclcx197 iclcx198 iclcx199 iclcx200 iclcx201 iclcx202 iclcx203 iclcx204 iclcx205 iclcx601 iclcx602 iclcx603 diff --git a/database/database.go b/database/database.go new file mode 100644 index 0000000..484b4cb --- /dev/null +++ b/database/database.go @@ -0,0 +1,428 @@ +package database + +import ( + "database/sql" + "fmt" + "log" + + "AUDIAG/rtcusertr/domain" + + //"domain.go" + _ "github.com/go-sql-driver/mysql" +) + +var ( + dbConnection = "rtcusertrdbuser:hurtz3585@tcp(ubodroid-1:3306)/rtcusertrdb" + dbType = "mysql" +) + +// Tool Funktionen +func CreateTool(tool domain.Tools) (resTool domain.Tools, err error) { + conn, err := sql.Open(dbType, dbConnection) + if err != nil { + log.Println("Error while connecting DB: ", err) + } + log.Println("Verbindung hergestellt") + log.Println("Name = ", tool.Name) + defer conn.Close() + + res, err := conn.Exec("INSERT INTO tools VALUES(?,?)", tool.Id, tool.Name) + if err != nil { + log.Println("Error while executing insert statement", err) + } + lastId, err := res.LastInsertId() + tool.Id = uint(lastId) + resTool = tool + + return resTool, err +} + +func DeleteTool(toolId uint) (result, err error) { + conn, err := sql.Open(dbType, dbConnection) + if err != nil { + log.Println("Error while connecting DB: ", err) + } + log.Println("DB Verbindung hergestellt") + defer conn.Close() + + _, err = conn.Exec("DELETE FROM tools WHERE id = ?", toolId) + if err != nil { + log.Fatal("Error while executing DELETE statement", err) + } + return result, err +} + +func ShowTool() (toolsArray []domain.Tools, err error) { + conn, err := sql.Open(dbType, dbConnection) + if err != nil { + log.Println("Error while connecting DB: ", err) + } + log.Println("DB Verbindung hergestellt") + defer conn.Close() + + results, err := conn.Query("SELECT * FROM tools") + if err != nil { + log.Fatal("Error while executing SELECt statement", err) + } + + var tool domain.Tools + for results.Next() { + err = results.Scan(&tool.Id, &tool.Name) + if err != nil { + log.Fatal("Error: ", err) + } + toolsArray = append(toolsArray, tool) + } + return toolsArray, err +} + +func GetTool(id uint) (tool domain.Tools, err error) { + conn, err := sql.Open(dbType, dbConnection) + if err != nil { + log.Println("Error while connecting DB: ", err) + } + log.Println("DB Verbindung hergestellt") + defer conn.Close() + + results, err := conn.Query("SELECT * FROM tools WHERE id=?", id) + if err != nil { + log.Fatal("Error while executing SELECt statement", err) + } + for results.Next() { + err = results.Scan(&tool.Id, &tool.Name) + if err != nil { + log.Fatal("Error: ", err) + } + } + + return tool, err +} + +func UpdateTool(tool domain.Tools) (resTool domain.Tools, err error) { + conn, err := sql.Open(dbType, dbConnection) + if err != nil { + log.Println("Error while connecting DB: ", err) + } + log.Println("Verbindung hergestellt") + log.Println("Name = ", tool.Name) + defer conn.Close() + + _, err = conn.Exec("UPDATE tools SET name=? WHERE id=?", tool.Name, tool.Id) + if err != nil { + log.Println("Error while executing insert statement", err) + } + + resTool = tool + + return resTool, err +} + +// ZTyp Funktionen +func CreateZTyp(ztyp domain.ZTyp) (resZTyp domain.ZTyp, err error) { + conn, err := sql.Open(dbType, dbConnection) + if err != nil { + log.Println("Error while connecting DB: ", err) + } + log.Println("Verbindung hergestellt") + log.Println("Name = ", ztyp.Name) + defer conn.Close() + + res, err := conn.Exec("INSERT INTO ztyp VALUES(?,?,?)", ztyp.Id, ztyp.Name, ztyp.Laufzeit) + if err != nil { + log.Println("Error while executing insert statement", err) + } + lastId, err := res.LastInsertId() + ztyp.Id = uint(lastId) + resZTyp = ztyp + + return resZTyp, err +} + +func DeleteZTyp(ztypId uint) (result, err error) { + conn, err := sql.Open(dbType, dbConnection) + if err != nil { + log.Println("Error while connecting DB: ", err) + } + log.Println("DB Verbindung hergestellt") + defer conn.Close() + + _, err = conn.Exec("DELETE FROM ztyp WHERE id = ?", ztypId) + if err != nil { + log.Fatal("Error while executing DELETE statement", err) + } + return result, err +} + +func ShowZTyp() (ztypArray []domain.ZTyp, err error) { + conn, err := sql.Open(dbType, dbConnection) + if err != nil { + log.Println("Error while connecting DB: ", err) + } + log.Println("DB Verbindung hergestellt") + defer conn.Close() + + results, err := conn.Query("SELECT * FROM ztyp") + if err != nil { + log.Fatal("Error while executing SELECt statement", err) + } + + var ztyp domain.ZTyp + for results.Next() { + err = results.Scan(&ztyp.Id, &ztyp.Name, &ztyp.Laufzeit) + if err != nil { + log.Fatal("Error: ", err) + } + ztypArray = append(ztypArray, ztyp) + } + return ztypArray, err +} + +func GetZTyp(id uint) (ztyp domain.ZTyp, err error) { + conn, err := sql.Open(dbType, dbConnection) + if err != nil { + log.Println("Error while connecting DB: ", err) + } + log.Println("DB Verbindung hergestellt") + defer conn.Close() + + results, err := conn.Query("SELECT * FROM ztyp WHERE id=?", id) + if err != nil { + log.Fatal("Error while executing SELECt statement", err) + } + defer results.Close() + for results.Next() { + err = results.Scan(&ztyp.Id, &ztyp.Name, &ztyp.Laufzeit) + if err != nil { + if err == sql.ErrNoRows { + log.Println("No result found with this ID ", err) + return ztyp, fmt.Errorf("GetZTyp %d: no such ID", id) + } + log.Fatal("Error: ", err) + } + } + err = results.Err() + return ztyp, err +} + +func UpdateZTyp(ztyp domain.ZTyp) (resZTyp domain.ZTyp, err error) { + conn, err := sql.Open(dbType, dbConnection) + if err != nil { + log.Println("Error while connecting DB: ", err) + } + log.Println("Verbindung hergestellt") + log.Println("Name = ", ztyp.Name) + defer conn.Close() + + _, err = conn.Exec("UPDATE ztyp SET name=?, laufzeit=? WHERE id=?", ztyp.Name, ztyp.Laufzeit, ztyp.Id) + if err != nil { + log.Println("Error while executing insert statement", err) + } + + resZTyp = ztyp + + return resZTyp, err +} + +// Ablageort Funktionen +func CreateAblOrt(ablort domain.AblageOrt) (resAblOrt domain.AblageOrt, err error) { + conn, err := sql.Open(dbType, dbConnection) + if err != nil { + log.Println("Error while connecting DB: ", err) + } + log.Println("Verbindung hergestellt") + log.Println("Name = ", ablort.Name) + defer conn.Close() + + res, err := conn.Exec("INSERT INTO ablageort VALUES(?,?,?,?)", ablort.Id, ablort.Name, ablort.Url, ablort.Pfad) + if err != nil { + log.Println("Error while executing insert statement", err) + } + lastId, err := res.LastInsertId() + ablort.Id = uint(lastId) + resAblOrt = ablort + + return resAblOrt, err +} + +func DeleteAblOrt(ablortId uint) (result, err error) { + conn, err := sql.Open(dbType, dbConnection) + if err != nil { + log.Println("Error while connecting DB: ", err) + } + log.Println("DB Verbindung hergestellt") + defer conn.Close() + + _, err = conn.Exec("DELETE FROM ablageort WHERE id = ?", ablortId) + if err != nil { + log.Fatal("Error while executing DELETE statement", err) + } + return result, err +} + +func ShowAblOrt() (ablortArray []domain.AblageOrt, err error) { + conn, err := sql.Open(dbType, dbConnection) + if err != nil { + log.Println("Error while connecting DB: ", err) + } + log.Println("DB Verbindung hergestellt") + defer conn.Close() + + results, err := conn.Query("SELECT * FROM ablageort") + if err != nil { + log.Fatal("Error while executing SELECt statement", err) + } + + var ablort domain.AblageOrt + for results.Next() { + err = results.Scan(&ablort.Id, &ablort.Name, &ablort.Url, &ablort.Pfad) + if err != nil { + log.Fatal("Error: ", err) + } + ablortArray = append(ablortArray, ablort) + } + return ablortArray, err +} + +func GetAblOrt(id uint) (ablort domain.AblageOrt, err error) { + conn, err := sql.Open(dbType, dbConnection) + if err != nil { + log.Println("Error while connecting DB: ", err) + } + log.Println("DB Verbindung hergestellt") + defer conn.Close() + + results, err := conn.Query("SELECT * FROM ablageort WHERE id=?", id) + if err != nil { + log.Fatal("Error while executing SELECt statement", err) + } + for results.Next() { + err = results.Scan(&ablort.Id, &ablort.Name, &ablort.Url, &ablort.Pfad) + if err != nil { + log.Fatal("Error: ", err) + } + } + + return ablort, err +} + +func UpdateAblOrt(ablort domain.AblageOrt) (resAblOrt domain.AblageOrt, err error) { + conn, err := sql.Open(dbType, dbConnection) + if err != nil { + log.Println("Error while connecting DB: ", err) + } + log.Println("Verbindung hergestellt") + log.Println("Name = ", ablort.Name) + defer conn.Close() + + _, err = conn.Exec("UPDATE ablageort SET name=?, url=?, pfad=? WHERE id=?", ablort.Name, ablort.Url, ablort.Pfad, ablort.Id) + if err != nil { + log.Println("Error while executing insert statement", err) + } + + resAblOrt = ablort + + return resAblOrt, err +} + +// Zertifikat Funktionen +func CreateZert(zert domain.Zertifikat) (resZert domain.Zertifikat, err error) { + conn, err := sql.Open(dbType, dbConnection) + if err != nil { + log.Println("Error while connecting DB: ", err) + } + log.Println("Verbindung hergestellt") + log.Println("Name = ", zert.Name) + log.Println("Erstellungsdatum = ", zert.ErstellDat) + log.Println("Typ = ", zert.Typ) + defer conn.Close() + + res, err := conn.Exec("INSERT INTO zertifikat VALUES(?,?,?,?,?,?,?,?,?)", zert.Id, zert.Name, zert.Typ, zert.ErstellDat, zert.GueltigBis, zert.AblageOrt, zert.ErstelltMit, zert.Email, zert.Bemerkung) + if err != nil { + log.Println("Error while executing insert statement", err) + } + lastId, err := res.LastInsertId() + zert.Id = uint64(lastId) + resZert = zert + + return resZert, err +} + +func DeleteZert(zertId uint64) (result, err error) { + conn, err := sql.Open(dbType, dbConnection) + if err != nil { + log.Println("Error while connecting DB: ", err) + } + log.Println("DB Verbindung hergestellt") + defer conn.Close() + + _, err = conn.Exec("DELETE FROM zertifikat WHERE id = ?", zertId) + if err != nil { + log.Fatal("Error while executing DELETE statement", err) + } + return result, err +} + +func ShowZert() (zertArray []domain.Zertifikat, err error) { + conn, err := sql.Open(dbType, dbConnection) + if err != nil { + log.Println("Error while connecting DB: ", err) + } + log.Println("DB Verbindung hergestellt") + defer conn.Close() + + results, err := conn.Query("SELECT * FROM zertifikat") + if err != nil { + log.Fatal("Error while executing SELECt statement", err) + } + + var zert domain.Zertifikat + for results.Next() { + err = results.Scan(&zert.Id, &zert.Name, &zert.Typ, &zert.ErstellDat, &zert.GueltigBis, &zert.AblageOrt, &zert.ErstelltMit, &zert.Email, &zert.Bemerkung) + if err != nil { + log.Fatal("Error: ", err) + } + zertArray = append(zertArray, zert) + } + return zertArray, err +} + +func GetZert(id uint64) (zert domain.Zertifikat, err error) { + conn, err := sql.Open(dbType, dbConnection) + if err != nil { + log.Println("Error while connecting DB: ", err) + } + log.Println("DB Verbindung hergestellt") + defer conn.Close() + + results, err := conn.Query("SELECT * FROM zertifikat WHERE id=?", id) + if err != nil { + log.Fatal("Error while executing SELECt statement", err) + } + for results.Next() { + err = results.Scan(&zert.Id, &zert.Name, &zert.Typ, &zert.ErstellDat, &zert.GueltigBis, &zert.AblageOrt, &zert.ErstelltMit, &zert.Email, &zert.Bemerkung) + if err != nil { + log.Fatal("Error: ", err) + } + } + + return zert, err +} + +func UpdateZert(zert domain.Zertifikat) (resZert domain.Zertifikat, err error) { + conn, err := sql.Open(dbType, dbConnection) + if err != nil { + log.Println("Error while connecting DB: ", err) + } + log.Println("Verbindung hergestellt") + log.Println("Name = ", zert.Name) + defer conn.Close() + + _, err = conn.Exec("UPDATE zertifikat SET name=?, typ=?, erstellungsdatum=?, gueltigbis=?, ablageort=?, erstelltmit=?, email=?, bemerkung=? WHERE id=?", zert.Name, zert.Typ, zert.ErstellDat, zert.GueltigBis, zert.AblageOrt, zert.ErstelltMit, zert.Email, zert.Bemerkung, zert.Id) + if err != nil { + log.Println("Error while executing insert statement", err) + } + + resZert = zert + + return resZert, err +} diff --git a/database/go.mod b/database/go.mod new file mode 100644 index 0000000..8aa754f --- /dev/null +++ b/database/go.mod @@ -0,0 +1,5 @@ +module database.go + +go 1.18 + +require github.com/go-sql-driver/mysql v1.6.0 // indirect diff --git a/database/go.sum b/database/go.sum new file mode 100644 index 0000000..20c16d6 --- /dev/null +++ b/database/go.sum @@ -0,0 +1,2 @@ +github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= +github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= diff --git a/domain/domain.go b/domain/domain.go new file mode 100644 index 0000000..365b67e --- /dev/null +++ b/domain/domain.go @@ -0,0 +1,8 @@ +package domain + +type KnotenE struct { + Id uint `json:"id"` + Fachbereich string `json:"fachbereich"` + Anzahl int `json:"anzahl"` + Tag string `json:"tag"` +} diff --git a/domain/go.mod b/domain/go.mod new file mode 100644 index 0000000..52bd6f4 --- /dev/null +++ b/domain/go.mod @@ -0,0 +1,3 @@ +module domain.go + +go 1.18 diff --git a/go.mod b/go.mod index 9d8c799..cf6d3fd 100644 --- a/go.mod +++ b/go.mod @@ -2,17 +2,10 @@ module rtcusertr.go go 1.18 -require ( - AUDIAG/rtcusertr/DocStract v0.0.0-00010101000000-000000000000 - github.com/sirupsen/logrus v1.4.2 -) +require github.com/sirupsen/logrus v1.9.0 -require ( - github.com/konsorten/go-windows-terminal-sequences v1.0.1 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/richardlehane/mscfb v1.0.4 // indirect - github.com/richardlehane/msoleps v1.0.1 // indirect - golang.org/x/sys v0.0.0-20190422165155-953cdadca894 // indirect -) +require golang.org/x/sys v0.0.0-20220817070843-5a390386f1f2 // indirect -replace AUDIAG/rtcusertr/DocStract => ./DocStract +replace AUDIAG/rtcusertr/database => ./database + +replace AUDIAG/rtcusertr/domain => ./domain diff --git a/go.sum b/go.sum index 7c0fe5b..0ded3cc 100644 --- a/go.sum +++ b/go.sum @@ -1,19 +1,16 @@ +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/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -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/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM= -github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk= -github.com/richardlehane/msoleps v1.0.1 h1:RfrALnSNXzmXLbGct/P2b4xkFz4e8Gmj/0Vj9M9xC1o= -github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg= -github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220817070843-5a390386f1f2 h1:fqTvyMIIj+HRzMmnzr9NtpHP6uVpvB5fkHcgPDC4nu8= +golang.org/x/sys v0.0.0-20220817070843-5a390386f1f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/rtcinfo.msg b/rtcinfo.msg deleted file mode 100644 index ed6b3a511977830a23978bb6c66e84f07ed1e40a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 162304 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 diff --git a/rtcusertr.go b/rtcusertr.go index 81a9235..d2ee88d 100644 --- a/rtcusertr.go +++ b/rtcusertr.go @@ -1,12 +1,16 @@ package main import ( - docstract "AUDIAG/rtcusertr/DocStract" + "AUDIAG/rtcusertr/database" + "AUDIAG/rtcusertr/domain" + "encoding/json" "fmt" "io/ioutil" + "net/http" "os" - "strings" + "strconv" + "github.com/gorilla/mux" "github.com/sirupsen/logrus" ) @@ -21,40 +25,149 @@ type Master struct { } func main() { - path, _ := os.Getwd() - pathTo := path + "Testdaten/rtcinfo" - pathFiles, _ := ioutil.ReadDir(pathTo) - - for _, file := range pathFiles { - if file.Name()[len(file.Name())-4:] != ".txt" { - continue - } - logrus.Infof("reading %s", file.Name()) - - data, err := ioutil.ReadFile(file.Name()) - - if err != nil { - panic(err) - } - - files, count, err := docstract.Extract(data) - if err != nil { - panic(err) - } - - fmt.Println("Found ", count, " files") - - for i, document := range *files { - if !strings.Contains(*document.FileName, ".") { - s := fmt.Sprintf("%d.txt", i) - document.FileName = &s - } - - if err := document.SaveFile(""); err != nil { - logrus.Warn(err) - } else { - logrus.Infof("Saved file %s", *document.FileName) - } - } + + fmt.Println("This is rtcusertrd!!!") + logFile, err := os.OpenFile("rtcusertr.log", os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644) + if err != nil { + logrus.Fatal(err) + } + + defer logFile.Close() + + logrus.SetOutput(logFile) + logrus.SetLevel(logrus.InfoLevel) + r := mux.NewRouter() + + r.HandleFunc("/api/kn", createKnotenEHandler).Methods("POST", "OPTIONS") + r.HandleFunc("/api/kn/{id:[0-9]+}", deleteKnotenEHandler).Methods("DELETE", "OPTIONS") + r.HandleFunc("/api/kn", showKnotenEHandler).Methods("GET", "OPTIONS") + r.HandleFunc("/api/kn/{id:[0-9]+}", getKnotenEHandler).Methods("GET", "OPTIONS") + r.HandleFunc("/api/kn/{id:[0-9]+}", updateKnotenEHandler).Methods("PUT", "OPTIONS") + + http.Handle("/", r) + r.Use(mux.CORSMethodMiddleware(r)) + http.ListenAndServe(":8081", r) + logrus.Info("running on localhost, Port 8081") + +} + +func createKnotenEHandler(writer http.ResponseWriter, req *http.Request) { + writer.Header().Set("Access-Control-Allow-Origin", "*") + if req.Method == http.MethodOptions { + return + } + body, err := ioutil.ReadAll(req.Body) + if err != nil { + writer.WriteHeader(http.StatusBadRequest) + } + var knoten domain.KnotenE + json.Unmarshal(body, &knoten) + logrus.Println("Name= ", knoten.Fachbereich) + logrus.Info("creating new Knoten-Eintrag", knoten.Fachbereich) + res, err := database.CreateTool(knoten) + if err != nil { + writer.WriteHeader(http.StatusInternalServerError) + } + + b, err := json.Marshal(res) + if err != nil { + logrus.Fatal("Error: ", err) + } + + location := fmt.Sprintf("%s/%d", req.URL.String(), res.Id) + writer.Header().Set("Location:", location) + writer.Header().Set("Content-Type", "application/json") + writer.WriteHeader(http.StatusCreated) + writer.Write(b) +} + +func deleteToolsHandler(writer http.ResponseWriter, req *http.Request) { + writer.Header().Set("Access-Control-Allow-Origin", "*") + if req.Method == http.MethodOptions { + return + } + toolsId, _ := strconv.ParseUint(mux.Vars(req)["id"], 10, 0) + log.Info("Deleting tool with ID", toolsId) + _, err := database.DeleteTool(uint(toolsId)) + if err != nil { + log.Fatal("Error: Delete could not be executed", err) + } + writer.WriteHeader(http.StatusNoContent) +} + +func showToolsHandler(writer http.ResponseWriter, req *http.Request) { + writer.Header().Set("Access-Control-Allow-Origin", "*") + if req.Method == http.MethodOptions { + return + } + res, err := database.ShowTool() + if err != nil { + log.Fatal("Error: Tool can't be shown ", err) + writer.WriteHeader(http.StatusInternalServerError) + } + + b, err := json.Marshal(res) + if err != nil { + log.Fatal("Error: ", err) + } + + location := req.URL.String() + writer.Header().Set("Location:", location) + writer.Header().Set("Content-Type", "application/json") + writer.WriteHeader(http.StatusOK) + writer.Write(b) +} + +func getToolsHandler(writer http.ResponseWriter, req *http.Request) { + writer.Header().Set("Access-Control-Allow-Origin", "*") + if req.Method == http.MethodOptions { + return + } + toolId, _ := strconv.ParseUint(mux.Vars(req)["id"], 10, 0) + res, err := database.GetTool(uint(toolId)) + if err != nil { + log.Fatal("Error: Tool can't be shown ", err) + writer.WriteHeader(http.StatusInternalServerError) + } + + b, err := json.Marshal(res) + if err != nil { + log.Fatal("Error: ", err) + } + + location := req.URL.String() + writer.Header().Set("Location:", location) + writer.Header().Set("Content-Type", "application/json") + writer.WriteHeader(http.StatusOK) + writer.Write(b) +} + +func updateToolsHandler(writer http.ResponseWriter, req *http.Request) { + writer.Header().Set("Access-Control-Allow-Origin", "*") + if req.Method == http.MethodOptions { + return } + body, err := ioutil.ReadAll(req.Body) + if err != nil { + writer.WriteHeader(http.StatusBadRequest) + } + var tool domain.Tools + json.Unmarshal(body, &tool) + log.Println("Name = ", tool.Name) + log.Info("updating Tool", tool.Name) + res, err := database.UpdateTool(tool) + if err != nil { + writer.WriteHeader(http.StatusInternalServerError) + } + + b, err := json.Marshal(res) + if err != nil { + log.Fatal("Error: ", err) + } + + location := fmt.Sprintf("%s/%d", req.URL.String(), res.Id) + writer.Header().Set("Location:", location) + writer.Header().Set("Content-Type", "application/json") + writer.WriteHeader(http.StatusOK) + writer.Write(b) }