Пример #1
0
// foreachHeaderElement splits v according to the "#rule" construction
// in RFC 2616 section 2.1 and calls fn for each non-empty element.
func foreachHeaderElement(v string, fn func(string)) {
	v = textproto.TrimString(v)
	if v == "" {
		return
	}
	if !strings.Contains(v, ",") {
		fn(v)
		return
	}
	for _, f := range strings.Split(v, ",") {
		if f = textproto.TrimString(f); f != "" {
			fn(f)
		}
	}
}
Пример #2
0
// writeHeader writes the specified MIMEHeader to the io.Writer.
// Header values will be trimmed but otherwise left alone.
// Headers with multiple values are not supported and will return an error.
func writeHeader(w io.Writer, header textproto.MIMEHeader) error {
	for k, vs := range header {
		_, err := fmt.Fprintf(w, "%s: ", k)
		if err != nil {
			return err
		}

		for i, v := range vs {
			v = textproto.TrimString(v)

			_, err := fmt.Fprintf(w, "%s", v)
			if err != nil {
				return err
			}

			if i < len(vs)-1 {
				return errors.New("Multiple header values are not supported.")
			}
		}

		_, err = fmt.Fprint(w, crlf)
		if err != nil {
			return err
		}
	}

	// Write a blank line as a spacer
	_, err := fmt.Fprint(w, crlf)
	if err != nil {
		return err
	}

	return nil
}
Пример #3
0
Файл: fs.go Проект: oshimaya/go
func checkIfMatch(w ResponseWriter, r *Request) condResult {
	im := r.Header.Get("If-Match")
	if im == "" {
		return condNone
	}
	for {
		im = textproto.TrimString(im)
		if len(im) == 0 {
			break
		}
		if im[0] == ',' {
			im = im[1:]
			continue
		}
		if im[0] == '*' {
			return condTrue
		}
		etag, remain := scanETag(im)
		if etag == "" {
			break
		}
		if etagStrongMatch(etag, w.Header().get("Etag")) {
			return condTrue
		}
		im = remain
	}

	return condFalse
}
Пример #4
0
Файл: fs.go Проект: oshimaya/go
func checkIfNoneMatch(w ResponseWriter, r *Request) condResult {
	inm := r.Header.get("If-None-Match")
	if inm == "" {
		return condNone
	}
	buf := inm
	for {
		buf = textproto.TrimString(buf)
		if len(buf) == 0 {
			break
		}
		if buf[0] == ',' {
			buf = buf[1:]
		}
		if buf[0] == '*' {
			return condFalse
		}
		etag, remain := scanETag(buf)
		if etag == "" {
			break
		}
		if etagWeakMatch(etag, w.Header().get("Etag")) {
			return condFalse
		}
		buf = remain
	}
	return condTrue
}
Пример #5
0
// Write writes a header in wire format.
func (h Header) Write(w io.Writer) error {
	var err error

	// Mid is required
	if h.get(HEADER_MID) == "" {
		return errors.New("Missing MID in header")
	}

	// Write mid, this is defined to be the first value
	_, err = fmt.Fprintf(w, "Mid: %s\r\n", h.get(HEADER_MID))
	if err != nil {
		return err
	}

	for k, slice := range h {
		if strings.EqualFold(k, HEADER_MID) {
			continue
		}

		for _, v := range slice {
			v = textproto.TrimString(v)
			_, err = fmt.Fprintf(w, "%s: %s\r\n", k, v)
			if err != nil {
				return err
			}
		}
	}
	return nil
}
Пример #6
0
// only allows single content
func SendMulti(auth Auth, email MultipartEmail) error {
	if len(email.Content) != 1 {
		panic("only 1 content supported")
	}
	a := smtp.PlainAuth("", auth.User, auth.Password, auth.Host)
	buf := new(bytes.Buffer)
	boundary := randomBoundary()
	header := make(textproto.MIMEHeader)
	header.Set("Subject", email.Subject)
	header.Set("From", email.From)
	header.Set("To", strings.Join(email.To, ", "))
	if len(email.Cc) > 0 {
		header.Set("Cc", strings.Join(email.Cc, ", "))
	}
	header.Set("MIME-Version", "1.0")
	header.Set("Content-Type", "multipart/mixed; boundary="+boundary)
	for k, v := range header {
		for _, s := range v {
			fmt.Fprintf(buf, "%s: %s%s", k, textproto.TrimString(s), crlf)
		}
	}
	fmt.Fprint(buf, crlf)
	mm := multipart.NewWriter(buf)
	mm.SetBoundary(boundary)
	{
		content := email.Content[0]
		header := make(textproto.MIMEHeader)
		header.Set("Content-Type", content.Type)
		header.Set("Content-Transfer-Encoding", "base64")
		part, err := mm.CreatePart(header)
		if err != nil {
			return err
		}
		lw := &lineWriter{Writer: part, Length: 75}
		e := base64.NewEncoder(base64.StdEncoding, lw)
		e.Write(content.Data)
		e.Close()
	}
	for _, a := range email.Attachments {
		header := make(textproto.MIMEHeader)
		header.Set("Content-Type", fmt.Sprintf(`%s; name="%s"`, a.Type, a.Filename))
		if len(a.ContentID) > 0 {
			header.Set("Content-ID", fmt.Sprintf(`<%s>`, a.ContentID))
		}
		header.Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, a.Filename))
		header.Set("Content-Transfer-Encoding", "base64")
		part, err := mm.CreatePart(header)
		if err != nil {
			return err
		}
		lw := &lineWriter{Writer: part, Length: 75}
		e := base64.NewEncoder(base64.StdEncoding, lw)
		e.Write(a.Data)
		e.Close()
	}
	mm.Close()
	addr := fmt.Sprintf("%s:%d", auth.Host, auth.Port)
	return smtp.SendMail(addr, a, email.From, email.To, buf.Bytes())

}
Пример #7
0
func (cd *ResponseCacheDirectives) addPair(token string, v string) error {
	var err error = nil

	switch token {
	case "must-revalidate":
		err = ErrMustRevalidateNoArgs
	case "no-cache":
		cd.NoCachePresent = true
		tokens := strings.Split(v, ",")
		if cd.NoCache == nil {
			cd.NoCache = make(FieldNames)
		}
		for _, t := range tokens {
			k := http.CanonicalHeaderKey(textproto.TrimString(t))
			cd.NoCache[k] = true
		}
	case "no-store":
		err = ErrNoStoreNoArgs
	case "no-transform":
		err = ErrNoTransformNoArgs
	case "public":
		err = ErrPublicNoArgs
	case "private":
		cd.PrivatePresent = true
		tokens := strings.Split(v, ",")
		if cd.Private == nil {
			cd.Private = make(FieldNames)
		}
		for _, t := range tokens {
			k := http.CanonicalHeaderKey(textproto.TrimString(t))
			cd.Private[k] = true
		}
	case "proxy-revalidate":
		err = ErrProxyRevalidateNoArgs
	case "max-age":
		cd.MaxAge, err = parseDeltaSeconds(v)
	case "s-maxage":
		cd.SMaxAge, err = parseDeltaSeconds(v)
	default:
		// TODO(pquerna): this sucks, making user re-parse, and its technically not 'quoted' like the original,
		// but this is still easier, just a SplitN on "="
		cd.Extensions = append(cd.Extensions, token+"="+v)
	}

	return err
}
Пример #8
0
// WriteSubset writes a header in wire format.
// If exclude is not nil, keys where exclude[key] == true are not written.
func (h Header) WriteSubset(w io.Writer, exclude map[string]bool) error {
	ws, ok := w.(writeStringer)
	if !ok {
		ws = stringWriter{w}
	}
	for _, kv := range h.sortedKeyValues(exclude) {
		for _, v := range kv.values {
			v = headerNewlineToSpace.Replace(v)
			v = textproto.TrimString(v)
			for _, s := range []string{kv.key, ": ", v, "\r\n"} {
				if _, err := ws.WriteString(s); err != nil {
					return err
				}
			}
		}
	}
	return nil
}
Пример #9
0
// WriteSubset writes a header in wire format.
// If exclude is not nil, keys where exclude[key] == true are not written.
func (h Header) WriteSubset(w io.Writer, exclude map[string]bool) error {
	ws, ok := w.(writeStringer) // 将w变为writeStringer
	if !ok {
		ws = stringWriter{w} // 转换为WriteStringer接口
	}
	kvs, sorter := h.sortedKeyValues(exclude) // 将头部信息进行排序
	for _, kv := range kvs {
		for _, v := range kv.values {
			v = headerNewlineToSpace.Replace(v)
			v = textproto.TrimString(v)
			for _, s := range []string{kv.key, ": ", v, "\r\n"} {
				if _, err := ws.WriteString(s); err != nil {
					return err
				}
			}
		}
	}
	headerSorterPool.Put(sorter)
	return nil
}
Пример #10
0
// WriteTo writes this header out, including every field except for Bcc.
func (h Header) WriteTo(w io.Writer) (int64, error) {
	// TODO: Change how headerWriter decides where to wrap, then switch to MaxHeaderLineLength
	writer := &headerWriter{w: w, maxLineLen: MaxHeaderTotalLength}
	var total int64
	for _, field := range sortedHeaderFields(h) {
		if field == "Bcc" {
			continue // skip writing out Bcc
		}
		for _, val := range h[field] {
			val = textproto.TrimString(val)
			writer.curLineLen = 0 // Reset for next header
			for _, s := range []string{field, ": ", mime.QEncoding.Encode("UTF-8", val), "\r\n"} {
				written, err := io.WriteString(writer, s)
				if err != nil {
					return total, err
				}
				total += int64(written)
			}
		}
	}
	return total, nil
}
Пример #11
0
Файл: fs.go Проект: oshimaya/go
// scanETag determines if a syntactically valid ETag is present at s. If so,
// the ETag and remaining text after consuming ETag is returned. Otherwise,
// it returns "", "".
func scanETag(s string) (etag string, remain string) {
	s = textproto.TrimString(s)
	start := 0
	if strings.HasPrefix(s, "W/") {
		start = 2
	}
	if len(s[start:]) < 2 || s[start] != '"' {
		return "", ""
	}
	// ETag is either W/"text" or "text".
	// See RFC 7232 2.3.
	for i := start + 1; i < len(s); i++ {
		c := s[i]
		switch {
		// Character values allowed in ETags.
		case c == 0x21 || c >= 0x23 && c <= 0x7E || c >= 0x80:
		case c == '"':
			return string(s[:i+1]), s[i+1:]
		default:
			break
		}
	}
	return "", ""
}
Пример #12
0
			Expect(reflect.TypeOf(result).String()).To(Equal(expectedType))
		})
	})

	Describe("#injectIconsIntoSvgTemplate ", func() {
		It("injects icons into a template", func() {
			const svgTemplateContainer = `
		  <svg>
		    <defs>
		      {{.Icons}}
		    <defs>
		  </svg>`

			stringToBeInjected := `<symbol id="hello"></symbol>`

			tmpl, _ := template.New("svgSpriteTemplate").Parse(textproto.TrimString(svgTemplateContainer))

			resultByte := injectIconsIntoSvgTemplate(stringToBeInjected, tmpl)
			result := string(resultByte)

			expectedResult := `<svg>
		    <defs>
		      <symbol id="hello"></symbol>
		    <defs>
		  </svg>`

			Expect(result).To(Equal(expectedResult))
		})
	})

	Describe("#exists", func() {