func TestGetForwardedIpAndTimeStamp(t *testing.T) {
	testIp := net.ParseIP("222.222.222.222")
	testTime := time.Unix(1397768380, 0)

	headers := map[string][]string{
		textproto.CanonicalMIMEHeaderKey("X-ORIGINAL-MSEC"): []string{fmt.Sprintf("%d.000", testTime.Unix())},
		textproto.CanonicalMIMEHeaderKey("X-Forwarded-For"): []string{"222.222.222.222, 123.123.123.123, 123.123.123.124"},
	}
	ip := getIpFromHeader("X-Forwarded-For", headers)
	if testIp.String() != ip.String() {
		t.Errorf("Expecting %s for ip got %s\n", testIp, ip)
	}
}
Beispiel #2
0
func getHeader(i map[string][]string, header string) string {
	h, ok := textproto.MIMEHeader(i)[textproto.CanonicalMIMEHeaderKey(header)]
	if ok {
		return h[0]
	}
	return ""
}
Beispiel #3
0
// AssertJSONCall asserts that when the given handler is called with
// the given parameters, the result is as specified.
func AssertJSONCall(c *gc.C, p JSONCallParams) {
	c.Logf("JSON call, url %q", p.URL)
	if p.ExpectStatus == 0 {
		p.ExpectStatus = http.StatusOK
	}
	rec := DoRequest(c, DoRequestParams{
		Do:            p.Do,
		ExpectError:   p.ExpectError,
		Handler:       p.Handler,
		Method:        p.Method,
		URL:           p.URL,
		Body:          p.Body,
		JSONBody:      p.JSONBody,
		Header:        p.Header,
		ContentLength: p.ContentLength,
		Username:      p.Username,
		Password:      p.Password,
		Cookies:       p.Cookies,
	})
	if p.ExpectError != "" {
		return
	}
	AssertJSONResponse(c, rec, p.ExpectStatus, p.ExpectBody)

	for k, v := range p.ExpectHeader {
		c.Assert(rec.HeaderMap[textproto.CanonicalMIMEHeaderKey(k)], gc.DeepEquals, v, gc.Commentf("header %q", k))
	}
}
Beispiel #4
0
// applyOverrides applies the transport's request overrides to req. If any
// overrides apply, req is cloned and the overrides are applied to the clone.
func (t *RequestModifyingTransport) applyOverrides(req *http.Request) *http.Request {
	// Only override GET and HEAD requests, just to be safe. We may want to
	// revisit this constraint later.
	if method := strings.ToUpper(req.Method); method != "GET" && method != "HEAD" {
		return req
	}

	requestURI := req.URL.RequestURI()

	t.overridesMu.Lock()
	defer t.overridesMu.Unlock()

	cloned := false
	for requestURIRegexp, override := range t.overrides {
		if requestURIRegexp.MatchString(requestURI) {
			if !cloned {
				req = cloneRequest(req)
				cloned = true
			}

			for name, val := range override.setHeaders {
				req.Header[textproto.CanonicalMIMEHeaderKey(name)] = val
			}

			if override.runOnlyOnce {
				delete(t.overrides, requestURIRegexp)
			}
		}
	}

	return req
}
Beispiel #5
0
// heaveHeader check the existence of header header
func (m *Message) HaveHeader(key string) bool {
	key = textproto.CanonicalMIMEHeaderKey(key)
	if len(m.Header.Get(key)) == 0 {
		return false
	}
	return true
}
Beispiel #6
0
func (*suite) TestContentHashHeaderCanonicalized(c *gc.C) {
	// The header key should be canonicalized, because otherwise
	// the actually produced header will be different from that
	// specified.
	canon := textproto.CanonicalMIMEHeaderKey(params.ContentHashHeader)
	c.Assert(canon, gc.Equals, params.ContentHashHeader)
}
Beispiel #7
0
// IsSet tests if a key is present in the Header
func (h Header) IsSet(key string) bool {
	if h == nil {
		return false
	}
	_, ok := h[textproto.CanonicalMIMEHeaderKey(key)]
	return ok
}
Beispiel #8
0
// Get gets the first value associated with key in the Header and
// returns it and true. If the key is unset it returns the empty string
// and false.
func (h Header) Get(key string) (string, bool) {
	v, ok := h[textproto.CanonicalMIMEHeaderKey(key)]
	if !ok {
		return "", false
	}
	return v[0], ok
}
Beispiel #9
0
func TestSetHeaders(t *testing.T) {
	expectedFromEmptyHeader := http.Header{
		textproto.CanonicalMIMEHeaderKey(openrtb.HEADER_VERSION): []string{openrtb.VERSION},
		"Content-Type": []string{"application/json; charset=utf-8"},
	}

	tests := []struct {
		input    http.Header
		expected http.Header
	}{
		// Should set from empty header.
		{
			http.Header{},
			expectedFromEmptyHeader,
		},

		// Should replace the old content type.
		{
			http.Header{"Content-Type": []string{"text/plain"}},
			expectedFromEmptyHeader,
		},

		// Should replace the old OpenRTB spec version.
		{
			http.Header{textproto.CanonicalMIMEHeaderKey(openrtb.HEADER_VERSION): []string{"2.1"}},
			expectedFromEmptyHeader,
		},

		// Should keep existing, non-overlapped headers.
		{
			http.Header{"X-Additional-Header": []string{"for test"}},
			http.Header{
				textproto.CanonicalMIMEHeaderKey(openrtb.HEADER_VERSION): []string{openrtb.VERSION},
				"Content-Type":        []string{"application/json; charset=utf-8"},
				"X-Additional-Header": []string{"for test"},
			},
		},
	}

	for i, test := range tests {
		t.Logf("Testint %d...", i)
		openrtb.SetHeaders(test.input)
		if !reflect.DeepEqual(test.input, test.expected) {
			t.Errorf("Expected the HTTP headers to be\n%v instead of\n%v.", test.expected, test.input)
		}
	}
}
Beispiel #10
0
// NewObjectFromStream ...
func NewObjectFromStream(header textproto.MIMEHeader, body io.ReadCloser) (*Object, error) {
	objectID, err := strconv.ParseInt(header.Get("Object-ID"), 10, 64)
	if err != nil {
		// Attempt to parse a Rets Response code (if it exists)
		resp, parseErr := ReadResponse(body)
		if parseErr != nil {
			return nil, err
		}
		// Include a GetObject (empty of content) so that its rets response can be retrieved
		emptyResult := Object{
			RetsMessage: resp,
			RetsError:   resp.Code != StatusOK,
		}
		return &emptyResult, err
	}
	preferred, err := strconv.ParseBool(header.Get("Preferred"))
	if err != nil {
		preferred = false
	}
	objectData := make(map[string]string)
	for _, v := range header[textproto.CanonicalMIMEHeaderKey("ObjectData")] {
		kv := strings.Split(v, "=")
		objectData[kv[0]] = kv[1]
	}
	blob, err := ioutil.ReadAll(body)
	if err != nil {
		return nil, err
	}

	// 5.6.7
	retsError, err := strconv.ParseBool(header.Get("RETS-Error"))
	retsMsg, err := ReadResponse(ioutil.NopCloser(bytes.NewReader(blob)))

	// there is a rets message, stash it and wipe the content
	if err == nil {
		blob = nil
	}

	object := Object{
		// required
		ObjectID:    int(objectID),
		ContentID:   header.Get("Content-ID"),
		ContentType: header.Get("Content-Type"),
		// optional
		UID:            header.Get("UID"),
		Description:    header.Get("Content-Description"),
		SubDescription: header.Get("Content-Sub-Description"),
		Location:       header.Get("Location"),
		RetsError:      retsError,
		RetsMessage:    retsMsg,
		Preferred:      preferred,
		ObjectData:     objectData,
		Blob:           blob,
	}

	return &object, nil
}
Beispiel #11
0
// GetHeaders returns valueS for header key key
func (m *Email) GetHeaders(key string) (headers []string, err error) {
	// if not parsed
	if !m.flagHeaderParsed {
		if err = m.parseHeader(); err != nil {
			return headers, err
		}
	}
	headers, _ = m.Header[textproto.CanonicalMIMEHeaderKey(key)]
	return
}
Beispiel #12
0
// Get gets the first value associated with the given key.
// If there are no values associated with the key, Get returns "".
// Get is a convenience method.  For more complex queries,
// access the map directly.
func (h Header) Get(key string) string {
	if h == nil {
		return ""
	}
	v := h[textproto.CanonicalMIMEHeaderKey(key)]
	if len(v) == 0 {
		return ""
	}
	return v[0]
}
func TestCompile(t *testing.T) {
	pat, err := Compile("hello, %% %b %D %h %H %l %m %p %q %r %s %t %T %u %U %v %V %>s %{X-LogFormat-Test}i %{X-LogFormat-Test}o world!")
	if err != nil {
		t.Errorf("Failed to compile: %s", err)
		return
	}

	b := &bytes.Buffer{}
	pat(b, dummyCtx{
		elapsed: 5 * time.Second,
		req: &http.Request{
			Header: http.Header{
				textproto.CanonicalMIMEHeaderKey("Content-Length"):   []string{"8192"},
				textproto.CanonicalMIMEHeaderKey("X-LogFormat-Test"): []string{"Hello, Request!"},
			},
			Method:     "GET",
			Proto:      "HTTP/1.1",
			RemoteAddr: "192.168.11.1",
			Host:       "example.com",
			URL: &url.URL{
				Host:     "example.com",
				Path:     "/hello_world",
				RawQuery: "hello=world",
			},
		},
		res: &dummyResponse{
			hdrs: http.Header{
				textproto.CanonicalMIMEHeaderKey("X-LogFormat-Test"): []string{"Hello, Response!"},
			},
			status: 400,
		},
	})

	re := regexp.MustCompile(`^hello, % 8192 5000000 192\.168\.11\.1 HTTP/1\.1 - GET \d+ \?hello=world GET //example\.com/hello_world\?hello=world HTTP/1\.1 400 \d{2}/[a-zA-Z]+/\d{4}:\d{2}:\d{2}:\d{2} [+-]\d{4} 5 - /hello_world example\.com example\.com 400 Hello, Request! Hello, Response! world!$`)

	if !re.Match(b.Bytes()) {
		t.Errorf("output did not match regexp")
		t.Logf("output: %s", b.String())
		t.Logf("regexp: %s", re)
		return
	}
}
func doRequest(req *http.Request) *http.Response {
	if _, ok := req.Header[textproto.CanonicalMIMEHeaderKey("User-Agent")]; !ok {
		// Setting a blank User-Agent causes the http lib not to output one, whereas if there
		// is no header, it will output a default one.
		// See: https://code.google.com/p/go/source/browse/src/pkg/net/http/request.go?name=go1.3.3#398
		req.Header.Set("User-Agent", "")
	}
	resp, err := http.DefaultTransport.RoundTrip(req)
	Expect(err).To(BeNil())
	return resp
}
Beispiel #15
0
Datei: s3.go Projekt: hughe/goamz
// Returns the header value for server-side encryption, or empty string if there is no SSE header.
func GetHeaderSSE(headers map[string][]string) string {
	// Headers returned in an HTTP response will have their key names connonicalized by the Go
	// http library, so we MUST run the key through textproto.CanonicalMIMEHeaderKey in order
	// to find it in the map
	// So headers in the http request must also have been added with a cannonicalized key to find them.
	// TODO: Change parameters in this file to use http.Header data type rather than map[string][]string
	if val := headers[textproto.CanonicalMIMEHeaderKey(sseHeaderKey)]; len(val) > 0 {
		return val[0]
	}
	return ""
}
Beispiel #16
0
func (this *ssdpDefaultManager) ssdpParseHeaderLine(raw *ssdpRawMessage, line []byte) {
	i := strings.Index(string(line), ":")
	if -1 == i {
		panic("Invalid header")
	}
	field := textproto.CanonicalMIMEHeaderKey(strings.TrimSpace(string(line[0:i])))
	value := strings.TrimSpace(string(line[i+1:]))
	if _, has := raw.header[field]; has {
		panic("Header field redefined")
	} else {
		raw.header[field] = value
	}
}
Beispiel #17
0
// Send does what it is supposed to do.
func (m *Mail) Send(host string, port int, user, pass string) error {

	// validate from address
	from, err := mail.ParseAddress(m.From)
	if err != nil {
		return err
	}

	// validate to address
	to, err := mail.ParseAddress(m.To)
	if err != nil {
		return err
	}

	// set headers for html email
	header := textproto.MIMEHeader{}
	header.Set(textproto.CanonicalMIMEHeaderKey("from"), from.Address)
	header.Set(textproto.CanonicalMIMEHeaderKey("to"), to.Address)
	header.Set(textproto.CanonicalMIMEHeaderKey("content-type"), "text/html; charset=UTF-8")
	header.Set(textproto.CanonicalMIMEHeaderKey("mime-version"), "1.0")
	header.Set(textproto.CanonicalMIMEHeaderKey("subject"), m.Subject)

	// init empty message
	var buffer bytes.Buffer

	// write header
	for key, value := range header {
		buffer.WriteString(fmt.Sprintf("%s: %s\r\n", key, value[0]))
	}

	// write body
	buffer.WriteString(fmt.Sprintf("\r\n%s", m.HTML))

	// send email
	addr := fmt.Sprintf("%s:%d", host, port)
	auth := smtp.PlainAuth("", user, pass, host)
	return smtp.SendMail(addr, auth, from.Address, []string{to.Address}, buffer.Bytes())
}
Beispiel #18
0
func RunServer(conf string) {
	server := ObjectServer{driveRoot: "/srv/node", hashPathPrefix: "", hashPathSuffix: "",
		checkMounts: true, disableFsync: false, asyncFinalize: false,
		allowedHeaders: map[string]bool{"Content-Disposition": true,
			"Content-Encoding":      true,
			"X-Delete-At":           true,
			"X-Object-Manifest":     true,
			"X-Static-Large-Object": true,
		},
		diskInUse: map[string]int64{},
	}

	if swiftconf, err := LoadIniFile("/etc/swift/swift.conf"); err == nil {
		server.hashPathPrefix = swiftconf.GetDefault("swift-hash", "swift_hash_path_prefix", "")
		server.hashPathSuffix = swiftconf.GetDefault("swift-hash", "swift_hash_path_suffix", "")
	}

	serverconf, err := LoadIniFile(conf)
	if err != nil {
		panic(fmt.Sprintf("Unable to load %s", conf))
	}
	server.driveRoot = serverconf.GetDefault("DEFAULT", "devices", "/srv/node")
	server.checkMounts = LooksTrue(serverconf.GetDefault("DEFAULT", "mount_check", "true"))
	server.disableFsync = LooksTrue(serverconf.GetDefault("DEFAULT", "disable_fsync", "false"))
	server.asyncFinalize = LooksTrue(serverconf.GetDefault("DEFAULT", "async_finalize", "false"))
	server.diskLimit, err = strconv.ParseInt(serverconf.GetDefault("DEFAULT", "disk_limit", "100"), 10, 64)
	if err != nil {
		panic("Invalid disk_limit format")
	}
	bindIP := serverconf.GetDefault("DEFAULT", "bind_ip", "0.0.0.0")
	bindPort, err := strconv.ParseInt(serverconf.GetDefault("DEFAULT", "bind_port", "8080"), 10, 64)
	if err != nil {
		panic("Invalid bind port format")
	}
	if allowedHeaders, ok := serverconf.Get("DEFAULT", "allowed_headers"); ok {
		headers := strings.Split(allowedHeaders, ",")
		for i := range headers {
			server.allowedHeaders[textproto.CanonicalMIMEHeaderKey(strings.TrimSpace(headers[i]))] = true
		}
	}

	sock, err := net.Listen("tcp", fmt.Sprintf("%s:%d", bindIP, bindPort))
	if err != nil {
		panic(fmt.Sprintf("Unable to bind %s:%d", bindIP, bindPort))
	}
	server.logger = SetupLogger(serverconf.GetDefault("DEFAULT", "log_facility", "LOG_LOCAL0"), "object-server")
	DropPrivileges(serverconf.GetDefault("DEFAULT", "user", "swift"))
	srv := &http.Server{Handler: server}
	srv.Serve(sock)
}
Beispiel #19
0
// RawHaveHeader check igf header header is present in raw mail
func RawHaveHeader(raw *[]byte, header string) bool {
	var bHeader []byte
	if strings.ToLower(header) == "message-id" {
		bHeader = []byte("Message-ID")
	} else {
		bHeader = []byte(textproto.CanonicalMIMEHeaderKey(header))
	}
	for _, line := range bytes.Split(RawGetHeaders(raw), []byte{13, 10}) {
		if bytes.HasPrefix(line, bHeader) {
			return true
		}
	}
	return false
}
Beispiel #20
0
func splitMimeHeader(s string) (string, string) {
	p := strings.IndexByte(s, ':')
	if p < 0 {
		return s, ""
	}
	key := textproto.CanonicalMIMEHeaderKey(s[:p])

	for p = p + 1; p < len(s); p++ {
		if s[p] != ' ' {
			break
		}
	}
	return key, s[p:]
}
Beispiel #21
0
// NewManager Create new Manager with provider name and json config string.
// provider name:
// 1. cookie
// 2. file
// 3. memory
// 4. redis
// 5. mysql
// json config:
// 1. is https  default false
// 2. hashfunc  default sha1
// 3. hashkey default beegosessionkey
// 4. maxage default is none
func NewManager(provideName, config string) (*Manager, error) {
	provider, ok := provides[provideName]
	if !ok {
		return nil, fmt.Errorf("session: unknown provide %q (forgotten import?)", provideName)
	}
	cf := new(managerConfig)
	cf.EnableSetCookie = true
	err := json.Unmarshal([]byte(config), cf)
	if err != nil {
		return nil, err
	}
	if cf.Maxlifetime == 0 {
		cf.Maxlifetime = cf.Gclifetime
	}

	if cf.EnableSidInHttpHeader {
		if cf.SessionNameInHttpHeader == "" {
			panic(errors.New("SessionNameInHttpHeader is empty"))
		}

		strMimeHeader := textproto.CanonicalMIMEHeaderKey(cf.SessionNameInHttpHeader)
		if cf.SessionNameInHttpHeader != strMimeHeader {
			strErrMsg := "SessionNameInHttpHeader (" + cf.SessionNameInHttpHeader + ") has the wrong format, it should be like this : " + strMimeHeader
			panic(errors.New(strErrMsg))
		}
	}

	err = provider.SessionInit(cf.Maxlifetime, cf.ProviderConfig)
	if err != nil {
		return nil, err
	}

	if cf.SessionIDLength == 0 {
		cf.SessionIDLength = 16
	}

	// 设置存储提供者cookie的CookieName
	CookieName = cf.CookieName

	return &Manager{
		provider,
		cf,
	}, nil
}
Beispiel #22
0
func ParseHeaders(mailData string) map[string]string {
	var headerSectionEnds int
	for i, char := range mailData[:len(mailData)-4] {
		if char == '\r' {
			if mailData[i+1] == '\n' && mailData[i+2] == '\r' && mailData[i+3] == '\n' {
				headerSectionEnds = i + 2
			}
		}
	}
	headers := make(map[string]string)
	// TODO header comments and textproto Reader instead of regex
	matches := headerRegex.FindAllStringSubmatch(mailData[:headerSectionEnds], -1)
	for _, h := range matches {
		name := textproto.CanonicalMIMEHeaderKey(strings.TrimSpace(strings.Replace(h[1], "\r\n", "", -1)))
		val := strings.TrimSpace(strings.Replace(h[2], "\r\n", "", -1))
		headers[name] = val
	}
	return headers
}
Beispiel #23
0
func (obj objectHandler) get(w http.ResponseWriter, r *http.Request) {
	owner, err := s3intf.GetOwner(obj.Bucket.Service, r, obj.Bucket.Service.Host())
	if err != nil {
		writeError(w, &HTTPError{Code: 20, HTTPCode: http.StatusBadRequest,
			Message:  "error getting owner: " + err.Error(),
			Resource: "/" + obj.Bucket.Name + "/" + obj.object})
		return
	}
	fn, media, body, size, md5, err := obj.Bucket.Service.Get(owner, obj.Bucket.Name, obj.object)
	log.Printf("GETing %s/%s: %q %s", obj.Bucket.Name, obj.object, fn, err)
	if err != nil {
		if err == s3intf.NotFound {
			w.WriteHeader(http.StatusNotFound)
			return
		}
		writeError(w, &HTTPError{Code: 21,
			Message:  "error getting " + obj.Bucket.Name + "/" + obj.object + ": " + err.Error(),
			Resource: "/" + obj.Bucket.Name + "/" + obj.object})
		return
	}
	if err = r.ParseForm(); err != nil {
		writeError(w, &HTTPError{Code: 22, HTTPCode: http.StatusBadRequest,
			Message:  "cannot parse form values: " + err.Error(),
			Resource: "/" + obj.Bucket.Name + "/" + obj.object})
		return
	}
	w.Header().Set("Content-Type", media)
	w.Header().Set("Content-Disposition", "inline; filename=\""+fn+"\"")
	w.Header().Set("Content-Length", strconv.Itoa(int(size)))
	w.Header().Set("ETag", hex.EncodeToString(md5))
	for k, v := range r.Form {
		k = textproto.CanonicalMIMEHeaderKey(k)
		switch k {
		case "Content-Type", "Content-Language", "Expires", "Cache-Control",
			"Content-Disposition", "Content-Encoding", "Content-Length":
			(map[string][]string(w.Header()))[k] = v
		}
	}
	if Debug {
		log.Printf("headers: %s", w.Header())
	}
	io.Copy(w, body)
}
Beispiel #24
0
// getRaw returns raw message
// some cleanup are made
// wrap headers line to 999 char max
func (m *Message) GetRaw() (rawMessage []byte, err error) {
	rawMessage = []byte{}
	// Header
	for key, hs := range m.Header {
		// clean key
		key = textproto.CanonicalMIMEHeaderKey(key)
		for _, value := range hs {
			//println("Les headers avant traitement: " + key + " -> " + value)
			// TODO clean value
			// split at 900
			// remove unsuported char
			//
			// On ne doit pas avoir autre chose que des char < 128
			// Attention si un jour on implemente l'extension SMTPUTF8
			// Voir RFC 6531 (SMTPUTF8 extension), RFC 6532 (Internationalized email headers) and RFC 6533 (Internationalized delivery status notifications).
			/*for _, c := range value {
				if c > 128 {
					return rawMessage, ErrNonAsciiCharDetected
				}
			}*/

			// Fold header
			//t := FoldHeader(key+": "+value) + "\r\n"
			//println("\nHeaders apres traitement: " + t)
			newHeader := []byte(key + ": " + value)
			FoldHeader(&newHeader)
			rawMessage = append(rawMessage, newHeader...)
			rawMessage = append(rawMessage, []byte{13, 10}...)

		}
	}

	rawMessage = append(rawMessage, []byte{13, 10}...)

	// Body
	b, err := ioutil.ReadAll(m.Body)
	if err != nil {
		return
	}
	rawMessage = append(rawMessage, b...)
	return
}
Beispiel #25
0
// CanonicalHeaderKey returns the canonical format of the
// header key s.  The canonicalization converts the first
// letter and any letter following a hyphen to upper case;
// the rest are converted to lowercase.  For example, the
// canonical key for "accept-encoding" is "Accept-Encoding".
func CanonicalHeaderKey(s string) string { return textproto.CanonicalMIMEHeaderKey(s) }
Beispiel #26
0
func checkMessage(msg *mail.TestMessage, adminsPlain []string, user string) error {
	sender, err := net_mail.ParseAddress(msg.Sender)
	if err != nil {
		return fmt.Errorf("unparsable Sender address: %s: %s", msg.Sender, err)
	}
	senderOK := user != "" && sender.Address == user
	if !senderOK {
		for _, a := range adminsPlain {
			if sender.Address == a {
				senderOK = true
				break
			}
		}
	}
	if !senderOK {
		return fmt.Errorf("invalid Sender: %s", msg.Sender)
	}

	if len(msg.To) == 0 && len(msg.Cc) == 0 && len(msg.Bcc) == 0 {
		return fmt.Errorf("one of To, Cc or Bcc must be non-empty")
	}

	if err := parseEmails(msg.To...); err != nil {
		return err
	}
	if err := parseEmails(msg.Cc...); err != nil {
		return err
	}
	if err := parseEmails(msg.Bcc...); err != nil {
		return err
	}

	if len(msg.Body) == 0 && len(msg.HTMLBody) == 0 {
		return fmt.Errorf("one of Body or HTMLBody must be non-empty")
	}

	if len(msg.Attachments) > 0 {
		msg.MIMETypes = make([]string, len(msg.Attachments))
		for i := range msg.Attachments {
			n := msg.Attachments[i].Name
			ext := strings.TrimLeft(strings.ToLower(filepath.Ext(n)), ".")
			if badExtensions.Has(ext) {
				return fmt.Errorf("illegal attachment extension for %q", n)
			}
			mimetype := extensionMapping[ext]
			if mimetype == "" {
				mimetype = "application/octet-stream"
			}
			msg.MIMETypes[i] = mimetype
		}
	}

	fixKeys := map[string]string{}
	for k := range msg.Headers {
		canonK := textproto.CanonicalMIMEHeaderKey(k)
		if !okHeaders.Has(canonK) {
			return fmt.Errorf("disallowed header: %s", k)
		}
		if canonK != k {
			fixKeys[k] = canonK
		}
	}
	for k, canonK := range fixKeys {
		vals := msg.Headers[k]
		delete(msg.Headers, k)
		msg.Headers[canonK] = vals
	}

	return nil
}
Beispiel #27
0
func handleForwardResponseTrailerHeader(w http.ResponseWriter, md ServerMetadata) {
	for k := range md.TrailerMD {
		tKey := textproto.CanonicalMIMEHeaderKey(fmt.Sprintf("%s%s", MetadataTrailerPrefix, k))
		w.Header().Add("Trailer", tKey)
	}
}
Beispiel #28
0
// NewFromEmail return a new DkimHeader by parsing an email
// Note: according to RFC 6376 an email can have multiple DKIM Header
// in this case we return the last inserted or the last with d== mail from
func newDkimHeaderFromEmail(email []byte) (*DKIMHeader, error) {
	m, err := mail.ReadMessage(bytes.NewReader(email))
	if err != nil {
		return nil, err
	}

	// DKIM header ?
	if len(m.Header[textproto.CanonicalMIMEHeaderKey("DKIM-Signature")]) == 0 {
		return nil, ErrDkimHeaderNotFound
	}

	// Get mail from domain
	mailFromDomain := ""
	mailfrom, err := mail.ParseAddress(m.Header.Get(textproto.CanonicalMIMEHeaderKey("From")))
	if err != nil {
		if err.Error() != "mail: no address" {
			return nil, err
		}
	} else {
		t := strings.SplitAfter(mailfrom.Address, "@")
		if len(t) > 1 {
			mailFromDomain = strings.ToLower(t[1])
		}
	}

	// get raw dkim header
	// we can't use m.header because header key will be converted with textproto.CanonicalMIMEHeaderKey
	// ie if key in header is not DKIM-Signature but Dkim-Signature or DKIM-signature ot... other
	// combination of case, verify will fail.
	rawHeaders, _, err := getHeadersBody(email)
	if err != nil {
		return nil, ErrBadMailFormat
	}
	rawHeadersList, err := getHeadersList(&rawHeaders)
	if err != nil {
		return nil, err
	}
	dkHeaders := []string{}
	for h := rawHeadersList.Front(); h != nil; h = h.Next() {
		if strings.HasPrefix(strings.ToLower(h.Value.(string)), "dkim-signature") {
			dkHeaders = append(dkHeaders, h.Value.(string))
		}
	}

	var keep *DKIMHeader
	var keepErr error
	//for _, dk := range m.Header[textproto.CanonicalMIMEHeaderKey("DKIM-Signature")] {
	for _, h := range dkHeaders {
		parsed, err := parseDkHeader(h)
		// if malformed dkim header try next
		if err != nil {
			keepErr = err
			continue
		}
		// Keep first dkim headers
		if keep == nil {
			keep = parsed
		}
		// if d flag == domain keep this header and return
		if mailFromDomain == parsed.Domain {
			return parsed, nil
		}
	}
	if keep == nil {
		return nil, keepErr
	}
	return keep, nil
}
Beispiel #29
0
// getHeaders returns all the headers corresponding to the key key
func (m *Message) GetHeaders(key string) []string {
	return m.Header[textproto.CanonicalMIMEHeaderKey(key)]
}
Beispiel #30
0
// delHeader deletes the values associated with key.
func (m *Message) DelHeader(key string) {
	delete(m.Header, textproto.CanonicalMIMEHeaderKey(key))
}