package onvif import ( "encoding/xml" "errors" "io" "strings" ) var ErrInvalidResponse = errors.New("ONVIF 返回内容无法识别") type profileEnvelope struct { Profiles []struct { Token string `xml:"token,attr"` Name string `xml:"Name"` Encoder struct { Encoding string `xml:"Encoding"` Resolution struct { Width int `xml:"Width"` Height int `xml:"Height"` } `xml:"Resolution"` } `xml:"VideoEncoderConfiguration"` } `xml:"Body>GetProfilesResponse>Profiles"` } func parseProfiles(data []byte) ([]Profile, error) { var envelope profileEnvelope if err := xml.Unmarshal(data, &envelope); err != nil || len(envelope.Profiles) == 0 || len(envelope.Profiles) > 128 { return nil, ErrInvalidResponse } result := make([]Profile, 0, len(envelope.Profiles)) for _, p := range envelope.Profiles { if strings.TrimSpace(p.Token) == "" || len(p.Token) > 255 || len([]rune(p.Name)) > 255 || p.Encoder.Resolution.Width <= 0 || p.Encoder.Resolution.Width > 32768 || p.Encoder.Resolution.Height <= 0 || p.Encoder.Resolution.Height > 32768 || len(p.Encoder.Encoding) > 32 { continue } result = append(result, Profile{Token: p.Token, Name: p.Name, Width: p.Encoder.Resolution.Width, Height: p.Encoder.Resolution.Height, Encoding: p.Encoder.Encoding}) } if len(result) == 0 { return nil, ErrInvalidResponse } return result, nil } func parseElement(data []byte, parent, name string) (string, error) { decoder := xml.NewDecoder(strings.NewReader(string(data))) depth := 0 for { token, err := decoder.Token() if err != nil { if errors.Is(err, io.EOF) { return "", ErrInvalidResponse } return "", ErrInvalidResponse } switch value := token.(type) { case xml.StartElement: if parent == "" || value.Name.Local == parent { if value.Name.Local == parent { depth++ } } if (parent == "" || depth > 0) && value.Name.Local == name { var text string if err := decoder.DecodeElement(&text, &value); err != nil { return "", ErrInvalidResponse } return strings.TrimSpace(text), nil } case xml.EndElement: if value.Name.Local == parent && depth > 0 { depth-- } } } }