pax_global_header00006660000000000000000000000064145336053140014516gustar00rootroot0000000000000052 comment=94c92a6d5d2b2591683a3a50f94b333a49b99220 goipp-1.1.0/000077500000000000000000000000001453360531400126335ustar00rootroot00000000000000goipp-1.1.0/.gitignore000066400000000000000000000000231453360531400146160ustar00rootroot00000000000000ipp-usb tags *.swp goipp-1.1.0/LICENSE000066400000000000000000000024571453360531400136500ustar00rootroot00000000000000BSD 2-Clause License Copyright (c) 2020, Alexander Pevzner All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. goipp-1.1.0/Makefile000066400000000000000000000000641453360531400142730ustar00rootroot00000000000000all: -gotags -R . > tags go build test: go test goipp-1.1.0/README.md000066400000000000000000000015321453360531400141130ustar00rootroot00000000000000# goipp [![godoc.org](https://godoc.org/github.com/OpenPrinting/goipp?status.svg)](http://godoc.org/github.com/OpenPrinting/goipp) ![GitHub](https://img.shields.io/github/license/OpenPrinting/goipp) [![Go Report Card](https://goreportcard.com/badge/github.com/OpenPrinting/goipp)](https://goreportcard.com/report/github.com/OpenPrinting/goipp) The goipp library is fairly complete implementation of IPP core protocol in pure Go. Essentially, it is IPP messages parser/composer. Transport is not implemented here, because Go standard library has an excellent built-in HTTP client, and it doesn't make a lot of sense to wrap it here. High-level requests, like "print a file" are also not implemented, only the low-level stuff. All documentation is on godoc.org -- follow the link above. Pull requests are welcomed, assuming they don't break existing API. goipp-1.1.0/_config.yml000066400000000000000000000000351453360531400147600ustar00rootroot00000000000000theme: jekyll-theme-architectgoipp-1.1.0/attr.go000066400000000000000000000040211453360531400141310ustar00rootroot00000000000000/* Go IPP - IPP core protocol implementation in pure Go * * Copyright (C) 2020 and up by Alexander Pevzner (pzz@apevzner.com) * See LICENSE for license terms and conditions * * Message attributes */ package goipp import ( "fmt" ) // Attributes represents a slice of attributes type Attributes []Attribute // Add Attribute to Attributes func (attrs *Attributes) Add(attr Attribute) { *attrs = append(*attrs, attr) } // Equal checks that attrs and attrs2 are equal func (attrs Attributes) Equal(attrs2 Attributes) bool { if len(attrs) != len(attrs2) { return false } for i, attr := range attrs { attr2 := attrs2[i] if !attr.Equal(attr2) { return false } } return true } // Attribute represents a single attribute, which consist of // the Name and one or more Values type Attribute struct { Name string // Attribute name Values Values // Slice of values } // MakeAttribute makes Attribute with single value func MakeAttribute(name string, tag Tag, value Value) Attribute { attr := Attribute{Name: name} attr.Values.Add(tag, value) return attr } // Equal checks that Attribute is equal to another Attribute // (i.e., names are the same and values are equal) func (a Attribute) Equal(a2 Attribute) bool { return a.Name == a2.Name && a.Values.Equal(a2.Values) } // Unpack attribute value from its wire representation func (a *Attribute) unpack(tag Tag, value []byte) error { var err error var val Value switch tag.Type() { case TypeVoid, TypeCollection: val = Void{} case TypeInteger: val = Integer(0) case TypeBoolean: val = Boolean(false) case TypeString: val = String("") case TypeDateTime: val = Time{} case TypeResolution: val = Resolution{} case TypeRange: val = Range{} case TypeTextWithLang: val = TextWithLang{} case TypeBinary: val = Binary(nil) default: panic(fmt.Sprintf("(Attribute) uppack(): tag=%s type=%s", tag, tag.Type())) } val, err = val.decode(value) if err == nil { a.Values.Add(tag, val) } else { err = fmt.Errorf("%s: %s", tag, err) } return err } goipp-1.1.0/const.go000066400000000000000000000006351453360531400143140ustar00rootroot00000000000000/* Go IPP - IPP core protocol implementation in pure Go * * Copyright (C) 2020 and up by Alexander Pevzner (pzz@apevzner.com) * See LICENSE for license terms and conditions * * Various constants */ package goipp const ( // ContentType is the HTTP content type for IPP messages ContentType = "application/ipp" // msgPrintIndent used for indentation by message pretty-printer msgPrintIndent = " " ) goipp-1.1.0/decoder.go000066400000000000000000000230241453360531400145700ustar00rootroot00000000000000/* Go IPP - IPP core protocol implementation in pure Go * * Copyright (C) 2020 and up by Alexander Pevzner (pzz@apevzner.com) * See LICENSE for license terms and conditions * * IPP Message decoder */ package goipp import ( "encoding/binary" "errors" "fmt" "io" ) // DecoderOptions represents message decoder options type DecoderOptions struct { // EnableWorkarounds, if set to true, enables various workarounds // for decoding IPP messages that violate IPP protocol specification // // Currently it includes the following workarounds: // * Pantum M7300FDW violates collection encoding rules. // Instead of using TagMemberName, it uses named attributes // within the collection // // The list of implemented workarounds may grow in the // future EnableWorkarounds bool } // messageDecoder represents Message decoder type messageDecoder struct { in io.Reader // Input stream off int // Offset of last read cnt int // Count of read bytes opt DecoderOptions // Options } // Decode the message func (md *messageDecoder) decode(m *Message) error { // Wire format: // // 2 bytes: Version // 2 bytes: Code (Operation or Status) // 4 bytes: RequestID // variable: attributes // 1 byte: TagEnd // Parse message header var err error m.Version, err = md.decodeVersion() if err == nil { m.Code, err = md.decodeCode() } if err == nil { m.RequestID, err = md.decodeU32() } // Now parse attributes done := false var group *Attributes var attr Attribute var prev *Attribute for err == nil && !done { var tag Tag tag, err = md.decodeTag() if err != nil { break } if tag.IsDelimiter() { prev = nil } if tag.IsGroup() { m.Groups.Add(Group{tag, nil}) } switch tag { case TagZero: err = errors.New("Invalid tag 0") case TagEnd: done = true case TagOperationGroup: group = &m.Operation case TagJobGroup: group = &m.Job case TagPrinterGroup: group = &m.Printer case TagUnsupportedGroup: group = &m.Unsupported case TagSubscriptionGroup: group = &m.Subscription case TagEventNotificationGroup: group = &m.EventNotification case TagResourceGroup: group = &m.Resource case TagDocumentGroup: group = &m.Document case TagSystemGroup: group = &m.System case TagFuture11Group: group = &m.Future11 case TagFuture12Group: group = &m.Future12 case TagFuture13Group: group = &m.Future13 case TagFuture14Group: group = &m.Future14 case TagFuture15Group: group = &m.Future15 default: // Decode attribute if tag == TagMemberName || tag == TagEndCollection { err = fmt.Errorf("Unexpected tag %s", tag) } else { attr, err = md.decodeAttribute(tag) } if err == nil && tag == TagBeginCollection { attr.Values[0].V, err = md.decodeCollection() } // If everything is OK, save attribute switch { case err != nil: case attr.Name == "": if prev != nil { prev.Values.Add(attr.Values[0].T, attr.Values[0].V) // Append value to the last Attribute of the // last Group in the m.Groups // // Note, if we are here, this last Attribute definitely exists, // because: // * prev != nil // * prev is set when new named attribute is added // * prev is reset when delimiter tag is encountered gLast := &m.Groups[len(m.Groups)-1] aLast := &gLast.Attrs[len(gLast.Attrs)-1] aLast.Values.Add(attr.Values[0].T, attr.Values[0].V) } else { err = errors.New("Additional value without preceding attribute") } case group != nil: group.Add(attr) prev = &(*group)[len(*group)-1] m.Groups[len(m.Groups)-1].Add(attr) default: err = errors.New("Attribute without a group") } } } if err != nil { err = fmt.Errorf("%s at 0x%x", err, md.off) } return err } // Decode a Collection // // Collection is like a nested object - an attribute which value is a sequence // of named attributes. Collections can be nested. // // Wire format: // ATTR: Tag = TagBeginCollection, - the outer attribute that // Name = "name", value - ignored contains the collection // // ATTR: Tag = TagMemberName, name = "", - member name \ // value - string, name of the next | // member | repeated for // | each member // ATTR: Tag = any attribute tag, name = "", - repeated for | // value = member value multi-value / // members // // ATTR: Tag = TagEndCollection, name = "", // value - ignored // // The format looks a bit baroque, but please note that it was added // in the IPP 2.0. For IPP 1.x collection looks like a single multi-value // TagBeginCollection attribute (attributes without names considered // next value for the previously defined named attributes) and so // 1.x parser silently ignores collections and doesn't get confused // with them. func (md *messageDecoder) decodeCollection() (Collection, error) { collection := make(Collection, 0) memberName := "" for { tag, err := md.decodeTag() if err != nil { return nil, err } // Delimiter cannot be inside a collection if tag.IsDelimiter() { err = fmt.Errorf("Collection: unexpected tag %s", tag) return nil, err } // Check for TagMemberName without the subsequent value attribute if (tag == TagMemberName || tag == TagEndCollection) && memberName != "" { err = fmt.Errorf("Collection: unexpected %s, expected value tag", tag) return nil, err } // Fetch next attribute attr, err := md.decodeAttribute(tag) if err != nil { return nil, err } // Process next attribute switch tag { case TagEndCollection: return collection, nil case TagMemberName: memberName = string(attr.Values[0].V.(String)) if memberName == "" { err = fmt.Errorf("Collection: %s value is empty", tag) return nil, err } case TagBeginCollection: // Decode nested collection attr.Values[0].V, err = md.decodeCollection() if err != nil { return nil, err } fallthrough default: if md.opt.EnableWorkarounds && memberName == "" && attr.Name != "" { // Workaround for: Pantum M7300FDW // // This device violates collection encoding rules. // Instead of using TagMemberName, it uses named // attributes within the collection memberName = attr.Name } if memberName != "" { attr.Name = memberName collection = append(collection, attr) memberName = "" } else if len(collection) > 0 { l := len(collection) collection[l-1].Values.Add(tag, attr.Values[0].V) } else { // We've got a value without preceding TagMemberName err = fmt.Errorf("Collection: unexpected %s, expected %s", tag, TagMemberName) return nil, err } } } } // Decode a tag func (md *messageDecoder) decodeTag() (Tag, error) { t, err := md.decodeU8() return Tag(t), err } // Decode a Version func (md *messageDecoder) decodeVersion() (Version, error) { code, err := md.decodeU16() return Version(code), err } // Decode a Code func (md *messageDecoder) decodeCode() (Code, error) { code, err := md.decodeU16() return Code(code), err } // Decode a single attribute // // Wire format: // 1 byte: Tag // 2+N bytes: Name length (2 bytes) + name string // 2+N bytes: Value length (2 bytes) + value bytes // // For the extended tag format, Tag is encoded as TagExtension and // 4 bytes of the actual tag value prepended to the value bytes func (md *messageDecoder) decodeAttribute(tag Tag) (Attribute, error) { var attr Attribute var value []byte var err error // Obtain attribute name and raw value attr.Name, err = md.decodeString() if err != nil { goto ERROR } value, err = md.decodeBytes() if err != nil { goto ERROR } // Handle TagExtension if tag == TagExtension { if len(value) < 4 { err = errors.New("Extension tag truncated") goto ERROR } t := binary.BigEndian.Uint32(value[:4]) value = value[4:] if t > 0x7fffffff { err = errors.New("Extension tag out of range") goto ERROR } tag = Tag(t) } // Unpack value err = attr.unpack(tag, value) if err != nil { goto ERROR } return attr, nil // Return a error ERROR: return Attribute{}, err } // Decode a 8-bit integer func (md *messageDecoder) decodeU8() (uint8, error) { buf := make([]byte, 1) err := md.read(buf) return buf[0], err } // Decode a 16-bit integer func (md *messageDecoder) decodeU16() (uint16, error) { buf := make([]byte, 2) err := md.read(buf) return binary.BigEndian.Uint16(buf[:]), err } // Decode a 32-bit integer func (md *messageDecoder) decodeU32() (uint32, error) { buf := make([]byte, 4) err := md.read(buf) return binary.BigEndian.Uint32(buf[:]), err } // Decode sequence of bytes func (md *messageDecoder) decodeBytes() ([]byte, error) { length, err := md.decodeU16() if err != nil { return nil, err } data := make([]byte, length) err = md.read(data) if err != nil { return nil, err } return data, nil } // Decode string func (md *messageDecoder) decodeString() (string, error) { data, err := md.decodeBytes() if err != nil { return "", err } return string(data), nil } // Read a piece of raw data from input stream func (md *messageDecoder) read(data []byte) error { md.off = md.cnt for len(data) > 0 { n, err := md.in.Read(data) if n > 0 { md.cnt += n data = data[n:] } else { md.off = md.cnt if err == nil || err == io.EOF { err = errors.New("Message truncated") } return err } } return nil } goipp-1.1.0/doc.go000066400000000000000000000111001453360531400137200ustar00rootroot00000000000000/* Go IPP - IPP core protocol implementation in pure Go /* * Copyright (C) 2020 and up by Alexander Pevzner (pzz@apevzner.com) * See LICENSE for license terms and conditions * * Package documentation */ /* Package goipp implements IPP core protocol, as defined by RFC 8010 It doesn't implement high-level operations, such as "print a document", "cancel print job" and so on. It's scope is limited to proper generation and parsing of IPP requests and responses. IPP protocol uses the following simple model: 1. Send a request 2. Receive a response Request and response both has a similar format, represented here by type Message, with the only difference, that Code field of that Message is the Operation code in request and Status code in response. So most of operations are common for request and response messages # Example (Get-Printer-Attributes): package main import ( "bytes" "net/http" "os" "github.com/OpenPrinting/goipp" ) const uri = "http://192.168.1.102:631" // Build IPP OpGetPrinterAttributes request func makeRequest() ([]byte, error) { m := goipp.NewRequest(goipp.DefaultVersion, goipp.OpGetPrinterAttributes, 1) m.Operation.Add(goipp.MakeAttribute("attributes-charset", goipp.TagCharset, goipp.String("utf-8"))) m.Operation.Add(goipp.MakeAttribute("attributes-natural-language", goipp.TagLanguage, goipp.String("en-US"))) m.Operation.Add(goipp.MakeAttribute("printer-uri", goipp.TagURI, goipp.String(uri))) m.Operation.Add(goipp.MakeAttribute("requested-attributes", goipp.TagKeyword, goipp.String("all"))) return m.EncodeBytes() } // Check that there is no error func check(err error) { if err != nil { panic(err) } } func main() { request, err := makeRequest() check(err) resp, err := http.Post(uri, goipp.ContentType, bytes.NewBuffer(request)) check(err) var respMsg goipp.Message err = respMsg.Decode(resp.Body) check(err) respMsg.Print(os.Stdout, false) } # Example (Print PDF file): package main import ( "bytes" "errors" "fmt" "io" "net/http" "os" "github.com/OpenPrinting/goipp" ) const ( PrinterURL = "http://192.168.1.102:631/ipp/print" TestPage = "onepage-a4.pdf" ) type T int // checkErr checks for an error. If err != nil, it prints error // message and exits func checkErr(err error, format string, args ...interface{}) { if err != nil { msg := fmt.Sprintf(format, args...) fmt.Fprintf(os.Stderr, "%s: %s\n", msg, err) os.Exit(1) } } // ExamplePrintPDF demo func main() { // Build and encode IPP request req := goipp.NewRequest(goipp.DefaultVersion, goipp.OpPrintJob, 1) req.Operation.Add(goipp.MakeAttribute("attributes-charset", goipp.TagCharset, goipp.String("utf-8"))) req.Operation.Add(goipp.MakeAttribute("attributes-natural-language", goipp.TagLanguage, goipp.String("en-US"))) req.Operation.Add(goipp.MakeAttribute("printer-uri", goipp.TagURI, goipp.String(PrinterURL))) req.Operation.Add(goipp.MakeAttribute("requesting-user-name", goipp.TagName, goipp.String("John Doe"))) req.Operation.Add(goipp.MakeAttribute("job-name", goipp.TagName, goipp.String("job name"))) req.Operation.Add(goipp.MakeAttribute("document-format", goipp.TagMimeType, goipp.String("application/pdf"))) payload, err := req.EncodeBytes() checkErr(err, "IPP encode") // Open document file file, err := os.Open(TestPage) checkErr(err, "Open document file") defer file.Close() // Build HTTP request body := io.MultiReader(bytes.NewBuffer(payload), file) httpReq, err := http.NewRequest(http.MethodPost, PrinterURL, body) checkErr(err, "HTTP") httpReq.Header.Set("content-type", goipp.ContentType) httpReq.Header.Set("accept", goipp.ContentType) httpReq.Header.Set("accept-encoding", "gzip, deflate, identity") // Execute HTTP request httpRsp, err := http.DefaultClient.Do(httpReq) if httpRsp != nil { defer httpRsp.Body.Close() } checkErr(err, "HTTP") if httpRsp.StatusCode/100 != 2 { checkErr(errors.New(httpRsp.Status), "HTTP") } // Decode IPP response rsp := &goipp.Message{} err = rsp.Decode(httpRsp.Body) checkErr(err, "IPP decode") if goipp.Status(rsp.Code) != goipp.StatusOk { err = errors.New(goipp.Status(rsp.Code).String()) checkErr(err, "IPP") } } */ package goipp goipp-1.1.0/encoder.go000066400000000000000000000114641453360531400146070ustar00rootroot00000000000000/* Go IPP - IPP core protocol implementation in pure Go * * Copyright (C) 2020 and up by Alexander Pevzner (pzz@apevzner.com) * See LICENSE for license terms and conditions * * IPP Message encoder */ package goipp import ( "errors" "fmt" "io" "math" ) // Type messageEncoder represents Message encoder type messageEncoder struct { out io.Writer // Output stream } // Encode the message func (me *messageEncoder) encode(m *Message) error { // Wire format: // // 2 bytes: Version // 2 bytes: Code (Operation or Status) // 4 bytes: RequestID // variable: attributes // 1 byte: TagEnd // Encode message header var err error err = me.encodeU16(uint16(m.Version)) if err == nil { err = me.encodeU16(uint16(m.Code)) } if err == nil { err = me.encodeU32(uint32(m.RequestID)) } // Encode attributes for _, grp := range m.attrGroups() { err = me.encodeTag(grp.Tag) if err == nil { for _, attr := range grp.Attrs { if attr.Name == "" { err = errors.New("Attribute without name") } else { err = me.encodeAttr(attr, true) } } } if err != nil { break } } if err == nil { err = me.encodeTag(TagEnd) } return err } // Encode attribute func (me *messageEncoder) encodeAttr(attr Attribute, checkTag bool) error { // Wire format // 1 byte: Tag // 2 bytes: len(Name) // variable: name // 2 bytes: len(Value) // variable Value // // And each additional value comes as attribute // without name if len(attr.Values) == 0 { return errors.New("Attribute without value") } name := attr.Name for _, val := range attr.Values { tag := val.T if checkTag { if tag.IsDelimiter() || tag == TagMemberName || tag == TagEndCollection { return fmt.Errorf("Tag %s cannot be used with value", tag) } if uint(tag)&0x80000000 != 0 { return fmt.Errorf("Tag %s exceeds extension tag range", tag) } } var err error if tag >= 0x100 { err = me.encodeTag(TagExtension) } else { err = me.encodeTag(tag) } if err != nil { return err } err = me.encodeName(name) if err != nil { return err } err = me.encodeValue(val.T, val.V) if err != nil { return err } name = "" // Each additional value comes without name } return nil } // Encode 8-bit integer func (me *messageEncoder) encodeU8(v uint8) error { return me.write([]byte{v}) } // Encode 16-bit integer func (me *messageEncoder) encodeU16(v uint16) error { return me.write([]byte{byte(v >> 8), byte(v)}) } // Encode 32-bit integer func (me *messageEncoder) encodeU32(v uint32) error { return me.write([]byte{byte(v >> 24), byte(v >> 16), byte(v >> 8), byte(v)}) } // Encode Tag func (me *messageEncoder) encodeTag(tag Tag) error { return me.encodeU8(byte(tag)) } // Encode Attribute name func (me *messageEncoder) encodeName(name string) error { if len(name) > math.MaxInt16 { return fmt.Errorf("Attribute name exceeds %d bytes", math.MaxInt16) } err := me.encodeU16(uint16(len(name))) if err == nil { err = me.write([]byte(name)) } return err } // Encode Attribute value func (me *messageEncoder) encodeValue(tag Tag, v Value) error { // Check Value type vs the Tag tagType := tag.Type() if tagType == TypeVoid { v = Void{} // Ignore supplied value } else if tagType != v.Type() { return fmt.Errorf("Tag %s: %s value required, %s present", tag, tagType, v.Type()) } // Encode the value // // If tag >= 0x100, tag is replaced with TagExtension, and actual // tag value prepended to the data bytes. See RFC 8010, 3.5.2 for // details data, err := v.encode() if err != nil { return err } valueLen := len(data) if tag >= 0x100 { valueLen += 4 // Prepend extension tag value to the data } if valueLen > math.MaxInt16 { return fmt.Errorf("Attribute value exceeds %d bytes", math.MaxInt16) } err = me.encodeU16(uint16(valueLen)) if err == nil && tag >= 0x100 { err = me.encodeU32(uint32(tag)) } if err == nil { err = me.write(data) } // Handle collection if collection, ok := v.(Collection); ok { return me.encodeCollection(tag, collection) } return err } // Encode collection func (me *messageEncoder) encodeCollection(tag Tag, collection Collection) error { for _, attr := range collection { if attr.Name == "" { return errors.New("Collection member without name") } attrName := MakeAttribute("", TagMemberName, String(attr.Name)) err := me.encodeAttr(attrName, false) if err == nil { err = me.encodeAttr(Attribute{Name: "", Values: attr.Values}, true) } if err != nil { return err } } return me.encodeAttr(MakeAttribute("", TagEndCollection, Void{}), false) } // Write a piece of raw data to output stream func (me *messageEncoder) write(data []byte) error { for len(data) > 0 { n, err := me.out.Write(data) if err != nil { return err } data = data[n:] } return nil } goipp-1.1.0/go.mod000066400000000000000000000000561453360531400137420ustar00rootroot00000000000000module github.com/OpenPrinting/goipp go 1.11 goipp-1.1.0/goipp_test.go000066400000000000000000004156061453360531400153530ustar00rootroot00000000000000/* Go IPP - IPP core protocol implementation in pure Go * * Copyright (C) 2020 and up by Alexander Pevzner (pzz@apevzner.com) * See LICENSE for license terms and conditions */ package goipp import ( "bytes" "errors" "fmt" "io" "io/ioutil" "reflect" "strings" "testing" "time" ) // errWriter implements io.Writer interface // // it accepts some first bytes and after that always returns an error type errWriter struct{ skip int } var _ = io.Writer(&errWriter{}) func (ewr *errWriter) Write(data []byte) (int, error) { if len(data) <= ewr.skip { ewr.skip -= len(data) return len(data), nil } n := ewr.skip ewr.skip = 0 return n, errors.New("I/O error") } // errValue implements Value interface and returns // error from its encode() and decode() methods type errValue struct{} var _ = Value(errValue{}) func (errValue) String() string { return "" } func (errValue) Type() Type { return TypeInteger } func (errValue) encode() ([]byte, error) { return nil, errors.New("encode error") } func (errValue) decode([]byte) (Value, error) { return nil, errors.New("decode error") } // Check that err == nil func assertNoError(t *testing.T, err error) { if err != nil { t.Errorf("%s", err) } } // Check that err != nil func assertWithError(t *testing.T, err error) { if err == nil { t.Errorf("Error expected") } } // Check that err != nil and contains expected test func assertErrorIs(t *testing.T, err error, s string) { if err == nil { if s != "" { t.Errorf("Error expected") } return } if !strings.HasPrefix(err.Error(), s) { t.Errorf("Error is %q, expected %q", err, s) } } // Check that value type is as specified func assertValueType(t *testing.T, val Value, typ Type) { if val.Type() != typ { t.Errorf("%s: type is %s, must be %s", reflect.TypeOf(val).Name(), val.Type(), typ) } } func assertDataSize(t *testing.T, data []byte, size int) { if len(data) != size { t.Errorf("data size must be %d, present %d", size, len(data)) } } // Check that encode() works without error and returns expected size func assertEncodeSize(t *testing.T, encode func() ([]byte, error), size int) { data, err := encode() assertNoError(t, err) assertDataSize(t, data, size) } // Check that decode() works without error and returns expected value func assertDecode(t *testing.T, data []byte, expected Value) { val, err := expected.decode(data) assertNoError(t, err) if !ValueEqual(val, expected) { t.Errorf("decode: expected %s, present %s", val, expected) } } // Check that decode returns error func assertDecodeErr(t *testing.T, data []byte, val Value) { _, err := val.decode(data) if err == nil { t.Errorf("decode: expected error") } } // parseTime parses time given in time.Layout format. // this function panics if time cannot be parsed func parseTime(s string) Time { t, err := time.Parse(time.Layout, s) if err != nil { panic(fmt.Sprintf("parseTime(%q): %s", s, err)) } return Time{t} } // Test String() methods for various types func TestString(t *testing.T) { // Here we test that T.String() doesn't crash for // values out of range for i := -1000; i <= 10000; i++ { _ = Op(i).String() _ = Status(i).String() _ = Type(i).String() _ = Tag(i).String() _ = Units(i).String() } } // Test Void Value func TestVoidValue(t *testing.T) { var v Void assertValueType(t, v, TypeVoid) assertEncodeSize(t, v.encode, 0) assertDecode(t, []byte{}, Void{}) assertDecode(t, []byte{1, 2, 3, 4}, Void{}) } // Test Integer Value func TestIntegerValue(t *testing.T) { var v Integer assertValueType(t, v, TypeInteger) assertEncodeSize(t, v.encode, 4) assertDecode(t, []byte{1, 2, 3, 4}, Integer(0x01020304)) assertDecodeErr(t, []byte{1, 2, 3}, Integer(0)) } // Test Boolean Value func TestBooleanValue(t *testing.T) { var v Boolean assertValueType(t, v, TypeBoolean) assertEncodeSize(t, v.encode, 1) assertDecode(t, []byte{0}, Boolean(false)) assertDecode(t, []byte{1}, Boolean(true)) assertDecodeErr(t, []byte{1, 2, 3}, Integer(0)) } // Test String Value func TestStringValue(t *testing.T) { var v String assertValueType(t, v, TypeString) assertEncodeSize(t, v.encode, 0) v = "12345" assertEncodeSize(t, v.encode, 5) assertDecode(t, []byte{}, String("")) assertDecode(t, []byte("hello"), String("hello")) } // Test Time Value func TestDateTimeValue(t *testing.T) { var v Time assertValueType(t, v, TypeDateTime) assertEncodeSize(t, v.encode, 11) tm := time.Date(2020, 1, 13, 15, 35, 12, 300000000, time.UTC) v = Time{tm} data, _ := v.encode() assertDecode(t, data, Time{tm}) assertDecodeErr(t, []byte{1, 2, 3}, Time{}) } // Test Resolution value func TestResolutionValue(t *testing.T) { v := Resolution{100, 100, UnitsDpi} assertValueType(t, v, TypeResolution) assertEncodeSize(t, v.encode, 9) data, _ := v.encode() assertDecode(t, data, v) assertDecodeErr(t, []byte{1, 2, 3}, Resolution{}) } // Test Range value func TestRangeValue(t *testing.T) { v := Range{100, 200} assertValueType(t, v, TypeRange) assertEncodeSize(t, v.encode, 8) data, _ := v.encode() assertDecode(t, data, v) assertDecodeErr(t, []byte{1, 2, 3}, Range{}) } // Test TextWithLang value func TestTextWithLang(t *testing.T) { v := TextWithLang{"ru_RU", "строка на росском языке"} data, err := v.encode() if err != nil { t.Errorf("(TestTextWithLang) encode(): %s", err) } v2, err := v.decode(data) if err != nil { t.Errorf("(TestTextWithLang) decode(): %s", err) } //if v != v2.(TextWithLang) { if !ValueEqual(v, v2) { t.Errorf("TestTextWithLang not the same after encode and decode") } } // Test Binary value func TestBinaryValue(t *testing.T) { v := Binary([]byte("12345")) assertValueType(t, v, TypeBinary) assertEncodeSize(t, v.encode, 5) data, _ := v.encode() assertDecode(t, data, v) } // Test (Attributes) Equal() func TestAttributesEqual(t *testing.T) { attr1 := MakeAttribute("attr1", TagInteger, Integer(1)) attr2 := MakeAttribute("attr2", TagInteger, Integer(2)) attr3 := MakeAttribute("attr3", TagInteger, Integer(3)) var attrs1, attrs2 Attributes attrs1.Add(attr1) attrs1.Add(attr2) attrs2.Add(attr1) attrs2.Add(attr2) if !attrs1.Equal(attrs2) { t.Errorf("(Attributes) Equal(): failed for equal attributes") } attrs2.Add(attr3) if attrs1.Equal(attrs2) { t.Errorf("(Attributes) Equal(): failed attributes of different length") } attrs2 = attrs2[:2] if !attrs1.Equal(attrs2) { t.Errorf("(Attributes) Equal(): failed for equal attributes") } attrs2[1] = attr3 if attrs1.Equal(attrs2) { t.Errorf("(Attributes) Equal(): failed attributes of different value") } } // Test (Message) Equal() func TestMessageEqual(t *testing.T) { var m1, m2 Message // Test: Version, Code, RequestID mismatch makes messages non-equal m1 = Message{Version: 0, Code: 1, RequestID: 2} m2 = m1 m2.Version++ if m1.Equal(m2) { t.Errorf("(Message) Equal(): ignores difference in Version") } m2 = m1 m2.Code++ if m1.Equal(m2) { t.Errorf("(Message) Equal(): ignores difference in Code") } m2 = m1 m2.RequestID++ if m1.Equal(m2) { t.Errorf("(Message) Equal(): ignores difference in RequestID") } } // Test Version func TestVersion(t *testing.T) { v := MakeVersion(1, 2) if v.Major() != 1 || v.Minor() != 2 { t.Errorf("Version test failed") } if v.String() != "1.2" { t.Errorf("(Version)String() test failed") } } // testEncodeDecodeMessage creates a quite complex message // for Encode/Decode test func testEncodeDecodeMessage() *Message { m := &Message{ Version: DefaultVersion, Code: 0x1234, RequestID: 0x87654321, } // Populate all groups m.Operation.Add(MakeAttribute("grp_operation", TagInteger, Integer(1))) m.Job.Add(MakeAttribute("grp_job", TagInteger, Integer(2))) m.Printer.Add(MakeAttribute("grp_printer", TagInteger, Integer(3))) m.Unsupported.Add(MakeAttribute("grp_unsupported", TagInteger, Integer(4))) m.Subscription.Add(MakeAttribute("grp_subscription", TagInteger, Integer(5))) m.EventNotification.Add(MakeAttribute("grp_eventnotification", TagInteger, Integer(6))) m.Resource.Add(MakeAttribute("grp_resource", TagInteger, Integer(7))) m.Document.Add(MakeAttribute("grp_document", TagInteger, Integer(8))) m.System.Add(MakeAttribute("grp_system", TagInteger, Integer(9))) m.Future11.Add(MakeAttribute("grp_future11", TagInteger, Integer(10))) m.Future12.Add(MakeAttribute("grp_future12", TagInteger, Integer(11))) m.Future13.Add(MakeAttribute("grp_future13", TagInteger, Integer(12))) m.Future14.Add(MakeAttribute("grp_future14", TagInteger, Integer(13))) m.Future15.Add(MakeAttribute("grp_future15", TagInteger, Integer(14))) // Use all possible attribute types m.Operation.Add(MakeAttribute("type_integer", TagInteger, Integer(123))) m.Operation.Add(MakeAttribute("type_boolean_t", TagBoolean, Boolean(true))) m.Operation.Add(MakeAttribute("type_boolean_f", TagBoolean, Boolean(false))) m.Operation.Add(MakeAttribute("type_void", TagUnsupportedValue, Void{})) m.Operation.Add(MakeAttribute("type_string_1", TagText, String("hello"))) m.Operation.Add(MakeAttribute("type_string_2", TagText, String(""))) m.Operation.Add(MakeAttribute("type_time_1", TagDateTime, parseTime("01/02 03:04:05PM '06 -0700"))) m.Operation.Add(MakeAttribute("type_time_2", TagDateTime, parseTime("01/02 03:04:05PM '06 +0700"))) m.Operation.Add(MakeAttribute("type_time_3", TagDateTime, parseTime("01/02 03:04:05PM '06 -0730"))) m.Operation.Add(MakeAttribute("type_resolution_1", TagResolution, Resolution{123, 456, UnitsDpi})) m.Operation.Add(MakeAttribute("type_resolution_2", TagResolution, Resolution{78, 90, UnitsDpcm})) m.Operation.Add(MakeAttribute("type_range", TagRange, Range{100, 1000})) m.Operation.Add(MakeAttribute("type_textlang_1", TagTextLang, TextWithLang{"hello", "en"})) m.Operation.Add(MakeAttribute("type_textlang_1", TagTextLang, TextWithLang{"привет", "ru"})) return m } // Test Message Encode, then Decode func TestEncodeDecode(t *testing.T) { m1 := testEncodeDecodeMessage() data, err := m1.EncodeBytes() assertNoError(t, err) m2 := &Message{} err = m2.DecodeBytes(data) assertNoError(t, err) } // Test encode errors func TestEncodeErrors(t *testing.T) { // Attribute without name m := NewRequest(DefaultVersion, OpGetPrinterAttributes, 0x12345678) a := MakeAttribute("attr", TagInteger, Integer(123)) a.Name = "" m.Operation.Add(a) err := m.Encode(ioutil.Discard) assertErrorIs(t, err, "Attribute without name") // Attribute without value m = NewRequest(DefaultVersion, OpGetPrinterAttributes, 0x12345678) a = MakeAttribute("attr", TagInteger, Integer(123)) a.Values = nil m.Operation.Add(a) err = m.Encode(ioutil.Discard) assertErrorIs(t, err, "Attribute without value") // Attribute name exceeds... m = NewRequest(DefaultVersion, OpGetPrinterAttributes, 0x12345678) a = MakeAttribute("attr", TagInteger, Integer(123)) a.Name = strings.Repeat("x", 32767) m.Operation.Add(a) err = m.Encode(ioutil.Discard) assertNoError(t, err) m = NewRequest(DefaultVersion, OpGetPrinterAttributes, 0x12345678) a = MakeAttribute("attr", TagInteger, Integer(123)) a.Name = strings.Repeat("x", 32767+1) m.Operation.Add(a) err = m.Encode(ioutil.Discard) assertErrorIs(t, err, "Attribute name exceeds 32767 bytes") // Attribute value exceeds... m = NewRequest(DefaultVersion, OpGetPrinterAttributes, 0x12345678) a = MakeAttribute("attr", TagText, String(strings.Repeat("x", 32767))) m.Operation.Add(a) err = m.Encode(ioutil.Discard) assertNoError(t, err) m = NewRequest(DefaultVersion, OpGetPrinterAttributes, 0x12345678) a = MakeAttribute("attr", TagText, String(strings.Repeat("x", 32767+1))) m.Operation.Add(a) err = m.Encode(ioutil.Discard) assertErrorIs(t, err, "Attribute value exceeds 32767 bytes") // Tag XXX cannot be used with value m = NewRequest(DefaultVersion, OpGetPrinterAttributes, 0x12345678) a = MakeAttribute("attr", TagJobGroup, Integer(123)) m.Operation.Add(a) err = m.Encode(ioutil.Discard) assertErrorIs(t, err, "Tag job-attributes-tag cannot be used with value") m = NewRequest(DefaultVersion, OpGetPrinterAttributes, 0x12345678) a = MakeAttribute("attr", TagMemberName, Integer(123)) m.Operation.Add(a) err = m.Encode(ioutil.Discard) assertErrorIs(t, err, "Tag memberAttrName cannot be used with value") m = NewRequest(DefaultVersion, OpGetPrinterAttributes, 0x12345678) a = MakeAttribute("attr", TagEndCollection, Integer(123)) m.Operation.Add(a) err = m.Encode(ioutil.Discard) assertErrorIs(t, err, "Tag endCollection cannot be used with value") // Collection member without name m = NewRequest(DefaultVersion, OpGetPrinterAttributes, 0x12345678) a = MakeAttribute("attr", TagBeginCollection, Collection{ MakeAttribute("", TagInteger, Integer(123)), }) m.Operation.Add(a) err = m.Encode(ioutil.Discard) assertErrorIs(t, err, "Collection member without name") // Tag XXX: YYY value required, ZZZ present m = NewRequest(DefaultVersion, OpGetPrinterAttributes, 0x12345678) a = MakeAttribute("attr", TagText, Integer(123)) m.Operation.Add(a) err = m.Encode(ioutil.Discard) assertErrorIs(t, err, "Tag textWithoutLanguage: String value required, Integer present") // I/O error m = testEncodeDecodeMessage() data, err := m.EncodeBytes() assertNoError(t, err) for skip := 0; skip < len(data); skip++ { err = m.Encode(&errWriter{skip}) assertErrorIs(t, err, "I/O error") } // encode error m = NewRequest(DefaultVersion, OpGetPrinterAttributes, 0x12345678) a = MakeAttribute("attr", TagInteger, errValue{}) m.Operation.Add(a) err = m.Encode(ioutil.Discard) assertErrorIs(t, err, "encode error") m = NewRequest(DefaultVersion, OpGetPrinterAttributes, 0x12345678) a = MakeAttribute("attr", TagBeginCollection, Collection{ MakeAttribute("attr", TagInteger, errValue{}), }) m.Operation.Add(a) err = m.Encode(ioutil.Discard) assertErrorIs(t, err, "encode error") } // Test decode errors func TestDecodeErrors(t *testing.T) { var d []byte var err error var m = &Message{} hdr := []byte{ 0x01, 0x01, // IPP version 0x00, 0x02, // Print-Job operation 0x01, 0x02, 0x03, 0x04, // Request ID } body := []byte{} // Message truncated body = []byte{ uint8(TagJobGroup), uint8(TagInteger), 0x00, 0x04, // Name length + name 'a', 't', 't', 'r', 0x00, 0x04, // Value length + value 0x00, 0x00, 0x54, 0x56, } d = append(hdr, body...) err = m.DecodeBytes(d) assertErrorIs(t, err, "Message truncated at") d, err = testEncodeDecodeMessage().EncodeBytes() assertNoError(t, err) for i := 0; i < len(d); i++ { err = m.DecodeBytes(d[:i]) assertErrorIs(t, err, "Message truncated at") } d = goodMessage1 for i := 0; i < len(d); i++ { err = m.DecodeBytes(d[:i]) assertErrorIs(t, err, "Message truncated at") } // Invalid tag 0 d = append(hdr, 0) err = m.DecodeBytes(d) assertErrorIs(t, err, "Invalid tag 0 at 0x8") // Attribute without a group body = []byte{ uint8(TagInteger), 0x00, 0x04, // Name length + name 'a', 't', 't', 'r', 0x00, 0x04, // Value length + value 0x00, 0x00, 0x54, 0x56, uint8(TagEnd), } d = append(hdr, uint8(TagJobGroup)) d = append(d, body...) err = m.DecodeBytes(d) assertNoError(t, err) err = m.DecodeBytes(append(hdr, body...)) assertErrorIs(t, err, "Attribute without a group at") // Additional value without preceding attribute body = []byte{ uint8(TagJobGroup), uint8(TagInteger), 0x00, 0x00, // No name 0x00, 0x04, // Value length + value 0x00, 0x00, 0x54, 0x56, uint8(TagEnd), } err = m.DecodeBytes(append(hdr, body...)) assertErrorIs(t, err, "Additional value without preceding attribute") // "Unexpected tag XXX" for _, tag := range []Tag{TagMemberName, TagEndCollection} { body = []byte{ uint8(TagJobGroup), uint8(TagInteger), 0x00, 0x04, // Name length + name 'a', 't', 't', 'r', 0x00, 0x04, // Value length + value 0x00, 0x00, 0x54, 0x56, } d = append(hdr, body...) d = append(d, uint8(tag)) d = append(d, uint8(TagEnd)) err = m.DecodeBytes(d) assertErrorIs(t, err, "Unexpected tag") } // Collection: unexpected tag XXX for tag := TagZero; tag.IsDelimiter(); tag++ { body = []byte{ uint8(TagJobGroup), uint8(TagBeginCollection), 0x00, 0x0a, // Name length + name 'c', 'o', 'l', 'l', 'e', 'c', 't', 'i', 'o', 'n', 0x00, 0x00, // No value uint8(TagMemberName), 0x00, 0x00, // No name 0x00, 0x06, // Value length + value 'm', 'e', 'm', 'b', 'e', 'r', uint8(TagInteger), 0x00, 0x00, // No name 0x00, 0x04, // Value length + value 0x00, 0x00, 0x54, 0x56, uint8(tag), uint8(TagEndCollection), 0x00, 0x00, // No name 0x00, 0x00, // No value } d = append(hdr, body...) d = append(d, uint8(TagEnd)) err = m.DecodeBytes(d) assertErrorIs(t, err, "Collection: unexpected tag") } // Collection: unexpected endCollection, expected value tag body = []byte{ uint8(TagJobGroup), uint8(TagBeginCollection), 0x00, 0x0a, // Name length + name 'c', 'o', 'l', 'l', 'e', 'c', 't', 'i', 'o', 'n', 0x00, 0x00, // No value uint8(TagMemberName), 0x00, 0x00, // No name 0x00, 0x06, // Value length + value 'm', 'e', 'm', 'b', 'e', 'r', uint8(TagEndCollection), 0x00, 0x00, // No name 0x00, 0x00, // No value uint8(TagEnd), } d = append(hdr, body...) err = m.DecodeBytes(d) assertErrorIs(t, err, "Collection: unexpected endCollection, expected value tag") // Collection: unexpected memberAttrName, expected value tag body = []byte{ uint8(TagJobGroup), uint8(TagBeginCollection), 0x00, 0x0a, // Name length + name 'c', 'o', 'l', 'l', 'e', 'c', 't', 'i', 'o', 'n', 0x00, 0x00, // No value uint8(TagMemberName), 0x00, 0x00, // No name 0x00, 0x07, // Value length + value 'm', 'e', 'm', 'b', 'e', 'r', '1', uint8(TagMemberName), 0x00, 0x00, // No name 0x00, 0x07, // Value length + value 'm', 'e', 'm', 'b', 'e', 'r', '2', uint8(TagInteger), 0x00, 0x00, // No name 0x00, 0x04, // Value length + value 0x00, 0x00, 0x54, 0x56, uint8(TagEndCollection), 0x00, 0x00, // No name 0x00, 0x00, // No value uint8(TagEnd), } d = append(hdr, body...) err = m.DecodeBytes(d) assertErrorIs(t, err, "Collection: unexpected memberAttrName, expected value tag") // Collection: memberAttrName value is empty body = []byte{ uint8(TagJobGroup), uint8(TagBeginCollection), 0x00, 0x0a, // Name length + name 'c', 'o', 'l', 'l', 'e', 'c', 't', 'i', 'o', 'n', 0x00, 0x00, // No value uint8(TagMemberName), 0x00, 0x00, // No name 0x00, 0x00, // No value uint8(TagInteger), 0x00, 0x00, // No name 0x00, 0x04, // Value length + value 0x00, 0x00, 0x54, 0x56, uint8(TagEndCollection), 0x00, 0x00, // No name 0x00, 0x00, // No value uint8(TagEnd), } d = append(hdr, body...) err = m.DecodeBytes(d) assertErrorIs(t, err, "Collection: memberAttrName value is empty") // Collection: unexpected integer, expected memberAttrName body = []byte{ uint8(TagJobGroup), uint8(TagBeginCollection), 0x00, 0x0a, // Name length + name 'c', 'o', 'l', 'l', 'e', 'c', 't', 'i', 'o', 'n', 0x00, 0x00, // No value //uint8(TagMemberName), //0x00, 0x00, // No name //0x00, 0x06, // Value length + value //'m', 'e', 'm', 'b', 'e', 'r', uint8(TagInteger), 0x00, 0x00, // No name 0x00, 0x04, // Value length + value 0x00, 0x00, 0x54, 0x56, uint8(TagEndCollection), 0x00, 0x00, // No name 0x00, 0x00, // No value uint8(TagEnd), } d = append(hdr, body...) err = m.DecodeBytes(d) assertErrorIs(t, err, "Collection: unexpected integer, expected memberAttrName") } // Test errors in decoding values func TestDecodeValueErrors(t *testing.T) { var d []byte var err error var m = &Message{} hdr := []byte{ 0x01, 0x01, // IPP version 0x00, 0x02, // Print-Job operation 0x01, 0x02, 0x03, 0x04, // Request ID } body := []byte{} // integer: value must be 4 bytes body = []byte{ uint8(TagJobGroup), uint8(TagInteger), 0x00, 0x04, // Name length + name 'a', 't', 't', 'r', 0x00, 0x03, // Value length + value 0x00, 0x54, 0x56, uint8(TagEnd), } d = append(hdr, body...) err = m.DecodeBytes(d) assertErrorIs(t, err, "integer: value must be 4 bytes") // boolean: value must be 1 byte body = []byte{ uint8(TagJobGroup), uint8(TagBoolean), 0x00, 0x04, // Name length + name 'a', 't', 't', 'r', 0x00, 0x03, // Value length + value 0x00, 0x54, 0x56, uint8(TagEnd), } d = append(hdr, body...) err = m.DecodeBytes(d) assertErrorIs(t, err, "boolean: value must be 1 byte") // dateTime: value must be 11 bytes body = []byte{ uint8(TagJobGroup), uint8(TagDateTime), 0x00, 0x04, // Name length + name 'a', 't', 't', 'r', 0x00, 0x03, // Value length + value 0x00, 0x54, 0x56, uint8(TagEnd), } d = append(hdr, body...) err = m.DecodeBytes(d) assertErrorIs(t, err, "dateTime: value must be 11 bytes") // dateTime: bad XXX var datetest = []struct { in []byte err string }{ // year month day hour min sec s/10 {[]byte{0x07, 0xe7, 0x02, 0x15, 0x11, 0x23, 0x32, 0x05, '+', 0x04, 0x00}, ""}, {[]byte{0x07, 0xe7, 0xff, 0x15, 0x11, 0x23, 0x32, 0x05, '+', 0x04, 0x00}, "dateTime: bad month 255"}, {[]byte{0x07, 0xe7, 0x02, 0xff, 0x11, 0x23, 0x32, 0x05, '+', 0x04, 0x00}, "dateTime: bad day 255"}, {[]byte{0x07, 0xe7, 0x02, 0x15, 0xff, 0x23, 0x32, 0x05, '+', 0x04, 0x00}, "dateTime: bad hours 255"}, {[]byte{0x07, 0xe7, 0x02, 0x15, 0x11, 0xff, 0x32, 0x05, '+', 0x04, 0x00}, "dateTime: bad minutes 255"}, {[]byte{0x07, 0xe7, 0x02, 0x15, 0x11, 0x23, 0xff, 0x05, '+', 0x04, 0x00}, "dateTime: bad seconds 255"}, {[]byte{0x07, 0xe7, 0x02, 0x15, 0x11, 0x23, 0x32, 0xff, '+', 0x04, 0x00}, "dateTime: bad deciseconds 255"}, {[]byte{0x07, 0xe7, 0x02, 0x15, 0x11, 0x23, 0x32, 0x05, '?', 0x04, 0x00}, "dateTime: bad UTC sign"}, {[]byte{0x07, 0xe7, 0x02, 0x15, 0x11, 0x23, 0x32, 0x05, '-', 0xff, 0x00}, "dateTime: bad UTC hours 255"}, {[]byte{0x07, 0xe7, 0x02, 0x15, 0x11, 0x23, 0x32, 0x05, '-', 0x04, 0xff}, "dateTime: bad UTC minutes 255"}, } for _, test := range datetest { body = []byte{ uint8(TagJobGroup), uint8(TagDateTime), 0x00, 0x04, // Name length + name 'a', 't', 't', 'r', 0x00, 0x0b, // Value length + value } d = append(hdr, body...) d = append(d, test.in...) d = append(d, uint8(TagEnd)) err = m.DecodeBytes(d) assertErrorIs(t, err, test.err) } // resolution: value must be 9 bytes body = []byte{ uint8(TagJobGroup), uint8(TagResolution), 0x00, 0x04, // Name length + name 'a', 't', 't', 'r', 0x00, 0x03, // Value length + value 0x00, 0x54, 0x56, uint8(TagEnd), } d = append(hdr, body...) err = m.DecodeBytes(d) assertErrorIs(t, err, "resolution: value must be 9 bytes ") // rangeOfInteger: value must be 8 bytes body = []byte{ uint8(TagJobGroup), uint8(TagRange), 0x00, 0x04, // Name length + name 'a', 't', 't', 'r', 0x00, 0x03, // Value length + value 0x00, 0x54, 0x56, uint8(TagEnd), } d = append(hdr, body...) err = m.DecodeBytes(d) assertErrorIs(t, err, "rangeOfInteger: value must be 8 bytes") // textWithLanguage: truncated language length body = []byte{ uint8(TagJobGroup), uint8(TagTextLang), 0x00, 0x04, // Name length + name 'a', 't', 't', 'r', 0x00, 0x01, // Value length 0x00, uint8(TagEnd), } d = append(hdr, body...) err = m.DecodeBytes(d) assertErrorIs(t, err, "textWithLanguage: truncated language length") // textWithLanguage: truncated language name body = []byte{ uint8(TagJobGroup), uint8(TagTextLang), 0x00, 0x04, // Name length + name 'a', 't', 't', 'r', 0x00, 0x03, // Value length 0x00, 0x02, // Language length 'e', uint8(TagEnd), } d = append(hdr, body...) err = m.DecodeBytes(d) assertErrorIs(t, err, "textWithLanguage: truncated language name") // textWithLanguage: truncated text length body = []byte{ uint8(TagJobGroup), uint8(TagTextLang), 0x00, 0x04, // Name length + name 'a', 't', 't', 'r', 0x00, 0x05, // Value length 0x00, 0x02, // Language length 'e', 'n', // Language name 0x00, // Text length uint8(TagEnd), } d = append(hdr, body...) err = m.DecodeBytes(d) assertErrorIs(t, err, "textWithLanguage: truncated text length") // textWithLanguage: truncated text string body = []byte{ uint8(TagJobGroup), uint8(TagTextLang), 0x00, 0x04, // Name length + name 'a', 't', 't', 'r', 0x00, 0x09, // Value length 0x00, 0x02, // Language length 'e', 'n', // Language name 0x00, 0x05, // Text length 'h', 'e', 'l', uint8(TagEnd), } d = append(hdr, body...) err = m.DecodeBytes(d) assertErrorIs(t, err, "textWithLanguage: truncated text string") // textWithLanguage: extra 2 bytes at the end of value body = []byte{ uint8(TagJobGroup), uint8(TagTextLang), 0x00, 0x04, // Name length + name 'a', 't', 't', 'r', 0x00, 0x0d, // Value length 0x00, 0x02, // Language length 'e', 'n', // Language name 0x00, 0x05, // Text length 'h', 'e', 'l', 'l', 'o', // Test string '?', '?', // Extra 2 bytes uint8(TagEnd), } d = append(hdr, body...) err = m.DecodeBytes(d) assertErrorIs(t, err, "textWithLanguage: extra 2 bytes at the end of value") } // Test TagExtension func TestTagExtension(t *testing.T) { // Ensure extension tag encodes and decodes well m1 := NewResponse(DefaultVersion, StatusOk, 0x12345678) m1.Operation.Add(MakeAttribute("attr", 0x12345678, Binary{1, 2, 3, 4, 5})) data, err := m1.EncodeBytes() assertNoError(t, err) m2 := Message{} err = m2.DecodeBytes(data) assertNoError(t, err) if !m1.Equal(m2) { t.Errorf("Message is not the same after encoding and decoding") } // Tag can't exceed 0x7fffffff, check that encoder validates it m1 = NewResponse(DefaultVersion, StatusOk, 0x12345678) tmp := uint32(0x81234567) m1.Operation.Add(MakeAttribute("attr", Tag(tmp), Binary{1, 2, 3, 4, 5})) _, err = m1.EncodeBytes() assertErrorIs(t, err, "Tag 0x81234567 exceeds extension tag range") // Now prepare to decoder tests var d []byte var m = &Message{} hdr := []byte{ 0x01, 0x01, // IPP version 0x00, 0x02, // Print-Job operation 0x01, 0x02, 0x03, 0x04, // Request ID } body := []byte{} // Extension tag truncated body = []byte{ uint8(TagJobGroup), uint8(TagExtension), 0x00, 0x04, // Name length + name 'a', 't', 't', 'r', 0x00, 0x03, // Value length + value 0x00, 0x54, 0x56, uint8(TagEnd), } d = append(hdr, body...) err = m.DecodeBytes(d) assertErrorIs(t, err, "Extension tag truncated") // Extension tag out of range body = []byte{ uint8(TagJobGroup), uint8(TagExtension), 0x00, 0x04, // Name length + name 'a', 't', 't', 'r', 0x00, 0x08, // Value length + value 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0, uint8(TagEnd), } d = append(hdr, body...) err = m.DecodeBytes(d) assertErrorIs(t, err, "Extension tag out of range") } // Test message decoding func testDecode(t *testing.T, data []byte, opt DecoderOptions, mustFail, mustEncode bool) { var m Message err := m.DecodeEx(bytes.NewBuffer(data), opt) if mustFail { assertWithError(t, err) } else { assertNoError(t, err) } if err != nil { return } //m.Print(os.Stdout, true) if !m.Equal(m) { t.Errorf("Message is not equal to itself") } if mustEncode { buf, err := m.EncodeBytes() assertNoError(t, err) if !bytes.Equal(buf, data) { t.Errorf("Message is not the same after decoding and encoding") } } // We can't test a lot of (*Message) Print(), so lets test // at least that it doesn't hand m.Print(ioutil.Discard, true) } func TestDecodeGoodMessage1(t *testing.T) { testDecode(t, goodMessage1, DecoderOptions{}, false, true) } func TestDecodeGoodMessage2(t *testing.T) { testDecode(t, goodMessage2, DecoderOptions{}, false, true) } func TestDecodeBadMessage1(t *testing.T) { testDecode(t, badMessage1, DecoderOptions{}, true, false) testDecode(t, badMessage1, DecoderOptions{EnableWorkarounds: true}, false, false) } func TestDecodeHPOfficeJetPro8730(t *testing.T) { testDecode(t, attrsHPOfficeJetPro8730, DecoderOptions{}, false, true) } func TestDecodePantumM7300FDW(t *testing.T) { testDecode(t, attrsPantumM7300FDW, DecoderOptions{EnableWorkarounds: false}, true, false) testDecode(t, attrsPantumM7300FDW, DecoderOptions{EnableWorkarounds: true}, false, false) } // ------------------------ Test Data ------------------------ // The good message - 1 var goodMessage1 = []byte{ 0x01, 0x01, // IPP version 0x00, 0x02, // Print-Job operation 0x00, 0x00, 0x00, 0x01, // Request ID uint8(TagOperationGroup), uint8(TagCharset), 0x00, 0x12, // Name length + name 'a', 't', 't', 'r', 'i', 'b', 'u', 't', 'e', 's', '-', 'c', 'h', 'a', 'r', 's', 'e', 't', 0x00, 0x05, // Value length + value 'u', 't', 'f', '-', '8', uint8(TagLanguage), 0x00, 0x1b, // Name length + name 'a', 't', 't', 'r', 'i', 'b', 'u', 't', 'e', 's', '-', 'n', 'a', 't', 'u', 'r', 'a', 'l', '-', 'l', 'a', 'n', 'g', 'u', 'a', 'g', 'e', 0x00, 0x02, // Value length + value 'e', 'n', uint8(TagURI), 0x00, 0x0b, // Name length + name 'p', 'r', 'i', 'n', 't', 'e', 'r', '-', 'u', 'r', 'i', 0x00, 0x1c, // Value length + value 'i', 'p', 'p', ':', '/', '/', 'l', 'o', 'c', 'a', 'l', 'h', 'o', 's', 't', '/', 'p', 'r', 'i', 'n', 't', 'e', 'r', 's', '/', 'f', 'o', 'o', uint8(TagJobGroup), uint8(TagBeginCollection), 0x00, 0x09, // Name length + name 'm', 'e', 'd', 'i', 'a', '-', 'c', 'o', 'l', 0x00, 0x00, // No value uint8(TagMemberName), 0x00, 0x00, // No name 0x00, 0x0a, // Value length + value 'm', 'e', 'd', 'i', 'a', '-', 's', 'i', 'z', 'e', uint8(TagBeginCollection), 0x00, 0x00, // Name length + name 0x00, 0x00, // No value uint8(TagMemberName), 0x00, 0x00, // No name 0x00, 0x0b, // Value length + value 'x', '-', 'd', 'i', 'm', 'e', 'n', 's', 'i', 'o', 'n', uint8(TagInteger), 0x00, 0x00, // No name 0x00, 0x04, // Value length + value 0x00, 0x00, 0x54, 0x56, uint8(TagMemberName), 0x00, 0x00, // No name 0x00, 0x0b, // Value length + value 'y', '-', 'd', 'i', 'm', 'e', 'n', 's', 'i', 'o', 'n', uint8(TagInteger), 0x00, 0x00, // No name 0x00, 0x04, // Value length + value 0x00, 0x00, 0x6d, 0x24, uint8(TagEndCollection), 0x00, 0x00, // No name 0x00, 0x00, // No value uint8(TagMemberName), 0x00, 0x00, // No name 0x00, 0x0b, // Value length + value 'm', 'e', 'd', 'i', 'a', '-', 'c', 'o', 'l', 'o', 'r', uint8(TagKeyword), 0x00, 0x00, // No name 0x00, 0x04, // Value length + value 'b', 'l', 'u', 'e', uint8(TagMemberName), 0x00, 0x00, // No name 0x00, 0x0a, // Value length + value 'm', 'e', 'd', 'i', 'a', '-', 't', 'y', 'p', 'e', uint8(TagKeyword), 0x00, 0x00, // No name 0x00, 0x05, // Value length + value 'p', 'l', 'a', 'i', 'n', uint8(TagEndCollection), 0x00, 0x00, // No name 0x00, 0x00, // No value uint8(TagBeginCollection), 0x00, 0x00, // No name 0x00, 0x00, // No value uint8(TagMemberName), 0x00, 0x00, // No name 0x00, 0x0a, // Value length + value 'm', 'e', 'd', 'i', 'a', '-', 's', 'i', 'z', 'e', uint8(TagBeginCollection), 0x00, 0x00, // Name length + name 0x00, 0x00, // No value uint8(TagMemberName), 0x00, 0x00, // No name 0x00, 0x0b, // Value length + value 'x', '-', 'd', 'i', 'm', 'e', 'n', 's', 'i', 'o', 'n', uint8(TagInteger), 0x00, 0x00, // No name 0x00, 0x04, // Value length + value 0x00, 0x00, 0x52, 0x08, uint8(TagMemberName), 0x00, 0x00, // No name 0x00, 0x0b, // Value length + value 'y', '-', 'd', 'i', 'm', 'e', 'n', 's', 'i', 'o', 'n', uint8(TagInteger), 0x00, 0x00, // No name 0x00, 0x04, // Value length + value 0x00, 0x00, 0x74, 0x04, uint8(TagEndCollection), 0x00, 0x00, // No name 0x00, 0x00, // No value uint8(TagMemberName), 0x00, 0x00, // No name 0x00, 0x0b, // Value length + value 'm', 'e', 'd', 'i', 'a', '-', 'c', 'o', 'l', 'o', 'r', uint8(TagKeyword), 0x00, 0x00, // No name 0x00, 0x05, // Value length + value 'p', 'l', 'a', 'i', 'd', uint8(TagMemberName), 0x00, 0x00, // No name 0x00, 0x0a, // Value length + value 'm', 'e', 'd', 'i', 'a', '-', 't', 'y', 'p', 'e', uint8(TagKeyword), 0x00, 0x00, // No name 0x00, 0x06, // Value length + value 'g', 'l', 'o', 's', 's', 'y', uint8(TagEndCollection), 0x00, 0x00, // No name 0x00, 0x00, // No value uint8(TagEnd), } // The good message - 2 var goodMessage2 = []byte{ 0x01, 0x01, // IPP version 0x00, 0x02, // Print-Job operation 0x00, 0x00, 0x00, 0x01, // Request ID uint8(TagOperationGroup), uint8(TagInteger), 0x00, 0x1f, // Name length + name 'n', 'o', 't', 'i', 'f', 'y', '-', 'l', 'e', 'a', 's', 'e', '-', 'd', 'u', 'r', 'a', 't', 'i', 'o', 'n', '-', 's', 'u', 'p', 'p', 'o', 'r', 't', 'e', 'd', 0x00, 0x04, // Value length + value 0x00, 0x00, 0x00, 0x01, uint8(TagRange), 0x00, 0x00, // No name 0x00, 0x08, // Value length + value 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x20, uint8(TagEnd), } // The bad message - 1 // // This message violates IPP encoding rules: instead of // using TagMemberName it uses named attributes // // It must not decode normally, but must decode with workarounds var badMessage1 = []byte{ 0x01, 0x01, // IPP version */ 0x00, 0x02, // Print-Job operation */ 0x00, 0x00, 0x00, 0x01, // Request ID */ uint8(TagOperationGroup), uint8(TagCharset), 0x00, 0x12, // Name length + name 'a', 't', 't', 'r', 'i', 'b', 'u', 't', 'e', 's', '-', 'c', 'h', 'a', 'r', 's', 'e', 't', 0x00, 0x05, // Value length + value 'u', 't', 'f', '-', '8', uint8(TagLanguage), 0x00, 0x1b, // Name length + name 'a', 't', 't', 'r', 'i', 'b', 'u', 't', 'e', 's', '-', 'n', 'a', 't', 'u', 'r', 'a', 'l', '-', 'l', 'a', 'n', 'g', 'u', 'a', 'g', 'e', 0x00, 0x02, // Value length + value 'e', 'n', uint8(TagURI), 0x00, 0x0b, // Name length + name 'p', 'r', 'i', 'n', 't', 'e', 'r', '-', 'u', 'r', 'i', 0x00, 0x1c, // Value length + value 'i', 'p', 'p', ':', '/', '/', 'l', 'o', 'c', 'a', 'l', 'h', 'o', 's', 't', '/', 'p', 'r', 'i', 'n', 't', 'e', 'r', 's', '/', 'f', 'o', 'o', uint8(TagJobGroup), uint8(TagBeginCollection), 0x00, 0x09, // Name length + name 'm', 'e', 'd', 'i', 'a', '-', 'c', 'o', 'l', 0x00, 0x00, // No value uint8(TagBeginCollection), 0x00, 0x0a, // Name length + name 'm', 'e', 'd', 'i', 'a', '-', 's', 'i', 'z', 'e', 0x00, 0x00, // No value uint8(TagInteger), 0x00, 0x0b, // Name length + name 'x', '-', 'd', 'i', 'm', 'e', 'n', 's', 'i', 'o', 'n', 0x00, 0x04, // Value length + value 0x00, 0x00, 0x54, 0x56, uint8(TagInteger), 0x00, 0x0b, // Name length + name 'y', '-', 'd', 'i', 'm', 'e', 'n', 's', 'i', 'o', 'n', 0x00, 0x04, // Value length + value 0x00, 0x00, 0x6d, 0x24, uint8(TagEndCollection), 0x00, 0x00, // No name 0x00, 0x00, // No value uint8(TagEndCollection), 0x00, 0x00, // No name 0x00, 0x00, // No value uint8(TagEnd), } // The big real example, Get-Printer-Attributes output // from the HP OfficeJet Pro 8730 var attrsHPOfficeJetPro8730 = []byte{ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x47, 0x00, 0x12, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2d, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x00, 0x05, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x48, 0x00, 0x1b, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2d, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x61, 0x6c, 0x2d, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x00, 0x02, 0x65, 0x6e, 0x04, 0x45, 0x00, 0x15, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x75, 0x72, 0x69, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x19, 0x69, 0x70, 0x70, 0x3a, 0x2f, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x2f, 0x69, 0x70, 0x70, 0x2f, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x45, 0x00, 0x00, 0x00, 0x1e, 0x69, 0x70, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x3a, 0x34, 0x34, 0x33, 0x2f, 0x69, 0x70, 0x70, 0x2f, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x44, 0x00, 0x16, 0x75, 0x72, 0x69, 0x2d, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x04, 0x6e, 0x6f, 0x6e, 0x65, 0x44, 0x00, 0x00, 0x00, 0x03, 0x74, 0x6c, 0x73, 0x44, 0x00, 0x1c, 0x75, 0x72, 0x69, 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x14, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2d, 0x75, 0x73, 0x65, 0x72, 0x2d, 0x6e, 0x61, 0x6d, 0x65, 0x44, 0x00, 0x00, 0x00, 0x14, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2d, 0x75, 0x73, 0x65, 0x72, 0x2d, 0x6e, 0x61, 0x6d, 0x65, 0x44, 0x00, 0x25, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x73, 0x65, 0x74, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2d, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x11, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x77, 0x69, 0x66, 0x69, 0x2d, 0x73, 0x73, 0x69, 0x64, 0x44, 0x00, 0x00, 0x00, 0x15, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x77, 0x69, 0x66, 0x69, 0x2d, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x42, 0x00, 0x11, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x77, 0x69, 0x66, 0x69, 0x2d, 0x73, 0x73, 0x69, 0x64, 0x00, 0x09, 0x41, 0x31, 0x2d, 0x35, 0x45, 0x46, 0x33, 0x37, 0x31, 0x23, 0x00, 0x12, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x77, 0x69, 0x66, 0x69, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x65, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x42, 0x00, 0x0c, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x6e, 0x61, 0x6d, 0x65, 0x00, 0x08, 0x48, 0x50, 0x30, 0x38, 0x43, 0x32, 0x32, 0x39, 0x41, 0x00, 0x10, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x45, 0x00, 0x11, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x6d, 0x6f, 0x72, 0x65, 0x2d, 0x69, 0x6e, 0x66, 0x6f, 0x00, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x2f, 0x23, 0x68, 0x49, 0x64, 0x2d, 0x70, 0x67, 0x41, 0x69, 0x72, 0x50, 0x72, 0x69, 0x6e, 0x74, 0x41, 0x00, 0x0c, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x69, 0x6e, 0x66, 0x6f, 0x00, 0x1e, 0x48, 0x50, 0x20, 0x4f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x4a, 0x65, 0x74, 0x20, 0x50, 0x72, 0x6f, 0x20, 0x38, 0x37, 0x33, 0x30, 0x20, 0x5b, 0x30, 0x38, 0x43, 0x32, 0x32, 0x39, 0x5d, 0x42, 0x00, 0x13, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x64, 0x6e, 0x73, 0x2d, 0x73, 0x64, 0x2d, 0x6e, 0x61, 0x6d, 0x65, 0x00, 0x1e, 0x48, 0x50, 0x20, 0x4f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x4a, 0x65, 0x74, 0x20, 0x50, 0x72, 0x6f, 0x20, 0x38, 0x37, 0x33, 0x30, 0x20, 0x5b, 0x30, 0x38, 0x43, 0x32, 0x32, 0x39, 0x5d, 0x41, 0x00, 0x16, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x6d, 0x61, 0x6b, 0x65, 0x2d, 0x61, 0x6e, 0x64, 0x2d, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x00, 0x15, 0x48, 0x50, 0x20, 0x4f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x4a, 0x65, 0x74, 0x20, 0x50, 0x72, 0x6f, 0x20, 0x38, 0x37, 0x33, 0x30, 0x23, 0x00, 0x0d, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x65, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x44, 0x00, 0x15, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2d, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x73, 0x00, 0x1a, 0x77, 0x69, 0x66, 0x69, 0x2d, 0x6e, 0x6f, 0x74, 0x2d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x64, 0x2d, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x41, 0x00, 0x15, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2d, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x00, 0x00, 0x44, 0x00, 0x16, 0x69, 0x70, 0x70, 0x2d, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x03, 0x31, 0x2e, 0x30, 0x44, 0x00, 0x00, 0x00, 0x03, 0x31, 0x2e, 0x31, 0x44, 0x00, 0x00, 0x00, 0x03, 0x32, 0x2e, 0x30, 0x23, 0x00, 0x14, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x23, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x23, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x23, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x39, 0x23, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x23, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0a, 0x23, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0b, 0x23, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x23, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x06, 0x23, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x13, 0x23, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x29, 0x23, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x2a, 0x23, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x23, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x07, 0x23, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x3b, 0x23, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x3c, 0x47, 0x00, 0x12, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x2d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x64, 0x00, 0x05, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x47, 0x00, 0x11, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x05, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x48, 0x00, 0x1b, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x61, 0x6c, 0x2d, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x2d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x64, 0x00, 0x02, 0x65, 0x6e, 0x48, 0x00, 0x24, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2d, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x61, 0x6c, 0x2d, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x02, 0x65, 0x6e, 0x48, 0x00, 0x00, 0x00, 0x02, 0x66, 0x72, 0x48, 0x00, 0x00, 0x00, 0x02, 0x64, 0x65, 0x48, 0x00, 0x00, 0x00, 0x02, 0x65, 0x73, 0x48, 0x00, 0x00, 0x00, 0x02, 0x69, 0x74, 0x48, 0x00, 0x00, 0x00, 0x02, 0x73, 0x76, 0x48, 0x00, 0x00, 0x00, 0x02, 0x64, 0x61, 0x48, 0x00, 0x00, 0x00, 0x02, 0x6e, 0x6f, 0x48, 0x00, 0x00, 0x00, 0x02, 0x6e, 0x6c, 0x48, 0x00, 0x00, 0x00, 0x02, 0x66, 0x69, 0x48, 0x00, 0x00, 0x00, 0x02, 0x6a, 0x61, 0x48, 0x00, 0x00, 0x00, 0x02, 0x70, 0x74, 0x48, 0x00, 0x00, 0x00, 0x02, 0x70, 0x6c, 0x48, 0x00, 0x00, 0x00, 0x02, 0x74, 0x72, 0x48, 0x00, 0x00, 0x00, 0x05, 0x7a, 0x68, 0x2d, 0x74, 0x77, 0x48, 0x00, 0x00, 0x00, 0x05, 0x7a, 0x68, 0x2d, 0x63, 0x6e, 0x48, 0x00, 0x00, 0x00, 0x02, 0x72, 0x75, 0x48, 0x00, 0x00, 0x00, 0x02, 0x63, 0x73, 0x48, 0x00, 0x00, 0x00, 0x02, 0x68, 0x75, 0x48, 0x00, 0x00, 0x00, 0x02, 0x6b, 0x6f, 0x48, 0x00, 0x00, 0x00, 0x02, 0x68, 0x65, 0x48, 0x00, 0x00, 0x00, 0x02, 0x65, 0x6c, 0x48, 0x00, 0x00, 0x00, 0x02, 0x61, 0x72, 0x48, 0x00, 0x00, 0x00, 0x02, 0x62, 0x67, 0x48, 0x00, 0x00, 0x00, 0x02, 0x68, 0x72, 0x48, 0x00, 0x00, 0x00, 0x02, 0x72, 0x6f, 0x48, 0x00, 0x00, 0x00, 0x02, 0x73, 0x6b, 0x48, 0x00, 0x00, 0x00, 0x02, 0x73, 0x6c, 0x48, 0x00, 0x23, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x2d, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x73, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x02, 0x65, 0x6e, 0x48, 0x00, 0x00, 0x00, 0x02, 0x66, 0x72, 0x48, 0x00, 0x00, 0x00, 0x02, 0x64, 0x65, 0x48, 0x00, 0x00, 0x00, 0x02, 0x65, 0x73, 0x48, 0x00, 0x00, 0x00, 0x02, 0x69, 0x74, 0x48, 0x00, 0x00, 0x00, 0x02, 0x73, 0x76, 0x48, 0x00, 0x00, 0x00, 0x02, 0x64, 0x61, 0x48, 0x00, 0x00, 0x00, 0x02, 0x6e, 0x6f, 0x48, 0x00, 0x00, 0x00, 0x02, 0x6e, 0x6c, 0x48, 0x00, 0x00, 0x00, 0x02, 0x66, 0x69, 0x48, 0x00, 0x00, 0x00, 0x02, 0x6a, 0x61, 0x48, 0x00, 0x00, 0x00, 0x02, 0x70, 0x74, 0x48, 0x00, 0x00, 0x00, 0x02, 0x70, 0x6c, 0x48, 0x00, 0x00, 0x00, 0x02, 0x74, 0x72, 0x48, 0x00, 0x00, 0x00, 0x05, 0x7a, 0x68, 0x2d, 0x74, 0x77, 0x48, 0x00, 0x00, 0x00, 0x05, 0x7a, 0x68, 0x2d, 0x63, 0x6e, 0x48, 0x00, 0x00, 0x00, 0x02, 0x72, 0x75, 0x48, 0x00, 0x00, 0x00, 0x02, 0x63, 0x73, 0x48, 0x00, 0x00, 0x00, 0x02, 0x68, 0x75, 0x48, 0x00, 0x00, 0x00, 0x02, 0x6b, 0x6f, 0x48, 0x00, 0x00, 0x00, 0x02, 0x68, 0x65, 0x48, 0x00, 0x00, 0x00, 0x02, 0x65, 0x6c, 0x48, 0x00, 0x00, 0x00, 0x02, 0x61, 0x72, 0x48, 0x00, 0x00, 0x00, 0x02, 0x62, 0x67, 0x48, 0x00, 0x00, 0x00, 0x02, 0x68, 0x72, 0x48, 0x00, 0x00, 0x00, 0x02, 0x72, 0x6f, 0x48, 0x00, 0x00, 0x00, 0x02, 0x73, 0x6b, 0x48, 0x00, 0x00, 0x00, 0x02, 0x73, 0x6c, 0x45, 0x00, 0x13, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x2d, 0x75, 0x72, 0x69, 0x00, 0x25, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x2f, 0x69, 0x70, 0x70, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2f, 0x65, 0x6e, 0x2e, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x49, 0x00, 0x17, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x2d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x00, 0x18, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6f, 0x63, 0x74, 0x65, 0x74, 0x2d, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x49, 0x00, 0x19, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x16, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x68, 0x70, 0x2d, 0x50, 0x43, 0x4c, 0x49, 0x00, 0x00, 0x00, 0x18, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x68, 0x70, 0x2d, 0x50, 0x43, 0x4c, 0x58, 0x4c, 0x49, 0x00, 0x00, 0x00, 0x16, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x6f, 0x73, 0x74, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x49, 0x00, 0x00, 0x00, 0x0f, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x64, 0x66, 0x49, 0x00, 0x00, 0x00, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x65, 0x67, 0x49, 0x00, 0x00, 0x00, 0x10, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x50, 0x43, 0x4c, 0x6d, 0x49, 0x00, 0x00, 0x00, 0x09, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x75, 0x72, 0x66, 0x49, 0x00, 0x00, 0x00, 0x10, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x70, 0x77, 0x67, 0x2d, 0x72, 0x61, 0x73, 0x74, 0x65, 0x72, 0x49, 0x00, 0x00, 0x00, 0x18, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6f, 0x63, 0x74, 0x65, 0x74, 0x2d, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x41, 0x00, 0x21, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x2d, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x05, 0x50, 0x43, 0x4c, 0x35, 0x63, 0x41, 0x00, 0x00, 0x00, 0x05, 0x50, 0x43, 0x4c, 0x58, 0x4c, 0x41, 0x00, 0x00, 0x00, 0x04, 0x50, 0x53, 0x2f, 0x33, 0x41, 0x00, 0x00, 0x00, 0x0c, 0x4e, 0x41, 0x54, 0x49, 0x56, 0x45, 0x4f, 0x46, 0x46, 0x49, 0x43, 0x45, 0x41, 0x00, 0x00, 0x00, 0x07, 0x50, 0x44, 0x46, 0x2f, 0x31, 0x2e, 0x37, 0x41, 0x00, 0x00, 0x00, 0x07, 0x50, 0x43, 0x4c, 0x33, 0x47, 0x55, 0x49, 0x41, 0x00, 0x00, 0x00, 0x04, 0x50, 0x43, 0x4c, 0x33, 0x41, 0x00, 0x00, 0x00, 0x03, 0x50, 0x4a, 0x4c, 0x41, 0x00, 0x00, 0x00, 0x09, 0x41, 0x75, 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x41, 0x00, 0x00, 0x00, 0x04, 0x4a, 0x50, 0x45, 0x47, 0x41, 0x00, 0x00, 0x00, 0x04, 0x50, 0x43, 0x4c, 0x4d, 0x41, 0x00, 0x00, 0x00, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x52, 0x61, 0x73, 0x74, 0x65, 0x72, 0x41, 0x00, 0x00, 0x00, 0x09, 0x50, 0x57, 0x47, 0x52, 0x61, 0x73, 0x74, 0x65, 0x72, 0x22, 0x00, 0x19, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x69, 0x73, 0x2d, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6e, 0x67, 0x2d, 0x6a, 0x6f, 0x62, 0x73, 0x00, 0x01, 0x01, 0x21, 0x00, 0x10, 0x71, 0x75, 0x65, 0x75, 0x65, 0x64, 0x2d, 0x6a, 0x6f, 0x62, 0x2d, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x16, 0x70, 0x64, 0x6c, 0x2d, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x09, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x65, 0x64, 0x21, 0x00, 0x0f, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x75, 0x70, 0x2d, 0x74, 0x69, 0x6d, 0x65, 0x00, 0x04, 0x00, 0x00, 0x07, 0xdf, 0x31, 0x00, 0x14, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x69, 0x6d, 0x65, 0x00, 0x0b, 0x07, 0xe4, 0x01, 0x13, 0x0b, 0x17, 0x17, 0x00, 0x2b, 0x00, 0x00, 0x44, 0x00, 0x15, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x04, 0x6e, 0x6f, 0x6e, 0x65, 0x44, 0x00, 0x00, 0x00, 0x07, 0x64, 0x65, 0x66, 0x6c, 0x61, 0x74, 0x65, 0x44, 0x00, 0x00, 0x00, 0x04, 0x67, 0x7a, 0x69, 0x70, 0x22, 0x00, 0x0f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x01, 0x01, 0x44, 0x00, 0x21, 0x6a, 0x6f, 0x62, 0x2d, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x06, 0x63, 0x6f, 0x70, 0x69, 0x65, 0x73, 0x44, 0x00, 0x00, 0x00, 0x0a, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x44, 0x00, 0x00, 0x00, 0x0e, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x2d, 0x63, 0x6f, 0x6c, 0x44, 0x00, 0x00, 0x00, 0x11, 0x6a, 0x6f, 0x62, 0x2d, 0x70, 0x61, 0x67, 0x65, 0x73, 0x2d, 0x70, 0x65, 0x72, 0x2d, 0x73, 0x65, 0x74, 0x44, 0x00, 0x00, 0x00, 0x05, 0x73, 0x69, 0x64, 0x65, 0x73, 0x44, 0x00, 0x00, 0x00, 0x15, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x64, 0x44, 0x00, 0x00, 0x00, 0x05, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x44, 0x00, 0x00, 0x00, 0x0d, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x2d, 0x71, 0x75, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x44, 0x00, 0x00, 0x00, 0x12, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x0a, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2d, 0x62, 0x69, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x09, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x63, 0x6f, 0x6c, 0x44, 0x00, 0x00, 0x00, 0x0b, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2d, 0x6d, 0x6f, 0x64, 0x65, 0x44, 0x00, 0x00, 0x00, 0x16, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x44, 0x00, 0x00, 0x00, 0x16, 0x70, 0x63, 0x6c, 0x6d, 0x2d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x10, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2d, 0x6d, 0x6f, 0x64, 0x65, 0x44, 0x00, 0x00, 0x00, 0x16, 0x69, 0x70, 0x70, 0x2d, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x2d, 0x66, 0x69, 0x64, 0x65, 0x6c, 0x69, 0x74, 0x79, 0x44, 0x00, 0x00, 0x00, 0x08, 0x6a, 0x6f, 0x62, 0x2d, 0x6e, 0x61, 0x6d, 0x65, 0x44, 0x00, 0x00, 0x00, 0x0b, 0x70, 0x61, 0x67, 0x65, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x44, 0x00, 0x00, 0x00, 0x1a, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x2d, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x69, 0x6e, 0x67, 0x44, 0x00, 0x00, 0x00, 0x18, 0x6a, 0x6f, 0x62, 0x2d, 0x6d, 0x61, 0x6e, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2d, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x44, 0x00, 0x00, 0x00, 0x09, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x44, 0x00, 0x00, 0x00, 0x16, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x2d, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x44, 0x00, 0x00, 0x00, 0x0d, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x2d, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x6e, 0x67, 0x46, 0x00, 0x1f, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x2d, 0x75, 0x72, 0x69, 0x2d, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x73, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x04, 0x68, 0x74, 0x74, 0x70, 0x46, 0x00, 0x00, 0x00, 0x05, 0x68, 0x74, 0x74, 0x70, 0x73, 0x41, 0x00, 0x11, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x2d, 0x69, 0x64, 0x01, 0x99, 0x4d, 0x46, 0x47, 0x3a, 0x48, 0x50, 0x3b, 0x4d, 0x44, 0x4c, 0x3a, 0x48, 0x50, 0x20, 0x4f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x4a, 0x65, 0x74, 0x20, 0x50, 0x72, 0x6f, 0x20, 0x38, 0x37, 0x33, 0x30, 0x3b, 0x43, 0x4d, 0x44, 0x3a, 0x50, 0x43, 0x4c, 0x35, 0x63, 0x2c, 0x50, 0x43, 0x4c, 0x58, 0x4c, 0x2c, 0x50, 0x4f, 0x53, 0x54, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x2c, 0x4e, 0x41, 0x54, 0x49, 0x56, 0x45, 0x4f, 0x46, 0x46, 0x49, 0x43, 0x45, 0x2c, 0x50, 0x44, 0x46, 0x2c, 0x50, 0x43, 0x4c, 0x33, 0x47, 0x55, 0x49, 0x2c, 0x50, 0x43, 0x4c, 0x33, 0x2c, 0x50, 0x4a, 0x4c, 0x2c, 0x41, 0x75, 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x2c, 0x4a, 0x50, 0x45, 0x47, 0x2c, 0x50, 0x43, 0x4c, 0x4d, 0x2c, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x52, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2c, 0x50, 0x57, 0x47, 0x52, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2c, 0x38, 0x30, 0x32, 0x2e, 0x31, 0x31, 0x2c, 0x38, 0x30, 0x32, 0x2e, 0x33, 0x2c, 0x44, 0x45, 0x53, 0x4b, 0x4a, 0x45, 0x54, 0x2c, 0x44, 0x59, 0x4e, 0x3b, 0x43, 0x4c, 0x53, 0x3a, 0x50, 0x52, 0x49, 0x4e, 0x54, 0x45, 0x52, 0x3b, 0x44, 0x45, 0x53, 0x3a, 0x44, 0x39, 0x4c, 0x32, 0x30, 0x41, 0x3b, 0x43, 0x49, 0x44, 0x3a, 0x48, 0x50, 0x49, 0x4a, 0x56, 0x49, 0x50, 0x41, 0x56, 0x39, 0x3b, 0x4c, 0x45, 0x44, 0x4d, 0x44, 0x49, 0x53, 0x3a, 0x55, 0x53, 0x42, 0x23, 0x46, 0x46, 0x23, 0x43, 0x43, 0x23, 0x30, 0x30, 0x2c, 0x55, 0x53, 0x42, 0x23, 0x46, 0x46, 0x23, 0x30, 0x34, 0x23, 0x30, 0x31, 0x3b, 0x4d, 0x43, 0x54, 0x3a, 0x4d, 0x46, 0x3b, 0x4d, 0x43, 0x4c, 0x3a, 0x44, 0x49, 0x3b, 0x4d, 0x43, 0x56, 0x3a, 0x33, 0x2e, 0x30, 0x3b, 0x53, 0x4e, 0x3a, 0x43, 0x4e, 0x37, 0x38, 0x33, 0x46, 0x36, 0x30, 0x57, 0x31, 0x3b, 0x53, 0x3a, 0x30, 0x33, 0x38, 0x30, 0x38, 0x30, 0x43, 0x34, 0x38, 0x34, 0x31, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x35, 0x38, 0x30, 0x30, 0x38, 0x30, 0x30, 0x30, 0x30, 0x34, 0x34, 0x31, 0x38, 0x30, 0x30, 0x33, 0x63, 0x34, 0x35, 0x31, 0x38, 0x30, 0x30, 0x34, 0x36, 0x34, 0x36, 0x31, 0x38, 0x30, 0x30, 0x33, 0x63, 0x34, 0x31, 0x31, 0x38, 0x30, 0x30, 0x34, 0x36, 0x3b, 0x5a, 0x3a, 0x30, 0x35, 0x30, 0x30, 0x30, 0x30, 0x30, 0x39, 0x30, 0x30, 0x30, 0x30, 0x30, 0x39, 0x30, 0x30, 0x30, 0x30, 0x30, 0x39, 0x30, 0x30, 0x30, 0x30, 0x30, 0x39, 0x30, 0x30, 0x30, 0x30, 0x30, 0x39, 0x2c, 0x31, 0x32, 0x30, 0x30, 0x30, 0x2c, 0x31, 0x37, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x2c, 0x31, 0x38, 0x31, 0x3b, 0x30, 0x00, 0x0d, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x61, 0x6c, 0x65, 0x72, 0x74, 0x00, 0x27, 0x63, 0x6f, 0x64, 0x65, 0x3d, 0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x3b, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x3d, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x3b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x3d, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x30, 0x00, 0x00, 0x00, 0x27, 0x63, 0x6f, 0x64, 0x65, 0x3d, 0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x3b, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x3d, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x3b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x3d, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x30, 0x00, 0x00, 0x00, 0x27, 0x63, 0x6f, 0x64, 0x65, 0x3d, 0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x3b, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x3d, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x3b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x3d, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x30, 0x00, 0x00, 0x00, 0x27, 0x63, 0x6f, 0x64, 0x65, 0x3d, 0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x3b, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x3d, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x3b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x3d, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x41, 0x00, 0x19, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x61, 0x6c, 0x65, 0x72, 0x74, 0x2d, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x09, 0x67, 0x65, 0x6e, 0x75, 0x69, 0x6e, 0x65, 0x48, 0x50, 0x41, 0x00, 0x00, 0x00, 0x09, 0x67, 0x65, 0x6e, 0x75, 0x69, 0x6e, 0x65, 0x48, 0x50, 0x41, 0x00, 0x00, 0x00, 0x09, 0x67, 0x65, 0x6e, 0x75, 0x69, 0x6e, 0x65, 0x48, 0x50, 0x41, 0x00, 0x00, 0x00, 0x09, 0x67, 0x65, 0x6e, 0x75, 0x69, 0x6e, 0x65, 0x48, 0x50, 0x45, 0x00, 0x0c, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x75, 0x75, 0x69, 0x64, 0x00, 0x2d, 0x75, 0x72, 0x6e, 0x3a, 0x75, 0x75, 0x69, 0x64, 0x3a, 0x64, 0x62, 0x63, 0x63, 0x34, 0x62, 0x35, 0x38, 0x2d, 0x66, 0x63, 0x34, 0x63, 0x2d, 0x66, 0x36, 0x66, 0x64, 0x2d, 0x62, 0x34, 0x64, 0x36, 0x2d, 0x32, 0x62, 0x30, 0x30, 0x64, 0x35, 0x35, 0x34, 0x61, 0x64, 0x34, 0x37, 0x23, 0x00, 0x29, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x63, 0x61, 0x70, 0x65, 0x2d, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x64, 0x2d, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x34, 0x00, 0x19, 0x6a, 0x6f, 0x62, 0x2d, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x73, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x2d, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x00, 0x00, 0x00, 0x0f, 0x66, 0x75, 0x6c, 0x6c, 0x62, 0x6c, 0x65, 0x65, 0x64, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x73, 0x4a, 0x00, 0x00, 0x00, 0x10, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x74, 0x6f, 0x70, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x13, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x11, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x12, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x72, 0x69, 0x67, 0x68, 0x74, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x05, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x44, 0x00, 0x00, 0x00, 0x14, 0x6e, 0x61, 0x5f, 0x69, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x5f, 0x35, 0x2e, 0x35, 0x78, 0x38, 0x2e, 0x35, 0x69, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x12, 0x6e, 0x61, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2d, 0x35, 0x78, 0x38, 0x5f, 0x35, 0x78, 0x38, 0x69, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x14, 0x6e, 0x61, 0x5f, 0x6f, 0x66, 0x69, 0x63, 0x69, 0x6f, 0x5f, 0x38, 0x2e, 0x35, 0x78, 0x31, 0x33, 0x2e, 0x34, 0x69, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x10, 0x6f, 0x6d, 0x5f, 0x31, 0x36, 0x6b, 0x5f, 0x31, 0x39, 0x35, 0x78, 0x32, 0x37, 0x30, 0x6d, 0x6d, 0x44, 0x00, 0x00, 0x00, 0x10, 0x6f, 0x6d, 0x5f, 0x31, 0x36, 0x6b, 0x5f, 0x31, 0x38, 0x34, 0x78, 0x32, 0x36, 0x30, 0x6d, 0x6d, 0x44, 0x00, 0x00, 0x00, 0x14, 0x72, 0x6f, 0x63, 0x5f, 0x31, 0x36, 0x6b, 0x5f, 0x37, 0x2e, 0x37, 0x35, 0x78, 0x31, 0x30, 0x2e, 0x37, 0x35, 0x69, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x14, 0x6a, 0x70, 0x6e, 0x5f, 0x6f, 0x75, 0x66, 0x75, 0x6b, 0x75, 0x5f, 0x31, 0x34, 0x38, 0x78, 0x32, 0x30, 0x30, 0x6d, 0x6d, 0x44, 0x00, 0x00, 0x00, 0x18, 0x6e, 0x61, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x2d, 0x31, 0x30, 0x5f, 0x34, 0x2e, 0x31, 0x32, 0x35, 0x78, 0x39, 0x2e, 0x35, 0x69, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x16, 0x6e, 0x61, 0x5f, 0x6d, 0x6f, 0x6e, 0x61, 0x72, 0x63, 0x68, 0x5f, 0x33, 0x2e, 0x38, 0x37, 0x35, 0x78, 0x37, 0x2e, 0x35, 0x69, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x10, 0x69, 0x73, 0x6f, 0x5f, 0x62, 0x35, 0x5f, 0x31, 0x37, 0x36, 0x78, 0x32, 0x35, 0x30, 0x6d, 0x6d, 0x44, 0x00, 0x00, 0x00, 0x10, 0x69, 0x73, 0x6f, 0x5f, 0x63, 0x35, 0x5f, 0x31, 0x36, 0x32, 0x78, 0x32, 0x32, 0x39, 0x6d, 0x6d, 0x44, 0x00, 0x00, 0x00, 0x10, 0x69, 0x73, 0x6f, 0x5f, 0x63, 0x36, 0x5f, 0x31, 0x31, 0x34, 0x78, 0x31, 0x36, 0x32, 0x6d, 0x6d, 0x44, 0x00, 0x00, 0x00, 0x10, 0x69, 0x73, 0x6f, 0x5f, 0x64, 0x6c, 0x5f, 0x31, 0x31, 0x30, 0x78, 0x32, 0x32, 0x30, 0x6d, 0x6d, 0x44, 0x00, 0x00, 0x00, 0x13, 0x6a, 0x70, 0x6e, 0x5f, 0x63, 0x68, 0x6f, 0x75, 0x33, 0x5f, 0x31, 0x32, 0x30, 0x78, 0x32, 0x33, 0x35, 0x6d, 0x6d, 0x44, 0x00, 0x00, 0x00, 0x12, 0x6a, 0x70, 0x6e, 0x5f, 0x63, 0x68, 0x6f, 0x75, 0x34, 0x5f, 0x39, 0x30, 0x78, 0x32, 0x30, 0x35, 0x6d, 0x6d, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x2d, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x00, 0x00, 0x00, 0x0c, 0x64, 0x75, 0x70, 0x6c, 0x65, 0x78, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x4a, 0x00, 0x00, 0x00, 0x05, 0x73, 0x69, 0x64, 0x65, 0x73, 0x44, 0x00, 0x00, 0x00, 0x14, 0x74, 0x77, 0x6f, 0x2d, 0x73, 0x69, 0x64, 0x65, 0x64, 0x2d, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x2d, 0x65, 0x64, 0x67, 0x65, 0x44, 0x00, 0x00, 0x00, 0x13, 0x74, 0x77, 0x6f, 0x2d, 0x73, 0x69, 0x64, 0x65, 0x64, 0x2d, 0x6c, 0x6f, 0x6e, 0x67, 0x2d, 0x65, 0x64, 0x67, 0x65, 0x4a, 0x00, 0x00, 0x00, 0x05, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x44, 0x00, 0x00, 0x00, 0x12, 0x6e, 0x61, 0x5f, 0x6c, 0x65, 0x74, 0x74, 0x65, 0x72, 0x5f, 0x38, 0x2e, 0x35, 0x78, 0x31, 0x31, 0x69, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x11, 0x6e, 0x61, 0x5f, 0x6c, 0x65, 0x67, 0x61, 0x6c, 0x5f, 0x38, 0x2e, 0x35, 0x78, 0x31, 0x34, 0x69, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x18, 0x6e, 0x61, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x37, 0x2e, 0x32, 0x35, 0x78, 0x31, 0x30, 0x2e, 0x35, 0x69, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x14, 0x6e, 0x61, 0x5f, 0x66, 0x6f, 0x6f, 0x6c, 0x73, 0x63, 0x61, 0x70, 0x5f, 0x38, 0x2e, 0x35, 0x78, 0x31, 0x33, 0x69, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x10, 0x69, 0x73, 0x6f, 0x5f, 0x61, 0x34, 0x5f, 0x32, 0x31, 0x30, 0x78, 0x32, 0x39, 0x37, 0x6d, 0x6d, 0x44, 0x00, 0x00, 0x00, 0x10, 0x6a, 0x69, 0x73, 0x5f, 0x62, 0x35, 0x5f, 0x31, 0x38, 0x32, 0x78, 0x32, 0x35, 0x37, 0x6d, 0x6d, 0x44, 0x00, 0x00, 0x00, 0x14, 0x6e, 0x61, 0x5f, 0x6f, 0x66, 0x69, 0x63, 0x69, 0x6f, 0x5f, 0x38, 0x2e, 0x35, 0x78, 0x31, 0x33, 0x2e, 0x34, 0x69, 0x6e, 0x4a, 0x00, 0x00, 0x00, 0x0a, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x44, 0x00, 0x00, 0x00, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x70, 0x2e, 0x61, 0x64, 0x76, 0x61, 0x6e, 0x63, 0x65, 0x64, 0x2d, 0x70, 0x68, 0x6f, 0x74, 0x6f, 0x44, 0x00, 0x00, 0x00, 0x09, 0x63, 0x61, 0x72, 0x64, 0x73, 0x74, 0x6f, 0x63, 0x6b, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x2d, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x00, 0x00, 0x00, 0x0c, 0x64, 0x75, 0x70, 0x6c, 0x65, 0x78, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x73, 0x4a, 0x00, 0x00, 0x00, 0x05, 0x73, 0x69, 0x64, 0x65, 0x73, 0x44, 0x00, 0x00, 0x00, 0x14, 0x74, 0x77, 0x6f, 0x2d, 0x73, 0x69, 0x64, 0x65, 0x64, 0x2d, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x2d, 0x65, 0x64, 0x67, 0x65, 0x44, 0x00, 0x00, 0x00, 0x13, 0x74, 0x77, 0x6f, 0x2d, 0x73, 0x69, 0x64, 0x65, 0x64, 0x2d, 0x6c, 0x6f, 0x6e, 0x67, 0x2d, 0x65, 0x64, 0x67, 0x65, 0x4a, 0x00, 0x00, 0x00, 0x05, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x44, 0x00, 0x00, 0x00, 0x14, 0x6e, 0x61, 0x5f, 0x69, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x5f, 0x35, 0x2e, 0x35, 0x78, 0x38, 0x2e, 0x35, 0x69, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x12, 0x6e, 0x61, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2d, 0x33, 0x78, 0x35, 0x5f, 0x33, 0x78, 0x35, 0x69, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x12, 0x6e, 0x61, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2d, 0x34, 0x78, 0x36, 0x5f, 0x34, 0x78, 0x36, 0x69, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x0c, 0x6e, 0x61, 0x5f, 0x35, 0x78, 0x37, 0x5f, 0x35, 0x78, 0x37, 0x69, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x12, 0x6e, 0x61, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2d, 0x35, 0x78, 0x38, 0x5f, 0x35, 0x78, 0x38, 0x69, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x10, 0x69, 0x73, 0x6f, 0x5f, 0x61, 0x35, 0x5f, 0x31, 0x34, 0x38, 0x78, 0x32, 0x31, 0x30, 0x6d, 0x6d, 0x44, 0x00, 0x00, 0x00, 0x10, 0x69, 0x73, 0x6f, 0x5f, 0x61, 0x36, 0x5f, 0x31, 0x30, 0x35, 0x78, 0x31, 0x34, 0x38, 0x6d, 0x6d, 0x44, 0x00, 0x00, 0x00, 0x12, 0x6f, 0x65, 0x5f, 0x70, 0x68, 0x6f, 0x74, 0x6f, 0x2d, 0x6c, 0x5f, 0x33, 0x2e, 0x35, 0x78, 0x35, 0x69, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x18, 0x6f, 0x6d, 0x5f, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x2d, 0x70, 0x68, 0x6f, 0x74, 0x6f, 0x5f, 0x31, 0x30, 0x30, 0x78, 0x31, 0x35, 0x30, 0x6d, 0x6d, 0x44, 0x00, 0x00, 0x00, 0x10, 0x6f, 0x6d, 0x5f, 0x31, 0x36, 0x6b, 0x5f, 0x31, 0x39, 0x35, 0x78, 0x32, 0x37, 0x30, 0x6d, 0x6d, 0x44, 0x00, 0x00, 0x00, 0x10, 0x6f, 0x6d, 0x5f, 0x31, 0x36, 0x6b, 0x5f, 0x31, 0x38, 0x34, 0x78, 0x32, 0x36, 0x30, 0x6d, 0x6d, 0x44, 0x00, 0x00, 0x00, 0x14, 0x72, 0x6f, 0x63, 0x5f, 0x31, 0x36, 0x6b, 0x5f, 0x37, 0x2e, 0x37, 0x35, 0x78, 0x31, 0x30, 0x2e, 0x37, 0x35, 0x69, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x14, 0x6a, 0x70, 0x6e, 0x5f, 0x68, 0x61, 0x67, 0x61, 0x6b, 0x69, 0x5f, 0x31, 0x30, 0x30, 0x78, 0x31, 0x34, 0x38, 0x6d, 0x6d, 0x44, 0x00, 0x00, 0x00, 0x14, 0x6a, 0x70, 0x6e, 0x5f, 0x6f, 0x75, 0x66, 0x75, 0x6b, 0x75, 0x5f, 0x31, 0x34, 0x38, 0x78, 0x32, 0x30, 0x30, 0x6d, 0x6d, 0x44, 0x00, 0x00, 0x00, 0x18, 0x6e, 0x61, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x2d, 0x31, 0x30, 0x5f, 0x34, 0x2e, 0x31, 0x32, 0x35, 0x78, 0x39, 0x2e, 0x35, 0x69, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x16, 0x6e, 0x61, 0x5f, 0x6d, 0x6f, 0x6e, 0x61, 0x72, 0x63, 0x68, 0x5f, 0x33, 0x2e, 0x38, 0x37, 0x35, 0x78, 0x37, 0x2e, 0x35, 0x69, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x10, 0x69, 0x73, 0x6f, 0x5f, 0x62, 0x35, 0x5f, 0x31, 0x37, 0x36, 0x78, 0x32, 0x35, 0x30, 0x6d, 0x6d, 0x44, 0x00, 0x00, 0x00, 0x10, 0x69, 0x73, 0x6f, 0x5f, 0x63, 0x35, 0x5f, 0x31, 0x36, 0x32, 0x78, 0x32, 0x32, 0x39, 0x6d, 0x6d, 0x44, 0x00, 0x00, 0x00, 0x10, 0x69, 0x73, 0x6f, 0x5f, 0x63, 0x36, 0x5f, 0x31, 0x31, 0x34, 0x78, 0x31, 0x36, 0x32, 0x6d, 0x6d, 0x44, 0x00, 0x00, 0x00, 0x10, 0x69, 0x73, 0x6f, 0x5f, 0x64, 0x6c, 0x5f, 0x31, 0x31, 0x30, 0x78, 0x32, 0x32, 0x30, 0x6d, 0x6d, 0x44, 0x00, 0x00, 0x00, 0x13, 0x6a, 0x70, 0x6e, 0x5f, 0x63, 0x68, 0x6f, 0x75, 0x33, 0x5f, 0x31, 0x32, 0x30, 0x78, 0x32, 0x33, 0x35, 0x6d, 0x6d, 0x44, 0x00, 0x00, 0x00, 0x12, 0x6a, 0x70, 0x6e, 0x5f, 0x63, 0x68, 0x6f, 0x75, 0x34, 0x5f, 0x39, 0x30, 0x78, 0x32, 0x30, 0x35, 0x6d, 0x6d, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x17, 0x6a, 0x6f, 0x62, 0x2d, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x73, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x2d, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x00, 0x00, 0x00, 0x0f, 0x66, 0x75, 0x6c, 0x6c, 0x62, 0x6c, 0x65, 0x65, 0x64, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x73, 0x4a, 0x00, 0x00, 0x00, 0x10, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x74, 0x6f, 0x70, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x28, 0x4a, 0x00, 0x00, 0x00, 0x13, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x28, 0x4a, 0x00, 0x00, 0x00, 0x11, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x28, 0x4a, 0x00, 0x00, 0x00, 0x12, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x72, 0x69, 0x67, 0x68, 0x74, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x28, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x2d, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x00, 0x00, 0x00, 0x0c, 0x64, 0x75, 0x70, 0x6c, 0x65, 0x78, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x4a, 0x00, 0x00, 0x00, 0x05, 0x73, 0x69, 0x64, 0x65, 0x73, 0x44, 0x00, 0x00, 0x00, 0x09, 0x6f, 0x6e, 0x65, 0x2d, 0x73, 0x69, 0x64, 0x65, 0x64, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x2d, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x00, 0x00, 0x00, 0x0c, 0x64, 0x75, 0x70, 0x6c, 0x65, 0x78, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x73, 0x4a, 0x00, 0x00, 0x00, 0x05, 0x73, 0x69, 0x64, 0x65, 0x73, 0x44, 0x00, 0x00, 0x00, 0x09, 0x6f, 0x6e, 0x65, 0x2d, 0x73, 0x69, 0x64, 0x65, 0x64, 0x37, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x16, 0x69, 0x70, 0x70, 0x2d, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x0c, 0x61, 0x69, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x2d, 0x31, 0x2e, 0x35, 0x44, 0x00, 0x00, 0x00, 0x0e, 0x69, 0x70, 0x70, 0x2d, 0x65, 0x76, 0x65, 0x72, 0x79, 0x77, 0x68, 0x65, 0x72, 0x65, 0x44, 0x00, 0x14, 0x77, 0x68, 0x69, 0x63, 0x68, 0x2d, 0x6a, 0x6f, 0x62, 0x73, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x09, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x44, 0x00, 0x00, 0x00, 0x0d, 0x6e, 0x6f, 0x74, 0x2d, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x44, 0x00, 0x00, 0x00, 0x03, 0x61, 0x6c, 0x6c, 0x22, 0x00, 0x11, 0x6a, 0x6f, 0x62, 0x2d, 0x69, 0x64, 0x73, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x01, 0x01, 0x22, 0x00, 0x1d, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2d, 0x75, 0x73, 0x65, 0x72, 0x2d, 0x75, 0x72, 0x69, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x01, 0x01, 0x44, 0x00, 0x22, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x2d, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x74, 0x69, 0x6d, 0x65, 0x2d, 0x6f, 0x75, 0x74, 0x2d, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x0b, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x2d, 0x6a, 0x6f, 0x62, 0x12, 0x00, 0x14, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x67, 0x65, 0x6f, 0x2d, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x41, 0x00, 0x10, 0x6d, 0x6f, 0x70, 0x72, 0x69, 0x61, 0x2d, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x65, 0x64, 0x00, 0x03, 0x31, 0x2e, 0x33, 0x22, 0x00, 0x1e, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 0x2d, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x01, 0x00, 0x31, 0x00, 0x1f, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2d, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x2d, 0x64, 0x61, 0x74, 0x65, 0x2d, 0x74, 0x69, 0x6d, 0x65, 0x00, 0x0b, 0x07, 0xe4, 0x01, 0x13, 0x0a, 0x31, 0x10, 0x00, 0x2b, 0x00, 0x00, 0x21, 0x00, 0x1a, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2d, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x2d, 0x74, 0x69, 0x6d, 0x65, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x1e, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2d, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x2d, 0x64, 0x61, 0x74, 0x65, 0x2d, 0x74, 0x69, 0x6d, 0x65, 0x00, 0x0b, 0x07, 0xe4, 0x01, 0x13, 0x0a, 0x31, 0x10, 0x00, 0x2b, 0x00, 0x00, 0x21, 0x00, 0x19, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2d, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x2d, 0x74, 0x69, 0x6d, 0x65, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x1b, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x0c, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x6b, 0x69, 0x6e, 0x64, 0x00, 0x08, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x00, 0x00, 0x00, 0x08, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x44, 0x00, 0x00, 0x00, 0x05, 0x70, 0x68, 0x6f, 0x74, 0x6f, 0x44, 0x00, 0x00, 0x00, 0x08, 0x70, 0x6f, 0x73, 0x74, 0x63, 0x61, 0x72, 0x64, 0x44, 0x00, 0x0f, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x12, 0x6e, 0x61, 0x5f, 0x6c, 0x65, 0x74, 0x74, 0x65, 0x72, 0x5f, 0x38, 0x2e, 0x35, 0x78, 0x31, 0x31, 0x69, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x11, 0x6e, 0x61, 0x5f, 0x6c, 0x65, 0x67, 0x61, 0x6c, 0x5f, 0x38, 0x2e, 0x35, 0x78, 0x31, 0x34, 0x69, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x18, 0x6e, 0x61, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x37, 0x2e, 0x32, 0x35, 0x78, 0x31, 0x30, 0x2e, 0x35, 0x69, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x14, 0x6e, 0x61, 0x5f, 0x69, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x5f, 0x35, 0x2e, 0x35, 0x78, 0x38, 0x2e, 0x35, 0x69, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x14, 0x6e, 0x61, 0x5f, 0x66, 0x6f, 0x6f, 0x6c, 0x73, 0x63, 0x61, 0x70, 0x5f, 0x38, 0x2e, 0x35, 0x78, 0x31, 0x33, 0x69, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x12, 0x6e, 0x61, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2d, 0x33, 0x78, 0x35, 0x5f, 0x33, 0x78, 0x35, 0x69, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x12, 0x6e, 0x61, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2d, 0x34, 0x78, 0x36, 0x5f, 0x34, 0x78, 0x36, 0x69, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x0c, 0x6e, 0x61, 0x5f, 0x35, 0x78, 0x37, 0x5f, 0x35, 0x78, 0x37, 0x69, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x12, 0x6e, 0x61, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2d, 0x35, 0x78, 0x38, 0x5f, 0x35, 0x78, 0x38, 0x69, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x10, 0x69, 0x73, 0x6f, 0x5f, 0x61, 0x34, 0x5f, 0x32, 0x31, 0x30, 0x78, 0x32, 0x39, 0x37, 0x6d, 0x6d, 0x44, 0x00, 0x00, 0x00, 0x10, 0x69, 0x73, 0x6f, 0x5f, 0x61, 0x35, 0x5f, 0x31, 0x34, 0x38, 0x78, 0x32, 0x31, 0x30, 0x6d, 0x6d, 0x44, 0x00, 0x00, 0x00, 0x10, 0x69, 0x73, 0x6f, 0x5f, 0x61, 0x36, 0x5f, 0x31, 0x30, 0x35, 0x78, 0x31, 0x34, 0x38, 0x6d, 0x6d, 0x44, 0x00, 0x00, 0x00, 0x10, 0x6a, 0x69, 0x73, 0x5f, 0x62, 0x35, 0x5f, 0x31, 0x38, 0x32, 0x78, 0x32, 0x35, 0x37, 0x6d, 0x6d, 0x44, 0x00, 0x00, 0x00, 0x12, 0x6f, 0x65, 0x5f, 0x70, 0x68, 0x6f, 0x74, 0x6f, 0x2d, 0x6c, 0x5f, 0x33, 0x2e, 0x35, 0x78, 0x35, 0x69, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x18, 0x6f, 0x6d, 0x5f, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x2d, 0x70, 0x68, 0x6f, 0x74, 0x6f, 0x5f, 0x31, 0x30, 0x30, 0x78, 0x31, 0x35, 0x30, 0x6d, 0x6d, 0x44, 0x00, 0x00, 0x00, 0x14, 0x6e, 0x61, 0x5f, 0x6f, 0x66, 0x69, 0x63, 0x69, 0x6f, 0x5f, 0x38, 0x2e, 0x35, 0x78, 0x31, 0x33, 0x2e, 0x34, 0x69, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x10, 0x6f, 0x6d, 0x5f, 0x31, 0x36, 0x6b, 0x5f, 0x31, 0x39, 0x35, 0x78, 0x32, 0x37, 0x30, 0x6d, 0x6d, 0x44, 0x00, 0x00, 0x00, 0x10, 0x6f, 0x6d, 0x5f, 0x31, 0x36, 0x6b, 0x5f, 0x31, 0x38, 0x34, 0x78, 0x32, 0x36, 0x30, 0x6d, 0x6d, 0x44, 0x00, 0x00, 0x00, 0x14, 0x72, 0x6f, 0x63, 0x5f, 0x31, 0x36, 0x6b, 0x5f, 0x37, 0x2e, 0x37, 0x35, 0x78, 0x31, 0x30, 0x2e, 0x37, 0x35, 0x69, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x14, 0x6a, 0x70, 0x6e, 0x5f, 0x68, 0x61, 0x67, 0x61, 0x6b, 0x69, 0x5f, 0x31, 0x30, 0x30, 0x78, 0x31, 0x34, 0x38, 0x6d, 0x6d, 0x44, 0x00, 0x00, 0x00, 0x14, 0x6a, 0x70, 0x6e, 0x5f, 0x6f, 0x75, 0x66, 0x75, 0x6b, 0x75, 0x5f, 0x31, 0x34, 0x38, 0x78, 0x32, 0x30, 0x30, 0x6d, 0x6d, 0x44, 0x00, 0x00, 0x00, 0x18, 0x6e, 0x61, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x2d, 0x31, 0x30, 0x5f, 0x34, 0x2e, 0x31, 0x32, 0x35, 0x78, 0x39, 0x2e, 0x35, 0x69, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x16, 0x6e, 0x61, 0x5f, 0x6d, 0x6f, 0x6e, 0x61, 0x72, 0x63, 0x68, 0x5f, 0x33, 0x2e, 0x38, 0x37, 0x35, 0x78, 0x37, 0x2e, 0x35, 0x69, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x10, 0x69, 0x73, 0x6f, 0x5f, 0x62, 0x35, 0x5f, 0x31, 0x37, 0x36, 0x78, 0x32, 0x35, 0x30, 0x6d, 0x6d, 0x44, 0x00, 0x00, 0x00, 0x10, 0x69, 0x73, 0x6f, 0x5f, 0x63, 0x35, 0x5f, 0x31, 0x36, 0x32, 0x78, 0x32, 0x32, 0x39, 0x6d, 0x6d, 0x44, 0x00, 0x00, 0x00, 0x10, 0x69, 0x73, 0x6f, 0x5f, 0x63, 0x36, 0x5f, 0x31, 0x31, 0x34, 0x78, 0x31, 0x36, 0x32, 0x6d, 0x6d, 0x44, 0x00, 0x00, 0x00, 0x10, 0x69, 0x73, 0x6f, 0x5f, 0x64, 0x6c, 0x5f, 0x31, 0x31, 0x30, 0x78, 0x32, 0x32, 0x30, 0x6d, 0x6d, 0x44, 0x00, 0x00, 0x00, 0x13, 0x6a, 0x70, 0x6e, 0x5f, 0x63, 0x68, 0x6f, 0x75, 0x33, 0x5f, 0x31, 0x32, 0x30, 0x78, 0x32, 0x33, 0x35, 0x6d, 0x6d, 0x44, 0x00, 0x00, 0x00, 0x12, 0x6a, 0x70, 0x6e, 0x5f, 0x63, 0x68, 0x6f, 0x75, 0x34, 0x5f, 0x39, 0x30, 0x78, 0x32, 0x30, 0x35, 0x6d, 0x6d, 0x44, 0x00, 0x00, 0x00, 0x10, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x33, 0x78, 0x35, 0x69, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x13, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x38, 0x2e, 0x35, 0x78, 0x31, 0x34, 0x69, 0x6e, 0x44, 0x00, 0x0d, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x00, 0x10, 0x69, 0x73, 0x6f, 0x5f, 0x61, 0x34, 0x5f, 0x32, 0x31, 0x30, 0x78, 0x32, 0x39, 0x37, 0x6d, 0x6d, 0x44, 0x00, 0x13, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x63, 0x6f, 0x6c, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x0a, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x44, 0x00, 0x00, 0x00, 0x0a, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x44, 0x00, 0x00, 0x00, 0x10, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x74, 0x6f, 0x70, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x11, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x12, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x72, 0x69, 0x67, 0x68, 0x74, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x13, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x44, 0x00, 0x00, 0x00, 0x0c, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x44, 0x00, 0x00, 0x00, 0x0f, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x2d, 0x6e, 0x61, 0x6d, 0x65, 0x34, 0x00, 0x11, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x63, 0x6f, 0x6c, 0x2d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0a, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x34, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x52, 0x08, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x74, 0x04, 0x37, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x10, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x74, 0x6f, 0x70, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x28, 0x4a, 0x00, 0x00, 0x00, 0x13, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x28, 0x4a, 0x00, 0x00, 0x00, 0x11, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x28, 0x4a, 0x00, 0x00, 0x00, 0x12, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x72, 0x69, 0x67, 0x68, 0x74, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x28, 0x4a, 0x00, 0x00, 0x00, 0x0c, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x44, 0x00, 0x00, 0x00, 0x04, 0x6d, 0x61, 0x69, 0x6e, 0x4a, 0x00, 0x00, 0x00, 0x0a, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x44, 0x00, 0x00, 0x00, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x79, 0x37, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x17, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x2d, 0x63, 0x6f, 0x6c, 0x2d, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x00, 0x00, 0x21, 0x00, 0x1b, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x04, 0x00, 0x00, 0x01, 0x28, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x1c, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x72, 0x69, 0x67, 0x68, 0x74, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x04, 0x00, 0x00, 0x01, 0x28, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x1a, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x74, 0x6f, 0x70, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x04, 0x00, 0x00, 0x01, 0x28, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x1d, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x04, 0x00, 0x00, 0x01, 0x28, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x16, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x04, 0x6d, 0x61, 0x69, 0x6e, 0x44, 0x00, 0x14, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x79, 0x44, 0x00, 0x00, 0x00, 0x14, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x70, 0x2e, 0x65, 0x63, 0x6f, 0x73, 0x6d, 0x61, 0x72, 0x74, 0x2d, 0x6c, 0x69, 0x74, 0x65, 0x44, 0x00, 0x00, 0x00, 0x21, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x70, 0x2e, 0x70, 0x72, 0x65, 0x6d, 0x69, 0x75, 0x6d, 0x2d, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x6d, 0x61, 0x74, 0x74, 0x65, 0x44, 0x00, 0x00, 0x00, 0x25, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x70, 0x2e, 0x74, 0x72, 0x69, 0x66, 0x6f, 0x6c, 0x64, 0x2d, 0x62, 0x72, 0x6f, 0x63, 0x68, 0x75, 0x72, 0x65, 0x2d, 0x67, 0x6c, 0x6f, 0x73, 0x73, 0x79, 0x2d, 0x31, 0x38, 0x30, 0x67, 0x73, 0x6d, 0x44, 0x00, 0x00, 0x00, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x70, 0x2e, 0x62, 0x72, 0x6f, 0x63, 0x68, 0x75, 0x72, 0x65, 0x2d, 0x6d, 0x61, 0x74, 0x74, 0x65, 0x44, 0x00, 0x00, 0x00, 0x16, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x70, 0x2e, 0x62, 0x72, 0x6f, 0x63, 0x68, 0x75, 0x72, 0x65, 0x2d, 0x67, 0x6c, 0x6f, 0x73, 0x73, 0x79, 0x44, 0x00, 0x00, 0x00, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x70, 0x2e, 0x61, 0x64, 0x76, 0x61, 0x6e, 0x63, 0x65, 0x64, 0x2d, 0x70, 0x68, 0x6f, 0x74, 0x6f, 0x44, 0x00, 0x00, 0x00, 0x16, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x79, 0x2d, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x44, 0x00, 0x00, 0x00, 0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x70, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x44, 0x00, 0x00, 0x00, 0x09, 0x63, 0x61, 0x72, 0x64, 0x73, 0x74, 0x6f, 0x63, 0x6b, 0x44, 0x00, 0x00, 0x00, 0x16, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x79, 0x2d, 0x68, 0x65, 0x61, 0x76, 0x79, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x44, 0x00, 0x00, 0x00, 0x15, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x79, 0x2d, 0x6c, 0x65, 0x74, 0x74, 0x65, 0x72, 0x68, 0x65, 0x61, 0x64, 0x34, 0x00, 0x14, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x54, 0x56, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x6d, 0x24, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x54, 0x56, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x8a, 0xe8, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x47, 0xef, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x68, 0x2e, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x36, 0x92, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x54, 0x56, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x54, 0x56, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x80, 0xfc, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x1d, 0xc4, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x31, 0x9c, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x27, 0xb0, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x3b, 0x88, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x31, 0x9c, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x45, 0x74, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x31, 0x9c, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x4f, 0x60, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x52, 0x08, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x74, 0x04, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x39, 0xd0, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x52, 0x08, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x29, 0x04, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x39, 0xd0, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x47, 0x18, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x64, 0x64, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x22, 0xba, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x31, 0x9c, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x27, 0x10, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x3a, 0x98, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x54, 0x56, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x84, 0xf4, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x4c, 0x2c, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x69, 0x78, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x47, 0xe0, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x65, 0x90, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x4c, 0xe5, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x6a, 0xa9, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x27, 0x10, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x39, 0xd0, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x39, 0xd0, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x4e, 0x20, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x28, 0xed, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x5e, 0x42, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x26, 0x72, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x4a, 0x6a, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x44, 0xc0, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x61, 0xa8, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x3f, 0x48, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x59, 0x74, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x2c, 0x88, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x3f, 0x48, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x2a, 0xf8, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x55, 0xf0, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x2e, 0xe0, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x5b, 0xcc, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x23, 0x28, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x50, 0x14, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x33, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x1d, 0xc4, 0x00, 0x00, 0x54, 0x56, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x33, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x31, 0x9c, 0x00, 0x00, 0x8a, 0xe8, 0x37, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x0b, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x72, 0x65, 0x61, 0x64, 0x79, 0x00, 0x10, 0x69, 0x73, 0x6f, 0x5f, 0x61, 0x34, 0x5f, 0x32, 0x31, 0x30, 0x78, 0x32, 0x39, 0x37, 0x6d, 0x6d, 0x34, 0x00, 0x0f, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x63, 0x6f, 0x6c, 0x2d, 0x72, 0x65, 0x61, 0x64, 0x79, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0a, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x34, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x52, 0x08, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x74, 0x04, 0x37, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x10, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x74, 0x6f, 0x70, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x28, 0x4a, 0x00, 0x00, 0x00, 0x13, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x28, 0x4a, 0x00, 0x00, 0x00, 0x11, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x28, 0x4a, 0x00, 0x00, 0x00, 0x12, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x72, 0x69, 0x67, 0x68, 0x74, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x28, 0x4a, 0x00, 0x00, 0x00, 0x0c, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x44, 0x00, 0x00, 0x00, 0x04, 0x6d, 0x61, 0x69, 0x6e, 0x4a, 0x00, 0x00, 0x00, 0x0a, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x44, 0x00, 0x00, 0x00, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x79, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0a, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x34, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x52, 0x08, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x74, 0x04, 0x37, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x10, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x74, 0x6f, 0x70, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x13, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x11, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x12, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x72, 0x69, 0x67, 0x68, 0x74, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0c, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x44, 0x00, 0x00, 0x00, 0x04, 0x6d, 0x61, 0x69, 0x6e, 0x4a, 0x00, 0x00, 0x00, 0x0a, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x44, 0x00, 0x00, 0x00, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x79, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0a, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x34, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x52, 0x08, 0x4a, 0x00, 0x00, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x74, 0x04, 0x37, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x10, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x74, 0x6f, 0x70, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x28, 0x4a, 0x00, 0x00, 0x00, 0x13, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x28, 0x4a, 0x00, 0x00, 0x00, 0x11, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x28, 0x4a, 0x00, 0x00, 0x00, 0x12, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x72, 0x69, 0x67, 0x68, 0x74, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x28, 0x4a, 0x00, 0x00, 0x00, 0x0c, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x44, 0x00, 0x00, 0x00, 0x04, 0x6d, 0x61, 0x69, 0x6e, 0x4a, 0x00, 0x00, 0x00, 0x0a, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x44, 0x00, 0x00, 0x00, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x79, 0x37, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x14, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x2d, 0x63, 0x6f, 0x6c, 0x2d, 0x72, 0x65, 0x61, 0x64, 0x79, 0x00, 0x00, 0x44, 0x00, 0x18, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x2d, 0x63, 0x6f, 0x6c, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x12, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x2d, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x30, 0x00, 0x10, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x72, 0x00, 0x00, 0x30, 0x00, 0x1c, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x72, 0x2d, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x21, 0x00, 0x10, 0x70, 0x61, 0x67, 0x65, 0x73, 0x2d, 0x70, 0x65, 0x72, 0x2d, 0x6d, 0x69, 0x6e, 0x75, 0x74, 0x65, 0x00, 0x04, 0x00, 0x00, 0x00, 0x18, 0x21, 0x00, 0x16, 0x70, 0x61, 0x67, 0x65, 0x73, 0x2d, 0x70, 0x65, 0x72, 0x2d, 0x6d, 0x69, 0x6e, 0x75, 0x74, 0x65, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x04, 0x00, 0x00, 0x00, 0x14, 0x33, 0x00, 0x17, 0x6a, 0x70, 0x65, 0x67, 0x2d, 0x6b, 0x2d, 0x6f, 0x63, 0x74, 0x65, 0x74, 0x73, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x33, 0x00, 0x1a, 0x6a, 0x70, 0x65, 0x67, 0x2d, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x33, 0x00, 0x1a, 0x6a, 0x70, 0x65, 0x67, 0x2d, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x40, 0x00, 0x33, 0x00, 0x16, 0x70, 0x64, 0x66, 0x2d, 0x6b, 0x2d, 0x6f, 0x63, 0x74, 0x65, 0x74, 0x73, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x33, 0x00, 0x14, 0x70, 0x64, 0x66, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x2d, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x73, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x22, 0x00, 0x17, 0x70, 0x64, 0x66, 0x2d, 0x66, 0x69, 0x74, 0x2d, 0x74, 0x6f, 0x2d, 0x70, 0x61, 0x67, 0x65, 0x2d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x00, 0x01, 0x00, 0x22, 0x00, 0x19, 0x70, 0x64, 0x66, 0x2d, 0x66, 0x69, 0x74, 0x2d, 0x74, 0x6f, 0x2d, 0x70, 0x61, 0x67, 0x65, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x01, 0x00, 0x44, 0x00, 0x16, 0x70, 0x64, 0x66, 0x2d, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x10, 0x69, 0x73, 0x6f, 0x2d, 0x33, 0x32, 0x30, 0x30, 0x30, 0x2d, 0x31, 0x5f, 0x32, 0x30, 0x30, 0x38, 0x44, 0x00, 0x00, 0x00, 0x09, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2d, 0x31, 0x2e, 0x37, 0x44, 0x00, 0x00, 0x00, 0x09, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2d, 0x31, 0x2e, 0x36, 0x44, 0x00, 0x00, 0x00, 0x09, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2d, 0x31, 0x2e, 0x35, 0x44, 0x00, 0x00, 0x00, 0x10, 0x69, 0x73, 0x6f, 0x2d, 0x31, 0x39, 0x30, 0x30, 0x35, 0x2d, 0x31, 0x5f, 0x32, 0x30, 0x30, 0x35, 0x44, 0x00, 0x00, 0x00, 0x09, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2d, 0x31, 0x2e, 0x34, 0x44, 0x00, 0x00, 0x00, 0x09, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2d, 0x31, 0x2e, 0x33, 0x44, 0x00, 0x00, 0x00, 0x09, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2d, 0x31, 0x2e, 0x32, 0x44, 0x00, 0x0d, 0x75, 0x72, 0x66, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x03, 0x43, 0x50, 0x31, 0x44, 0x00, 0x00, 0x00, 0x0f, 0x4d, 0x54, 0x31, 0x2d, 0x32, 0x2d, 0x38, 0x2d, 0x39, 0x2d, 0x31, 0x30, 0x2d, 0x31, 0x31, 0x44, 0x00, 0x00, 0x00, 0x07, 0x50, 0x51, 0x33, 0x2d, 0x34, 0x2d, 0x35, 0x44, 0x00, 0x00, 0x00, 0x09, 0x52, 0x53, 0x33, 0x30, 0x30, 0x2d, 0x36, 0x30, 0x30, 0x44, 0x00, 0x00, 0x00, 0x06, 0x53, 0x52, 0x47, 0x42, 0x32, 0x34, 0x44, 0x00, 0x00, 0x00, 0x04, 0x4f, 0x42, 0x31, 0x30, 0x44, 0x00, 0x00, 0x00, 0x02, 0x57, 0x38, 0x44, 0x00, 0x00, 0x00, 0x05, 0x44, 0x45, 0x56, 0x57, 0x38, 0x44, 0x00, 0x00, 0x00, 0x08, 0x44, 0x45, 0x56, 0x52, 0x47, 0x42, 0x32, 0x34, 0x44, 0x00, 0x00, 0x00, 0x0a, 0x41, 0x44, 0x4f, 0x42, 0x45, 0x52, 0x47, 0x42, 0x32, 0x34, 0x44, 0x00, 0x00, 0x00, 0x03, 0x44, 0x4d, 0x33, 0x44, 0x00, 0x00, 0x00, 0x03, 0x46, 0x4e, 0x33, 0x44, 0x00, 0x00, 0x00, 0x05, 0x49, 0x53, 0x31, 0x2d, 0x32, 0x44, 0x00, 0x00, 0x00, 0x04, 0x56, 0x31, 0x2e, 0x34, 0x42, 0x00, 0x0c, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x2d, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x00, 0x08, 0x63, 0x79, 0x61, 0x6e, 0x20, 0x69, 0x6e, 0x6b, 0x42, 0x00, 0x00, 0x00, 0x0b, 0x6d, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x61, 0x20, 0x69, 0x6e, 0x6b, 0x42, 0x00, 0x00, 0x00, 0x0a, 0x79, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x20, 0x69, 0x6e, 0x6b, 0x42, 0x00, 0x00, 0x00, 0x09, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x20, 0x69, 0x6e, 0x6b, 0x42, 0x00, 0x0d, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x00, 0x07, 0x23, 0x30, 0x30, 0x46, 0x46, 0x46, 0x46, 0x42, 0x00, 0x00, 0x00, 0x07, 0x23, 0x46, 0x46, 0x30, 0x30, 0x46, 0x46, 0x42, 0x00, 0x00, 0x00, 0x07, 0x23, 0x46, 0x46, 0x46, 0x46, 0x30, 0x30, 0x42, 0x00, 0x00, 0x00, 0x07, 0x23, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x44, 0x00, 0x0c, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x00, 0x0d, 0x69, 0x6e, 0x6b, 0x2d, 0x63, 0x61, 0x72, 0x74, 0x72, 0x69, 0x64, 0x67, 0x65, 0x44, 0x00, 0x00, 0x00, 0x0d, 0x69, 0x6e, 0x6b, 0x2d, 0x63, 0x61, 0x72, 0x74, 0x72, 0x69, 0x64, 0x67, 0x65, 0x44, 0x00, 0x00, 0x00, 0x0d, 0x69, 0x6e, 0x6b, 0x2d, 0x63, 0x61, 0x72, 0x74, 0x72, 0x69, 0x64, 0x67, 0x65, 0x44, 0x00, 0x00, 0x00, 0x0d, 0x69, 0x6e, 0x6b, 0x2d, 0x63, 0x61, 0x72, 0x74, 0x72, 0x69, 0x64, 0x67, 0x65, 0x21, 0x00, 0x11, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x2d, 0x6c, 0x6f, 0x77, 0x2d, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x21, 0x00, 0x12, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x2d, 0x68, 0x69, 0x67, 0x68, 0x2d, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x00, 0x04, 0x00, 0x00, 0x00, 0x64, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x64, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x64, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x64, 0x21, 0x00, 0x0d, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x2d, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x00, 0x04, 0x00, 0x00, 0x00, 0x3c, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x46, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x3c, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x46, 0x30, 0x00, 0x0e, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x79, 0x00, 0x65, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x69, 0x6e, 0x6b, 0x43, 0x61, 0x72, 0x74, 0x72, 0x69, 0x64, 0x67, 0x65, 0x3b, 0x6d, 0x61, 0x78, 0x63, 0x61, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x3d, 0x31, 0x30, 0x30, 0x3b, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x3d, 0x36, 0x30, 0x3b, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x79, 0x54, 0x68, 0x61, 0x74, 0x49, 0x73, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x3b, 0x75, 0x6e, 0x69, 0x74, 0x3d, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x3b, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x61, 0x6e, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x63, 0x79, 0x61, 0x6e, 0x3b, 0x30, 0x00, 0x00, 0x00, 0x68, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x69, 0x6e, 0x6b, 0x43, 0x61, 0x72, 0x74, 0x72, 0x69, 0x64, 0x67, 0x65, 0x3b, 0x6d, 0x61, 0x78, 0x63, 0x61, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x3d, 0x31, 0x30, 0x30, 0x3b, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x3d, 0x37, 0x30, 0x3b, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x79, 0x54, 0x68, 0x61, 0x74, 0x49, 0x73, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x3b, 0x75, 0x6e, 0x69, 0x74, 0x3d, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x3b, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x61, 0x6e, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x6d, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x61, 0x3b, 0x30, 0x00, 0x00, 0x00, 0x67, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x69, 0x6e, 0x6b, 0x43, 0x61, 0x72, 0x74, 0x72, 0x69, 0x64, 0x67, 0x65, 0x3b, 0x6d, 0x61, 0x78, 0x63, 0x61, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x3d, 0x31, 0x30, 0x30, 0x3b, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x3d, 0x36, 0x30, 0x3b, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x79, 0x54, 0x68, 0x61, 0x74, 0x49, 0x73, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x3b, 0x75, 0x6e, 0x69, 0x74, 0x3d, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x3b, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x61, 0x6e, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x79, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x3b, 0x30, 0x00, 0x00, 0x00, 0x66, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x69, 0x6e, 0x6b, 0x43, 0x61, 0x72, 0x74, 0x72, 0x69, 0x64, 0x67, 0x65, 0x3b, 0x6d, 0x61, 0x78, 0x63, 0x61, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x3d, 0x31, 0x30, 0x30, 0x3b, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x3d, 0x37, 0x30, 0x3b, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x79, 0x54, 0x68, 0x61, 0x74, 0x49, 0x73, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x3b, 0x75, 0x6e, 0x69, 0x74, 0x3d, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x3b, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x61, 0x6e, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x3b, 0x41, 0x00, 0x1a, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x79, 0x2d, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x0e, 0x43, 0x79, 0x61, 0x6e, 0x20, 0x43, 0x61, 0x72, 0x74, 0x72, 0x69, 0x64, 0x67, 0x65, 0x41, 0x00, 0x00, 0x00, 0x11, 0x4d, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x61, 0x20, 0x43, 0x61, 0x72, 0x74, 0x72, 0x69, 0x64, 0x67, 0x65, 0x41, 0x00, 0x00, 0x00, 0x10, 0x59, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x20, 0x43, 0x61, 0x72, 0x74, 0x72, 0x69, 0x64, 0x67, 0x65, 0x41, 0x00, 0x00, 0x00, 0x0f, 0x42, 0x6c, 0x61, 0x63, 0x6b, 0x20, 0x43, 0x61, 0x72, 0x74, 0x72, 0x69, 0x64, 0x67, 0x65, 0x42, 0x00, 0x15, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x66, 0x69, 0x72, 0x6d, 0x77, 0x61, 0x72, 0x65, 0x2d, 0x6e, 0x61, 0x6d, 0x65, 0x00, 0x16, 0x57, 0x45, 0x42, 0x50, 0x44, 0x4c, 0x50, 0x50, 0x31, 0x4e, 0x30, 0x30, 0x31, 0x2e, 0x31, 0x39, 0x31, 0x39, 0x41, 0x2e, 0x30, 0x30, 0x41, 0x00, 0x1f, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x66, 0x69, 0x72, 0x6d, 0x77, 0x61, 0x72, 0x65, 0x2d, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x16, 0x57, 0x45, 0x42, 0x50, 0x44, 0x4c, 0x50, 0x50, 0x31, 0x4e, 0x30, 0x30, 0x31, 0x2e, 0x31, 0x39, 0x31, 0x39, 0x41, 0x2e, 0x30, 0x30, 0x30, 0x00, 0x18, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x66, 0x69, 0x72, 0x6d, 0x77, 0x61, 0x72, 0x65, 0x2d, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x16, 0x57, 0x45, 0x42, 0x50, 0x44, 0x4c, 0x50, 0x50, 0x31, 0x4e, 0x30, 0x30, 0x31, 0x2e, 0x31, 0x39, 0x31, 0x39, 0x41, 0x2e, 0x30, 0x30, 0x30, 0x00, 0x12, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x2d, 0x74, 0x72, 0x61, 0x79, 0x00, 0x86, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x73, 0x68, 0x65, 0x65, 0x74, 0x46, 0x65, 0x65, 0x64, 0x41, 0x75, 0x74, 0x6f, 0x4e, 0x6f, 0x6e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x61, 0x62, 0x6c, 0x65, 0x3b, 0x64, 0x69, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x3d, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x3b, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x66, 0x65, 0x65, 0x64, 0x3d, 0x32, 0x39, 0x37, 0x30, 0x30, 0x30, 0x3b, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x78, 0x66, 0x65, 0x65, 0x64, 0x3d, 0x32, 0x31, 0x30, 0x30, 0x30, 0x30, 0x3b, 0x6d, 0x61, 0x78, 0x63, 0x61, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x3d, 0x2d, 0x32, 0x3b, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x3d, 0x2d, 0x32, 0x3b, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3d, 0x30, 0x3b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x54, 0x72, 0x61, 0x79, 0x31, 0x30, 0x00, 0x13, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2d, 0x74, 0x72, 0x61, 0x79, 0x00, 0x6e, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x3b, 0x6d, 0x61, 0x78, 0x63, 0x61, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x3d, 0x2d, 0x32, 0x3b, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x3d, 0x2d, 0x32, 0x3b, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3d, 0x35, 0x3b, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3d, 0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x3b, 0x70, 0x61, 0x67, 0x65, 0x64, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x79, 0x3d, 0x66, 0x61, 0x63, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x3b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x54, 0x72, 0x61, 0x79, 0x31, 0x21, 0x00, 0x0e, 0x63, 0x6f, 0x70, 0x69, 0x65, 0x73, 0x2d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x23, 0x00, 0x12, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x2d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x13, 0x00, 0x16, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x2d, 0x63, 0x6f, 0x6c, 0x2d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x00, 0x00, 0x23, 0x00, 0x1d, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x64, 0x2d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x23, 0x00, 0x15, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x2d, 0x71, 0x75, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x2d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x32, 0x00, 0x1a, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x00, 0x09, 0x00, 0x00, 0x02, 0x58, 0x00, 0x00, 0x02, 0x58, 0x03, 0x44, 0x00, 0x0d, 0x73, 0x69, 0x64, 0x65, 0x73, 0x2d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x00, 0x09, 0x6f, 0x6e, 0x65, 0x2d, 0x73, 0x69, 0x64, 0x65, 0x64, 0x44, 0x00, 0x12, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2d, 0x62, 0x69, 0x6e, 0x2d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x00, 0x09, 0x66, 0x61, 0x63, 0x65, 0x2d, 0x64, 0x6f, 0x77, 0x6e, 0x44, 0x00, 0x13, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2d, 0x6d, 0x6f, 0x64, 0x65, 0x2d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x00, 0x04, 0x61, 0x75, 0x74, 0x6f, 0x44, 0x00, 0x18, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2d, 0x6d, 0x6f, 0x64, 0x65, 0x2d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x00, 0x04, 0x61, 0x75, 0x74, 0x6f, 0x44, 0x00, 0x22, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x2d, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x69, 0x6e, 0x67, 0x2d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x00, 0x24, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x2d, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2d, 0x75, 0x6e, 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x2d, 0x63, 0x6f, 0x70, 0x69, 0x65, 0x73, 0x21, 0x00, 0x11, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x2d, 0x75, 0x70, 0x2d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x44, 0x00, 0x28, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x2d, 0x75, 0x70, 0x2d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x00, 0x10, 0x74, 0x6f, 0x72, 0x69, 0x67, 0x68, 0x74, 0x2d, 0x74, 0x6f, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x44, 0x00, 0x1e, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x2d, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x00, 0x04, 0x61, 0x75, 0x74, 0x6f, 0x44, 0x00, 0x15, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x2d, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x6e, 0x67, 0x2d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x00, 0x04, 0x61, 0x75, 0x74, 0x6f, 0x33, 0x00, 0x10, 0x63, 0x6f, 0x70, 0x69, 0x65, 0x73, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x63, 0x23, 0x00, 0x14, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x33, 0x00, 0x1b, 0x6a, 0x6f, 0x62, 0x2d, 0x70, 0x61, 0x67, 0x65, 0x73, 0x2d, 0x70, 0x65, 0x72, 0x2d, 0x73, 0x65, 0x74, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x7f, 0xff, 0xff, 0xff, 0x23, 0x00, 0x1f, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x64, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x23, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x23, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x23, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x06, 0x23, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x07, 0x23, 0x00, 0x17, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x2d, 0x71, 0x75, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x23, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x23, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x32, 0x00, 0x1c, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x09, 0x00, 0x00, 0x01, 0x2c, 0x00, 0x00, 0x01, 0x2c, 0x03, 0x32, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x02, 0x58, 0x00, 0x00, 0x02, 0x58, 0x03, 0x32, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x04, 0xb0, 0x00, 0x00, 0x04, 0xb0, 0x03, 0x44, 0x00, 0x0f, 0x73, 0x69, 0x64, 0x65, 0x73, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x09, 0x6f, 0x6e, 0x65, 0x2d, 0x73, 0x69, 0x64, 0x65, 0x64, 0x44, 0x00, 0x00, 0x00, 0x14, 0x74, 0x77, 0x6f, 0x2d, 0x73, 0x69, 0x64, 0x65, 0x64, 0x2d, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x2d, 0x65, 0x64, 0x67, 0x65, 0x44, 0x00, 0x00, 0x00, 0x13, 0x74, 0x77, 0x6f, 0x2d, 0x73, 0x69, 0x64, 0x65, 0x64, 0x2d, 0x6c, 0x6f, 0x6e, 0x67, 0x2d, 0x65, 0x64, 0x67, 0x65, 0x44, 0x00, 0x14, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2d, 0x62, 0x69, 0x6e, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x09, 0x66, 0x61, 0x63, 0x65, 0x2d, 0x64, 0x6f, 0x77, 0x6e, 0x44, 0x00, 0x15, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2d, 0x6d, 0x6f, 0x64, 0x65, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x04, 0x61, 0x75, 0x74, 0x6f, 0x44, 0x00, 0x00, 0x00, 0x0f, 0x61, 0x75, 0x74, 0x6f, 0x2d, 0x6d, 0x6f, 0x6e, 0x6f, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x44, 0x00, 0x00, 0x00, 0x0a, 0x6d, 0x6f, 0x6e, 0x6f, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x44, 0x00, 0x00, 0x00, 0x05, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x44, 0x00, 0x1a, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2d, 0x6d, 0x6f, 0x64, 0x65, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x04, 0x61, 0x75, 0x74, 0x6f, 0x44, 0x00, 0x00, 0x00, 0x0f, 0x61, 0x75, 0x74, 0x6f, 0x2d, 0x6d, 0x6f, 0x6e, 0x6f, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x44, 0x00, 0x00, 0x00, 0x0a, 0x6d, 0x6f, 0x6e, 0x6f, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x44, 0x00, 0x00, 0x00, 0x05, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x44, 0x00, 0x00, 0x00, 0x12, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x2d, 0x6d, 0x6f, 0x6e, 0x6f, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x22, 0x00, 0x15, 0x70, 0x61, 0x67, 0x65, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x01, 0x01, 0x44, 0x00, 0x24, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x2d, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x69, 0x6e, 0x67, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x24, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x2d, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2d, 0x75, 0x6e, 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x2d, 0x63, 0x6f, 0x70, 0x69, 0x65, 0x73, 0x44, 0x00, 0x00, 0x00, 0x22, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x2d, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2d, 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x2d, 0x63, 0x6f, 0x70, 0x69, 0x65, 0x73, 0x21, 0x00, 0x13, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x2d, 0x75, 0x70, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x44, 0x00, 0x2a, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x2d, 0x75, 0x70, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x10, 0x74, 0x6f, 0x72, 0x69, 0x67, 0x68, 0x74, 0x2d, 0x74, 0x6f, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x44, 0x00, 0x13, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x05, 0x70, 0x61, 0x67, 0x65, 0x73, 0x44, 0x00, 0x00, 0x00, 0x05, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x44, 0x00, 0x00, 0x00, 0x09, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x63, 0x6f, 0x6c, 0x44, 0x00, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x2d, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x04, 0x61, 0x75, 0x74, 0x6f, 0x44, 0x00, 0x00, 0x00, 0x0a, 0x70, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x75, 0x61, 0x6c, 0x44, 0x00, 0x17, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x2d, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x6e, 0x67, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x04, 0x61, 0x75, 0x74, 0x6f, 0x44, 0x00, 0x00, 0x00, 0x08, 0x61, 0x75, 0x74, 0x6f, 0x2d, 0x66, 0x69, 0x74, 0x44, 0x00, 0x00, 0x00, 0x04, 0x66, 0x69, 0x6c, 0x6c, 0x44, 0x00, 0x00, 0x00, 0x03, 0x66, 0x69, 0x74, 0x44, 0x00, 0x00, 0x00, 0x04, 0x6e, 0x6f, 0x6e, 0x65, 0x45, 0x00, 0x0d, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x73, 0x00, 0x31, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x2f, 0x77, 0x65, 0x62, 0x41, 0x70, 0x70, 0x73, 0x2f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x2e, 0x70, 0x6e, 0x67, 0x45, 0x00, 0x00, 0x00, 0x2b, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x2f, 0x77, 0x65, 0x62, 0x41, 0x70, 0x70, 0x73, 0x2f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x6e, 0x67, 0x45, 0x00, 0x00, 0x00, 0x31, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x2f, 0x77, 0x65, 0x62, 0x41, 0x70, 0x70, 0x73, 0x2f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x6c, 0x61, 0x72, 0x67, 0x65, 0x2e, 0x70, 0x6e, 0x67, 0x45, 0x00, 0x17, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x79, 0x2d, 0x69, 0x6e, 0x66, 0x6f, 0x2d, 0x75, 0x72, 0x69, 0x00, 0x26, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x2f, 0x23, 0x68, 0x49, 0x64, 0x2d, 0x70, 0x67, 0x49, 0x6e, 0x6b, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x44, 0x00, 0x1e, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x2d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x00, 0x04, 0x61, 0x75, 0x74, 0x6f, 0x44, 0x00, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x04, 0x61, 0x75, 0x74, 0x6f, 0x44, 0x00, 0x00, 0x00, 0x05, 0x70, 0x68, 0x6f, 0x74, 0x6f, 0x44, 0x00, 0x00, 0x00, 0x08, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x44, 0x00, 0x00, 0x00, 0x04, 0x74, 0x65, 0x78, 0x74, 0x44, 0x00, 0x00, 0x00, 0x11, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x61, 0x6e, 0x64, 0x2d, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x44, 0x00, 0x1e, 0x70, 0x77, 0x67, 0x2d, 0x72, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2d, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x68, 0x65, 0x65, 0x74, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x00, 0x07, 0x72, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x44, 0x00, 0x22, 0x70, 0x77, 0x67, 0x2d, 0x72, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2d, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x07, 0x73, 0x67, 0x72, 0x61, 0x79, 0x5f, 0x38, 0x44, 0x00, 0x00, 0x00, 0x06, 0x73, 0x72, 0x67, 0x62, 0x5f, 0x38, 0x44, 0x00, 0x00, 0x00, 0x0b, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2d, 0x72, 0x67, 0x62, 0x5f, 0x38, 0x44, 0x00, 0x00, 0x00, 0x05, 0x72, 0x67, 0x62, 0x5f, 0x38, 0x32, 0x00, 0x28, 0x70, 0x77, 0x67, 0x2d, 0x72, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2d, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x09, 0x00, 0x00, 0x01, 0x2c, 0x00, 0x00, 0x01, 0x2c, 0x03, 0x32, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x02, 0x58, 0x00, 0x00, 0x02, 0x58, 0x03, 0x41, 0x00, 0x16, 0x65, 0x70, 0x63, 0x6c, 0x2d, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x03, 0x31, 0x2e, 0x30, 0x22, 0x00, 0x17, 0x6d, 0x61, 0x6e, 0x75, 0x61, 0x6c, 0x2d, 0x64, 0x75, 0x70, 0x6c, 0x65, 0x78, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x01, 0x00, 0x32, 0x00, 0x20, 0x70, 0x63, 0x6c, 0x6d, 0x2d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x09, 0x00, 0x00, 0x01, 0x2c, 0x00, 0x00, 0x01, 0x2c, 0x03, 0x32, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x02, 0x58, 0x00, 0x00, 0x02, 0x58, 0x03, 0x32, 0x00, 0x1e, 0x70, 0x63, 0x6c, 0x6d, 0x2d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x00, 0x09, 0x00, 0x00, 0x02, 0x58, 0x00, 0x00, 0x02, 0x58, 0x03, 0x21, 0x00, 0x1b, 0x70, 0x63, 0x6c, 0x6d, 0x2d, 0x73, 0x74, 0x72, 0x69, 0x70, 0x2d, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x21, 0x00, 0x1b, 0x70, 0x63, 0x6c, 0x6d, 0x2d, 0x73, 0x74, 0x72, 0x69, 0x70, 0x2d, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x2d, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x44, 0x00, 0x15, 0x70, 0x63, 0x6c, 0x6d, 0x2d, 0x72, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x2d, 0x73, 0x69, 0x64, 0x65, 0x00, 0x07, 0x72, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x44, 0x00, 0x21, 0x70, 0x63, 0x6c, 0x6d, 0x2d, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2d, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x2d, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 0x00, 0x04, 0x6a, 0x70, 0x65, 0x67, 0x44, 0x00, 0x00, 0x00, 0x05, 0x66, 0x6c, 0x61, 0x74, 0x65, 0x44, 0x00, 0x00, 0x00, 0x03, 0x72, 0x6c, 0x65, 0x44, 0x00, 0x22, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x2d, 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x2d, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x00, 0x06, 0x63, 0x6f, 0x70, 0x69, 0x65, 0x73, 0x44, 0x00, 0x00, 0x00, 0x15, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x64, 0x44, 0x00, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x67, 0x65, 0x74, 0x2d, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x0f, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x41, 0x00, 0x14, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x41, 0x00, 0x1b, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2d, 0x75, 0x6e, 0x69, 0x74, 0x00, 0x00, 0x44, 0x00, 0x18, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x79, 0x2d, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x00, 0x07, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x44, 0x00, 0x1a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x79, 0x2d, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x07, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x44, 0x00, 0x00, 0x00, 0x05, 0x73, 0x6f, 0x75, 0x6e, 0x64, 0x44, 0x00, 0x00, 0x00, 0x03, 0x70, 0x69, 0x6e, 0x23, 0x00, 0x1a, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x2d, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0a, 0x21, 0x00, 0x1b, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x2d, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x74, 0x69, 0x6d, 0x65, 0x2d, 0x6f, 0x75, 0x74, 0x00, 0x04, 0x00, 0x00, 0x00, 0x78, 0x22, 0x00, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x2d, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x6a, 0x6f, 0x62, 0x73, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x01, 0x00, 0x03, } // Get-Printer-Attributes output from Pantum M7300FDW var attrsPantumM7300FDW = []byte{ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x47, 0x00, 0x12, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2d, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x00, 0x05, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x48, 0x00, 0x1b, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2d, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x61, 0x6c, 0x2d, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x00, 0x05, 0x65, 0x6e, 0x2d, 0x55, 0x53, 0x04, 0x22, 0x00, 0x0f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x01, 0x00, 0x49, 0x00, 0x19, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x09, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x75, 0x72, 0x66, 0x49, 0x00, 0x00, 0x00, 0x10, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x70, 0x77, 0x67, 0x2d, 0x72, 0x61, 0x73, 0x74, 0x65, 0x72, 0x49, 0x00, 0x00, 0x00, 0x18, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6f, 0x63, 0x74, 0x65, 0x74, 0x2d, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x41, 0x00, 0x10, 0x6d, 0x6f, 0x70, 0x72, 0x69, 0x61, 0x2d, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x65, 0x64, 0x00, 0x03, 0x31, 0x2e, 0x33, 0x41, 0x00, 0x10, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x0e, 0x70, 0x61, 0x6e, 0x74, 0x75, 0x6d, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x41, 0x00, 0x0c, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x69, 0x6e, 0x66, 0x6f, 0x00, 0x12, 0x50, 0x61, 0x6e, 0x74, 0x75, 0x6d, 0x20, 0x49, 0x50, 0x50, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x45, 0x00, 0x11, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x6d, 0x6f, 0x72, 0x65, 0x2d, 0x69, 0x6e, 0x66, 0x6f, 0x00, 0x26, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x3a, 0x36, 0x30, 0x30, 0x30, 0x30, 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2d, 0x6a, 0x75, 0x6d, 0x70, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x41, 0x00, 0x16, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x6d, 0x61, 0x6b, 0x65, 0x2d, 0x61, 0x6e, 0x64, 0x2d, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x00, 0x16, 0x50, 0x61, 0x6e, 0x74, 0x75, 0x6d, 0x20, 0x4d, 0x37, 0x33, 0x30, 0x30, 0x46, 0x44, 0x57, 0x20, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x41, 0x00, 0x11, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x2d, 0x69, 0x64, 0x00, 0x45, 0x4d, 0x46, 0x47, 0x3a, 0x50, 0x61, 0x6e, 0x74, 0x75, 0x6d, 0x3b, 0x43, 0x4d, 0x44, 0x3a, 0x3a, 0x44, 0x57, 0x2d, 0x50, 0x53, 0x2c, 0x44, 0x57, 0x2d, 0x50, 0x43, 0x4c, 0x2c, 0x55, 0x52, 0x46, 0x3b, 0x4d, 0x44, 0x4c, 0x3a, 0x2d, 0x50, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x3b, 0x43, 0x4c, 0x53, 0x3a, 0x50, 0x52, 0x49, 0x4e, 0x54, 0x45, 0x52, 0x3b, 0x44, 0x45, 0x53, 0x3a, 0x50, 0x61, 0x6e, 0x74, 0x75, 0x6d, 0x3b, 0x45, 0x00, 0x0c, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x75, 0x75, 0x69, 0x64, 0x00, 0x2d, 0x75, 0x72, 0x6e, 0x3a, 0x75, 0x75, 0x69, 0x64, 0x3a, 0x30, 0x37, 0x62, 0x63, 0x35, 0x61, 0x34, 0x37, 0x2d, 0x65, 0x64, 0x66, 0x32, 0x2d, 0x34, 0x36, 0x36, 0x31, 0x2d, 0x38, 0x37, 0x34, 0x38, 0x2d, 0x38, 0x36, 0x32, 0x30, 0x66, 0x37, 0x39, 0x64, 0x34, 0x61, 0x63, 0x34, 0x45, 0x00, 0x0d, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x73, 0x00, 0x25, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x3a, 0x36, 0x30, 0x30, 0x30, 0x30, 0x2f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x68, 0x69, 0x70, 0x34, 0x38, 0x2e, 0x70, 0x6e, 0x67, 0x45, 0x00, 0x00, 0x00, 0x26, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x3a, 0x36, 0x30, 0x30, 0x30, 0x30, 0x2f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x68, 0x69, 0x70, 0x31, 0x32, 0x38, 0x2e, 0x70, 0x6e, 0x67, 0x45, 0x00, 0x00, 0x00, 0x26, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x3a, 0x36, 0x30, 0x30, 0x30, 0x30, 0x2f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x68, 0x69, 0x70, 0x35, 0x31, 0x32, 0x2e, 0x70, 0x6e, 0x67, 0x42, 0x00, 0x13, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x64, 0x6e, 0x73, 0x2d, 0x73, 0x64, 0x2d, 0x6e, 0x61, 0x6d, 0x65, 0x00, 0x1d, 0x50, 0x61, 0x6e, 0x74, 0x75, 0x6d, 0x20, 0x4d, 0x37, 0x33, 0x30, 0x30, 0x46, 0x44, 0x57, 0x20, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x20, 0x31, 0x43, 0x36, 0x46, 0x43, 0x44, 0x44, 0x00, 0x0d, 0x75, 0x72, 0x66, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x04, 0x56, 0x31, 0x2e, 0x34, 0x44, 0x00, 0x00, 0x00, 0x02, 0x57, 0x38, 0x44, 0x00, 0x00, 0x00, 0x03, 0x49, 0x53, 0x31, 0x44, 0x00, 0x00, 0x00, 0x04, 0x43, 0x50, 0x39, 0x39, 0x44, 0x00, 0x00, 0x00, 0x03, 0x50, 0x51, 0x34, 0x44, 0x00, 0x00, 0x00, 0x04, 0x4f, 0x42, 0x31, 0x30, 0x44, 0x00, 0x00, 0x00, 0x05, 0x52, 0x53, 0x36, 0x30, 0x30, 0x44, 0x00, 0x00, 0x00, 0x03, 0x44, 0x4d, 0x31, 0x44, 0x00, 0x0c, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x6b, 0x69, 0x6e, 0x64, 0x00, 0x08, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x00, 0x00, 0x00, 0x08, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x34, 0x00, 0x14, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x00, 0x21, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x04, 0x00, 0x00, 0x54, 0x56, 0x21, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x04, 0x00, 0x00, 0x6d, 0x24, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x04, 0x00, 0x00, 0x52, 0x08, 0x21, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x04, 0x00, 0x00, 0x74, 0x04, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x04, 0x00, 0x00, 0x39, 0xd0, 0x21, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x04, 0x00, 0x00, 0x52, 0x08, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x04, 0x00, 0x00, 0x29, 0x04, 0x21, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x04, 0x00, 0x00, 0x39, 0xd0, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x04, 0x00, 0x00, 0x2c, 0x88, 0x21, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x04, 0x00, 0x00, 0x3f, 0x48, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x04, 0x00, 0x00, 0x2a, 0xf8, 0x21, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x04, 0x00, 0x00, 0x55, 0xf0, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x04, 0x00, 0x00, 0x27, 0x10, 0x21, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x04, 0x00, 0x00, 0x39, 0xd0, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x04, 0x00, 0x00, 0x2e, 0xe0, 0x21, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x04, 0x00, 0x00, 0x5b, 0xcc, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x04, 0x00, 0x00, 0x28, 0xed, 0x21, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x04, 0x00, 0x00, 0x5e, 0x42, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x04, 0x00, 0x00, 0x54, 0x56, 0x21, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x04, 0x00, 0x00, 0x8a, 0xe8, 0x37, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x0b, 0x78, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x08, 0x00, 0x00, 0x27, 0x10, 0x00, 0x00, 0x39, 0xd0, 0x33, 0x00, 0x0b, 0x79, 0x2d, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x08, 0x00, 0x00, 0x54, 0x60, 0x00, 0x00, 0x8b, 0x10, 0x37, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x0f, 0x73, 0x69, 0x64, 0x65, 0x73, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x09, 0x6f, 0x6e, 0x65, 0x2d, 0x73, 0x69, 0x64, 0x65, 0x64, 0x44, 0x00, 0x00, 0x00, 0x14, 0x74, 0x77, 0x6f, 0x2d, 0x73, 0x69, 0x64, 0x65, 0x64, 0x2d, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x2d, 0x65, 0x64, 0x67, 0x65, 0x44, 0x00, 0x00, 0x00, 0x13, 0x74, 0x77, 0x6f, 0x2d, 0x73, 0x69, 0x64, 0x65, 0x64, 0x2d, 0x6c, 0x6f, 0x6e, 0x67, 0x2d, 0x65, 0x64, 0x67, 0x65, 0x03, } goipp-1.1.0/group.go000066400000000000000000000022641453360531400143220ustar00rootroot00000000000000/* Go IPP - IPP core protocol implementation in pure Go * * Copyright (C) 2020 and up by Alexander Pevzner (pzz@apevzner.com) * See LICENSE for license terms and conditions * * Groups of attributes */ package goipp // Group represents a group of attributes. // // Since 1.1.0 type Group struct { Tag Tag // Group tag Attrs Attributes // Group attributes } // Groups represents a sequence of groups // // The primary purpose of this type is to represent // messages with repeated groups with the same group tag // // See Message type documentation for more details // // Since 1.1.0 type Groups []Group // Add Attribute to the Group func (g *Group) Add(attr Attribute) { g.Attrs.Add(attr) } // Equal checks that groups g and g2 are equal func (g Group) Equal(g2 Group) bool { return g.Tag == g2.Tag && g.Attrs.Equal(g2.Attrs) } // Add Group to Groups func (groups *Groups) Add(g Group) { *groups = append(*groups, g) } // Equal checks that groups and groups2 are equal func (groups Groups) Equal(groups2 Groups) bool { if len(groups) != len(groups2) { return false } for i, g := range groups { g2 := groups2[i] if !g.Equal(g2) { return false } } return true } goipp-1.1.0/index.md000066400000000000000000000015221453360531400142640ustar00rootroot00000000000000# goipp [![godoc.org](https://godoc.org/github.com/OpenPrinting/goipp?status.svg)](http://godoc.org/github.com/OpenPrinting/goipp) ![GitHub](https://img.shields.io/github/license/OpenPrinting/goipp) The goipp library is fairly complete implementation of IPP core protocol in pure Go. Essentially, it is IPP messages parser/composer. Transport is not implemented here, because Go standard library has an excellent built-in HTTP client, and it doesn't make a lot of sense to wrap it here. High-level requests, like "print a file" are also not implemented, only the low-level stuff. All documentation is on godoc.org -- follow the link above. Pull requests are welcomed, assuming they don't break existing API. For more information and software downloads, please visit the [Project's page at GitHub](https://github.com/OpenPrinting/sane-airscan) goipp-1.1.0/message.go000066400000000000000000000171201453360531400146070ustar00rootroot00000000000000/* Go IPP - IPP core protocol implementation in pure Go * * Copyright (C) 2020 and up by Alexander Pevzner (pzz@apevzner.com) * See LICENSE for license terms and conditions * * IPP protocol messages */ package goipp import ( "bytes" "fmt" "io" ) // Code represents Op(operation) or Status codes type Code uint16 // Version represents a protocol version. It consist // of Major and Minor version codes, packed into a single // 16-bit word type Version uint16 // DefaultVersion is the default IPP version (2.0 for now) const DefaultVersion Version = 0x0200 // MakeVersion makes version from major and minor parts func MakeVersion(major, minor uint8) Version { return Version(major)<<8 | Version(minor) } // Major returns a major part of version func (v Version) Major() uint8 { return uint8(v >> 8) } // Minor returns a minor part of version func (v Version) Minor() uint8 { return uint8(v) } // String() converts version to string (i.e., "2.0") func (v Version) String() string { return fmt.Sprintf("%d.%d", v.Major(), v.Minor()) } // Message represents a single IPP message, which may be either // client request or server response type Message struct { // Common header Version Version // Protocol version Code Code // Operation for request, status for response RequestID uint32 // Set in request, returned in response // Groups of Attributes // // This field allows to represent messages with repeated // groups of attributes with the same group tag. The most // noticeable use case is the Get-Jobs response which uses // multiple Job groups, one per returned job. See RFC 8011, // 4.2.6.2. for more details // // See also the following discussions which explain the demand // to implement this interface: // https://github.com/OpenPrinting/goipp/issues/2 // https://github.com/OpenPrinting/goipp/pull/3 // // With respect to backward compatibility, the following // behavior is implemented here: // 1. (*Message).Decode() fills both Groups and named per-group // fields (i.e., Operation, Job etc) // 2. (*Message).Encode() and (*Message) Print, if Groups != nil, // uses Groups and ignores named per-group fields. Otherwise, // named fields are used as in 1.0.0 // 3. (*Message) Equal(), for each message uses Groups if // it is not nil or named per-group fields otherwise. // In another words, Equal() compares messages as if // they were encoded // // Since 1.1.0 Groups Groups // Attributes, by group Operation Attributes // Operation attributes Job Attributes // Job attributes Printer Attributes // Printer attributes Unsupported Attributes // Unsupported attributes Subscription Attributes // Subscription attributes EventNotification Attributes // Event Notification attributes Resource Attributes // Resource attributes Document Attributes // Document attributes System Attributes // System attributes Future11 Attributes // \ Future12 Attributes // \ Future13 Attributes // | Reserved for future extensions Future14 Attributes // / Future15 Attributes // / } // NewRequest creates a new request message // // Use DefaultVersion as a first argument, if you don't // have any specific needs func NewRequest(v Version, op Op, id uint32) *Message { return &Message{ Version: v, Code: Code(op), RequestID: id, } } // NewResponse creates a new response message // // Use DefaultVersion as a first argument, if you don't func NewResponse(v Version, status Status, id uint32) *Message { return &Message{ Version: v, Code: Code(status), RequestID: id, } } // Equal checks that two messages are equal func (m Message) Equal(m2 Message) bool { if m.Version != m2.Version || m.Code != m2.Code || m.RequestID != m2.RequestID { return false } groups := m.attrGroups() groups2 := m2.attrGroups() return groups.Equal(groups2) } // Reset the message into initial state func (m *Message) Reset() { *m = Message{} } // Encode message func (m *Message) Encode(out io.Writer) error { me := messageEncoder{ out: out, } return me.encode(m) } // EncodeBytes encodes message to byte slice func (m *Message) EncodeBytes() ([]byte, error) { var buf bytes.Buffer err := m.Encode(&buf) return buf.Bytes(), err } // Decode reads message from io.Reader func (m *Message) Decode(in io.Reader) error { return m.DecodeEx(in, DecoderOptions{}) } // DecodeEx reads message from io.Reader // // It is extended version of the Decode method, with additional // DecoderOptions parameter func (m *Message) DecodeEx(in io.Reader, opt DecoderOptions) error { md := messageDecoder{ in: in, opt: opt, } m.Reset() return md.decode(m) } // DecodeBytes decodes message from byte slice func (m *Message) DecodeBytes(data []byte) error { return m.Decode(bytes.NewBuffer(data)) } // DecodeBytesEx decodes message from byte slice // // It is extended version of the DecodeBytes method, with additional // DecoderOptions parameter func (m *Message) DecodeBytesEx(data []byte, opt DecoderOptions) error { return m.DecodeEx(bytes.NewBuffer(data), opt) } // Print pretty-prints the message. The 'request' parameter affects // interpretation of Message.Code: it is interpreted either // as Op or as Status func (m *Message) Print(out io.Writer, request bool) { out.Write([]byte("{\n")) fmt.Fprintf(out, msgPrintIndent+"VERSION %s\n", m.Version) if request { fmt.Fprintf(out, msgPrintIndent+"OPERATION %s\n", Op(m.Code)) } else { fmt.Fprintf(out, msgPrintIndent+"STATUS %s\n", Status(m.Code)) } for _, grp := range m.attrGroups() { fmt.Fprintf(out, "\n"+msgPrintIndent+"GROUP %s\n", grp.Tag) for _, attr := range grp.Attrs { m.printAttribute(out, attr, 1) out.Write([]byte("\n")) } } out.Write([]byte("}\n")) } // Pretty-print an attribute. Handles Collection attributes // recursively func (m *Message) printAttribute(out io.Writer, attr Attribute, indent int) { m.printIndent(out, indent) fmt.Fprintf(out, "ATTR %q", attr.Name) tag := TagZero for _, val := range attr.Values { if val.T != tag { fmt.Fprintf(out, " %s:", val.T) tag = val.T } if collection, ok := val.V.(Collection); ok { out.Write([]byte(" {\n")) for _, attr2 := range collection { m.printAttribute(out, attr2, indent+1) out.Write([]byte("\n")) } m.printIndent(out, indent) out.Write([]byte("}")) } else { fmt.Fprintf(out, " %s", val.V) } } } // Print indentation func (m *Message) printIndent(out io.Writer, indent int) { for i := 0; i < indent; i++ { out.Write([]byte(msgPrintIndent)) } } // Get attributes by group. Groups with nil Attributes are skipped, // but groups with non-nil are not, even if len(Attributes) == 0 // // This is a helper function for message encoder and pretty-printer func (m *Message) attrGroups() Groups { // If m.Groups is set, use it if m.Groups != nil { return m.Groups } // Initialize slice of groups groups := Groups{ {TagOperationGroup, m.Operation}, {TagJobGroup, m.Job}, {TagPrinterGroup, m.Printer}, {TagUnsupportedGroup, m.Unsupported}, {TagSubscriptionGroup, m.Subscription}, {TagEventNotificationGroup, m.EventNotification}, {TagResourceGroup, m.Resource}, {TagDocumentGroup, m.Document}, {TagSystemGroup, m.System}, {TagFuture11Group, m.Future11}, {TagFuture12Group, m.Future12}, {TagFuture13Group, m.Future13}, {TagFuture14Group, m.Future14}, {TagFuture15Group, m.Future15}, } // Skip all empty groups out := 0 for in := 0; in < len(groups); in++ { if groups[in].Attrs != nil { groups[out] = groups[in] out++ } } return groups[:out] } goipp-1.1.0/op.go000066400000000000000000000422021453360531400136000ustar00rootroot00000000000000/* Go IPP - IPP core protocol implementation in pure Go * * Copyright (C) 2020 and up by Alexander Pevzner (pzz@apevzner.com) * See LICENSE for license terms and conditions * * IPP Operation Codes */ package goipp import ( "fmt" ) // Op represents an IPP Operation Code type Op Code // Op codes const ( OpPrintJob Op = 0x0002 // Print-Job: Print a single file OpPrintURI Op = 0x0003 // Print-URI: Print a single URL OpValidateJob Op = 0x0004 // Validate-Job: Validate job values prior to submission OpCreateJob Op = 0x0005 // Create-Job: Create an empty print job OpSendDocument Op = 0x0006 // Send-Document: Add a file to a job OpSendURI Op = 0x0007 // Send-URI: Add a URL to a job OpCancelJob Op = 0x0008 // Cancel-Job: Cancel a job OpGetJobAttributes Op = 0x0009 // Get-Job-Attribute: Get information about a job OpGetJobs Op = 0x000a // Get-Jobs: Get a list of jobs OpGetPrinterAttributes Op = 0x000b // Get-Printer-Attributes: Get information about a printer OpHoldJob Op = 0x000c // Hold-Job: Hold a job for printing OpReleaseJob Op = 0x000d // Release-Job: Release a job for printing OpRestartJob Op = 0x000e // Restart-Job: Reprint a job OpPausePrinter Op = 0x0010 // Pause-Printer: Stop a printer OpResumePrinter Op = 0x0011 // Resume-Printer: Start a printer OpPurgeJobs Op = 0x0012 // Purge-Jobs: Delete all jobs OpSetPrinterAttributes Op = 0x0013 // Set-Printer-Attributes: Set printer values OpSetJobAttributes Op = 0x0014 // Set-Job-Attributes: Set job values OpGetPrinterSupportedValues Op = 0x0015 // Get-Printer-Supported-Values: Get supported values OpCreatePrinterSubscriptions Op = 0x0016 // Create-Printer-Subscriptions: Create one or more printer subscriptions OpCreateJobSubscriptions Op = 0x0017 // Create-Job-Subscriptions: Create one of more job subscriptions OpGetSubscriptionAttributes Op = 0x0018 // Get-Subscription-Attributes: Get subscription information OpGetSubscriptions Op = 0x0019 // Get-Subscriptions: Get list of subscriptions OpRenewSubscription Op = 0x001a // Renew-Subscription: Renew a printer subscription OpCancelSubscription Op = 0x001b // Cancel-Subscription: Cancel a subscription OpGetNotifications Op = 0x001c // Get-Notifications: Get notification events OpSendNotifications Op = 0x001d // Send-Notifications: Send notification events OpGetResourceAttributes Op = 0x001e // Get-Resource-Attributes: Get resource information OpGetResourceData Op = 0x001f // Get-Resource-Data: Get resource data OpGetResources Op = 0x0020 // Get-Resources: Get list of resources OpGetPrintSupportFiles Op = 0x0021 // Get-Printer-Support-Files: Get printer support files OpEnablePrinter Op = 0x0022 // Enable-Printer: Accept new jobs for a printer OpDisablePrinter Op = 0x0023 // Disable-Printer: Reject new jobs for a printer OpPausePrinterAfterCurrentJob Op = 0x0024 // Pause-Printer-After-Current-Job: Stop printer after the current job OpHoldNewJobs Op = 0x0025 // Hold-New-Jobs: Hold new jobs OpReleaseHeldNewJobs Op = 0x0026 // Release-Held-New-Jobs: Release new jobs that were previously held OpDeactivatePrinter Op = 0x0027 // Deactivate-Printer: Stop a printer and do not accept jobs OpActivatePrinter Op = 0x0028 // Activate-Printer: Start a printer and accept jobs OpRestartPrinter Op = 0x0029 // Restart-Printer: Restart a printer OpShutdownPrinter Op = 0x002a // Shutdown-Printer: Turn a printer off OpStartupPrinter Op = 0x002b // Startup-Printer: Turn a printer on OpReprocessJob Op = 0x002c // Reprocess-Job: Reprint a job OpCancelCurrentJob Op = 0x002d // Cancel-Current-Job: Cancel the current job OpSuspendCurrentJob Op = 0x002e // Suspend-Current-Job: Suspend the current job OpResumeJob Op = 0x002f // Resume-Job: Resume the current job OpPromoteJob Op = 0x0030 // Promote-Job: Promote a job to print sooner OpScheduleJobAfter Op = 0x0031 // Schedule-Job-After: Schedule a job to print after another OpCancelDocument Op = 0x0033 // Cancel-Document: Cancel a document OpGetDocumentAttributes Op = 0x0034 // Get-Document-Attributes: Get document information OpGetDocuments Op = 0x0035 // Get-Documents: Get a list of documents in a job OpDeleteDocument Op = 0x0036 // Delete-Document: Delete a document OpSetDocumentAttributes Op = 0x0037 // Set-Document-Attributes: Set document values OpCancelJobs Op = 0x0038 // Cancel-Jobs: Cancel all jobs (administrative) OpCancelMyJobs Op = 0x0039 // Cancel-My-Jobs: Cancel a user's jobs OpResubmitJob Op = 0x003a // Resubmit-Job: Copy and reprint a job OpCloseJob Op = 0x003b // Close-Job: Close a job and start printing OpIdentifyPrinter Op = 0x003c // Identify-Printer: Make the printer beep, flash, or display a message for identification OpValidateDocument Op = 0x003d // Validate-Document: Validate document values prior to submission OpAddDocumentImages Op = 0x003e // Add-Document-Images: Add image(s) from the specified scanner source OpAcknowledgeDocument Op = 0x003f // Acknowledge-Document: Acknowledge processing of a document OpAcknowledgeIdentifyPrinter Op = 0x0040 // Acknowledge-Identify-Printer: Acknowledge action on an Identify-Printer request OpAcknowledgeJob Op = 0x0041 // Acknowledge-Job: Acknowledge processing of a job OpFetchDocument Op = 0x0042 // Fetch-Document: Fetch a document for processing OpFetchJob Op = 0x0043 // Fetch-Job: Fetch a job for processing OpGetOutputDeviceAttributes Op = 0x0044 // Get-Output-Device-Attributes: Get printer information for a specific output device OpUpdateActiveJobs Op = 0x0045 // Update-Active-Jobs: Update the list of active jobs that a proxy has processed OpDeregisterOutputDevice Op = 0x0046 // Deregister-Output-Device: Remove an output device OpUpdateDocumentStatus Op = 0x0047 // Update-Document-Status: Update document values OpUpdateJobStatus Op = 0x0048 // Update-Job-Status: Update job values OpupdateOutputDeviceAttributes Op = 0x0049 // Update-Output-Device-Attributes: Update output device values OpGetNextDocumentData Op = 0x004a // Get-Next-Document-Data: Scan more document data OpAllocatePrinterResources Op = 0x004b // Allocate-Printer-Resources: Use resources for a printer OpCreatePrinter Op = 0x004c // Create-Printer: Create a new service OpDeallocatePrinterResources Op = 0x004d // Deallocate-Printer-Resources: Stop using resources for a printer OpDeletePrinter Op = 0x004e // Delete-Printer: Delete an existing service OpGetPrinters Op = 0x004f // Get-Printers: Get a list of services OpShutdownOnePrinter Op = 0x0050 // Shutdown-One-Printer: Shutdown a service OpStartupOnePrinter Op = 0x0051 // Startup-One-Printer: Start a service OpCancelResource Op = 0x0052 // Cancel-Resource: Uninstall a resource OpCreateResource Op = 0x0053 // Create-Resource: Create a new (empty) resource OpInstallResource Op = 0x0054 // Install-Resource: Install a resource OpSendResourceData Op = 0x0055 // Send-Resource-Data: Upload the data for a resource OpSetResourceAttributes Op = 0x0056 // Set-Resource-Attributes: Set resource object attributes OpCreateResourceSubscriptions Op = 0x0057 // Create-Resource-Subscriptions: Create event subscriptions for a resource OpCreateSystemSubscriptions Op = 0x0058 // Create-System-Subscriptions: Create event subscriptions for a system OpDisableAllPrinters Op = 0x0059 // Disable-All-Printers: Stop accepting new jobs on all services OpEnableAllPrinters Op = 0x005a // Enable-All-Printers: Start accepting new jobs on all services OpGetSystemAttributes Op = 0x005b // Get-System-Attributes: Get system object attributes OpGetSystemSupportedValues Op = 0x005c // Get-System-Supported-Values: Get supported values for system object attributes OpPauseAllPrinters Op = 0x005d // Pause-All-Printers: Stop all services immediately OpPauseAllPrintersAfterCurrentJob Op = 0x005e // Pause-All-Printers-After-Current-Job: Stop all services after processing the current jobs OpRegisterOutputDevice Op = 0x005f // Register-Output-Device: Register a remote service OpRestartSystem Op = 0x0060 // Restart-System: Restart all services OpResumeAllPrinters Op = 0x0061 // Resume-All-Printers: Start job processing on all services OpSetSystemAttributes Op = 0x0062 // Set-System-Attributes: Set system object attributes OpShutdownAllPrinters Op = 0x0063 // Shutdown-All-Printers: Shutdown all services OpStartupAllPrinters Op = 0x0064 // Startup-All-Printers: Startup all services OpCupsGetDefault Op = 0x4001 // CUPS-Get-Default: Get the default printer OpCupsGetPrinters Op = 0x4002 // CUPS-Get-Printers: Get a list of printers and/or classes OpCupsAddModifyPrinter Op = 0x4003 // CUPS-Add-Modify-Printer: Add or modify a printer OpCupsDeletePrinter Op = 0x4004 // CUPS-Delete-Printer: Delete a printer OpCupsGetClasses Op = 0x4005 // CUPS-Get-Classes: Get a list of classes OpCupsAddModifyClass Op = 0x4006 // CUPS-Add-Modify-Class: Add or modify a class OpCupsDeleteClass Op = 0x4007 // CUPS-Delete-Class: Delete a class OpCupsAcceptJobs Op = 0x4008 // CUPS-Accept-Jobs: Accept new jobs on a printer OpCupsRejectJobs Op = 0x4009 // CUPS-Reject-Jobs: Reject new jobs on a printer OpCupsSetDefault Op = 0x400a // CUPS-Set-Default: Set the default printer OpCupsGetDevices Op = 0x400b // CUPS-Get-Devices: Get a list of supported devices OpCupsGetPpds Op = 0x400c // CUPS-Get-PPDs: Get a list of supported drivers OpCupsMoveJob Op = 0x400d // CUPS-Move-Job: Move a job to a different printer OpCupsAuthenticateJob Op = 0x400e // CUPS-Authenticate-Job: Authenticate a job OpCupsGetPpd Op = 0x400f // CUPS-Get-PPD: Get a PPD file OpCupsGetDocument Op = 0x4027 // CUPS-Get-Document: Get a document file OpCupsCreateLocalPrinter Op = 0x4028 // CUPS-Create-Local-Printer: Create a local (temporary) printer ) // String() returns a Status name, as defined by RFC 8010 func (op Op) String() string { if int(op) < len(opNames) { if s := opNames[op]; s != "" { return s } } return fmt.Sprintf("0x%4.4x", int(op)) } var opNames = [...]string{ OpPrintJob: "Print-Job", OpPrintURI: "Print-URI", OpValidateJob: "Validate-Job", OpCreateJob: "Create-Job", OpSendDocument: "Send-Document", OpSendURI: "Send-URI", OpCancelJob: "Cancel-Job", OpGetJobAttributes: "Get-Job-Attribute", OpGetJobs: "Get-Jobs", OpGetPrinterAttributes: "Get-Printer-Attributes", OpHoldJob: "Hold-Job", OpReleaseJob: "Release-Job", OpRestartJob: "Restart-Job", OpPausePrinter: "Pause-Printer", OpResumePrinter: "Resume-Printer", OpPurgeJobs: "Purge-Jobs", OpSetPrinterAttributes: "Set-Printer-Attributes", OpSetJobAttributes: "Set-Job-Attributes", OpGetPrinterSupportedValues: "Get-Printer-Supported-Values", OpCreatePrinterSubscriptions: "Create-Printer-Subscriptions", OpCreateJobSubscriptions: "Create-Job-Subscriptions", OpGetSubscriptionAttributes: "Get-Subscription-Attributes", OpGetSubscriptions: "Get-Subscriptions", OpRenewSubscription: "Renew-Subscription", OpCancelSubscription: "Cancel-Subscription", OpGetNotifications: "Get-Notifications", OpSendNotifications: "Send-Notifications", OpGetResourceAttributes: "Get-Resource-Attributes", OpGetResourceData: "Get-Resource-Data", OpGetResources: "Get-Resources", OpGetPrintSupportFiles: "Get-Printer-Support-Files", OpEnablePrinter: "Enable-Printer", OpDisablePrinter: "Disable-Printer", OpPausePrinterAfterCurrentJob: "Pause-Printer-After-Current-Job", OpHoldNewJobs: "Hold-New-Jobs", OpReleaseHeldNewJobs: "Release-Held-New-Jobs", OpDeactivatePrinter: "Deactivate-Printer", OpActivatePrinter: "Activate-Printer", OpRestartPrinter: "Restart-Printer", OpShutdownPrinter: "Shutdown-Printer", OpStartupPrinter: "Startup-Printer", OpReprocessJob: "Reprocess-Job", OpCancelCurrentJob: "Cancel-Current-Job", OpSuspendCurrentJob: "Suspend-Current-Job", OpResumeJob: "Resume-Job", OpPromoteJob: "Promote-Job", OpScheduleJobAfter: "Schedule-Job-After", OpCancelDocument: "Cancel-Document", OpGetDocumentAttributes: "Get-Document-Attributes", OpGetDocuments: "Get-Documents", OpDeleteDocument: "Delete-Document", OpSetDocumentAttributes: "Set-Document-Attributes", OpCancelJobs: "Cancel-Jobs", OpCancelMyJobs: "Cancel-My-Jobs", OpResubmitJob: "Resubmit-Job", OpCloseJob: "Close-Job", OpIdentifyPrinter: "Identify-Printer", OpValidateDocument: "Validate-Document", OpAddDocumentImages: "Add-Document-Images", OpAcknowledgeDocument: "Acknowledge-Document", OpAcknowledgeIdentifyPrinter: "Acknowledge-Identify-Printer", OpAcknowledgeJob: "Acknowledge-Job", OpFetchDocument: "Fetch-Document", OpFetchJob: "Fetch-Job", OpGetOutputDeviceAttributes: "Get-Output-Device-Attributes", OpUpdateActiveJobs: "Update-Active-Jobs", OpDeregisterOutputDevice: "Deregister-Output-Device", OpUpdateDocumentStatus: "Update-Document-Status", OpUpdateJobStatus: "Update-Job-Status", OpupdateOutputDeviceAttributes: "Update-Output-Device-Attributes", OpGetNextDocumentData: "Get-Next-Document-Data", OpAllocatePrinterResources: "Allocate-Printer-Resources", OpCreatePrinter: "Create-Printer", OpDeallocatePrinterResources: "Deallocate-Printer-Resources", OpDeletePrinter: "Delete-Printer", OpGetPrinters: "Get-Printers", OpShutdownOnePrinter: "Shutdown-One-Printer", OpStartupOnePrinter: "Startup-One-Printer", OpCancelResource: "Cancel-Resource", OpCreateResource: "Create-Resource", OpInstallResource: "Install-Resource", OpSendResourceData: "Send-Resource-Data", OpSetResourceAttributes: "Set-Resource-Attributes", OpCreateResourceSubscriptions: "Create-Resource-Subscriptions", OpCreateSystemSubscriptions: "Create-System-Subscriptions", OpDisableAllPrinters: "Disable-All-Printers", OpEnableAllPrinters: "Enable-All-Printers", OpGetSystemAttributes: "Get-System-Attributes", OpGetSystemSupportedValues: "Get-System-Supported-Values", OpPauseAllPrinters: "Pause-All-Printers", OpPauseAllPrintersAfterCurrentJob: "Pause-All-Printers-After-Current-Job", OpRegisterOutputDevice: "Register-Output-Device", OpRestartSystem: "Restart-System", OpResumeAllPrinters: "Resume-All-Printers", OpSetSystemAttributes: "Set-System-Attributes", OpShutdownAllPrinters: "Shutdown-All-Printers", OpStartupAllPrinters: "Startup-All-Printers", OpCupsGetDefault: "CUPS-Get-Default", OpCupsGetPrinters: "CUPS-Get-Printers", OpCupsAddModifyPrinter: "CUPS-Add-Modify-Printer", OpCupsDeletePrinter: "CUPS-Delete-Printer", OpCupsGetClasses: "CUPS-Get-Classes", OpCupsAddModifyClass: "CUPS-Add-Modify-Class", OpCupsDeleteClass: "CUPS-Delete-Class", OpCupsAcceptJobs: "CUPS-Accept-Jobs", OpCupsRejectJobs: "CUPS-Reject-Jobs", OpCupsSetDefault: "CUPS-Set-Default", OpCupsGetDevices: "CUPS-Get-Devices", OpCupsGetPpds: "CUPS-Get-PPDs", OpCupsMoveJob: "CUPS-Move-Job", OpCupsAuthenticateJob: "CUPS-Authenticate-Job", OpCupsGetPpd: "CUPS-Get-PPD", OpCupsGetDocument: "CUPS-Get-Document", OpCupsCreateLocalPrinter: "CUPS-Create-Local-Printer", } goipp-1.1.0/status.go000066400000000000000000000233061453360531400145110ustar00rootroot00000000000000/* Go IPP - IPP core protocol implementation in pure Go * * Copyright (C) 2020 and up by Alexander Pevzner (pzz@apevzner.com) * See LICENSE for license terms and conditions * * IPP Status Codes */ package goipp import ( "fmt" ) // Status represents an IPP Status Code type Status Code // Status codes const ( StatusOk Status = 0x0000 // successful-ok StatusOkIgnoredOrSubstituted Status = 0x0001 // successful-ok-ignored-or-substituted-attributes StatusOkConflicting Status = 0x0002 // successful-ok-conflicting-attributes StatusOkIgnoredSubscriptions Status = 0x0003 // successful-ok-ignored-subscriptions StatusOkIgnoredNotifications Status = 0x0004 // successful-ok-ignored-notifications StatusOkTooManyEvents Status = 0x0005 // successful-ok-too-many-events StatusOkButCancelSubscription Status = 0x0006 // successful-ok-but-cancel-subscription StatusOkEventsComplete Status = 0x0007 // successful-ok-events-complete StatusRedirectionOtherSite Status = 0x0200 // redirection-other-site StatusCupsSeeOther Status = 0x0280 // cups-see-other StatusErrorBadRequest Status = 0x0400 // client-error-bad-request StatusErrorForbidden Status = 0x0401 // client-error-forbidden StatusErrorNotAuthenticated Status = 0x0402 // client-error-not-authenticated StatusErrorNotAuthorized Status = 0x0403 // client-error-not-authorized StatusErrorNotPossible Status = 0x0404 // client-error-not-possible StatusErrorTimeout Status = 0x0405 // client-error-timeout StatusErrorNotFound Status = 0x0406 // client-error-not-found StatusErrorGone Status = 0x0407 // client-error-gone StatusErrorRequestEntity Status = 0x0408 // client-error-request-entity-too-large StatusErrorRequestValue Status = 0x0409 // client-error-request-value-too-long StatusErrorDocumentFormatNotSupported Status = 0x040a // client-error-document-format-not-supported StatusErrorAttributesOrValues Status = 0x040b // client-error-attributes-or-values-not-supported StatusErrorURIScheme Status = 0x040c // client-error-uri-scheme-not-supported StatusErrorCharset Status = 0x040d // client-error-charset-not-supported StatusErrorConflicting Status = 0x040e // client-error-conflicting-attributes StatusErrorCompressionNotSupported Status = 0x040f // client-error-compression-not-supported StatusErrorCompressionError Status = 0x0410 // client-error-compression-error StatusErrorDocumentFormatError Status = 0x0411 // client-error-document-format-error StatusErrorDocumentAccess Status = 0x0412 // client-error-document-access-error StatusErrorAttributesNotSettable Status = 0x0413 // client-error-attributes-not-settable StatusErrorIgnoredAllSubscriptions Status = 0x0414 // client-error-ignored-all-subscriptions StatusErrorTooManySubscriptions Status = 0x0415 // client-error-too-many-subscriptions StatusErrorIgnoredAllNotifications Status = 0x0416 // client-error-ignored-all-notifications StatusErrorPrintSupportFileNotFound Status = 0x0417 // client-error-print-support-file-not-found StatusErrorDocumentPassword Status = 0x0418 // client-error-document-password-error StatusErrorDocumentPermission Status = 0x0419 // client-error-document-permission-error StatusErrorDocumentSecurity Status = 0x041a // client-error-document-security-error StatusErrorDocumentUnprintable Status = 0x041b // client-error-document-unprintable-error StatusErrorAccountInfoNeeded Status = 0x041c // client-error-account-info-needed StatusErrorAccountClosed Status = 0x041d // client-error-account-closed StatusErrorAccountLimitReached Status = 0x041e // client-error-account-limit-reached StatusErrorAccountAuthorizationFailed Status = 0x041f // client-error-account-authorization-failed StatusErrorNotFetchable Status = 0x0420 // client-error-not-fetchable StatusErrorInternal Status = 0x0500 // server-error-internal-error StatusErrorOperationNotSupported Status = 0x0501 // server-error-operation-not-supported StatusErrorServiceUnavailable Status = 0x0502 // server-error-service-unavailable StatusErrorVersionNotSupported Status = 0x0503 // server-error-version-not-supported StatusErrorDevice Status = 0x0504 // server-error-device-error StatusErrorTemporary Status = 0x0505 // server-error-temporary-error StatusErrorNotAcceptingJobs Status = 0x0506 // server-error-not-accepting-jobs StatusErrorBusy Status = 0x0507 // server-error-busy StatusErrorJobCanceled Status = 0x0508 // server-error-job-canceled StatusErrorMultipleJobsNotSupported Status = 0x0509 // server-error-multiple-document-jobs-not-supported StatusErrorPrinterIsDeactivated Status = 0x050a // server-error-printer-is-deactivated StatusErrorTooManyJobs Status = 0x050b // server-error-too-many-jobs StatusErrorTooManyDocuments Status = 0x050c // server-error-too-many-documents ) // String() returns a Status name, as defined by RFC 8010 func (status Status) String() string { if int(status) < len(statusNames) { if s := statusNames[status]; s != "" { return s } } return fmt.Sprintf("0x%4.4x", int(status)) } var statusNames = [...]string{ StatusOk: "successful-ok", StatusOkIgnoredOrSubstituted: "successful-ok-ignored-or-substituted-attributes", StatusOkConflicting: "successful-ok-conflicting-attributes", StatusOkIgnoredSubscriptions: "successful-ok-ignored-subscriptions", StatusOkIgnoredNotifications: "successful-ok-ignored-notifications", StatusOkTooManyEvents: "successful-ok-too-many-events", StatusOkButCancelSubscription: "successful-ok-but-cancel-subscription", StatusOkEventsComplete: "successful-ok-events-complete", StatusRedirectionOtherSite: "redirection-other-site", StatusCupsSeeOther: "cups-see-other", StatusErrorBadRequest: "client-error-bad-request", StatusErrorForbidden: "client-error-forbidden", StatusErrorNotAuthenticated: "client-error-not-authenticated", StatusErrorNotAuthorized: "client-error-not-authorized", StatusErrorNotPossible: "client-error-not-possible", StatusErrorTimeout: "client-error-timeout", StatusErrorNotFound: "client-error-not-found", StatusErrorGone: "client-error-gone", StatusErrorRequestEntity: "client-error-request-entity-too-large", StatusErrorRequestValue: "client-error-request-value-too-long", StatusErrorDocumentFormatNotSupported: "client-error-document-format-not-supported", StatusErrorAttributesOrValues: "client-error-attributes-or-values-not-supported", StatusErrorURIScheme: "client-error-uri-scheme-not-supported", StatusErrorCharset: "client-error-charset-not-supported", StatusErrorConflicting: "client-error-conflicting-attributes", StatusErrorCompressionNotSupported: "client-error-compression-not-supported", StatusErrorCompressionError: "client-error-compression-error", StatusErrorDocumentFormatError: "client-error-document-format-error", StatusErrorDocumentAccess: "client-error-document-access-error", StatusErrorAttributesNotSettable: "client-error-attributes-not-settable", StatusErrorIgnoredAllSubscriptions: "client-error-ignored-all-subscriptions", StatusErrorTooManySubscriptions: "client-error-too-many-subscriptions", StatusErrorIgnoredAllNotifications: "client-error-ignored-all-notifications", StatusErrorPrintSupportFileNotFound: "client-error-print-support-file-not-found", StatusErrorDocumentPassword: "client-error-document-password-error", StatusErrorDocumentPermission: "client-error-document-permission-error", StatusErrorDocumentSecurity: "client-error-document-security-error", StatusErrorDocumentUnprintable: "client-error-document-unprintable-error", StatusErrorAccountInfoNeeded: "client-error-account-info-needed", StatusErrorAccountClosed: "client-error-account-closed", StatusErrorAccountLimitReached: "client-error-account-limit-reached", StatusErrorAccountAuthorizationFailed: "client-error-account-authorization-failed", StatusErrorNotFetchable: "client-error-not-fetchable", StatusErrorInternal: "server-error-internal-error", StatusErrorOperationNotSupported: "server-error-operation-not-supported", StatusErrorServiceUnavailable: "server-error-service-unavailable", StatusErrorVersionNotSupported: "server-error-version-not-supported", StatusErrorDevice: "server-error-device-error", StatusErrorTemporary: "server-error-temporary-error", StatusErrorNotAcceptingJobs: "server-error-not-accepting-jobs", StatusErrorBusy: "server-error-busy", StatusErrorJobCanceled: "server-error-job-canceled", StatusErrorMultipleJobsNotSupported: "server-error-multiple-document-jobs-not-supported", StatusErrorPrinterIsDeactivated: "server-error-printer-is-deactivated", StatusErrorTooManyJobs: "server-error-too-many-jobs", StatusErrorTooManyDocuments: "server-error-too-many-documents", } goipp-1.1.0/tag.go000066400000000000000000000134651453360531400137460ustar00rootroot00000000000000/* Go IPP - IPP core protocol implementation in pure Go * * Copyright (C) 2020 and up by Alexander Pevzner (pzz@apevzner.com) * See LICENSE for license terms and conditions * * IPP Tags */ package goipp import ( "fmt" ) // Tag represents a tag used in a binary representation // of the IPP message type Tag int // Tag values const ( // Delimiter tags TagZero Tag = 0x00 // Zero tag - used for separators TagOperationGroup Tag = 0x01 // Operation group TagJobGroup Tag = 0x02 // Job group TagEnd Tag = 0x03 // End-of-attributes TagPrinterGroup Tag = 0x04 // Printer group TagUnsupportedGroup Tag = 0x05 // Unsupported attributes group TagSubscriptionGroup Tag = 0x06 // Subscription group TagEventNotificationGroup Tag = 0x07 // Event group TagResourceGroup Tag = 0x08 // Resource group TagDocumentGroup Tag = 0x09 // Document group TagSystemGroup Tag = 0x0a // System group TagFuture11Group Tag = 0x0b // Future group 11 TagFuture12Group Tag = 0x0c // Future group 12 TagFuture13Group Tag = 0x0d // Future group 13 TagFuture14Group Tag = 0x0e // Future group 14 TagFuture15Group Tag = 0x0f // Future group 15 // Value tags TagUnsupportedValue Tag = 0x10 // Unsupported value TagDefault Tag = 0x11 // Default value TagUnknown Tag = 0x12 // Unknown value TagNoValue Tag = 0x13 // No-value value TagNotSettable Tag = 0x15 // Not-settable value TagDeleteAttr Tag = 0x16 // Delete-attribute value TagAdminDefine Tag = 0x17 // Admin-defined value TagInteger Tag = 0x21 // Integer value TagBoolean Tag = 0x22 // Boolean value TagEnum Tag = 0x23 // Enumeration value TagString Tag = 0x30 // Octet string value TagDateTime Tag = 0x31 // Date/time value TagResolution Tag = 0x32 // Resolution value TagRange Tag = 0x33 // Range value TagBeginCollection Tag = 0x34 // Beginning of collection value TagTextLang Tag = 0x35 // Text-with-language value TagNameLang Tag = 0x36 // Name-with-language value TagEndCollection Tag = 0x37 // End of collection value TagText Tag = 0x41 // Text value TagName Tag = 0x42 // Name value TagReservedString Tag = 0x43 // Reserved for future string value TagKeyword Tag = 0x44 // Keyword value TagURI Tag = 0x45 // URI value TagURIScheme Tag = 0x46 // URI scheme value TagCharset Tag = 0x47 // Character set value TagLanguage Tag = 0x48 // Language value TagMimeType Tag = 0x49 // MIME media type value TagMemberName Tag = 0x4a // Collection member name value TagExtension Tag = 0x7f // Extension point for 32-bit tags ) // IsDelimiter returns true for delimiter tags func (tag Tag) IsDelimiter() bool { return uint(tag) < 0x10 } // IsGroup returns true for group tags func (tag Tag) IsGroup() bool { return tag.IsDelimiter() && tag != TagZero && tag != TagEnd } // Type returns Type of Value that corresponds to the tag func (tag Tag) Type() Type { if tag.IsDelimiter() { return TypeInvalid } switch tag { case TagInteger, TagEnum: return TypeInteger case TagBoolean: return TypeBoolean case TagUnsupportedValue, TagDefault, TagUnknown, TagNotSettable, TagDeleteAttr, TagAdminDefine: // These tags not expected to have value return TypeVoid case TagText, TagName, TagReservedString, TagKeyword, TagURI, TagURIScheme, TagCharset, TagLanguage, TagMimeType, TagMemberName: return TypeString case TagDateTime: return TypeDateTime case TagResolution: return TypeResolution case TagRange: return TypeRange case TagTextLang, TagNameLang: return TypeTextWithLang case TagBeginCollection: return TypeCollection case TagEndCollection: return TypeVoid default: return TypeBinary } } // String() returns a tag name, as defined by RFC 8010 func (tag Tag) String() string { if 0 <= tag && int(tag) < len(tagNames) { if s := tagNames[tag]; s != "" { return s } } if tag < 0x100 { return fmt.Sprintf("0x%2.2x", uint(tag)) } return fmt.Sprintf("0x%8.8x", uint(tag)) } var tagNames = [...]string{ // Delimiter tags TagZero: "zero", TagOperationGroup: "operation-attributes-tag", TagJobGroup: "job-attributes-tag", TagEnd: "end-of-attributes-tag", TagPrinterGroup: "printer-attributes-tag", TagUnsupportedGroup: "unsupported-attributes-tag", TagSubscriptionGroup: "subscription-attributes-tag", TagEventNotificationGroup: "event-notification-attributes-tag", TagResourceGroup: "resource-attributes-tag", TagDocumentGroup: "document-attributes-tag", TagSystemGroup: "system-attributes-tag", // Value tags TagUnsupportedValue: "unsupported", TagDefault: "default", TagUnknown: "unknown", TagNoValue: "no-value", TagNotSettable: "not-settable", TagDeleteAttr: "delete-attribute", TagAdminDefine: "admin-define", TagInteger: "integer", TagBoolean: "boolean", TagEnum: "enum", TagString: "octetString", TagDateTime: "dateTime", TagResolution: "resolution", TagRange: "rangeOfInteger", TagBeginCollection: "collection", TagTextLang: "textWithLanguage", TagNameLang: "nameWithLanguage", TagEndCollection: "endCollection", TagText: "textWithoutLanguage", TagName: "nameWithoutLanguage", TagKeyword: "keyword", TagURI: "uri", TagURIScheme: "uriScheme", TagCharset: "charset", TagLanguage: "naturalLanguage", TagMimeType: "mimeMediaType", TagMemberName: "memberAttrName", } goipp-1.1.0/type.go000066400000000000000000000027161453360531400141510ustar00rootroot00000000000000/* Go IPP - IPP core protocol implementation in pure Go * * Copyright (C) 2020 and up by Alexander Pevzner (pzz@apevzner.com) * See LICENSE for license terms and conditions * * Enumeration of value types */ package goipp import ( "fmt" ) // Type enumerates all possible value types type Type int // Type values const ( TypeInvalid Type = -1 // Invalid Value type TypeVoid Type = iota // Value is Void TypeInteger // Value is Integer TypeBoolean // Value is Boolean TypeString // Value is String TypeDateTime // Value is Time TypeResolution // Value is Resolution TypeRange // Value is Range TypeTextWithLang // Value is TextWithLang TypeBinary // Value is Binary TypeCollection // Value is Collection ) // String converts Type to string, for debugging func (t Type) String() string { if t == TypeInvalid { return "Invalid" } if 0 <= t && int(t) < len(typeNames) { if s := typeNames[t]; s != "" { return s } } return fmt.Sprintf("0x%4.4x", uint(t)) } var typeNames = [...]string{ TypeVoid: "Void", TypeInteger: "Integer", TypeBoolean: "Boolean", TypeString: "String", TypeDateTime: "DateTime", TypeResolution: "Resolution", TypeRange: "Range", TypeTextWithLang: "TextWithLang", TypeBinary: "Binary", TypeCollection: "Collection", } goipp-1.1.0/value.go000066400000000000000000000340061453360531400143010ustar00rootroot00000000000000/* Go IPP - IPP core protocol implementation in pure Go * * Copyright (C) 2020 and up by Alexander Pevzner (pzz@apevzner.com) * See LICENSE for license terms and conditions * * Values for message attributes */ package goipp import ( "bytes" "encoding/binary" "errors" "fmt" "math" "time" ) // Values represents a sequence of values with tags. // Usually Values used as a "payload" of Attribute type Values []struct { T Tag // The tag V Value // The value } // Add Value to Values func (values *Values) Add(t Tag, v Value) { *values = append(*values, struct { T Tag V Value }{t, v}) } // String converts Values to string func (values Values) String() string { if len(values) == 1 { return values[0].V.String() } var buf bytes.Buffer buf.Write([]byte("[")) for i, v := range values { if i != 0 { buf.Write([]byte(",")) } buf.Write([]byte(v.V.String())) } buf.Write([]byte("]")) return buf.String() } // Equal performs deep check of equality of two Values func (values Values) Equal(values2 Values) bool { if len(values) != len(values2) { return false } for i, v := range values { v2 := values2[i] if v.T != v2.T || !ValueEqual(v.V, v2.V) { return false } } return true } // Value represents an attribute value // // IPP uses typed values, and type of each value is unambiguously // defined by the attribute tag type Value interface { String() string Type() Type encode() ([]byte, error) decode([]byte) (Value, error) } // ValueEqual checks if two values are equal // // Equality means that types and values are equal. For structured // values, like Collection, deep comparison is performed func ValueEqual(v1, v2 Value) bool { if v1.Type() != v2.Type() { return false } switch v1.Type() { case TypeDateTime: return v1.(Time).Equal(v2.(Time).Time) case TypeBinary: return bytes.Equal(v1.(Binary), v2.(Binary)) case TypeCollection: c1 := Attributes(v1.(Collection)) c2 := Attributes(v2.(Collection)) return c1.Equal(c2) } return v1 == v2 } // Void is the Value that represents "no value" // // Use with: TagUnsupportedValue, TagDefault, TagUnknown, // TagNotSettable, TagDeleteAttr, TagAdminDefine type Void struct{} // String converts Void Value to string func (Void) String() string { return "" } // Type returns type of Value (TypeVoid for Void) func (Void) Type() Type { return TypeVoid } // Encode Void Value into wire format func (v Void) encode() ([]byte, error) { return []byte{}, nil } // Decode Void Value from wire format func (Void) decode([]byte) (Value, error) { return Void{}, nil } // Integer is the Value that represents 32-bit signed int // // Use with: TagInteger, TagEnum type Integer int32 // String converts Integer value to string func (v Integer) String() string { return fmt.Sprintf("%d", int32(v)) } // Type returns type of Value (TypeInteger for Integer) func (Integer) Type() Type { return TypeInteger } // Encode Integer Value into wire format func (v Integer) encode() ([]byte, error) { return []byte{byte(v >> 24), byte(v >> 16), byte(v >> 8), byte(v)}, nil } // Decode Integer Value from wire format func (Integer) decode(data []byte) (Value, error) { if len(data) != 4 { return nil, errors.New("value must be 4 bytes") } return Integer(binary.BigEndian.Uint32(data)), nil } // Boolean is the Value that contains true of false // // Use with: TagBoolean type Boolean bool // String converts Boolean value to string func (v Boolean) String() string { return fmt.Sprintf("%t", bool(v)) } // Type returns type of Value (TypeBoolean for Boolean) func (Boolean) Type() Type { return TypeBoolean } // Encode Boolean Value into wire format func (v Boolean) encode() ([]byte, error) { if v { return []byte{1}, nil } return []byte{0}, nil } // Decode Boolean Value from wire format func (Boolean) decode(data []byte) (Value, error) { if len(data) != 1 { return nil, errors.New("value must be 1 byte") } return Boolean(data[0] != 0), nil } // String is the Value that represents string of text // // Use with: TagText, TagName, TagReservedString, TagKeyword, TagURI, // TagURIScheme, TagCharset, TagLanguage, TagMimeType, TagMemberName type String string // String converts String value to string func (v String) String() string { return string(v) } // Type returns type of Value (TypeString for String) func (String) Type() Type { return TypeString } // Encode String Value into wire format func (v String) encode() ([]byte, error) { return []byte(v), nil } // Decode String Value from wire format func (String) decode(data []byte) (Value, error) { return String(data), nil } // Time is the Value that represents DataTime // // Use with: TagTime type Time struct{ time.Time } // String converts Time value to string func (v Time) String() string { return v.Time.Format(time.RFC3339) } // Type returns type of Value (TypeDateTime for Time) func (Time) Type() Type { return TypeDateTime } // Encode Time Value into wire format func (v Time) encode() ([]byte, error) { // From RFC2579: // // field octets contents range // ----- ------ -------- ----- // 1 1-2 year* 0..65536 // 2 3 month 1..12 // 3 4 day 1..31 // 4 5 hour 0..23 // 5 6 minutes 0..59 // 6 7 seconds 0..60 // (use 60 for leap-second) // 7 8 deci-seconds 0..9 // 8 9 direction from UTC '+' / '-' // 9 10 hours from UTC* 0..13 // 10 11 minutes from UTC 0..59 // // * Notes: // - the value of year is in network-byte order // - daylight saving time in New Zealand is +13 year := v.Year() _, zone := v.Zone() dir := byte('+') if zone < 0 { zone = -zone dir = '-' } return []byte{ byte(year >> 8), byte(year), byte(v.Month()), byte(v.Day()), byte(v.Hour()), byte(v.Minute()), byte(v.Second()), byte(v.Nanosecond() / 100000000), dir, byte(zone / 3600), byte((zone / 60) % 60), }, nil } // Decode Time Value from wire format func (Time) decode(data []byte) (Value, error) { // Check size if len(data) != 11 { return nil, errors.New("value must be 11 bytes") } // Validate ranges var err error switch { case data[2] < 1 || data[2] > 12: err = fmt.Errorf("bad month %d", data[2]) case data[3] < 1 || data[3] > 31: err = fmt.Errorf("bad day %d", data[3]) case data[4] > 23: err = fmt.Errorf("bad hours %d", data[4]) case data[5] > 59: err = fmt.Errorf("bad minutes %d", data[5]) case data[6] > 60: err = fmt.Errorf("bad seconds %d", data[6]) case data[7] > 9: err = fmt.Errorf("bad deciseconds %d", data[7]) case data[8] != '+' && data[8] != '-': return nil, errors.New("bad UTC sign") case data[9] > 11: err = fmt.Errorf("bad UTC hours %d", data[9]) case data[10] > 59: err = fmt.Errorf("bad UTC minutes %d", data[10]) } if err != nil { return Time{}, err } // Decode time zone tzName := fmt.Sprintf("UTC%c%d", data[8], data[9]) if data[10] != 0 { tzName += fmt.Sprintf(":%d", data[10]) } tzOff := 3600*int(data[9]) + 60*int(data[10]) if data[8] == '-' { tzOff = -tzOff } tz := time.FixedZone(tzName, tzOff) // Decode time t := time.Date( int(binary.BigEndian.Uint16(data[0:2])), // year time.Month(data[2]), // month int(data[3]), // day int(data[4]), // hour int(data[5]), // min int(data[6]), // sec int(data[7])*100000000, // nsec tz, // time zone ) return Time{t}, nil } // Resolution is the Value that represents image resolution. // // Use with: TagResolution type Resolution struct { Xres, Yres int // X/Y resolutions Units Units // Resolution units } // String converts Resolution value to string func (v Resolution) String() string { return fmt.Sprintf("%dx%d%s", v.Xres, v.Yres, v.Units) } // Type returns type of Value (TypeResolution for Resolution) func (Resolution) Type() Type { return TypeResolution } // Encode Resolution Value into wire format func (v Resolution) encode() ([]byte, error) { // Wire format // 4 bytes: Xres // 4 bytes: Yres // 1 byte: Units x, y := v.Xres, v.Yres return []byte{ byte(x >> 24), byte(x >> 16), byte(x >> 8), byte(x), byte(y >> 24), byte(y >> 16), byte(y >> 8), byte(y), byte(v.Units), }, nil } // Decode Resolution Value from wire format func (Resolution) decode(data []byte) (Value, error) { if len(data) != 9 { return nil, errors.New("value must be 9 bytes") } return Resolution{ Xres: int(binary.BigEndian.Uint32(data[0:4])), Yres: int(binary.BigEndian.Uint32(data[4:8])), Units: Units(data[8]), }, nil } // Units represents resolution units type Units uint8 // Resolution units codes const ( UnitsDpi Units = 3 // Dots per inch UnitsDpcm Units = 4 // Dots per cm ) // String converts Units to string func (u Units) String() string { switch u { case UnitsDpi: return "dpi" case UnitsDpcm: return "dpcm" default: return fmt.Sprintf("0x%2.2x", uint8(u)) } } // Range is the Value that represents a range of 32-bit signed integers // // Use with: TagRange type Range struct { Lower, Upper int // Lower/upper bounds } // String converts Range value to string func (v Range) String() string { return fmt.Sprintf("%d-%d", v.Lower, v.Upper) } // Type returns type of Value (TypeRange for Range) func (Range) Type() Type { return TypeRange } // Encode Range Value into wire format func (v Range) encode() ([]byte, error) { // Wire format // 4 bytes: Lower // 4 bytes: Upper l, u := v.Lower, v.Upper return []byte{ byte(l >> 24), byte(l >> 16), byte(l >> 8), byte(l), byte(u >> 24), byte(u >> 16), byte(u >> 8), byte(u), }, nil } // Decode Range Value from wire format func (Range) decode(data []byte) (Value, error) { if len(data) != 8 { return nil, errors.New("value must be 8 bytes") } return Range{ Lower: int(binary.BigEndian.Uint32(data[0:4])), Upper: int(binary.BigEndian.Uint32(data[4:8])), }, nil } // TextWithLang is the Value that represents a combination // of two strings: // * text on some natural language (i.e., "hello") // * name of that language (i.e., "en") // // Use with: TagTextLang, TagNameLang type TextWithLang struct { Lang, Text string // Language and text } // String converts TextWithLang value to string func (v TextWithLang) String() string { return v.Text + " [" + v.Lang + "]" } // Type returns type of Value (TypeTextWithLang for TextWithLang) func (TextWithLang) Type() Type { return TypeTextWithLang } // Encode TextWithLang Value into wire format func (v TextWithLang) encode() ([]byte, error) { // Wire format // 2 bytes: len(Lang) // variable: Lang // 2 bytes: len(Text) // variable: Text lang := []byte(v.Lang) text := []byte(v.Text) if len(lang) > math.MaxUint16 { return nil, fmt.Errorf("Lang exceeds %d bytes", math.MaxUint16) } if len(text) > math.MaxUint16 { return nil, fmt.Errorf("Text exceeds %d bytes", math.MaxUint16) } data := make([]byte, 2+2+len(lang)+len(text)) binary.BigEndian.PutUint16(data, uint16(len(lang))) copy(data[2:], []byte(lang)) data2 := data[2+len(lang):] binary.BigEndian.PutUint16(data2, uint16(len(text))) copy(data2[2:], []byte(text)) return data, nil } // Decode TextWithLang Value from wire format func (TextWithLang) decode(data []byte) (Value, error) { var langLen, textLen int var lang, text string // Unpack language length if len(data) < 2 { return nil, errors.New("truncated language length") } langLen = int(binary.BigEndian.Uint16(data[0:2])) data = data[2:] // Unpack language value if len(data) < langLen { return nil, errors.New("truncated language name") } lang = string(data[:langLen]) data = data[langLen:] // Unpack text length if len(data) < 2 { return nil, errors.New("truncated text length") } textLen = int(binary.BigEndian.Uint16(data[0:2])) data = data[2:] // Unpack text value if len(data) < textLen { return nil, errors.New("truncated text string") } text = string(data[:textLen]) data = data[textLen:] // We must have consumed all bytes at this point if len(data) != 0 { return nil, fmt.Errorf("extra %d bytes at the end of value", len(data)) } // Return a value return TextWithLang{Lang: lang, Text: text}, nil } // Binary is the Value that represents a raw binary data type Binary []byte // String converts Binary value to string func (v Binary) String() string { return fmt.Sprintf("%x", []byte(v)) } // Type returns type of Value (TypeBinary for Binary) func (Binary) Type() Type { return TypeBinary } // Encode TextWithLang Value into wire format func (v Binary) encode() ([]byte, error) { return []byte(v), nil } // Decode Binary Value from wire format func (Binary) decode(data []byte) (Value, error) { return Binary(data), nil } // Collection is the Value that represents collection of attributes // // Use with: TagBeginCollection type Collection Attributes // Add Attribute to Attributes func (v *Collection) Add(attr Attribute) { *v = append(*v, attr) } // Equal checks that two collections are equal func (v Collection) Equal(v2 Attributes) bool { return Attributes(v).Equal(Attributes(v2)) } // String converts Collection to string func (v Collection) String() string { var buf bytes.Buffer buf.Write([]byte("{")) for i, attr := range v { if i > 0 { buf.Write([]byte(" ")) } fmt.Fprintf(&buf, "%s=%s", attr.Name, attr.Values) } buf.Write([]byte("}")) return buf.String() } // Type returns type of Value (TypeCollection for Collection) func (Collection) Type() Type { return TypeCollection } // Encode Collection Value into wire format func (Collection) encode() ([]byte, error) { // Note, TagBeginCollection attribute contains // no data, collection itself handled the different way return []byte{}, nil } // Decode Collection Value from wire format func (Collection) decode(data []byte) (Value, error) { panic("internal error") }