Ejemplo n.º 1
0
// qDecode decodes a Q encoded string.
func qDecode(s string) ([]byte, error) {
	length := len(s)
	for i := 0; i < len(s); i++ {
		if s[i] == '=' {
			length -= 2
			i += 2
		}
	}
	dec := make([]byte, length)

	n := 0
	for i := 0; i < len(s); i++ {
		switch c := s[i]; {
		case c == '_':
			dec[n] = ' '
		case c == '=':
			if i+2 >= len(s) {
				return []byte(""), io.ErrUnexpectedEOF
			}
			buf, err := internal.ReadHexByte([]byte(s[i+1:]))
			if err != nil {
				return []byte(""), err
			}
			dec[n] = buf
			i += 2
		case (c >= ' ' && c <= '~') || c == '\n' || c == '\r' || c == '\t':
			dec[n] = c
		default:
			return []byte(""), fmt.Errorf("quotedprintable: invalid unescaped byte %#02x in Q encoded string at byte %d", c, i)
		}
		n++
	}

	return dec, nil
}
Ejemplo n.º 2
0
// Decode decodes src into at most MaxDecodedLen(len(src)) bytes to dst,
// returning the actual number of bytes written to dst.
func Decode(dst, src []byte) (n int, err error) {
	var eol, trimLen, eolLen int
	for i := 0; i < len(src); i++ {
		if i == eol {
			eol = bytes.IndexByte(src[i:], '\n') + i + 1
			if eol == i {
				eol = len(src)
				eolLen = 0
			} else if eol-2 >= i && src[eol-2] == '\r' {
				eolLen = 2
			} else {
				eolLen = 1
			}

			// Count the number of bytes to trim
			trimLen = 0
			for {
				if trimLen == eol-eolLen-i {
					break
				}

				switch src[eol-eolLen-trimLen-1] {
				case '\n', '\r', ' ', '\t':
					trimLen++
					continue
				case '=':
					if trimLen > 0 {
						trimLen += eolLen + 1
						eolLen = 0
						err = fmt.Errorf("quotedprintable: invalid bytes after =: %q", src[eol-trimLen+1:eol])
					} else {
						trimLen = eolLen + 1
						eolLen = 0
					}
				}
				break
			}
		}

		// Skip trimmable bytes
		if trimLen > 0 && i == eol-trimLen-eolLen {
			if err != nil {
				return n, err
			}

			i += trimLen - 1
			continue
		}

		switch c := src[i]; {
		case c == '=':
			if i+2 >= len(src) {
				return n, io.ErrUnexpectedEOF
			}
			b, convErr := internal.ReadHexByte(src[i+1:])
			if convErr != nil {
				return n, convErr
			}
			dst[n] = b
			n++
			i += 2
		case (c >= ' ' && c <= '~') || c == '\n' || c == '\r' || c == '\t':
			dst[n] = c
			n++
		default:
			return n, fmt.Errorf("quotedprintable: invalid unescaped byte 0x%02x in quoted-printable body", c)
		}
	}

	return n, nil
}