func Decode()

in openpgp/clearsign/clearsign.go [86:196]


func Decode(data []byte) (b *Block, rest []byte) {
	// start begins with a newline. However, at the very beginning of
	// the byte array, we'll accept the start string without it.
	rest = data
	if bytes.HasPrefix(data, start[1:]) {
		rest = rest[len(start)-1:]
	} else if i := bytes.Index(data, start); i >= 0 {
		rest = rest[i+len(start):]
	} else {
		return nil, data
	}

	// Consume the start line and check it does not have a suffix.
	suffix, rest := getLine(rest)
	if len(suffix) != 0 {
		return nil, data
	}

	var line []byte
	b = &Block{
		Headers: make(textproto.MIMEHeader),
	}

	// Next come a series of header lines.
	for {
		// This loop terminates because getLine's second result is
		// always smaller than its argument.
		if len(rest) == 0 {
			return nil, data
		}
		// An empty line marks the end of the headers.
		if line, rest = getLine(rest); len(line) == 0 {
			break
		}

		// Reject headers with control or Unicode characters.
		if i := bytes.IndexFunc(line, func(r rune) bool {
			return r < 0x20 || r > 0x7e
		}); i != -1 {
			return nil, data
		}

		i := bytes.Index(line, []byte{':'})
		if i == -1 {
			return nil, data
		}

		key, val := string(line[0:i]), string(line[i+1:])
		key = strings.TrimSpace(key)
		if key != "Hash" {
			return nil, data
		}
		val = strings.TrimSpace(val)
		b.Headers.Add(key, val)
	}

	firstLine := true
	for {
		start := rest

		line, rest = getLine(rest)
		if len(line) == 0 && len(rest) == 0 {
			// No armored data was found, so this isn't a complete message.
			return nil, data
		}
		if bytes.Equal(line, endText) {
			// Back up to the start of the line because armor expects to see the
			// header line.
			rest = start
			break
		}

		// The final CRLF isn't included in the hash so we don't write it until
		// we've seen the next line.
		if firstLine {
			firstLine = false
		} else {
			b.Bytes = append(b.Bytes, crlf...)
		}

		if bytes.HasPrefix(line, dashEscape) {
			line = line[2:]
		}
		line = bytes.TrimRight(line, " \t")
		b.Bytes = append(b.Bytes, line...)

		b.Plaintext = append(b.Plaintext, line...)
		b.Plaintext = append(b.Plaintext, lf)
	}

	// We want to find the extent of the armored data (including any newlines at
	// the end).
	i := bytes.Index(rest, end)
	if i == -1 {
		return nil, data
	}
	i += len(end)
	for i < len(rest) && (rest[i] == '\r' || rest[i] == '\n') {
		i++
	}
	armored := rest[:i]
	rest = rest[i:]

	var err error
	b.ArmoredSignature, err = armor.Decode(bytes.NewBuffer(armored))
	if err != nil {
		return nil, data
	}

	return b, rest
}