Ejemplo n.º 1
0
func TestGetObject(t *testing.T) {
	header := http.Header{}
	textproto.MIMEHeader(header).Add("Content-Type", "image/jpeg")
	textproto.MIMEHeader(header).Add("Content-ID", "123456")
	textproto.MIMEHeader(header).Add("Object-ID", "1")
	textproto.MIMEHeader(header).Add("Preferred", "1")
	textproto.MIMEHeader(header).Add("UID", "1a234234234")
	textproto.MIMEHeader(header).Add("Content-Description", "Outhouse")
	textproto.MIMEHeader(header).Add("Content-Sub-Description", "The urinal")
	textproto.MIMEHeader(header).Add("Location", "http://www.simpleboundary.com/image-5.jpg")

	var body string = `<binary data 1>`
	reader := ioutil.NopCloser(bytes.NewReader([]byte(body)))

	quit := make(chan struct{})
	defer close(quit)
	results := parseGetObjectResult(quit, header, reader)
	result := <-results

	o := result.Object
	testutils.Ok(t, result.Err)
	testutils.Equals(t, true, o.Preferred)
	testutils.Equals(t, "image/jpeg", o.ContentType)
	testutils.Equals(t, "123456", o.ContentId)
	testutils.Equals(t, 1, o.ObjectId)
	testutils.Equals(t, "1a234234234", o.Uid)
	testutils.Equals(t, "Outhouse", o.Description)
	testutils.Equals(t, "The urinal", o.SubDescription)
	testutils.Equals(t, "<binary data 1>", string(o.Blob))
	testutils.Equals(t, "http://www.simpleboundary.com/image-5.jpg", o.Location)
	testutils.Equals(t, false, o.RetsError)
}
Ejemplo n.º 2
0
func (p *Multipart) AddText(mediaType string, txt string) error {
	if p.isClosed {
		return ErrPartClosed
	}

	p.header = textproto.MIMEHeader(map[string][]string{
		"Content-Type":              {mediaType},
		"Content-Transfer-Encoding": {"quoted-printable"},
	})

	w, err := p.writer.CreatePart(p.header)
	if err != nil {
		return err
	}

	encoder := qp.NewWriter(w)
	_, err = io.WriteString(encoder, txt)
	if err != nil {
		return err
	}

	encoder.Close()

	fmt.Fprintf(w, crlf)
	fmt.Fprintf(w, crlf)
	return nil
}
Ejemplo n.º 3
0
// AddText applies quoted-printable encoding to the content of r before writing
// the encoded result in a new sub-part with media MIME type set to mediaType.
//
// Specifying the charset in the mediaType string is recommended
// ("plain/text; charset=utf-8").
func (p *Multipart) AddText(mediaType string, r io.Reader) error {
	if p.isClosed {
		return ErrPartClosed
	}

	p.header = textproto.MIMEHeader(map[string][]string{
		"Content-Type":              {mediaType},
		"Content-Transfer-Encoding": {"quoted-printable"},
	})

	w, err := p.writer.CreatePart(p.header)
	if err != nil {
		return err
	}

	reader := bufio.NewReader(r)
	encoder := qp.NewWriter(w)
	defer encoder.Close()
	buffer := make([]byte, maxLineLen)
	for {
		read, err := reader.Read(buffer[:])
		if err != nil {
			if err != io.EOF {
				return err
			}
			break
		}
		encoder.Write(buffer[:read])
	}
	fmt.Fprintf(w, crlf)
	fmt.Fprintf(w, crlf)
	return nil
}
Ejemplo n.º 4
0
func getHeader(i map[string][]string, header string) string {
	h, ok := textproto.MIMEHeader(i)[textproto.CanonicalMIMEHeaderKey(header)]
	if ok {
		return h[0]
	}
	return ""
}
Ejemplo n.º 5
0
// ForEach ...
func (r *GetObjectResponse) ForEach(result GetObjectResult) error {
	resp := r.response
	defer resp.Body.Close()
	mediaType, params, err := mime.ParseMediaType(resp.Header.Get("Content-Type"))
	if err != nil {
		return err
	}
	// its not multipart, just leave
	if !strings.HasPrefix(mediaType, "multipart/") {
		return result(NewObjectFromStream(textproto.MIMEHeader(resp.Header), resp.Body))
	}
	// its multipart, need to break it up
	partsReader := multipart.NewReader(resp.Body, params["boundary"])
	for {
		part, err := partsReader.NextPart()
		switch {
		case err == io.EOF:
			return nil
		case err != nil:
			return err
		}
		err = result(NewObjectFromStream(part.Header, part))
		if err != nil {
			return err
		}
	}
	// return nil
}
Ejemplo n.º 6
0
// getOneRequestFile reads the first file from the request (if multipart/),
// or returns the body if not
func getOneRequestFile(r *http.Request) (reqFile, error) {
	f := reqFile{ReadCloser: r.Body}
	contentType := r.Header.Get("Content-Type")
	logger.Info("msg", "readRequestOneFile", "ct", contentType)
	if !strings.HasPrefix(contentType, "multipart/") {
		f.FileHeader.Header = textproto.MIMEHeader(r.Header)
		return f, nil
	}
	defer r.Body.Close()
	if err := r.ParseMultipartForm(1 << 20); err != nil {
		return f, errors.New("error parsing request as multipart-form: " + err.Error())
	}
	if r.MultipartForm == nil || len(r.MultipartForm.File) == 0 {
		return f, errors.New("no files?")
	}

	for _, fileHeaders := range r.MultipartForm.File {
		for _, fileHeader := range fileHeaders {
			var err error
			if f.ReadCloser, err = fileHeader.Open(); err != nil {
				return f, fmt.Errorf("error opening part %q: %s", fileHeader.Filename, err)
			}
			f.FileHeader = *fileHeader
			return f, nil
		}
	}
	return reqFile{}, nil
}
Ejemplo n.º 7
0
func (cb *couchBackend) mkArticle(ar Article) *nntp.Article {
	url := fmt.Sprintf("%s/%s/article", cb.db.DBURL(), cleanupId(ar.MsgId, true))
	return &nntp.Article{
		Header: textproto.MIMEHeader(ar.Headers),
		Body:   &lazyOpener{url, nil, nil},
		Bytes:  ar.Bytes,
		Lines:  ar.Lines,
	}
}
Ejemplo n.º 8
0
// Text sets the text content of the email.
func (e *Email) Text(text string) {
	if nil == e.alternative {
		panic("e.alternative IS NIL")
	}
	out, _ := e.alternative.CreatePart(textproto.MIMEHeader(map[string][]string{
		"Content-Type": []string{"text/plain; charset=utf-8"},
	}))
	fmt.Fprintln(out, text)
}
Ejemplo n.º 9
0
// AddAttachment encodes the content of r in base64 and writes it as an
// attachment of type attachType in this part.
//
// filename is the file name that will be suggested by the mail user agent to a
// user who would like to download the attachment. It's also the value to which
// the Content-ID header will be set. A name with an extension such as
// "report.docx" or "photo.jpg" is recommended. RFC 5987 is not supported, so
// the charset is restricted to ASCII characters.
//
// mediaType indicates the content type of the attachment. If an empty string is
// passed, mime.TypeByExtension will first be called to deduce a value from the
// extension of filemame before defaulting to "application/octet-stream".
//
// In the following example, the media MIME type will be set to "image/png"
// based on the ".png" extension of the filename "gopher.png":
// 	part.AddAttachment(Inline, "gopher.png", "", image)
func (p *Multipart) AddAttachment(attachType AttachmentType, filename, mediaType string, r io.Reader) (err error) {
	if p.isClosed {
		return ErrPartClosed
	}

	// Default Content-Type value
	if mediaType == "" && filename != "" {
		mediaType = mime.TypeByExtension(filepath.Ext(filename))
	}
	if mediaType == "" {
		mediaType = "application/octet-stream"
	}

	header := textproto.MIMEHeader(map[string][]string{
		"Content-Type":              {mediaType},
		"Content-ID":                {fmt.Sprintf("<%s>", filename)},
		"Content-Location":          {fmt.Sprintf("%s", filename)},
		"Content-Transfer-Encoding": {"base64"},
		"Content-Disposition":       {fmt.Sprintf("%s;\r\n\tfilename=%s;", attachType, filename)},
	})

	w, err := p.writer.CreatePart(header)
	if err != nil {
		return err
	}

	encoder := base64.NewEncoder(base64.StdEncoding, w)
	data := bufio.NewReader(r)

	buffer := make([]byte, int(math.Ceil(maxLineLen/4)*3))
	for {
		read, err := io.ReadAtLeast(data, buffer[:], len(buffer))
		if err != nil {
			if err == io.EOF {
				break
			} else if err != io.ErrUnexpectedEOF {
				return err
			}
		}

		if _, err := encoder.Write(buffer[:read]); err != nil {
			return err
		}

		if read == len(buffer) {
			fmt.Fprintf(w, crlf)
		}
	}
	encoder.Close()
	fmt.Fprintf(w, crlf)

	return nil
}
Ejemplo n.º 10
0
// GetHeader returns the undecoded value of header if found. To access the
// raw (potentially encoded) value of header, use the Message.Header.
func (m *Message) GetHeader(header string) string {
	e := textproto.MIMEHeader(m.Header).Get(header)
	if e == "" {
		return ""
	}
	dec := new(qp.WordDecoder)
	decoded, err := dec.DecodeHeader(e)
	if err != nil {
		return ""
	}
	return decoded
}
Ejemplo n.º 11
0
func parseGetObjectResult(quit <-chan struct{}, header http.Header, body io.ReadCloser) <-chan GetObjectResult {
	data := make(chan GetObjectResult)
	go func() {
		defer body.Close()
		defer close(data)
		select {
		case data <- parseHeadersAndStream(textproto.MIMEHeader(header), body):
		case <-quit:
			return
		}
	}()
	return data
}
Ejemplo n.º 12
0
func (m *Message) GetMultipleHeaderValues(header string) (values []string) {
	headers := textproto.MIMEHeader(m.Header)
	list := headers[header]
	for _, v := range list {
		dec := new(qp.WordDecoder)
		decoded, err := dec.DecodeHeader(v)
		if err != nil {
			continue
		}
		values = append(values, decoded)
	}
	return values
}
Ejemplo n.º 13
0
func newResponseParameters(shared bool, cacheRequest *cacheRequest, resource *Resource) (int, int64, http.Header, io.ReadCloser, error) {
	age, err := resource.Age()
	if err != nil {
		return int(http.StatusInternalServerError), -1, nil, nil, err
	}

	contentLength := resource.ContentLength()
	statusCode := resource.Status()

	headers := make(http.Header)

	for key, mimeheaders := range resource.Header() {
		for _, header := range mimeheaders {
			textproto.MIMEHeader(headers).Add(key, header)
		}
	}

	// http://httpwg.github.io/specs/rfc7234.html#warn.113
	if age > (time.Hour*24) && resource.HeuristicFreshness() > (time.Hour*24) {
		textproto.MIMEHeader(headers).Add("Warning", `113 - "Heuristic Expiration"`)
	}

	// http://httpwg.github.io/specs/rfc7234.html#warn.110
	freshness, err := freshness(shared, resource, cacheRequest)
	if err != nil || freshness <= 0 {
		textproto.MIMEHeader(headers).Add("Warning", `110 - "Response is Stale"`)
	}

	debugf("resource is %s old, updating age from %s", age.String(), headers.Get("Age"))

	textproto.MIMEHeader(headers).Set("Age", fmt.Sprintf("%.f", math.Floor(age.Seconds())))
	textproto.MIMEHeader(headers).Set("Via", resource.Via())

	body := resource

	return statusCode, contentLength, headers, body, nil
}
Ejemplo n.º 14
0
// Walk over the parts of the email, calling todo on every part.
// The part.Body given to todo is reused, so read if you want to use it!
//
// By default this is recursive, except dontDescend is true.
func Walk(part MailPart, todo TodoFunc, dontDescend bool) error {
	br, e := temp.NewReadSeeker(part.Body)
	if e != nil {
		return e
	}
	defer func() { _ = br.Close() }()
	msg, hsh, e := ReadAndHashMessage(br)
	if e != nil {
		return errgo.Notef(e, "WalkMail")
	}
	ct, params, decoder, e := getCT(msg.Header)
	logger.Info("msg", "Walk message", "hsh", hsh, "headers", msg.Header)
	if e != nil {
		return errgo.Notef(e, "WalkMail")
	}
	if ct == "" {
		ct = "message/rfc822"
	}
	child := MailPart{ContentType: ct, MediaType: params,
		Header: textproto.MIMEHeader(msg.Header),
		Body:   msg.Body, Parent: &part,
		Level: part.Level + 1,
		Seq:   nextSeqInt()}
	child.Header.Add("X-Hash", hsh)
	if child.Header.Get(HashKeyName) == "" {
		child.Header.Add(HashKeyName, hsh)
	}
	logger.Debug("msg", "message", "sequence", child.Seq, "content-type", ct, "params", params)
	if strings.HasPrefix(ct, "multipart/") {
		return WalkMultipart(child, todo, dontDescend)
	}
	if !dontDescend && strings.HasPrefix(ct, "message/") { //mail
		if decoder != nil {
			child.Body = decoder(child.Body)
		}
		if e = Walk(child, todo, dontDescend); e != nil {
			return errgo.Notef(e, "WalkMail descending")
		}
		return nil
	}
	//simple
	if decoder != nil {
		child.Body = decoder(child.Body)
	}
	if e = todo(child); e != nil {
		return errgo.Notef(e, "todo")
	}
	return nil
}
Ejemplo n.º 15
0
func TestGetObject(t *testing.T) {
	header := http.Header{}
	textproto.MIMEHeader(header).Add("Content-Type", "image/jpeg")
	textproto.MIMEHeader(header).Add("Content-ID", "123456")
	textproto.MIMEHeader(header).Add("Object-ID", "1")
	textproto.MIMEHeader(header).Add("Preferred", "1")
	textproto.MIMEHeader(header).Add("UID", "1a234234234")
	textproto.MIMEHeader(header).Add("Content-Description", "Outhouse")
	textproto.MIMEHeader(header).Add("Content-Sub-Description", "The urinal")
	textproto.MIMEHeader(header).Add("Location", "http://www.simpleboundary.com/image-5.jpg")

	var body = `<binary data 1>`

	response := GetObjectResponse{
		response: &http.Response{
			Header: header,
			Body:   ioutil.NopCloser(strings.NewReader(body)),
		},
	}
	defer response.Close()
	var objects []*Object
	err := response.ForEach(func(o *Object, err error) error {
		objects = append(objects, o)
		return nil
	})
	testutils.Ok(t, err)

	testutils.Equals(t, 1, len(objects))

	o := objects[0]
	testutils.Equals(t, true, o.Preferred)
	testutils.Equals(t, "image/jpeg", o.ContentType)
	testutils.Equals(t, "123456", o.ContentID)
	testutils.Equals(t, 1, o.ObjectID)
	testutils.Equals(t, "1a234234234", o.UID)
	testutils.Equals(t, "Outhouse", o.Description)
	testutils.Equals(t, "The urinal", o.SubDescription)
	testutils.Equals(t, "<binary data 1>", string(o.Blob))
	testutils.Equals(t, "http://www.simpleboundary.com/image-5.jpg", o.Location)
	testutils.Equals(t, false, o.RetsError)
}
Ejemplo n.º 16
0
func (h Headers) Set(key, value string) {
	textproto.MIMEHeader(h).Set(key, value)
}
Ejemplo n.º 17
0
func (h Headers) Add(key, value string) {
	textproto.MIMEHeader(h).Add(key, value)
}
Ejemplo n.º 18
0
Archivo: mo.go Proyecto: ane/go-gettext
func ParsePO(r io.ReadSeeker) (*Catalog, error) {
	var magic uint32
	if err := binary.Read(r, binary.LittleEndian, &magic); err != nil {
		return nil, err
	}

	var bo binary.ByteOrder
	if magic == leMagic {
		bo = binary.LittleEndian
	} else if magic == beMagic {
		bo = binary.BigEndian
	} else {
		return nil, ErrInvalidMagic
	}

	var version, stringCount, origOffset, transOffset uint32
	if err := binary.Read(r, bo, &version); err != nil {
		return nil, err
	}
	if err := binary.Read(r, bo, &stringCount); err != nil {
		return nil, err
	}
	if err := binary.Read(r, bo, &origOffset); err != nil {
		return nil, err
	}
	if err := binary.Read(r, bo, &transOffset); err != nil {
		return nil, err
	}

	// TODO: Check version

	stringOffsets := make([]struct{ origStart, origLen, transStart, transLen int32 }, stringCount)

	if o, err := r.Seek(int64(origOffset), 0); err != nil {
		return nil, err
	} else if o != int64(origOffset) {
		return nil, ErrTruncated
	}

	for i := 0; i < int(stringCount); i++ {
		if err := binary.Read(r, bo, &stringOffsets[i].origLen); err != nil {
			return nil, err
		}
		if err := binary.Read(r, bo, &stringOffsets[i].origStart); err != nil {
			return nil, err
		}
	}

	if o, err := r.Seek(int64(transOffset), 0); err != nil {
		return nil, err
	} else if o != int64(transOffset) {
		return nil, ErrTruncated
	}

	for i := 0; i < int(stringCount); i++ {
		if err := binary.Read(r, bo, &stringOffsets[i].transLen); err != nil {
			return nil, err
		}
		if err := binary.Read(r, bo, &stringOffsets[i].transStart); err != nil {
			return nil, err
		}
	}

	catalog := Catalog{
		Strings:       make(map[string]*Translation, stringCount),
		PluralFormula: GermanicPluralFormula,
	}

	for _, so := range stringOffsets {
		if o, err := r.Seek(int64(so.origStart), 0); err != nil {
			return nil, err
		} else if o != int64(so.origStart) {
			return nil, ErrTruncated
		}
		origBytes := make([]byte, so.origLen)
		if _, err := r.Read(origBytes); err != nil {
			return nil, err
		}

		if o, err := r.Seek(int64(so.transStart), 0); err != nil {
			return nil, err
		} else if o != int64(so.transStart) {
			return nil, ErrTruncated
		}
		transBytes := make([]byte, so.transLen)
		if _, err := r.Read(transBytes); err != nil {
			return nil, err
		}

		if len(origBytes) == 0 {
			// Translation meta header
			header, err := textproto.NewReader(
				bufio.NewReader(bytes.NewReader(transBytes))).ReadMIMEHeader()
			if err != nil {
				catalog.Header = header
			} else {
				catalog.Header = textproto.MIMEHeader(make(map[string][]string))
			}
		} else {
			origParts := strings.Split(string(origBytes), "\x00")
			transParts := strings.Split(string(transBytes), "\x00")
			if len(transParts) > 0 {
				t := &Translation{
					Translation: transParts,
				}
				catalog.Strings[origParts[0]] = t
				if len(origParts) > 1 {
					t.Plural = origParts[1]
				}
			}
		}
	}

	return &catalog, nil
}
Ejemplo n.º 19
0
func (h Header) Add(key, value string) {
	//都是相同的map结构
	textproto.MIMEHeader(h).Add(key, value) //将header类型转换
}
Ejemplo n.º 20
0
// Get gets the first value associated with the given key.
// If there are no values associated with the key, Get returns "".
// To access multiple values of a key, access the map directly
// with CanonicalHeaderKey.
func (h Header) Get(key string) string { // 获得header对应的key
	return textproto.MIMEHeader(h).Get(key)
}
Ejemplo n.º 21
0
// Set sets the header entries associated with key to
// the single element value.  It replaces any existing
// values associated with key.
func (h Header) Set(key, value string) { // 设置key, value
	textproto.MIMEHeader(h).Set(key, value)
}
Ejemplo n.º 22
0
func (c *Client) UploadMedia(userID, albumID string, m *UploadMediaInfo, contentType string, contentLength int64, r io.Reader) (*Media, error) {
	if userID == "" {
		userID = "default"
	}
	if albumID == "" {
		albumID = "default"
	}
	const metaDataContentType = "application/atom+xml"
	var media *Media
	var err error
	var totalContentLength int64
	pipeOut, pipeIn := io.Pipe()
	uri := fmt.Sprintf("%s/data/feed/api/user/%s/albumid/%s", c.BaseURL, userID, albumID)
	writer := multipart.NewWriter(pipeIn)
	wg := new(sync.WaitGroup)
	wg.Add(1)

	metaData, _ := xml.Marshal(m)
	totalContentLength += int64(3 + len(writer.Boundary()))        // --boundary\n
	totalContentLength += int64(14 + len(metaDataContentType) + 1) // Content-Type: xxxx\n\n
	totalContentLength += int64(len(metaData) + 1)                 // {xml}\n
	totalContentLength += int64(3 + len(writer.Boundary()))        // --boundary\n
	totalContentLength += int64(14 + len(contentType) + 1)         // Content-Type: xxxx\n\n
	totalContentLength += int64(len(metaData) + 1)                 // {binary}\n
	totalContentLength += int64(3 + len(writer.Boundary()))        // --boundary\n
	go func() {
		defer wg.Done()
		var resp *http.Response
		var req *http.Request
		req, err = http.NewRequest("POST", uri, pipeOut)
		if err != nil {
			return
		}
		req.Header.Set("Content-Type", fmt.Sprintf("multipart/related; boundary=%q", writer.Boundary()))
		req.Header.Set("Content-Length", fmt.Sprintf("%d", totalContentLength))
		resp, err = c.client.Do(req)
		if err != nil {
			return
		}
		defer resp.Body.Close()
		if resp.StatusCode != 201 {
			buff, _ := ioutil.ReadAll(resp.Body)
			err = fmt.Errorf("API Error: %s", string(buff))
			return
		}
		media, err = parsePhotoFeed(resp.Body)
	}()

	metaDataPart, err := writer.CreatePart(textproto.MIMEHeader(map[string][]string{
		"Content-Type": []string{metaDataContentType},
	}))
	if err != nil {
		return nil, err
	}
	metaDataPart.Write(metaData)
	binaryPart, err := writer.CreatePart(textproto.MIMEHeader(map[string][]string{
		"Content-Type": []string{contentType},
	}))
	if _, err = io.Copy(binaryPart, r); err != nil {
		return nil, err
	}
	writer.Close()
	pipeIn.Close()
	wg.Wait()
	return media, err
}
Ejemplo n.º 23
0
// SetHeader adds header to the list of headers and sets it to quoted-printable
// encoded value.
func (m *Message) SetHeader(header, value string) {
	textproto.MIMEHeader(m.Header).Set(header, value)
}
Ejemplo n.º 24
0
// AddHeader appends the header value to the list of values for this header key
func (m *Message) AddHeader(header, value string) {
	textproto.MIMEHeader(m.Header).Add(header, value)
}
Ejemplo n.º 25
0
func (server vermServer) FileUploader(w http.ResponseWriter, req *http.Request, replicating bool) (*fileUpload, error) {
	// deal with '/..' etc.
	path := path.Clean(req.URL.Path)

	location := ""
	if replicating {
		location = path
		lastSlash := strings.LastIndex(path, "/")
		if lastSlash < 4 {
			return nil, &WrongLocationError{path}
		}
		path = path[0 : lastSlash-3]
	}

	// don't allow uploads to the root directory itself, which would be unmanageable
	if len(path) <= 1 {
		path = DefaultDirectoryIfNotGivenByClient
	}

	// make a tempfile in the requested (or default, as above) directory
	directory := server.RootDataDir + path
	err := os.MkdirAll(directory, DirectoryPermission)
	if err != nil {
		return nil, err
	}

	var tempFile *os.File
	tempFile, err = ioutil.TempFile(directory, "_upload")
	if err != nil {
		return nil, err
	}

	// if the upload is a raw post, the input stream is the request body
	var input io.Reader = req.Body

	// but if the upload is a browser form, the input stream needs multipart decoding
	contentType := mediaTypeOrDefault(textproto.MIMEHeader(req.Header))
	if contentType == "multipart/form-data" {
		file, mpheader, mperr := req.FormFile(UploadedFieldFieldForMultipart)
		if mperr != nil {
			return nil, mperr
		}
		input = file
		contentType = mediaTypeOrDefault(mpheader.Header)
	}

	// determine the appropriate extension from the content type
	extension := mimeext.ExtensionByType(contentType)

	// if the file is both gzip-encoded and is actually a gzip file itself, strip the redundant encoding
	storageEncoding := req.Header.Get("Content-Encoding")
	if extension == ".gz" && storageEncoding != "" {
		input, err = EncodingDecoder(storageEncoding, input)
		if err != nil {
			return nil, err
		}
		storageEncoding = ""
	}

	// as we read from the stream, copy it into the tempfile - potentially in encoded format (except for the above case)
	input = io.TeeReader(input, tempFile)

	// but uncompress the stream before feeding it to the hasher
	input, err = EncodingDecoder(storageEncoding, input)
	if err != nil {
		return nil, err
	}

	// in addition to handling gzip content-encoding, if an actual .gz file is uploaded,
	// we need to decompressed it and hash its contents rather than the raw file itself;
	// otherwise there would be an ambiguity between application/octet-stream files with
	// gzip on-disk compression and application/gzip files with no compression, and they
	// would appear to have different hashes, which would break replication
	if extension == ".gz" {
		input, err = gzip.NewReader(input)
		if err != nil {
			return nil, err
		}
	}

	return &fileUpload{
		replicating: replicating,
		root:        server.RootDataDir,
		path:        path,
		location:    location,
		contentType: contentType,
		extension:   extension,
		encoding:    storageEncoding,
		input:       input,
		hasher:      sha256.New(),
		tempFile:    tempFile,
	}, nil
}
Ejemplo n.º 26
0
// ExtractingFilter is a filter for the mail pipeline which extracts archives
func ExtractingFilter(inch <-chan i18nmail.MailPart, outch chan<- i18nmail.MailPart,
	files chan<- ArchFileItem, errch chan<- error, ctx *Context) {
	defer func() {
		logger.Debug("msg", "ExtractingFilter closes", "outch", outch)
		close(outch)
	}()

	allIn := make(chan i18nmail.MailPart, 1024)
	var wg sync.WaitGroup // for waiting all input to finish
	go func() {
		for part := range inch {
			wg.Add(1)
			allIn <- part
		}
		wg.Wait()
		close(allIn)
	}()

	for part := range allIn {
		var (
			makeReader func(io.Reader) (uncompr.Lister, error)
			zr         uncompr.Lister
			err        error
		)
		body := io.Reader(part.Body)
		if part.ContentType == "application/x-ole-storage" {
			r, err := NewOLEStorageReader(body)
			if err != nil {
				goto Error
			}
			child := part.Spawn()
			child.ContentType, child.Body = "message/rfc822", r
			child.Header = textproto.MIMEHeader(map[string][]string{
				"X-FileName": []string{
					safeFn(part.Header.Get("X-FileName")+".eml", true),
				}})
			wg.Add(1)
			allIn <- child
			wg.Done()
			continue
		}

		switch part.ContentType {
		case "application/zip":
			makeReader = uncompr.NewZipLister
		case "application/rar":
			makeReader = uncompr.NewRarLister
		//case "application/tar": makeReader = UnTar
		default:
			goto Skip
		}
		zr, err = makeReader(body)
		if err != nil {
			goto Error
		}
		for i, z := range zr.List() {
			rc, err := z.Open()
			if err != nil {
				logger.Warn("msg", "open zip element", "i", i, "error", err)
				continue
			}
			chunk, err := ioutil.ReadAll(rc)
			_ = rc.Close()
			if err != nil {
				logger.Warn("msg", "read zip element", "i", i, "error", err)
				continue
			}
			child := part.Spawn()
			child.ContentType = FixContentType(chunk, "application/octet-stream",
				z.Name())
			child.Body = bytes.NewBuffer(chunk)
			child.Header = textproto.MIMEHeader(make(map[string][]string, 1))
			child.Header.Add("X-FileName", safeFn(z.Name(), true))
			wg.Add(1)
			allIn <- child
		}
		wg.Done()
		continue
	Error:
		logger.Error("msg", "ExtractingFilter", "error", err)
		if err != nil {
			errch <- err
		}
	Skip:
		wg.Done()
		outch <- part
	}
}
Ejemplo n.º 27
0
// Del deletes the values associated with the key.
func (h Header) Del(key, value string) {
	textproto.MIMEHeader(h).Del(key)
}
Ejemplo n.º 28
0
func (h Headers) Get(key string) string {
	return textproto.MIMEHeader(h).Get(key)
}
Ejemplo n.º 29
0
func (h Headers) Del(key string) {
	textproto.MIMEHeader(h).Del(key)
}
Ejemplo n.º 30
0
func NewEntity(msg *mail.Message, dumpDir string) (*Entity, error) {
	shared := &sharedData{
		dumpDir: dumpDir,
	}
	return newEntity(textproto.MIMEHeader(msg.Header), msg.Body, shared)
}