func CreateNodeUpload(u *user.User, params map[string]string, files FormFiles) (node *Node, err error) { for param := range params { if !util.IsValidParamName(param) { return nil, errors.New("invalid param: " + param) } if param == "parts" && params[param] == "close" { return nil, errors.New("Cannot set parts=close when creating a node, did you do a POST when you meant to PUT?") } } for file := range files { if !util.IsValidFileName(file) { return nil, errors.New("invalid file param: " + file) } } // if copying node or creating subset node from parent, check if user has rights to the original node if _, hasCopyData := params["copy_data"]; hasCopyData { _, err = Load(params["copy_data"], u.Uuid) if err != nil { return } } if _, hasParentNode := params["parent_node"]; hasParentNode { _, err = Load(params["parent_node"], u.Uuid) if err != nil { return } } node = New() node.Type = "basic" if u.Uuid != "" { node.Acl.SetOwner(u.Uuid) node.Acl.Set(u.Uuid, acl.Rights{"read": true, "write": true, "delete": true}) node.Public = false } else { node.Acl = acl.Acl{Owner: "", Read: make([]string, 0), Write: make([]string, 0), Delete: make([]string, 0)} node.Public = true } err = node.Mkdir() if err != nil { return } err = node.Update(params, files) if err != nil { return } err = node.Save() return }
// helper function for create & update func ParseMultipartForm(r *http.Request) (params map[string]string, files node.FormFiles, err error) { params = make(map[string]string) files = make(node.FormFiles) reader, err := r.MultipartReader() if err != nil { return } tmpPath := "" for { if part, err := reader.NextPart(); err == nil { // params don't have a FileName() and files must have FormName() of either "upload", "attributes", or an integer if part.FileName() == "" { if !util.IsValidParamName(part.FormName()) { return nil, nil, errors.New("invalid param: " + part.FormName()) } buffer := make([]byte, 32*1024) n, err := part.Read(buffer) if n == 0 || err != nil { break } params[part.FormName()] = fmt.Sprintf("%s", buffer[0:n]) } else { if _, er := strconv.Atoi(part.FormName()); er != nil && !util.IsValidFileName(part.FormName()) { return nil, nil, errors.New("invalid file param: " + part.FormName()) } tmpPath = fmt.Sprintf("%s/temp/%d%d", conf.Conf["data-path"], rand.Int(), rand.Int()) /* if fname[len(fname)-3:] == ".gz" && params["decompress"] == "true" { fname = fname[:len(fname)-3] reader, err = gzip.NewReader(&part) if err != nil { break } } else { reader = &part } */ files[part.FormName()] = node.FormFile{Name: part.FileName(), Path: tmpPath, Checksum: make(map[string]string)} if tmpFile, err := os.Create(tmpPath); err == nil { defer tmpFile.Close() if part.FormName() == "upload" { md5c := make(chan checkSumCom) writeChecksum(md5.New, md5c) for { buffer := make([]byte, 32*1024) n, err := part.Read(buffer) if n == 0 || err != nil { md5c <- checkSumCom{n: 0} break } md5c <- checkSumCom{buf: buffer[0:n], n: n} tmpFile.Write(buffer[0:n]) } md5r := <-md5c files[part.FormName()].Checksum["md5"] = md5r.checksum } else { for { buffer := make([]byte, 32*1024) n, err := part.Read(buffer) if n == 0 || err != nil { break } tmpFile.Write(buffer[0:n]) } } } else { return nil, nil, err } } } else if err.Error() != "EOF" { return nil, nil, err } else { break } } _, hasUpload := files["upload"] _, hasCopyData := params["copy_data"] if hasUpload && hasCopyData { os.Remove(tmpPath) err = errors.New("Cannot specify upload file path and copy_data node in same request.") return nil, nil, err } return }
// helper function for create & update func ParseMultipartForm(r *http.Request) (params map[string]string, files node.FormFiles, err error) { params = make(map[string]string) files = make(node.FormFiles) reader, err := r.MultipartReader() if err != nil { return } tmpPath := "" for { if part, err := reader.NextPart(); err == nil { // params don't have a FileName() // files must have FormName() of either "upload", "gzip", "bzip2", "attributes", "subset_indices", or an integer if part.FileName() == "" { if !util.IsValidParamName(part.FormName()) { return nil, files, errors.New("invalid param: " + part.FormName()) } buffer := make([]byte, 32*1024) n, err := part.Read(buffer) if n == 0 || err != nil { break } formValue := fmt.Sprintf("%s", buffer[0:n]) if part.FormName() == "upload_url" { tmpPath = fmt.Sprintf("%s/temp/%d%d", conf.PATH_DATA, rand.Int(), rand.Int()) files[part.FormName()] = node.FormFile{Name: "", Path: tmpPath, Checksum: make(map[string]string)} // download from url if tmpFile, err := os.Create(tmpPath); err == nil { defer tmpFile.Close() var tmpform = files[part.FormName()] md5h := md5.New() dst := io.MultiWriter(tmpFile, md5h) fileName, body, err := fetchFileStream(formValue) if err != nil { return nil, files, errors.New("unable to stream url: " + err.Error()) } defer body.Close() if _, err = io.Copy(dst, body); err != nil { return nil, files, err } tmpform.Name = fileName tmpform.Checksum["md5"] = fmt.Sprintf("%x", md5h.Sum(nil)) files[part.FormName()] = tmpform } else { return nil, files, err } } else { // regular form field params[part.FormName()] = formValue } } else { // determine file type isSubsetFile := false if part.FormName() == "subset_indices" { isSubsetFile = true } isPartsFile := false if _, er := strconv.Atoi(part.FormName()); er == nil { isPartsFile = true } if !isPartsFile && !util.IsValidFileName(part.FormName()) { return nil, files, errors.New("invalid file param: " + part.FormName()) } // download it tmpPath = fmt.Sprintf("%s/temp/%d%d", conf.PATH_DATA, rand.Int(), rand.Int()) files[part.FormName()] = node.FormFile{Name: part.FileName(), Path: tmpPath, Checksum: make(map[string]string)} if tmpFile, err := os.Create(tmpPath); err == nil { defer tmpFile.Close() if util.IsValidUploadFile(part.FormName()) || isPartsFile || isSubsetFile { // handle upload or parts files var tmpform = files[part.FormName()] md5h := md5.New() dst := io.MultiWriter(tmpFile, md5h) ucReader, ucErr := archive.UncompressReader(part.FormName(), part) if ucErr != nil { return nil, files, ucErr } if _, err = io.Copy(dst, ucReader); err != nil { return nil, files, err } if archive.IsValidUncompress(part.FormName()) { tmpform.Name = util.StripSuffix(part.FileName()) } tmpform.Checksum["md5"] = fmt.Sprintf("%x", md5h.Sum(nil)) files[part.FormName()] = tmpform } else { // handle file where md5 not needed if _, err = io.Copy(tmpFile, part); err != nil { return nil, files, err } } } else { return nil, files, err } } } else if err.Error() != "EOF" { return nil, files, err } else { break } } return }