Migrate report parsing code to library
Change-Id: I156290b8bf7fff314266f62980eb100af600198a
This commit is contained in:
105
dmarc.go
105
dmarc.go
@@ -1,105 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
type DateRange struct {
|
||||
// TODO: should be int but Y! trailing spaces
|
||||
Begin string `xml:"begin"`
|
||||
End string `xml:"end"`
|
||||
}
|
||||
|
||||
type ReportMetadata struct {
|
||||
OrgName string `xml:"org_name"`
|
||||
Email string `xml:"email"`
|
||||
ExtraContact string `xml:"extra_contact_info"`
|
||||
ReportId string `xml:"report_id"`
|
||||
DateRange DateRange `xml:"date_range"`
|
||||
}
|
||||
|
||||
type PolicyPublished struct {
|
||||
Domain string `xml:"domain"`
|
||||
Adkim string `xml:"adkim"`
|
||||
Aspf string `xml:"aspf"`
|
||||
Policy string `xml:"p"`
|
||||
SubdomainPolicy string `xml:"sp"`
|
||||
Percentage int `xml:"pct"`
|
||||
}
|
||||
|
||||
type PolicyEvaluated struct {
|
||||
Disposition string `xml:"disposition"`
|
||||
Dkim string `xml:"dkim"`
|
||||
Spf string `xml:"spf"`
|
||||
}
|
||||
|
||||
type Row struct {
|
||||
// TODO: Figure out how to cast this to an IP
|
||||
SourceIp string `xml:"source_ip"`
|
||||
Count int `xml:"count"`
|
||||
PolicyEvaluated PolicyEvaluated `xml:"policy_evaluated"`
|
||||
}
|
||||
|
||||
type Identifiers struct {
|
||||
HeaderFrom string `xml:"header_from"`
|
||||
}
|
||||
|
||||
type AuthResult struct {
|
||||
// FIXME: this could be either DKIM or SPF
|
||||
XMLName xml.Name
|
||||
Domain string `xml:"domain"`
|
||||
Result string `xml:"result"`
|
||||
}
|
||||
|
||||
type AuthResults struct {
|
||||
AuthResult []AuthResult `xml:",any"`
|
||||
}
|
||||
|
||||
type Record struct {
|
||||
Row Row `xml:"row"`
|
||||
Identifiers Identifiers `xml:"identifiers"`
|
||||
AuthResults AuthResults `xml:"auth_results"`
|
||||
}
|
||||
|
||||
type FeedbackReport struct {
|
||||
XMLName xml.Name `xml:"feedback"`
|
||||
ReportMetadata ReportMetadata `xml:"report_metadata"`
|
||||
PolicyPublished PolicyPublished `xml:"policy_published"`
|
||||
Record []Record `xml:"record"`
|
||||
}
|
||||
|
||||
xmlFile, err := os.Open("/Users/gcolburn/go/src/github.com/gc1code/dmarcparser/samples/yahoo.xml") // For read access.
|
||||
if err != nil {
|
||||
fmt.Printf("os error: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
defer xmlFile.Close()
|
||||
|
||||
decoder := xml.NewDecoder(xmlFile)
|
||||
var inElement string
|
||||
for {
|
||||
t, _ := decoder.Token()
|
||||
if t == nil {
|
||||
break
|
||||
}
|
||||
switch se := t.(type) {
|
||||
case xml.StartElement:
|
||||
inElement = se.Name.Local
|
||||
if inElement == "feedback" {
|
||||
f := FeedbackReport{}
|
||||
|
||||
xmlerr := decoder.DecodeElement(&f, &se)
|
||||
if xmlerr != nil {
|
||||
fmt.Printf("decode error: %v", xmlerr)
|
||||
}
|
||||
fmt.Printf("XMLName: %#v\n", f)
|
||||
}
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
98
dmarc/report.go
Normal file
98
dmarc/report.go
Normal file
@@ -0,0 +1,98 @@
|
||||
package dmarc
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"io"
|
||||
)
|
||||
|
||||
type DateRange struct {
|
||||
// TODO: should be int but Y! trailing spaces
|
||||
Begin string `xml:"begin"`
|
||||
End string `xml:"end"`
|
||||
}
|
||||
|
||||
type ReportMetadata struct {
|
||||
OrgName string `xml:"org_name"`
|
||||
Email string `xml:"email"`
|
||||
ExtraContact string `xml:"extra_contact_info"`
|
||||
ReportId string `xml:"report_id"`
|
||||
DateRange DateRange `xml:"date_range"`
|
||||
}
|
||||
|
||||
type PolicyPublished struct {
|
||||
Domain string `xml:"domain"`
|
||||
Adkim string `xml:"adkim"`
|
||||
Aspf string `xml:"aspf"`
|
||||
Policy string `xml:"p"`
|
||||
SubdomainPolicy string `xml:"sp"`
|
||||
Percentage int `xml:"pct"`
|
||||
}
|
||||
|
||||
type PolicyEvaluated struct {
|
||||
Disposition string `xml:"disposition"`
|
||||
Dkim string `xml:"dkim"`
|
||||
Spf string `xml:"spf"`
|
||||
}
|
||||
|
||||
type Row struct {
|
||||
// TODO: Figure out how to cast this to an IP
|
||||
SourceIp string `xml:"source_ip"`
|
||||
Count int `xml:"count"`
|
||||
PolicyEvaluated PolicyEvaluated `xml:"policy_evaluated"`
|
||||
}
|
||||
|
||||
type Identifiers struct {
|
||||
HeaderFrom string `xml:"header_from"`
|
||||
}
|
||||
|
||||
type AuthResult struct {
|
||||
// FIXME: this could be either DKIM or SPF
|
||||
XMLName xml.Name
|
||||
Domain string `xml:"domain"`
|
||||
Result string `xml:"result"`
|
||||
}
|
||||
|
||||
type AuthResults struct {
|
||||
AuthResult []AuthResult `xml:",any"`
|
||||
}
|
||||
|
||||
type Record struct {
|
||||
Row Row `xml:"row"`
|
||||
Identifiers Identifiers `xml:"identifiers"`
|
||||
AuthResults AuthResults `xml:"auth_results"`
|
||||
}
|
||||
|
||||
type FeedbackReport struct {
|
||||
XMLName xml.Name `xml:"feedback"`
|
||||
ReportMetadata ReportMetadata `xml:"report_metadata"`
|
||||
PolicyPublished PolicyPublished `xml:"policy_published"`
|
||||
Record []Record `xml:"record"`
|
||||
}
|
||||
|
||||
func ParseReader(xmlFileReader io.Reader) FeedbackReport {
|
||||
var f FeedbackReport
|
||||
|
||||
decoder := xml.NewDecoder(xmlFileReader)
|
||||
var inElement string
|
||||
|
||||
for {
|
||||
t, _ := decoder.Token()
|
||||
if t == nil {
|
||||
break
|
||||
}
|
||||
switch se := t.(type) {
|
||||
case xml.StartElement:
|
||||
inElement = se.Name.Local
|
||||
if inElement == "feedback" {
|
||||
decoder.DecodeElement(&f, &se)
|
||||
// xmlerr := decoder.DecodeElement(&f, &se)
|
||||
// if xmlerr != nil {
|
||||
// fmt.Printf("decode error: %v\n", xmlerr)
|
||||
// }
|
||||
// fmt.Printf("XMLName: %#v\n", f)
|
||||
}
|
||||
default:
|
||||
}
|
||||
}
|
||||
return f
|
||||
}
|
||||
30
dmarcparser.go
Normal file
30
dmarcparser.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"github.com/gc1code/dmarcparser/dmarc"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
var filename = flag.String("filename", "none", "Path to DMARC Aggregate Report XML")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
if *filename == "none" {
|
||||
fmt.Printf("XML File required.\n")
|
||||
return
|
||||
}
|
||||
|
||||
xmlFile, err := os.Open(*filename) // For read access.
|
||||
if err != nil {
|
||||
fmt.Printf("os error: %v\n", err)
|
||||
return
|
||||
}
|
||||
defer xmlFile.Close()
|
||||
|
||||
feedbackReport := dmarc.ParseReader(xmlFile)
|
||||
fmt.Printf("XMLName: %#v\n", feedbackReport)
|
||||
}
|
||||
Reference in New Issue
Block a user