mirror of
https://github.com/Eggbertx/gochan.git
synced 2025-09-11 11:46:24 -07:00
Remove file i/o from gcsql package for better organization
This commit is contained in:
parent
5b5d5ab3ec
commit
9542949413
7 changed files with 86 additions and 50 deletions
|
@ -407,15 +407,35 @@ func utilHandler(writer http.ResponseWriter, request *http.Request) {
|
|||
if fileOnly {
|
||||
fileName := post.Filename
|
||||
if fileName != "" && fileName != "deleted" {
|
||||
if err = post.DeleteFiles(true); err != nil {
|
||||
if wantsJSON {
|
||||
serverutil.ServeJSON(writer, map[string]interface{}{
|
||||
"error": err,
|
||||
var files []string
|
||||
var errStr string
|
||||
|
||||
if files, err = post.GetFilePaths(); err != nil {
|
||||
errStr = gclog.Print(gclog.LErrorLog, "Error getting file upload info: ", err.Error())
|
||||
serverutil.ServeError(writer, errStr, wantsJSON, map[string]interface{}{
|
||||
"postid": post.ID,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if err = post.UnlinkUploads(true); err != nil {
|
||||
gclog.Printf(gclog.LErrorLog,
|
||||
"Error unlinking post uploads for #%d: %s", post.ID, err.Error())
|
||||
serverutil.ServeError(writer, err.Error(), wantsJSON, map[string]interface{}{
|
||||
"postid": post.ID,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
for _, filePath := range files {
|
||||
if err = os.Remove(filePath); err != nil {
|
||||
fileBase := path.Base(filePath)
|
||||
errStr = gclog.Printf(gclog.LErrorLog, "Error deleting %s: %s", fileBase, err.Error())
|
||||
serverutil.ServeError(writer, errStr, wantsJSON, map[string]interface{}{
|
||||
"postid": post.ID,
|
||||
"file": fileBase,
|
||||
})
|
||||
} else {
|
||||
serverutil.ServeErrorPage(writer, gclog.Print(gclog.LErrorLog,
|
||||
"Error deleting files from post: ", err.Error()))
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package gcsql
|
|||
import (
|
||||
"database/sql"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/gochan-org/gochan/pkg/gclog"
|
||||
|
@ -82,6 +81,8 @@ func (board *Board) PopulateData(id int) error {
|
|||
return QueryRowSQL(sql, interfaceSlice(id), interfaceSlice(&board.ID, &board.Section, &board.Dir, &board.ListOrder, &board.Title, &board.Subtitle, &board.Description, &board.MaxFilesize, &board.DefaultStyle, &board.Locked, &board.CreatedOn, &board.Anonymous, &board.ForcedAnon, &board.AutosageAfter, &board.NoImagesAfter, &board.MaxMessageLength, &board.EmbedsAllowed, &board.RedirectToThread, &board.RequireFile, &board.EnableCatalog))
|
||||
}
|
||||
|
||||
// Delete deletes the board from the database (if a row with the struct's ID exists) and
|
||||
// returns any errors. It does not remove the board directory or its files
|
||||
func (board *Board) Delete() error {
|
||||
exists := DoesBoardExistByID(board.ID)
|
||||
if !exists {
|
||||
|
@ -92,13 +93,6 @@ func (board *Board) Delete() error {
|
|||
}
|
||||
const delSql = `DELETE FROM DBPREFIXboards WHERE id = ?`
|
||||
_, err := ExecSQL(delSql, board.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
absPath := board.AbsolutePath()
|
||||
gclog.Printf(gclog.LStaffLog,
|
||||
"Deleting board /%s/, absolute path: %s\n", board.Dir, absPath)
|
||||
err = os.RemoveAll(absPath)
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
package gcsql
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"database/sql"
|
||||
"path"
|
||||
"time"
|
||||
|
||||
|
@ -173,44 +172,47 @@ func GetPostsFromIP(ip string, limit int, onlyNotDeleted bool) ([]Post, error) {
|
|||
return posts, nil
|
||||
}
|
||||
|
||||
func (p *Post) DeleteFiles(leaveDeletedBox bool) error {
|
||||
board, boardWasFound, err := GetBoardFromPostID(p.ID)
|
||||
// GetFilePaths returns an array of absolute paths to uploaded files and thumbnails associated
|
||||
// with this post, and any errors that occurred
|
||||
func (p *Post) GetFilePaths() ([]string, error) {
|
||||
boardDir, err := p.GetBoardDir()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !boardWasFound {
|
||||
return fmt.Errorf("could not find board for post %v", p.ID)
|
||||
return nil, err
|
||||
}
|
||||
const filenameSQL = `SELECT filename FROM DBPREFIXfiles WHERE post_id = ?`
|
||||
rows, err := QuerySQL(filenameSQL, p.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
var paths []string
|
||||
if err == sql.ErrNoRows {
|
||||
return paths, nil
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var filenames []string
|
||||
documentRoot := config.GetSystemCriticalConfig().DocumentRoot
|
||||
for rows.Next() {
|
||||
var filename string
|
||||
if err = rows.Scan(&filename); err != nil {
|
||||
return err
|
||||
return paths, err
|
||||
}
|
||||
filenames = append(filenames, filename)
|
||||
}
|
||||
|
||||
systemCriticalCfg := config.GetSystemCriticalConfig()
|
||||
//Remove files from disk
|
||||
for _, filename := range filenames {
|
||||
_, filenameBase, fileExt := gcutil.GetFileParts(filename)
|
||||
thumbExt := fileExt
|
||||
if thumbExt == "gif" || thumbExt == "webm" || thumbExt == "mp4" {
|
||||
thumbExt = "jpg"
|
||||
}
|
||||
uploadPath := path.Join(systemCriticalCfg.DocumentRoot, board, "/src/", filenameBase+"."+fileExt)
|
||||
thumbPath := path.Join(systemCriticalCfg.DocumentRoot, board, "/thumb/", filenameBase+"t."+thumbExt)
|
||||
catalogThumbPath := path.Join(systemCriticalCfg.DocumentRoot, board, "/thumb/", filenameBase+"c."+thumbExt)
|
||||
os.Remove(uploadPath)
|
||||
os.Remove(thumbPath)
|
||||
os.Remove(catalogThumbPath)
|
||||
paths = append(paths,
|
||||
path.Join(documentRoot, boardDir, "/src/", filenameBase+"."+fileExt),
|
||||
path.Join(documentRoot, boardDir, "/thumb/", filenameBase+"t."+thumbExt), // thumbnail path
|
||||
)
|
||||
if p.ParentID == 0 {
|
||||
paths = append(paths, path.Join(documentRoot, boardDir, "/thumb/", filenameBase+"c."+thumbExt)) // catalog thumbnail path
|
||||
}
|
||||
}
|
||||
return paths, nil
|
||||
}
|
||||
|
||||
// UnlinkUploads disassociates the post with any uploads in DBPREFIXfiles
|
||||
// that may have been uploaded with it, optionally leaving behind a "File Deleted"
|
||||
// frame where the thumbnail appeared
|
||||
func (p *Post) UnlinkUploads(leaveDeletedBox bool) error {
|
||||
var sqlStr string
|
||||
if leaveDeletedBox {
|
||||
// leave a "File Deleted" box
|
||||
|
@ -218,6 +220,6 @@ func (p *Post) DeleteFiles(leaveDeletedBox bool) error {
|
|||
} else {
|
||||
sqlStr = `DELETE FROM DBPREFIXfiles WHERE post_id = ?`
|
||||
}
|
||||
_, err = ExecSQL(sqlStr, p.ID)
|
||||
_, err := ExecSQL(sqlStr, p.ID)
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -257,14 +257,6 @@ func UpdatePost(postID int, email, subject string, message template.HTML, messag
|
|||
return err
|
||||
}
|
||||
|
||||
// DeleteFilesFromPost deletes all files belonging to a given post
|
||||
func DeleteFilesFromPost(postID int, leaveDeletedBox bool) error {
|
||||
post := &Post{
|
||||
ID: postID,
|
||||
}
|
||||
return post.DeleteFiles(leaveDeletedBox)
|
||||
}
|
||||
|
||||
// DeletePost deletes a post with a given ID
|
||||
func DeletePost(postID int, checkIfTopPost bool) error {
|
||||
if checkIfTopPost {
|
||||
|
@ -281,7 +273,6 @@ func DeletePost(postID int, checkIfTopPost bool) error {
|
|||
}
|
||||
}
|
||||
|
||||
DeleteFilesFromPost(postID, false)
|
||||
const sql = `UPDATE DBPREFIXposts SET is_deleted = TRUE, deleted_at = CURRENT_TIMESTAMP WHERE id = ?`
|
||||
_, err := ExecSQL(sql, postID)
|
||||
return err
|
||||
|
|
|
@ -290,7 +290,7 @@ func (p *Post) GetBoardDir() (string, error) {
|
|||
SELECT board_id FROM DBPREFIXthreads WHERE id = (
|
||||
SELECT thread_id FROM DBPREFIXposts WHERE id = ? LIMIT 1) LIMIT 1)`
|
||||
|
||||
err := QueryRowSQL(sql, []interface{}{p.ParentID}, interfaceSlice(&p.boardDir))
|
||||
err := QueryRowSQL(sql, []interface{}{p.ID}, interfaceSlice(&p.boardDir))
|
||||
return p.boardDir, err
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"html"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
@ -530,6 +531,13 @@ var actions = []Action{
|
|||
Permissions: AdminPerms,
|
||||
JSONoutput: NoJSON,
|
||||
Callback: func(writer http.ResponseWriter, request *http.Request, wantsJSON bool) (output interface{}, err error) {
|
||||
var currentUser string
|
||||
currentUser, err = getCurrentStaff(request)
|
||||
if err != nil {
|
||||
return "", errors.New(gclog.Println(gclog.LErrorLog,
|
||||
"Error parsing current user:", err.Error()))
|
||||
}
|
||||
|
||||
pageBuffer := bytes.NewBufferString("")
|
||||
var board gcsql.Board
|
||||
requestType, boardID, err := boardsRequestType(request)
|
||||
|
@ -550,6 +558,13 @@ var actions = []Action{
|
|||
return "", err
|
||||
}
|
||||
err = board.Delete()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
absPath := board.AbsolutePath()
|
||||
gclog.Printf(gclog.LStaffLog,
|
||||
"Board /%s/ deleted by %s, absolute path: %s\n", board.Dir, currentUser, absPath)
|
||||
err = os.RemoveAll(absPath)
|
||||
case "edit":
|
||||
// edit button clicked, fill the input fields with board data to be edited
|
||||
board, err = gcsql.GetBoardFromID(boardID)
|
||||
|
|
|
@ -18,6 +18,20 @@ func ServeJSON(writer http.ResponseWriter, data map[string]interface{}) {
|
|||
MinifyWriter(writer, []byte(jsonStr), "application/json")
|
||||
}
|
||||
|
||||
// ServeError serves the given map as a JSON file (with the error string included) if wantsJSON is true,
|
||||
// otherwise it serves a regular HTML error page
|
||||
func ServeError(writer http.ResponseWriter, err string, wantsJSON bool, data map[string]interface{}) {
|
||||
if wantsJSON {
|
||||
servedMap := data
|
||||
if _, ok := servedMap["error"]; !ok {
|
||||
servedMap["error"] = err
|
||||
}
|
||||
ServeJSON(writer, servedMap)
|
||||
} else {
|
||||
ServeErrorPage(writer, err)
|
||||
}
|
||||
}
|
||||
|
||||
// ServeErrorPage shows a general error page if something goes wrong
|
||||
func ServeErrorPage(writer http.ResponseWriter, err string) {
|
||||
writer.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue