summaryrefslogtreecommitdiff
path: root/http
diff options
context:
space:
mode:
Diffstat (limited to 'http')
-rw-r--r--http/fs_config.go29
-rw-r--r--http/fs_config_test.go15
-rw-r--r--http/parse.go147
-rw-r--r--http/response.go54
-rw-r--r--http/uploads.go130
5 files changed, 0 insertions, 375 deletions
diff --git a/http/fs_config.go b/http/fs_config.go
deleted file mode 100644
index de5b1389..00000000
--- a/http/fs_config.go
+++ /dev/null
@@ -1,29 +0,0 @@
-package http
-
-import (
- "strings"
- "path"
-)
-
-// FsConfig describes file location and controls access to them.
-type FsConfig struct {
- // Dir contains name of directory to control access to.
- Dir string
-
- // Forbid specifies list of file extensions which are forbidden for access.
- // Example: .php, .exe, .bat, .htaccess and etc.
- Forbid []string
-}
-
-// Forbid must return true if file extension is not allowed for the upload.
-func (cfg FsConfig) Forbids(filename string) bool {
- ext := strings.ToLower(path.Ext(filename))
-
- for _, v := range cfg.Forbid {
- if ext == v {
- return true
- }
- }
-
- return false
-}
diff --git a/http/fs_config_test.go b/http/fs_config_test.go
deleted file mode 100644
index 05f568e5..00000000
--- a/http/fs_config_test.go
+++ /dev/null
@@ -1,15 +0,0 @@
-package http
-
-import (
- "testing"
- "github.com/stretchr/testify/assert"
-)
-
-func TestFsConfig_Forbids(t *testing.T) {
- cfg := FsConfig{Forbid: []string{".php"}}
-
- assert.True(t, cfg.Forbids("index.php"))
- assert.True(t, cfg.Forbids("index.PHP"))
- assert.True(t, cfg.Forbids("phpadmin/index.bak.php"))
- assert.False(t, cfg.Forbids("index.html"))
-}
diff --git a/http/parse.go b/http/parse.go
deleted file mode 100644
index 898f39a1..00000000
--- a/http/parse.go
+++ /dev/null
@@ -1,147 +0,0 @@
-package http
-
-import (
- "strings"
- "net/http"
- "os"
-)
-
-const maxLevel = 127
-
-type dataTree map[string]interface{}
-type fileTree map[string]interface{}
-
-// parseData parses incoming request body into data tree.
-func parseData(r *http.Request) (dataTree, error) {
- data := make(dataTree)
- for k, v := range r.PostForm {
- data.push(k, v)
- }
-
- for k, v := range r.MultipartForm.Value {
- data.push(k, v)
- }
-
- return data, nil
-}
-
-// pushes value into data tree.
-func (d dataTree) push(k string, v []string) {
- if len(v) == 0 {
- // skip empty values
- return
- }
-
- indexes := make([]string, 0)
- for _, index := range strings.Split(k, "[") {
- indexes = append(indexes, strings.Trim(index, "]"))
- }
-
- if len(indexes) <= maxLevel {
- d.mount(indexes, v)
- }
-}
-
-// mount mounts data tree recursively.
-func (d dataTree) mount(i []string, v []string) {
- if len(v) == 0 {
- return
- }
-
- if len(i) == 1 {
- // single value context
- d[i[0]] = v[0]
- return
- }
-
- if len(i) == 2 && i[1] == "" {
- // non associated array of elements
- d[i[0]] = v
- return
- }
-
- if p, ok := d[i[0]]; ok {
- p.(dataTree).mount(i[1:], v)
- }
-
- d[i[0]] = make(dataTree)
- d[i[0]].(dataTree).mount(i[1:], v)
-}
-
-// parse incoming dataTree request into JSON (including multipart form dataTree)
-func parseUploads(r *http.Request, cfg *FsConfig) (*Uploads, error) {
- u := &Uploads{
- cfg: cfg,
- tree: make(fileTree),
- list: make([]*FileUpload, 0),
- }
-
- for k, v := range r.MultipartForm.File {
- files := make([]*FileUpload, 0, len(v))
- for _, f := range v {
- files = append(files, NewUpload(f))
- }
-
- u.list = append(u.list, files...)
- u.tree.push(k, files)
- }
-
- return u, nil
-}
-
-// exists if file exists.
-func exists(path string) bool {
- _, err := os.Stat(path)
- if err == nil {
- return true
- }
-
- if os.IsNotExist(err) {
- return false
- }
-
- return false
-}
-
-// pushes new file upload into it's proper place.
-func (d fileTree) push(k string, v []*FileUpload) {
- if len(v) == 0 {
- // skip empty values
- return
- }
-
- indexes := make([]string, 0)
- for _, index := range strings.Split(k, "[") {
- indexes = append(indexes, strings.Trim(index, "]"))
- }
-
- if len(indexes) <= maxLevel {
- d.mount(indexes, v)
- }
-}
-
-// mount mounts data tree recursively.
-func (d fileTree) mount(i []string, v []*FileUpload) {
- if len(v) == 0 {
- return
- }
-
- if len(i) == 1 {
- // single value context
- d[i[0]] = v[0]
- return
- }
-
- if len(i) == 2 && i[1] == "" {
- // non associated array of elements
- d[i[0]] = v
- return
- }
-
- if p, ok := d[i[0]]; ok {
- p.(fileTree).mount(i[1:], v)
- }
-
- d[i[0]] = make(fileTree)
- d[i[0]].(fileTree).mount(i[1:], v)
-}
diff --git a/http/response.go b/http/response.go
deleted file mode 100644
index dd092353..00000000
--- a/http/response.go
+++ /dev/null
@@ -1,54 +0,0 @@
-package http
-
-import (
- "encoding/json"
- "github.com/spiral/roadrunner"
- "net/http"
- "io"
-)
-
-// Response handles PSR7 response logic.
-type Response struct {
- // Status contains response status.
- Status int `json:"status"`
-
- // Headers contains list of response headers.
- Headers map[string][]string `json:"headers"`
-
- // associated body payload.
- body interface{}
-}
-
-// NewResponse creates new response based on given roadrunner payload.
-func NewResponse(p *roadrunner.Payload) (*Response, error) {
- r := &Response{body: p.Body}
- if err := json.Unmarshal(p.Context, r); err != nil {
- return nil, err
- }
-
- return r, nil
-}
-
-// Write writes response headers, status and body into ResponseWriter.
-func (r *Response) Write(w http.ResponseWriter) error {
- for k, v := range r.Headers {
- for _, h := range v {
- w.Header().Add(k, h)
-
- }
- }
-
- w.WriteHeader(r.Status)
-
- if data, ok := r.body.([]byte); ok {
- w.Write(data)
- }
-
- if rc, ok := r.body.(io.Reader); ok {
- if _, err := io.Copy(w, rc); err != nil {
- return err
- }
- }
-
- return nil
-}
diff --git a/http/uploads.go b/http/uploads.go
deleted file mode 100644
index cdd3e52c..00000000
--- a/http/uploads.go
+++ /dev/null
@@ -1,130 +0,0 @@
-package http
-
-import (
- "encoding/json"
- "os"
- "sync"
- "mime/multipart"
- "io/ioutil"
- "io"
-)
-
-const (
- // There is no error, the file uploaded with success.
- UploadErrorOK = 0
-
- // No file was uploaded.
- UploadErrorNoFile = 4
-
- // Missing a temporary folder.
- UploadErrorNoTmpDir = 5
-
- // Failed to write file to disk.
- UploadErrorCantWrite = 6
-
- // Forbid file extension.
- UploadErrorExtension = 7
-)
-
-// tree manages uploaded files tree and temporary files.
-type Uploads struct {
- // associated temp directory and forbidden extensions.
- cfg *FsConfig
-
- // pre processed data tree for Uploads.
- tree fileTree
-
- // flat list of all file Uploads.
- list []*FileUpload
-}
-
-// MarshalJSON marshal tree tree into JSON.
-func (u *Uploads) MarshalJSON() ([]byte, error) {
- return json.Marshal(u.tree)
-}
-
-// Open moves all uploaded files to temp directory, return error in case of issue with temp directory. File errors
-// will be handled individually.
-func (u *Uploads) Open() error {
- var wg sync.WaitGroup
- for _, f := range u.list {
- wg.Add(1)
- go func(f *FileUpload) {
- defer wg.Done()
- f.Open(u.cfg)
- }(f)
- }
-
- wg.Wait()
- return nil
-}
-
-// Clear deletes all temporary files.
-func (u *Uploads) Clear() {
- for _, f := range u.list {
- if f.TempFilename != "" && exists(f.TempFilename) {
- os.Remove(f.TempFilename)
- }
- }
-}
-
-// FileUpload represents singular file NewUpload.
-type FileUpload struct {
- // Name contains filename specified by the client.
- Name string `json:"name"`
-
- // MimeType contains mime-type provided by the client.
- MimeType string `json:"type"`
-
- // Size of the uploaded file.
- Size int64 `json:"size"`
-
- // Error indicates file upload error (if any). See http://php.net/manual/en/features.file-upload.errors.php
- Error int `json:"error"`
-
- // TempFilename points to temporary file location.
- TempFilename string `json:"tmpName"`
-
- // associated file header
- header *multipart.FileHeader
-}
-
-// NewUpload wraps net/http upload into PRS-7 compatible structure.
-func NewUpload(f *multipart.FileHeader) *FileUpload {
- return &FileUpload{
- Name: f.Filename,
- MimeType: f.Header.Get("Content-Type"),
- Error: UploadErrorOK,
- header: f,
- }
-}
-
-func (f *FileUpload) Open(cfg *FsConfig) error {
- if cfg.Forbids(f.Name) {
- f.Error = UploadErrorExtension
- return nil
- }
-
- file, err := f.header.Open()
- if err != nil {
- f.Error = UploadErrorNoFile
- return err
- }
- defer file.Close()
-
- tmp, err := ioutil.TempFile(cfg.Dir, "upload")
- if err != nil {
- // most likely cause of this issue is missing tmp dir
- f.Error = UploadErrorNoTmpDir
- return err
- }
-
- f.TempFilename = tmp.Name()
- defer tmp.Close()
-
- if f.Size, err = io.Copy(tmp, file); err != nil {
- f.Error = UploadErrorCantWrite
- }
-
- return err
-}