mirror of
https://github.com/Eggbertx/gochan.git
synced 2025-08-17 10:56:24 -07:00
Make config.Username useful (applies given username ownership to files)
This commit is contained in:
parent
d0e59b4580
commit
76a4f92e18
6 changed files with 157 additions and 38 deletions
|
@ -160,12 +160,18 @@ func BuildBoardPages(board *gcsql.Board) error {
|
|||
boardPageFile, err = os.OpenFile(path.Join(criticalCfg.DocumentRoot, board.Dir, "1.html"),
|
||||
os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0777)
|
||||
if err != nil {
|
||||
errEv.Err(err).
|
||||
errEv.Err(err).Caller().
|
||||
Str("page", "board.html").
|
||||
Caller().Msg("Failed getting board page")
|
||||
Msg("Failed getting board page")
|
||||
return fmt.Errorf("failed opening /%s/board.html: %s", board.Dir, err.Error())
|
||||
}
|
||||
defer boardPageFile.Close()
|
||||
|
||||
if err = config.TakeOwnershipOfFile(boardPageFile); err != nil {
|
||||
errEv.Err(err).Caller().
|
||||
Msg("Unable to take ownership of board.html")
|
||||
return fmt.Errorf("unable to take ownership of /%s/board.html: %s", board.Dir, err.Error())
|
||||
}
|
||||
// Render board page template to the file,
|
||||
// packaging the board/section list, threads, and board info
|
||||
captchaCfg := config.GetSiteConfig().Captcha
|
||||
|
@ -199,13 +205,17 @@ func BuildBoardPages(board *gcsql.Board) error {
|
|||
// catalog JSON file is built with the pages because pages are recorded in the JSON file
|
||||
catalogJSONFile, err := os.OpenFile(path.Join(criticalCfg.DocumentRoot, board.Dir, "catalog.json"), os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0777)
|
||||
if err != nil {
|
||||
errEv.Err(err).
|
||||
Str("subject", "catalog.json").
|
||||
Caller().Msg("Failed opening catalog.json")
|
||||
errEv.Err(err).Caller().
|
||||
Msg("Failed opening catalog.json")
|
||||
return fmt.Errorf("failed opening /%s/catalog.json: %s", board.Dir, err.Error())
|
||||
}
|
||||
defer catalogJSONFile.Close()
|
||||
|
||||
if err = config.TakeOwnershipOfFile(catalogJSONFile); err != nil {
|
||||
errEv.Err(err).Caller().
|
||||
Msg("Unable to take ownership of catalog.json")
|
||||
return fmt.Errorf("unable to take ownership of /%s/catalog.json: %s", board.Dir, err.Error())
|
||||
}
|
||||
for _, page := range catalog.pages {
|
||||
catalog.currentPage++
|
||||
var currentPageFilepath string
|
||||
|
@ -213,13 +223,20 @@ func BuildBoardPages(board *gcsql.Board) error {
|
|||
currentPageFilepath = path.Join(criticalCfg.DocumentRoot, board.Dir, pageFilename)
|
||||
currentPageFile, err = os.OpenFile(currentPageFilepath, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0777)
|
||||
if err != nil {
|
||||
errEv.Err(err).
|
||||
errEv.Err(err).Caller().
|
||||
Str("page", pageFilename).
|
||||
Caller().Msg("Failed getting board page")
|
||||
Msg("Failed getting board page")
|
||||
continue
|
||||
}
|
||||
defer currentPageFile.Close()
|
||||
|
||||
if err = config.TakeOwnershipOfFile(currentPageFile); err != nil {
|
||||
errEv.Err(err).Caller().
|
||||
Str("page", pageFilename).
|
||||
Msg("Unable to update file ownership")
|
||||
return errors.New("unable to set board page file ownership")
|
||||
}
|
||||
|
||||
// Render the boardpage template
|
||||
captchaCfg := config.GetSiteConfig().Captcha
|
||||
if err = serverutil.MinifyTemplate(gctemplates.BoardPage, map[string]interface{}{
|
||||
|
@ -329,9 +346,19 @@ func buildBoard(board *gcsql.Board, force bool) error {
|
|||
return fmt.Errorf(pathExistsStr, dirPath)
|
||||
}
|
||||
if !dirInfo.IsDir() {
|
||||
errEv.Err(os.ErrExist).
|
||||
Str("dirPath", dirPath).
|
||||
Caller().Send()
|
||||
return fmt.Errorf(dirIsAFileStr, dirPath)
|
||||
}
|
||||
} else if err = os.Mkdir(dirPath, 0666); err != nil {
|
||||
errEv.Err(os.ErrExist).
|
||||
Str("dirPath", dirPath).
|
||||
Caller().Send()
|
||||
return fmt.Errorf(genericErrStr, dirPath, err.Error())
|
||||
}
|
||||
if err = config.TakeOwnership(dirPath); err != nil {
|
||||
|
||||
return fmt.Errorf(genericErrStr, dirPath, err.Error())
|
||||
}
|
||||
|
||||
|
@ -356,7 +383,11 @@ func buildBoard(board *gcsql.Board, force bool) error {
|
|||
errEv.Err(err).
|
||||
Str("resPath", resPath).
|
||||
Caller().Send()
|
||||
|
||||
return fmt.Errorf(genericErrStr, resPath, err.Error())
|
||||
}
|
||||
if err = config.TakeOwnership(resPath); err != nil {
|
||||
errEv.Err(err).Caller().
|
||||
Str("resPath", resPath).Send()
|
||||
return fmt.Errorf(genericErrStr, resPath, err.Error())
|
||||
}
|
||||
|
||||
|
@ -382,6 +413,11 @@ func buildBoard(board *gcsql.Board, force bool) error {
|
|||
Caller().Send()
|
||||
return err
|
||||
}
|
||||
if config.TakeOwnership(srcPath); err != nil {
|
||||
errEv.Err(err).Caller().
|
||||
Str("srcPath", srcPath).Send()
|
||||
return fmt.Errorf(genericErrStr, srcPath, err.Error())
|
||||
}
|
||||
|
||||
if thumbInfo != nil {
|
||||
if !force {
|
||||
|
@ -391,6 +427,13 @@ func buildBoard(board *gcsql.Board, force bool) error {
|
|||
return fmt.Errorf(dirIsAFileStr, thumbPath)
|
||||
}
|
||||
} else if err = os.Mkdir(thumbPath, 0666); err != nil {
|
||||
errEv.Err(err).Caller().
|
||||
Str("thumbPath", thumbPath).Send()
|
||||
return fmt.Errorf(genericErrStr, thumbPath, err.Error())
|
||||
}
|
||||
if config.TakeOwnership(thumbPath); err != nil {
|
||||
errEv.Err(err).Caller().
|
||||
Str("thumbPath", thumbPath).Send()
|
||||
return fmt.Errorf(genericErrStr, thumbPath, err.Error())
|
||||
}
|
||||
|
||||
|
@ -424,13 +467,19 @@ func buildBoard(board *gcsql.Board, force bool) error {
|
|||
func BuildBoardListJSON() error {
|
||||
boardsJsonPath := path.Join(config.GetSystemCriticalConfig().DocumentRoot, "boards.json")
|
||||
boardListFile, err := os.OpenFile(boardsJsonPath, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0777)
|
||||
errEv := gcutil.LogError(nil).Str("building", "boards.json")
|
||||
defer errEv.Discard()
|
||||
if err != nil {
|
||||
gcutil.LogError(err).
|
||||
Str("building", "boardsList").Send()
|
||||
return errors.New("Failed opening boards.json for writing: " + err.Error())
|
||||
errEv.Err(err).Caller().Send()
|
||||
return errors.New("unable to open boards.json for writing: " + err.Error())
|
||||
}
|
||||
defer boardListFile.Close()
|
||||
|
||||
if err = config.TakeOwnershipOfFile(boardListFile); err != nil {
|
||||
errEv.Err(err).Caller().Send()
|
||||
return errors.New("unable to update boards.json ownership: " + err.Error())
|
||||
}
|
||||
|
||||
boardsMap := map[string][]boardJSON{
|
||||
"boards": {},
|
||||
}
|
||||
|
@ -452,12 +501,12 @@ func BuildBoardListJSON() error {
|
|||
// TODO: properly check if the board is in a hidden section
|
||||
boardJSON, err := json.Marshal(boardsMap)
|
||||
if err != nil {
|
||||
gcutil.LogError(err).Str("building", "boards.json").Send()
|
||||
errEv.Err(err).Caller().Send()
|
||||
return errors.New("Failed to create boards.json: " + err.Error())
|
||||
}
|
||||
|
||||
if _, err = serverutil.MinifyWriter(boardListFile, boardJSON, "application/json"); err != nil {
|
||||
gcutil.LogError(err).Str("building", "boards.json").Send()
|
||||
errEv.Err(err).Caller().Send()
|
||||
return errors.New("Failed writing boards.json file: " + err.Error())
|
||||
}
|
||||
return nil
|
||||
|
|
|
@ -112,6 +112,11 @@ func BuildFrontPage() error {
|
|||
}
|
||||
defer frontFile.Close()
|
||||
|
||||
if err = config.TakeOwnershipOfFile(frontFile); err != nil {
|
||||
errEv.Err(err).Caller().Send()
|
||||
return errors.New("Failed setting file ownership for front page: " + err.Error())
|
||||
}
|
||||
|
||||
var recentPostsArr []recentPost
|
||||
siteCfg := config.GetSiteConfig()
|
||||
recentPostsArr, err = getRecentPosts()
|
||||
|
@ -164,8 +169,10 @@ func BuildPageFooter(writer io.Writer) (err error) {
|
|||
func BuildJS() error {
|
||||
// build consts.js from template
|
||||
err := gctemplates.InitTemplates("js")
|
||||
errEv := gcutil.LogError(nil).Str("building", "consts.js")
|
||||
defer errEv.Discard()
|
||||
if err != nil {
|
||||
gcutil.LogError(err).Str("template", "consts.js").Send()
|
||||
errEv.Err(err).Caller().Send()
|
||||
return errors.New("Error loading consts.js template:" + err.Error())
|
||||
}
|
||||
|
||||
|
@ -174,13 +181,16 @@ func BuildJS() error {
|
|||
constsJSPath := path.Join(criticalCfg.DocumentRoot, "js", "consts.js")
|
||||
constsJSFile, err := os.OpenFile(constsJSPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
|
||||
if err != nil {
|
||||
gcutil.LogError(err).
|
||||
Str("building", "consts.js").
|
||||
Str("filePath", constsJSPath).Send()
|
||||
return fmt.Errorf("error opening %q for writing: %s", constsJSPath, err.Error())
|
||||
errEv.Err(err).Caller().Send()
|
||||
return fmt.Errorf("error opening consts.js for writing: %s", err.Error())
|
||||
}
|
||||
defer constsJSFile.Close()
|
||||
|
||||
if err = config.TakeOwnershipOfFile(constsJSFile); err != nil {
|
||||
errEv.Err(err).Caller().Send()
|
||||
return fmt.Errorf("unable to update file ownership for consts.js: %s", err.Error())
|
||||
}
|
||||
|
||||
if err = serverutil.MinifyTemplate(gctemplates.JsConsts,
|
||||
map[string]interface{}{
|
||||
"webroot": criticalCfg.WebRoot,
|
||||
|
@ -189,10 +199,8 @@ func BuildJS() error {
|
|||
"timezone": criticalCfg.TimeZone,
|
||||
},
|
||||
constsJSFile, "text/javascript"); err != nil {
|
||||
gcutil.LogError(err).
|
||||
Str("building", "consts.js").
|
||||
Str("filePath", constsJSPath).Send()
|
||||
return fmt.Errorf("error building %q: %s", constsJSPath, err.Error())
|
||||
errEv.Err(err).Caller().Send()
|
||||
return fmt.Errorf("error building consts.js: %s", err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -86,6 +86,12 @@ func BuildCatalog(boardID int) error {
|
|||
errEv.Err(err).Caller().Send()
|
||||
return fmt.Errorf("failed opening /%s/catalog.html: %s", board.Dir, err.Error())
|
||||
}
|
||||
defer catalogFile.Close()
|
||||
|
||||
if err = config.TakeOwnershipOfFile(catalogFile); err != nil {
|
||||
errEv.Err(err).Caller().Send()
|
||||
return fmt.Errorf("failed taking ownership of /%s/catalog.html: %s", board.Dir, err.Error())
|
||||
}
|
||||
|
||||
threadOPs, err := getBoardTopPosts(boardID)
|
||||
if err != nil {
|
||||
|
|
|
@ -85,10 +85,15 @@ func BuildThreadPages(op *gcsql.Post) error {
|
|||
threadPageFilepath := path.Join(criticalCfg.DocumentRoot, board.Dir, "res", strconv.Itoa(op.ID)+".html")
|
||||
threadPageFile, err = os.OpenFile(threadPageFilepath, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0777)
|
||||
if err != nil {
|
||||
errEv.Err(err).
|
||||
Caller().Send()
|
||||
return fmt.Errorf("unable to open opening /%s/res/%d.html: %s", board.Dir, op.ID, err.Error())
|
||||
errEv.Err(err).Caller().Send()
|
||||
return fmt.Errorf("unable to open /%s/res/%d.html: %s", board.Dir, op.ID, err.Error())
|
||||
}
|
||||
defer threadPageFile.Close()
|
||||
if err = config.TakeOwnershipOfFile(threadPageFile); err != nil {
|
||||
errEv.Err(err).Caller().Send()
|
||||
return fmt.Errorf("unable to set file permissions for /%s/res/%d.html: %s", board.Dir, op.ID, err.Error())
|
||||
}
|
||||
errEv.Int("op", posts[0].ID)
|
||||
|
||||
// render thread page
|
||||
captchaCfg := config.GetSiteConfig().Captcha
|
||||
|
@ -103,8 +108,7 @@ func BuildThreadPages(op *gcsql.Post) error {
|
|||
"useCaptcha": captchaCfg.UseCaptcha() && !captchaCfg.OnlyNeededForThreads,
|
||||
"captcha": captchaCfg,
|
||||
}, threadPageFile, "text/html"); err != nil {
|
||||
errEv.Err(err).
|
||||
Caller().Send()
|
||||
errEv.Err(err).Caller().Send()
|
||||
return fmt.Errorf("failed building /%s/res/%d threadpage: %s", board.Dir, posts[0].ID, err.Error())
|
||||
}
|
||||
|
||||
|
@ -113,13 +117,16 @@ func BuildThreadPages(op *gcsql.Post) error {
|
|||
path.Join(criticalCfg.DocumentRoot, board.Dir, "res", strconv.Itoa(posts[0].ID)+".json"),
|
||||
os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0777)
|
||||
if err != nil {
|
||||
errEv.Err(err).
|
||||
Int("op", posts[0].ID).
|
||||
Caller().Send()
|
||||
errEv.Err(err).Caller().Send()
|
||||
return fmt.Errorf("failed opening /%s/res/%d.json: %s", board.Dir, posts[0].ID, err.Error())
|
||||
}
|
||||
defer threadJSONFile.Close()
|
||||
|
||||
if err = config.TakeOwnershipOfFile(threadJSONFile); err != nil {
|
||||
errEv.Err(err).Caller().Send()
|
||||
return fmt.Errorf("failed setting file permissions for /%s/res/%d.json: %s", board.Dir, posts[0].ID, err.Error())
|
||||
}
|
||||
|
||||
threadMap := make(map[string][]Post)
|
||||
|
||||
threadMap["posts"] = posts
|
||||
|
@ -130,7 +137,6 @@ func BuildThreadPages(op *gcsql.Post) error {
|
|||
}
|
||||
if _, err = threadJSONFile.Write(threadJSON); err != nil {
|
||||
errEv.Err(err).
|
||||
Int("op", posts[0].ID).
|
||||
Caller().Send()
|
||||
return fmt.Errorf("failed writing /%s/res/%d.json: %s", board.Dir, posts[0].ID, err.Error())
|
||||
}
|
||||
|
|
|
@ -5,8 +5,11 @@ import (
|
|||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/user"
|
||||
"path"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gochan-org/gochan/pkg/gcutil"
|
||||
|
@ -17,6 +20,8 @@ var (
|
|||
"ListenIP", "Port", "Username", "UseFastCGI", "DocumentRoot", "TemplateDir", "LogDir",
|
||||
"DBtype", "DBhost", "DBname", "DBusername", "DBpassword", "SiteDomain", "Styles",
|
||||
}
|
||||
uid int
|
||||
gid int
|
||||
)
|
||||
|
||||
// MissingField represents a field missing from the configuration file
|
||||
|
@ -74,6 +79,22 @@ func GetDefaultString(key string) string {
|
|||
return str
|
||||
}
|
||||
|
||||
func TakeOwnership(fp string) error {
|
||||
if runtime.GOOS == "windows" || fp == "" {
|
||||
// Chown returns an error in Windows
|
||||
return nil
|
||||
}
|
||||
return os.Chown(fp, uid, gid)
|
||||
}
|
||||
|
||||
func TakeOwnershipOfFile(f *os.File) error {
|
||||
if runtime.GOOS == "windows" || f == nil {
|
||||
// Chown returns an error in Windows
|
||||
return nil
|
||||
}
|
||||
return f.Chown(uid, gid)
|
||||
}
|
||||
|
||||
// ParseJSON loads and parses JSON data, returning a GochanConfig pointer, any critical missing
|
||||
// fields that don't have defaults, and any error from parsing the file. This doesn't mean that the
|
||||
// values are valid, just that they exist
|
||||
|
@ -148,7 +169,7 @@ func InitConfig(versionStr string) {
|
|||
Version: ParseVersion(versionStr),
|
||||
},
|
||||
SiteConfig: SiteConfig{
|
||||
Username: "gochan",
|
||||
Username: "",
|
||||
FirstPage: []string{"index.html", "firstrun.html", "1.html"},
|
||||
Lockdown: false,
|
||||
LockdownMessage: "This imageboard has temporarily disabled posting. We apologize for the inconvenience",
|
||||
|
@ -255,6 +276,21 @@ func InitConfig(versionStr string) {
|
|||
os.Exit(1)
|
||||
}
|
||||
|
||||
if runtime.GOOS != "windows" {
|
||||
var gcUser *user.User
|
||||
if cfg.Username != "" {
|
||||
gcUser, err = user.Lookup(cfg.Username)
|
||||
} else {
|
||||
gcUser, err = user.Current()
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
uid, _ = strconv.Atoi(gcUser.Uid)
|
||||
gid, _ = strconv.Atoi(gcUser.Gid)
|
||||
}
|
||||
|
||||
if _, err = os.Stat(cfg.DocumentRoot); err != nil {
|
||||
fmt.Println(err.Error())
|
||||
os.Exit(1)
|
||||
|
|
|
@ -268,15 +268,18 @@ func MakePost(writer http.ResponseWriter, request *http.Request) {
|
|||
return
|
||||
}
|
||||
documentRoot := config.GetSystemCriticalConfig().DocumentRoot
|
||||
var filePath, thumbPath, catalogThumbPath string
|
||||
if upload != nil {
|
||||
filePath = path.Join(documentRoot, postBoard.Dir, "src", upload.Filename)
|
||||
thumbPath = path.Join(documentRoot, postBoard.Dir, "thumb", upload.ThumbnailPath("thumb"))
|
||||
catalogThumbPath = path.Join(documentRoot, postBoard.Dir, "thumb", upload.ThumbnailPath("catalog"))
|
||||
}
|
||||
|
||||
if err = post.Insert(emailCommand != "sage", postBoard.ID, false, false, false, false); err != nil {
|
||||
errEv.Err(err).Caller().
|
||||
Str("sql", "postInsertion").
|
||||
Msg("Unable to insert post")
|
||||
if upload != nil {
|
||||
filePath := path.Join(documentRoot, postBoard.Dir, "src", upload.Filename)
|
||||
thumbPath := path.Join(documentRoot, postBoard.Dir, "thumb", upload.ThumbnailPath("thumb"))
|
||||
catalogThumbPath := path.Join(documentRoot, postBoard.Dir, "thumb", upload.ThumbnailPath("catalog"))
|
||||
os.Remove(filePath)
|
||||
os.Remove(thumbPath)
|
||||
os.Remove(catalogThumbPath)
|
||||
|
@ -289,15 +292,26 @@ func MakePost(writer http.ResponseWriter, request *http.Request) {
|
|||
errEv.Err(err).Caller().
|
||||
Str("sql", "postInsertion").
|
||||
Msg("Unable to attach upload to post")
|
||||
filePath := path.Join(documentRoot, postBoard.Dir, "src", upload.Filename)
|
||||
thumbPath := path.Join(documentRoot, postBoard.Dir, "thumb", upload.ThumbnailPath("thumb"))
|
||||
catalogThumbPath := path.Join(documentRoot, postBoard.Dir, "thumb", upload.ThumbnailPath("catalog"))
|
||||
os.Remove(filePath)
|
||||
os.Remove(thumbPath)
|
||||
os.Remove(catalogThumbPath)
|
||||
serverutil.ServeErrorPage(writer, "Unable to attach upload: "+err.Error())
|
||||
return
|
||||
}
|
||||
if upload != nil {
|
||||
if err = config.TakeOwnership(filePath); err != nil {
|
||||
errEv.Err(err).Caller().
|
||||
Str("file", filePath).Send()
|
||||
}
|
||||
if err = config.TakeOwnership(thumbPath); err != nil {
|
||||
errEv.Err(err).Caller().
|
||||
Str("thumbnail", thumbPath).Send()
|
||||
}
|
||||
if err = config.TakeOwnership(catalogThumbPath); err != nil && !os.IsNotExist(err) {
|
||||
errEv.Err(err).Caller().
|
||||
Str("catalogThumbnail", catalogThumbPath).Send()
|
||||
}
|
||||
}
|
||||
|
||||
// rebuild the board page
|
||||
if err = building.BuildBoards(false, postBoard.ID); err != nil {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue