go-tg-screenshot-bot
292 строки · 6.5 Кб
1package dbus2
3import (4"encoding/binary"5"io"6"reflect"7)
8
9type decoder struct {10in io.Reader11order binary.ByteOrder12pos int13fds []int14}
15
16// newDecoder returns a new decoder that reads values from in. The input is
17// expected to be in the given byte order.
18func newDecoder(in io.Reader, order binary.ByteOrder, fds []int) *decoder {19dec := new(decoder)20dec.in = in21dec.order = order22dec.fds = fds23return dec24}
25
26// align aligns the input to the given boundary and panics on error.
27func (dec *decoder) align(n int) {28if dec.pos%n != 0 {29newpos := (dec.pos + n - 1) & ^(n - 1)30empty := make([]byte, newpos-dec.pos)31if _, err := io.ReadFull(dec.in, empty); err != nil {32panic(err)33}34dec.pos = newpos35}36}
37
38// Calls binary.Read(dec.in, dec.order, v) and panics on read errors.
39func (dec *decoder) binread(v interface{}) {40if err := binary.Read(dec.in, dec.order, v); err != nil {41panic(err)42}43}
44
45func (dec *decoder) Decode(sig Signature) (vs []interface{}, err error) {46defer func() {47var ok bool48v := recover()49if err, ok = v.(error); ok {50if err == io.EOF || err == io.ErrUnexpectedEOF {51err = FormatError("unexpected EOF")52}53}54}()55vs = make([]interface{}, 0)56s := sig.str57for s != "" {58err, rem := validSingle(s, &depthCounter{})59if err != nil {60return nil, err61}62v := dec.decode(s[:len(s)-len(rem)], 0)63vs = append(vs, v)64s = rem65}66return vs, nil67}
68
69func (dec *decoder) decode(s string, depth int) interface{} {70dec.align(alignment(typeFor(s)))71switch s[0] {72case 'y':73var b [1]byte74if _, err := dec.in.Read(b[:]); err != nil {75panic(err)76}77dec.pos++78return b[0]79case 'b':80i := dec.decode("u", depth).(uint32)81switch {82case i == 0:83return false84case i == 1:85return true86default:87panic(FormatError("invalid value for boolean"))88}89case 'n':90var i int1691dec.binread(&i)92dec.pos += 293return i94case 'i':95var i int3296dec.binread(&i)97dec.pos += 498return i99case 'x':100var i int64101dec.binread(&i)102dec.pos += 8103return i104case 'q':105var i uint16106dec.binread(&i)107dec.pos += 2108return i109case 'u':110var i uint32111dec.binread(&i)112dec.pos += 4113return i114case 't':115var i uint64116dec.binread(&i)117dec.pos += 8118return i119case 'd':120var f float64121dec.binread(&f)122dec.pos += 8123return f124case 's':125length := dec.decode("u", depth).(uint32)126b := make([]byte, int(length)+1)127if _, err := io.ReadFull(dec.in, b); err != nil {128panic(err)129}130dec.pos += int(length) + 1131return string(b[:len(b)-1])132case 'o':133return ObjectPath(dec.decode("s", depth).(string))134case 'g':135length := dec.decode("y", depth).(byte)136b := make([]byte, int(length)+1)137if _, err := io.ReadFull(dec.in, b); err != nil {138panic(err)139}140dec.pos += int(length) + 1141sig, err := ParseSignature(string(b[:len(b)-1]))142if err != nil {143panic(err)144}145return sig146case 'v':147if depth >= 64 {148panic(FormatError("input exceeds container depth limit"))149}150var variant Variant151sig := dec.decode("g", depth).(Signature)152if len(sig.str) == 0 {153panic(FormatError("variant signature is empty"))154}155err, rem := validSingle(sig.str, &depthCounter{})156if err != nil {157panic(err)158}159if rem != "" {160panic(FormatError("variant signature has multiple types"))161}162variant.sig = sig163variant.value = dec.decode(sig.str, depth+1)164return variant165case 'h':166idx := dec.decode("u", depth).(uint32)167if int(idx) < len(dec.fds) {168return UnixFD(dec.fds[idx])169}170return UnixFDIndex(idx)171case 'a':172if len(s) > 1 && s[1] == '{' {173ksig := s[2:3]174vsig := s[3 : len(s)-1]175v := reflect.MakeMap(reflect.MapOf(typeFor(ksig), typeFor(vsig)))176if depth >= 63 {177panic(FormatError("input exceeds container depth limit"))178}179length := dec.decode("u", depth).(uint32)180// Even for empty maps, the correct padding must be included181dec.align(8)182spos := dec.pos183for dec.pos < spos+int(length) {184dec.align(8)185if !isKeyType(v.Type().Key()) {186panic(InvalidTypeError{v.Type()})187}188kv := dec.decode(ksig, depth+2)189vv := dec.decode(vsig, depth+2)190v.SetMapIndex(reflect.ValueOf(kv), reflect.ValueOf(vv))191}192return v.Interface()193}194if depth >= 64 {195panic(FormatError("input exceeds container depth limit"))196}197sig := s[1:]198length := dec.decode("u", depth).(uint32)199// capacity can be determined only for fixed-size element types200var capacity int201if s := sigByteSize(sig); s != 0 {202capacity = int(length) / s203}204v := reflect.MakeSlice(reflect.SliceOf(typeFor(sig)), 0, capacity)205// Even for empty arrays, the correct padding must be included206align := alignment(typeFor(s[1:]))207if len(s) > 1 && s[1] == '(' {208//Special case for arrays of structs209//structs decode as a slice of interface{} values210//but the dbus alignment does not match this211align = 8212}213dec.align(align)214spos := dec.pos215for dec.pos < spos+int(length) {216ev := dec.decode(s[1:], depth+1)217v = reflect.Append(v, reflect.ValueOf(ev))218}219return v.Interface()220case '(':221if depth >= 64 {222panic(FormatError("input exceeds container depth limit"))223}224dec.align(8)225v := make([]interface{}, 0)226s = s[1 : len(s)-1]227for s != "" {228err, rem := validSingle(s, &depthCounter{})229if err != nil {230panic(err)231}232ev := dec.decode(s[:len(s)-len(rem)], depth+1)233v = append(v, ev)234s = rem235}236return v237default:238panic(SignatureError{Sig: s})239}240}
241
242// sigByteSize tries to calculates size of the given signature in bytes.
243//
244// It returns zero when it can't, for example when it contains non-fixed size
245// types such as strings, maps and arrays that require reading of the transmitted
246// data, for that we would need to implement the unread method for Decoder first.
247func sigByteSize(sig string) int {248var total int249for offset := 0; offset < len(sig); {250switch sig[offset] {251case 'y':252total += 1253offset += 1254case 'n', 'q':255total += 2256offset += 1257case 'b', 'i', 'u', 'h':258total += 4259offset += 1260case 'x', 't', 'd':261total += 8262offset += 1263case '(':264i := 1265depth := 1266for i < len(sig[offset:]) && depth != 0 {267if sig[offset+i] == '(' {268depth++269} else if sig[offset+i] == ')' {270depth--271}272i++273}274s := sigByteSize(sig[offset+1 : offset+i-1])275if s == 0 {276return 0277}278total += s279offset += i280default:281return 0282}283}284return total285}
286
287// A FormatError is an error in the wire format.
288type FormatError string289
290func (e FormatError) Error() string {291return "dbus: wire format error: " + string(e)292}
293