github.com/Azareal/Gosora@v0.0.0-20210729070923-553e66b59003/routes/attachments.go (about)

     1  package routes
     2  
     3  import (
     4  	"database/sql"
     5  	"net/http"
     6  	"path/filepath"
     7  	"strconv"
     8  	"strings"
     9  
    10  	c "github.com/Azareal/Gosora/common"
    11  )
    12  
    13  var maxAgeYear = "max-age=" + strconv.Itoa(int(c.Year))
    14  
    15  func ShowAttachment(w http.ResponseWriter, r *http.Request, u *c.User, filename string) c.RouteError {
    16  	sid, err := strconv.Atoi(r.FormValue("sid"))
    17  	if err != nil {
    18  		return c.LocalError("The sid is not an integer", w, r, u)
    19  	}
    20  	sectionTable := r.FormValue("stype")
    21  
    22  	filename = c.Stripslashes(filename)
    23  	if filename == "" {
    24  		return c.LocalError("Bad filename", w, r, u)
    25  	}
    26  	ext := filepath.Ext(filename)
    27  	if ext == "" || !c.AllowedFileExts.Contains(strings.TrimPrefix(ext, ".")) {
    28  		return c.LocalError("Bad extension", w, r, u)
    29  	}
    30  
    31  	// TODO: Use the same hook table as upstream
    32  	hTbl := c.GetHookTable()
    33  	skip, rerr := c.H_route_attach_start_hook(hTbl, w, r, u, filename)
    34  	if skip || rerr != nil {
    35  		return rerr
    36  	}
    37  
    38  	a, err := c.Attachments.GetForRenderRoute(filename, sid, sectionTable)
    39  	// ErrCorruptAttachPath is a possibility now
    40  	if err == sql.ErrNoRows {
    41  		return c.NotFound(w, r, nil)
    42  	} else if err != nil {
    43  		return c.InternalError(err, w, r)
    44  	}
    45  
    46  	skip, rerr = c.H_route_attach_post_get_hook(hTbl, w, r, u, a)
    47  	if skip || rerr != nil {
    48  		return rerr
    49  	}
    50  
    51  	if a.SectionTable == "forums" {
    52  		_, ferr := c.SimpleForumUserCheck(w, r, u, sid)
    53  		if ferr != nil {
    54  			return ferr
    55  		}
    56  		if !u.Perms.ViewTopic {
    57  			return c.NoPermissions(w, r, u)
    58  		}
    59  	} else {
    60  		return c.LocalError("Unknown section", w, r, u)
    61  	}
    62  
    63  	if a.OriginTable != "topics" && a.OriginTable != "replies" {
    64  		return c.LocalError("Unknown origin", w, r, u)
    65  	}
    66  
    67  	if !u.Loggedin {
    68  		w.Header().Set("Cache-Control", maxAgeYear)
    69  	} else {
    70  		guest := c.GuestUser
    71  		_, ferr := c.SimpleForumUserCheck(w, r, &guest, sid)
    72  		if ferr != nil {
    73  			return ferr
    74  		}
    75  		h := w.Header()
    76  		if guest.Perms.ViewTopic {
    77  			h.Set("Cache-Control", maxAgeYear)
    78  		} else {
    79  			h.Set("Cache-Control", "private")
    80  		}
    81  	}
    82  
    83  	// TODO: Fix the problem where non-existent files aren't greeted with custom 404s on ServeFile()'s side
    84  	http.ServeFile(w, r, "./attachs/"+filename)
    85  	return nil
    86  }
    87  
    88  func deleteAttachment(w http.ResponseWriter, r *http.Request, u *c.User, aid int, js bool) c.RouteError {
    89  	e := c.DeleteAttachment(aid)
    90  	if e == sql.ErrNoRows {
    91  		return c.NotFoundJSQ(w, r, nil, js)
    92  	} else if e != nil {
    93  		return c.InternalErrorJSQ(e, w, r, js)
    94  	}
    95  	return nil
    96  }
    97  
    98  // TODO: Stop duplicating this code
    99  // TODO: Use a transaction here
   100  // TODO: Move this function to neutral ground
   101  func uploadAttachment(w http.ResponseWriter, r *http.Request, u *c.User, sid int, stable string, oid int, otable, extra string) (pathMap map[string]string, rerr c.RouteError) {
   102  	pathMap = make(map[string]string)
   103  	files, rerr := uploadFilesWithHash(w, r, u, "./attachs/")
   104  	if rerr != nil {
   105  		return nil, rerr
   106  	}
   107  
   108  	for _, filename := range files {
   109  		aid, err := c.Attachments.Add(sid, stable, oid, otable, u.ID, filename, extra)
   110  		if err != nil {
   111  			return nil, c.InternalError(err, w, r)
   112  		}
   113  
   114  		_, ok := pathMap[filename]
   115  		if ok {
   116  			pathMap[filename] += "," + strconv.Itoa(aid)
   117  		} else {
   118  			pathMap[filename] = strconv.Itoa(aid)
   119  		}
   120  
   121  		err = c.Attachments.AddLinked(otable, oid)
   122  		if err != nil {
   123  			return nil, c.InternalError(err, w, r)
   124  		}
   125  	}
   126  
   127  	return pathMap, nil
   128  }