mirror of
https://github.com/Eggbertx/gochan.git
synced 2025-08-20 09:26:23 -07:00
Store configuration-dependent variables in a JavaScript file
As opposed to every single HTML file
This commit is contained in:
parent
7a729fd050
commit
424f419199
19 changed files with 282 additions and 237 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -9,4 +9,6 @@ vagrant/*.log
|
|||
html/boards.json
|
||||
html/index.html
|
||||
html/test*
|
||||
html/javascript/consts.js
|
||||
templates/override
|
||||
**/*.bak
|
|
@ -10,9 +10,9 @@ var settings = [];
|
|||
var current_staff;
|
||||
var dropdown_div_created = false;
|
||||
var $qr;
|
||||
|
||||
var movable_postpreviews = true;
|
||||
var expandable_postrefs = true;
|
||||
var opRegex = /(\d)+(p(\d)+)?.html$/;
|
||||
|
||||
function preparePostPreviews(is_inline) {
|
||||
var m_type = "mousemove";
|
||||
|
@ -336,15 +336,36 @@ $jq(document).keydown(function(e) {
|
|||
}
|
||||
});
|
||||
|
||||
function getPageThread() {
|
||||
var pathArr = window.location.pathname.split("/");
|
||||
if(pathArr.length < 3) {
|
||||
return {board: "", boardID: -1, thread: 0};
|
||||
} else if(pathArr.length == 3) {
|
||||
return {board: pathArr[1], boardID: $jq("form#postform input[name=boardid]").val() -1, thread: 0};
|
||||
} else if(pathArr.length > 3) {
|
||||
return {board: pathArr[1], boardID: $jq("form#postform input[name=boardid]").val() -1, thread: parseInt(pathArr[3].replace(".html",""))};
|
||||
function getBoard() {
|
||||
var rootIndex = window.location.pathname.indexOf(webroot);
|
||||
var board = window.location.pathname.substring(rootIndex+webroot.length);
|
||||
if(board.length > 0 && board.indexOf("/") > -1) {
|
||||
board = board.split("/")[0];
|
||||
} else {
|
||||
board = "";
|
||||
}
|
||||
return board;
|
||||
}
|
||||
|
||||
function getPageThread() {
|
||||
var arr = opRegex.exec(window.location.pathname);
|
||||
var info = {
|
||||
board: getBoard(),
|
||||
boardID: -1,
|
||||
op: -1,
|
||||
page: 0
|
||||
};
|
||||
if(arr != null && arr.length > 1) info.op = arr[1];
|
||||
if(arr != null && arr.length > 3) info.page = arr[3];
|
||||
if(arr.board != "") info.boardID = $jq("form#postform input[name=boardid]").val() -1;
|
||||
return info;
|
||||
}
|
||||
|
||||
function changePage(sel) {
|
||||
var info = getPageThread();
|
||||
if(info.board == "" || info.op == -1) return;
|
||||
if(sel.value != "")
|
||||
window.location = webroot + info.board + "/res/" + info.op + "p" + sel.value + ".html";
|
||||
}
|
||||
|
||||
function getSetting(id) {
|
||||
|
@ -465,7 +486,7 @@ function initQR(pageThread) {
|
|||
method:"POST",
|
||||
enctype:"multipart/form-data"
|
||||
}).append(
|
||||
"<input type=\"hidden\" name=\"threadid\" value=\"" + pageThread.thread +"\" />" +
|
||||
"<input type=\"hidden\" name=\"threadid\" value=\"" + pageThread.op +"\" />" +
|
||||
"<input type=\"hidden\" name=\"boardid\" value=\"1\" />" +
|
||||
"<div id=\"qrpostname\"><input id=\"qrpostname\" type=\"text\" name=\"postname\" value=\"" + getCookie("name","") + "\" placeholder=\"Name\"/></div>" +
|
||||
"<div id=\"qrpostemail\"><input id=\"qrpostemail\" type=\"text\" name=\"postemail\" value=\"" + getCookie("email","") + "\" placeholder=\"Email\"/></div>" +
|
||||
|
|
|
@ -71,7 +71,7 @@ func buildFrontPage() string {
|
|||
}
|
||||
}
|
||||
|
||||
if err = front_page_tmpl.Execute(front_file, map[string]interface{}{
|
||||
if err = frontPageTmpl.Execute(front_file, map[string]interface{}{
|
||||
"config": config,
|
||||
"sections": allSections,
|
||||
"boards": allBoards,
|
||||
|
@ -237,7 +237,7 @@ func buildBoardPages(board *Board) (html string) {
|
|||
|
||||
// Render board page template to the file,
|
||||
// packaging the board/section list, threads, and board info
|
||||
if err = img_boardpage_tmpl.Execute(board_page_file, map[string]interface{}{
|
||||
if err = boardpageTmpl.Execute(board_page_file, map[string]interface{}{
|
||||
"config": config,
|
||||
"boards": allBoards,
|
||||
"sections": allSections,
|
||||
|
@ -280,7 +280,7 @@ func buildBoardPages(board *Board) (html string) {
|
|||
}
|
||||
|
||||
// Render the boardpage template, don't forget config
|
||||
if err = img_boardpage_tmpl.Execute(current_page_file, map[string]interface{}{
|
||||
if err = boardpageTmpl.Execute(current_page_file, map[string]interface{}{
|
||||
"config": config,
|
||||
"boards": allBoards,
|
||||
"sections": allSections,
|
||||
|
@ -370,6 +370,23 @@ func buildBoards(which ...int) (html string) {
|
|||
return
|
||||
}
|
||||
|
||||
func buildJSConstants() string {
|
||||
err := initTemplates("js")
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
jsPath := path.Join(config.DocumentRoot, "javascript", "consts.js")
|
||||
jsFile, err := os.OpenFile(jsPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
|
||||
if err != nil {
|
||||
return handleError(1, "Error opening '"+jsPath+"' for writing: "+err.Error())
|
||||
}
|
||||
|
||||
if err = jsTmpl.Execute(jsFile, config); err != nil {
|
||||
return handleError(1, "Error building '"+jsPath+"': "+err.Error())
|
||||
}
|
||||
return "Built '" + jsPath + "' successfully."
|
||||
}
|
||||
|
||||
func buildCatalog(which int) string {
|
||||
err := initTemplates("catalog")
|
||||
if err != nil {
|
||||
|
@ -398,7 +415,7 @@ func buildCatalog(which int) string {
|
|||
}
|
||||
threadPages := paginate(config.PostsPerThreadPage, threadInterfaces)
|
||||
|
||||
if err = catalog_tmpl.Execute(catalogFile, map[string]interface{}{
|
||||
if err = catalogTmpl.Execute(catalogFile, map[string]interface{}{
|
||||
"boards": allBoards,
|
||||
"config": config,
|
||||
"board": board,
|
||||
|
@ -453,7 +470,7 @@ func buildThreadPages(op *Post) (html string) {
|
|||
}
|
||||
|
||||
// render main page
|
||||
if err = img_threadpage_tmpl.Execute(current_page_file, map[string]interface{}{
|
||||
if err = threadpageTmpl.Execute(current_page_file, map[string]interface{}{
|
||||
"config": config,
|
||||
"boards": allBoards,
|
||||
"board": board,
|
||||
|
@ -504,7 +521,7 @@ func buildThreadPages(op *Post) (html string) {
|
|||
return
|
||||
}
|
||||
|
||||
if err = img_threadpage_tmpl.Execute(current_page_file, map[string]interface{}{
|
||||
if err = threadpageTmpl.Execute(current_page_file, map[string]interface{}{
|
||||
"config": config,
|
||||
"boards": allBoards,
|
||||
"board": board,
|
||||
|
|
|
@ -93,7 +93,7 @@ func serveCaptcha(writer http.ResponseWriter, request *http.Request) {
|
|||
captchaStruct.Result = "Incorrect CAPTCHA"
|
||||
}
|
||||
}
|
||||
if err = captcha_tmpl.Execute(writer, captchaStruct); err != nil {
|
||||
if err = captchaTmpl.Execute(writer, captchaStruct); err != nil {
|
||||
handleError(0, customError(err))
|
||||
fmt.Fprintf(writer, "Error executing captcha template")
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ func main() {
|
|||
handleError(0, customError(err))
|
||||
os.Exit(2)
|
||||
}
|
||||
println(1, buildJSConstants())
|
||||
initCaptcha()
|
||||
tempCleanerTicker = time.NewTicker(time.Minute * 5)
|
||||
go tempCleaner()
|
||||
|
|
|
@ -47,7 +47,7 @@ func callManageFunction(writer http.ResponseWriter, request *http.Request) {
|
|||
|
||||
if action != "getstaffjquery" && action != "postinfo" {
|
||||
managePageBuffer.WriteString("<!DOCTYPE html>\n<html>\n<head>\n")
|
||||
if err = manage_header_tmpl.Execute(&managePageBuffer, config); err != nil {
|
||||
if err = manageHeaderTmpl.Execute(&managePageBuffer, config); err != nil {
|
||||
handleError(0, customError(err))
|
||||
fmt.Fprintf(writer, mangePageHTML+err.Error()+"\n</body>\n</html>")
|
||||
return
|
||||
|
@ -419,11 +419,12 @@ var manage_functions = map[string]ManageFunction{
|
|||
status = "Error writing gochan.json: %s\n" + err.Error()
|
||||
} else {
|
||||
status = "Wrote gochan.json successfully <br />"
|
||||
buildJSConstants()
|
||||
}
|
||||
}
|
||||
}
|
||||
manageConfigBuffer := bytes.NewBufferString("")
|
||||
if err := manage_config_tmpl.Execute(manageConfigBuffer,
|
||||
if err := manageConfigTmpl.Execute(manageConfigBuffer,
|
||||
map[string]interface{}{"config": config, "status": status},
|
||||
); err != nil {
|
||||
html += handleError(1, err.Error())
|
||||
|
@ -668,7 +669,7 @@ var manage_functions = map[string]ManageFunction{
|
|||
}
|
||||
manageBansBuffer := bytes.NewBufferString("")
|
||||
|
||||
if err := manage_bans_tmpl.Execute(manageBansBuffer,
|
||||
if err := manageBansTmpl.Execute(manageBansBuffer,
|
||||
map[string]interface{}{"config": config, "banlist": banlist, "post": post},
|
||||
); err != nil {
|
||||
pageHTML += handleError(1, err.Error())
|
||||
|
@ -880,7 +881,7 @@ var manage_functions = map[string]ManageFunction{
|
|||
}
|
||||
allSections, _ = getSectionArr("")
|
||||
|
||||
if err := manage_boards_tmpl.Execute(manageBoardsBuffer, map[string]interface{}{
|
||||
if err := manageBoardsTmpl.Execute(manageBoardsBuffer, map[string]interface{}{
|
||||
"config": config,
|
||||
"board": board,
|
||||
"section_arr": allSections,
|
||||
|
@ -937,7 +938,8 @@ var manage_functions = map[string]ManageFunction{
|
|||
resetBoardSectionArrays()
|
||||
return buildFrontPage() + "<hr />\n" +
|
||||
buildBoardListJSON() + "<hr />\n" +
|
||||
buildBoards() + "<hr />\n"
|
||||
buildBoards() + "<hr />\n" +
|
||||
buildJSConstants() + "<hr />\n"
|
||||
}},
|
||||
"rebuildboards": {
|
||||
Permissions: 3,
|
||||
|
|
293
src/posting.go
293
src/posting.go
|
@ -395,165 +395,162 @@ func makePost(writer http.ResponseWriter, request *http.Request) {
|
|||
if err != nil {
|
||||
serveErrorPage(writer, handleError(1, "Couldn't read file: "+err.Error()))
|
||||
return
|
||||
} else {
|
||||
post.FilenameOriginal = html.EscapeString(handler.Filename)
|
||||
filetype := getFileExtension(post.FilenameOriginal)
|
||||
thumbFiletype := strings.ToLower(filetype)
|
||||
if thumbFiletype == "gif" || thumbFiletype == "webm" {
|
||||
thumbFiletype = "jpg"
|
||||
}
|
||||
}
|
||||
|
||||
post.Filename = getNewFilename() + "." + getFileExtension(post.FilenameOriginal)
|
||||
boardArr, _ := getBoardArr(map[string]interface{}{"id": request.FormValue("boardid")}, "")
|
||||
if len(boardArr) == 0 {
|
||||
serveErrorPage(writer, "No boards have been created yet")
|
||||
return
|
||||
}
|
||||
_boardDir, _ := getBoardArr(map[string]interface{}{"id": request.FormValue("boardid")}, "")
|
||||
boardDir := _boardDir[0].Dir
|
||||
filePath := path.Join(config.DocumentRoot, "/"+boardDir+"/src/", post.Filename)
|
||||
thumbPath := path.Join(config.DocumentRoot, "/"+boardDir+"/thumb/", strings.Replace(post.Filename, "."+filetype, "t."+thumbFiletype, -1))
|
||||
catalogThumbPath := path.Join(config.DocumentRoot, "/"+boardDir+"/thumb/", strings.Replace(post.Filename, "."+filetype, "c."+thumbFiletype, -1))
|
||||
post.FilenameOriginal = html.EscapeString(handler.Filename)
|
||||
filetype := getFileExtension(post.FilenameOriginal)
|
||||
thumbFiletype := strings.ToLower(filetype)
|
||||
if thumbFiletype == "gif" || thumbFiletype == "webm" {
|
||||
thumbFiletype = "jpg"
|
||||
}
|
||||
|
||||
if err = ioutil.WriteFile(filePath, data, 0777); err != nil {
|
||||
handleError(0, "Couldn't write file '%s': %s\n", post.Filename, err.Error())
|
||||
serveErrorPage(writer, "Couldn't write file \""+post.FilenameOriginal+"\"")
|
||||
post.Filename = getNewFilename() + "." + getFileExtension(post.FilenameOriginal)
|
||||
boardArr, _ := getBoardArr(map[string]interface{}{"id": request.FormValue("boardid")}, "")
|
||||
if len(boardArr) == 0 {
|
||||
serveErrorPage(writer, "No boards have been created yet")
|
||||
return
|
||||
}
|
||||
_boardDir, _ := getBoardArr(map[string]interface{}{"id": request.FormValue("boardid")}, "")
|
||||
boardDir := _boardDir[0].Dir
|
||||
filePath := path.Join(config.DocumentRoot, "/"+boardDir+"/src/", post.Filename)
|
||||
thumbPath := path.Join(config.DocumentRoot, "/"+boardDir+"/thumb/", strings.Replace(post.Filename, "."+filetype, "t."+thumbFiletype, -1))
|
||||
catalogThumbPath := path.Join(config.DocumentRoot, "/"+boardDir+"/thumb/", strings.Replace(post.Filename, "."+filetype, "c."+thumbFiletype, -1))
|
||||
|
||||
if err = ioutil.WriteFile(filePath, data, 0777); err != nil {
|
||||
handleError(0, "Couldn't write file '%s': %s\n", post.Filename, err.Error())
|
||||
serveErrorPage(writer, "Couldn't write file \""+post.FilenameOriginal+"\"")
|
||||
return
|
||||
}
|
||||
|
||||
// Calculate image checksum
|
||||
post.FileChecksum = fmt.Sprintf("%x", md5.Sum(data))
|
||||
|
||||
var allowsVids bool
|
||||
if err = queryRowSQL("SELECT embeds_allowed FROM "+config.DBprefix+"boards WHERE id = ? LIMIT 1",
|
||||
[]interface{}{post.BoardID},
|
||||
[]interface{}{&allowsVids},
|
||||
); err != nil {
|
||||
serveErrorPage(writer, handleError(1, "Couldn't get board info: "+err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
if filetype == "webm" {
|
||||
if !allowsVids || !config.AllowVideoUploads {
|
||||
serveErrorPage(writer, "Video uploading is not currently enabled for this board.")
|
||||
os.Remove(filePath)
|
||||
return
|
||||
}
|
||||
|
||||
// Calculate image checksum
|
||||
post.FileChecksum = fmt.Sprintf("%x", md5.Sum(data))
|
||||
|
||||
var allowsVids bool
|
||||
if err = queryRowSQL("SELECT embeds_allowed FROM "+config.DBprefix+"boards WHERE id = ? LIMIT 1",
|
||||
[]interface{}{post.BoardID},
|
||||
[]interface{}{&allowsVids},
|
||||
); err != nil {
|
||||
serveErrorPage(writer, handleError(1, "Couldn't get board info: "+err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
if filetype == "webm" {
|
||||
if !allowsVids || !config.AllowVideoUploads {
|
||||
serveErrorPage(writer, "Video uploading is not currently enabled for this board.")
|
||||
os.Remove(filePath)
|
||||
return
|
||||
}
|
||||
|
||||
accessLog.Printf("Receiving post with video: %s from %s, referrer: %s", handler.Filename, post.IP, request.Referer())
|
||||
if post.ParentID == 0 {
|
||||
if err := createVideoThumbnail(filePath, thumbPath, config.ThumbWidth); err != nil {
|
||||
serveErrorPage(writer, handleError(1, err.Error()))
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if err := createVideoThumbnail(filePath, thumbPath, config.ThumbWidth_reply); err != nil {
|
||||
serveErrorPage(writer, handleError(1, err.Error()))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if err := createVideoThumbnail(filePath, catalogThumbPath, config.ThumbWidth_catalog); err != nil {
|
||||
accessLog.Printf("Receiving post with video: %s from %s, referrer: %s", handler.Filename, post.IP, request.Referer())
|
||||
if post.ParentID == 0 {
|
||||
if err := createVideoThumbnail(filePath, thumbPath, config.ThumbWidth); err != nil {
|
||||
serveErrorPage(writer, handleError(1, err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
outputBytes, err := exec.Command("ffprobe", "-v", "quiet", "-show_format", "-show_streams", filePath).CombinedOutput()
|
||||
if err != nil {
|
||||
serveErrorPage(writer, handleError(1, "Error getting video info: "+err.Error()))
|
||||
return
|
||||
}
|
||||
if outputBytes != nil {
|
||||
outputStringArr := strings.Split(string(outputBytes), "\n")
|
||||
for _, line := range outputStringArr {
|
||||
lineArr := strings.Split(line, "=")
|
||||
if len(lineArr) < 2 {
|
||||
continue
|
||||
}
|
||||
value, _ := strconv.Atoi(lineArr[1])
|
||||
switch lineArr[0] {
|
||||
case "width":
|
||||
post.ImageW = value
|
||||
case "height":
|
||||
post.ImageH = value
|
||||
case "size":
|
||||
post.Filesize = value
|
||||
}
|
||||
}
|
||||
if post.ParentID == 0 {
|
||||
post.ThumbW, post.ThumbH = getThumbnailSize(post.ImageW, post.ImageH, "op")
|
||||
} else {
|
||||
post.ThumbW, post.ThumbH = getThumbnailSize(post.ImageW, post.ImageH, "reply")
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// Attempt to load uploaded file with imaging library
|
||||
img, err := imaging.Open(filePath)
|
||||
if err != nil {
|
||||
os.Remove(filePath)
|
||||
handleError(1, "Couldn't open uploaded file \""+post.Filename+"\""+err.Error())
|
||||
handleError(1, "Couldn't open uploaded file \"%s\": %s\n", post.Filename, err.Error())
|
||||
serveErrorPage(writer, "Upload filetype not supported")
|
||||
if err := createVideoThumbnail(filePath, thumbPath, config.ThumbWidth_reply); err != nil {
|
||||
serveErrorPage(writer, handleError(1, err.Error()))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if err := createVideoThumbnail(filePath, catalogThumbPath, config.ThumbWidth_catalog); err != nil {
|
||||
serveErrorPage(writer, handleError(1, err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
outputBytes, err := exec.Command("ffprobe", "-v", "quiet", "-show_format", "-show_streams", filePath).CombinedOutput()
|
||||
if err != nil {
|
||||
serveErrorPage(writer, handleError(1, "Error getting video info: "+err.Error()))
|
||||
return
|
||||
}
|
||||
if outputBytes != nil {
|
||||
outputStringArr := strings.Split(string(outputBytes), "\n")
|
||||
for _, line := range outputStringArr {
|
||||
lineArr := strings.Split(line, "=")
|
||||
if len(lineArr) < 2 {
|
||||
continue
|
||||
}
|
||||
value, _ := strconv.Atoi(lineArr[1])
|
||||
switch lineArr[0] {
|
||||
case "width":
|
||||
post.ImageW = value
|
||||
case "height":
|
||||
post.ImageH = value
|
||||
case "size":
|
||||
post.Filesize = value
|
||||
}
|
||||
}
|
||||
if post.ParentID == 0 {
|
||||
post.ThumbW, post.ThumbH = getThumbnailSize(post.ImageW, post.ImageH, "op")
|
||||
} else {
|
||||
// Get image filesize
|
||||
stat, err := os.Stat(filePath)
|
||||
if err != nil {
|
||||
serveErrorPage(writer, handleError(1, "Couldn't get image filesize: "+err.Error()))
|
||||
post.ThumbW, post.ThumbH = getThumbnailSize(post.ImageW, post.ImageH, "reply")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Attempt to load uploaded file with imaging library
|
||||
img, err := imaging.Open(filePath)
|
||||
if err != nil {
|
||||
os.Remove(filePath)
|
||||
handleError(1, "Couldn't open uploaded file \""+post.Filename+"\""+err.Error())
|
||||
handleError(1, "Couldn't open uploaded file \"%s\": %s\n", post.Filename, err.Error())
|
||||
serveErrorPage(writer, "Upload filetype not supported")
|
||||
return
|
||||
}
|
||||
// Get image filesize
|
||||
stat, err := os.Stat(filePath)
|
||||
if err != nil {
|
||||
serveErrorPage(writer, handleError(1, "Couldn't get image filesize: "+err.Error()))
|
||||
return
|
||||
}
|
||||
post.Filesize = int(stat.Size())
|
||||
|
||||
// Get image width and height, as well as thumbnail width and height
|
||||
post.ImageW = img.Bounds().Max.X
|
||||
post.ImageH = img.Bounds().Max.Y
|
||||
if post.ParentID == 0 {
|
||||
post.ThumbW, post.ThumbH = getThumbnailSize(post.ImageW, post.ImageH, "op")
|
||||
} else {
|
||||
post.ThumbW, post.ThumbH = getThumbnailSize(post.ImageW, post.ImageH, "reply")
|
||||
}
|
||||
|
||||
accessLog.Print("Receiving post with image: " + handler.Filename + " from " + post.IP + ", referrer: " + request.Referer())
|
||||
|
||||
if request.FormValue("spoiler") == "on" {
|
||||
// If spoiler is enabled, symlink thumbnail to spoiler image
|
||||
if _, err := os.Stat(path.Join(config.DocumentRoot, "spoiler.png")); err != nil {
|
||||
serveErrorPage(writer, "missing /spoiler.png")
|
||||
return
|
||||
}
|
||||
if err = syscall.Symlink(path.Join(config.DocumentRoot, "spoiler.png"), thumbPath); err != nil {
|
||||
serveErrorPage(writer, err.Error())
|
||||
return
|
||||
}
|
||||
} else if config.ThumbWidth >= post.ImageW && config.ThumbHeight >= post.ImageH {
|
||||
// If image fits in thumbnail size, symlink thumbnail to original
|
||||
post.ThumbW = img.Bounds().Max.X
|
||||
post.ThumbH = img.Bounds().Max.Y
|
||||
if err := syscall.Symlink(filePath, thumbPath); err != nil {
|
||||
serveErrorPage(writer, err.Error())
|
||||
return
|
||||
}
|
||||
} else {
|
||||
var thumbnail image.Image
|
||||
var catalogThumbnail image.Image
|
||||
if post.ParentID == 0 {
|
||||
// If this is a new thread, generate thumbnail and catalog thumbnail
|
||||
thumbnail = createImageThumbnail(img, "op")
|
||||
catalogThumbnail = createImageThumbnail(img, "catalog")
|
||||
if err = imaging.Save(catalogThumbnail, catalogThumbPath); err != nil {
|
||||
serveErrorPage(writer, handleError(1, "Couldn't generate catalog thumbnail: "+err.Error()))
|
||||
return
|
||||
} else {
|
||||
post.Filesize = int(stat.Size())
|
||||
}
|
||||
|
||||
// Get image width and height, as well as thumbnail width and height
|
||||
post.ImageW = img.Bounds().Max.X
|
||||
post.ImageH = img.Bounds().Max.Y
|
||||
if post.ParentID == 0 {
|
||||
post.ThumbW, post.ThumbH = getThumbnailSize(post.ImageW, post.ImageH, "op")
|
||||
} else {
|
||||
post.ThumbW, post.ThumbH = getThumbnailSize(post.ImageW, post.ImageH, "reply")
|
||||
}
|
||||
|
||||
accessLog.Print("Receiving post with image: " + handler.Filename + " from " + post.IP + ", referrer: " + request.Referer())
|
||||
|
||||
if request.FormValue("spoiler") == "on" {
|
||||
// If spoiler is enabled, symlink thumbnail to spoiler image
|
||||
if _, err := os.Stat(path.Join(config.DocumentRoot, "spoiler.png")); err != nil {
|
||||
serveErrorPage(writer, "missing /spoiler.png")
|
||||
return
|
||||
}
|
||||
if err = syscall.Symlink(path.Join(config.DocumentRoot, "spoiler.png"), thumbPath); err != nil {
|
||||
serveErrorPage(writer, err.Error())
|
||||
return
|
||||
}
|
||||
} else if config.ThumbWidth >= post.ImageW && config.ThumbHeight >= post.ImageH {
|
||||
// If image fits in thumbnail size, symlink thumbnail to original
|
||||
post.ThumbW = img.Bounds().Max.X
|
||||
post.ThumbH = img.Bounds().Max.Y
|
||||
if err := syscall.Symlink(filePath, thumbPath); err != nil {
|
||||
serveErrorPage(writer, err.Error())
|
||||
return
|
||||
}
|
||||
} else {
|
||||
var thumbnail image.Image
|
||||
var catalogThumbnail image.Image
|
||||
if post.ParentID == 0 {
|
||||
// If this is a new thread, generate thumbnail and catalog thumbnail
|
||||
thumbnail = createImageThumbnail(img, "op")
|
||||
catalogThumbnail = createImageThumbnail(img, "catalog")
|
||||
if err = imaging.Save(catalogThumbnail, catalogThumbPath); err != nil {
|
||||
serveErrorPage(writer, handleError(1, "Couldn't generate catalog thumbnail: "+err.Error()))
|
||||
return
|
||||
}
|
||||
} else {
|
||||
thumbnail = createImageThumbnail(img, "reply")
|
||||
}
|
||||
if err = imaging.Save(thumbnail, thumbPath); err != nil {
|
||||
serveErrorPage(writer, handleError(1, "Couldn't save thumbnail: "+err.Error()))
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
thumbnail = createImageThumbnail(img, "reply")
|
||||
}
|
||||
if err = imaging.Save(thumbnail, thumbPath); err != nil {
|
||||
serveErrorPage(writer, handleError(1, "Couldn't save thumbnail: "+err.Error()))
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -588,7 +585,7 @@ func makePost(writer http.ResponseWriter, request *http.Request) {
|
|||
var banpageBuffer bytes.Buffer
|
||||
|
||||
banpageBuffer.Write([]byte(""))
|
||||
if err = banpage_tmpl.Execute(&banpageBuffer, map[string]interface{}{
|
||||
if err = banpageTmpl.Execute(&banpageBuffer, map[string]interface{}{
|
||||
"config": config, "ban": banStatus, "banBoards": boards[post.BoardID-1].Dir,
|
||||
}); err != nil {
|
||||
fmt.Fprintf(writer, handleError(1, err.Error()))
|
||||
|
@ -755,7 +752,7 @@ func banHandler(writer http.ResponseWriter, request *http.Request) {
|
|||
var banpageBuffer bytes.Buffer
|
||||
|
||||
banpageBuffer.Write([]byte(""))
|
||||
if err = banpage_tmpl.Execute(&banpageBuffer, map[string]interface{}{
|
||||
if err = banpageTmpl.Execute(&banpageBuffer, map[string]interface{}{
|
||||
"config": config, "ban": banStatus, "banBoards": banStatus.Boards, "post": Post{},
|
||||
}); err != nil {
|
||||
fmt.Fprintf(writer, handleError(1, err.Error())+"\n</body>\n</html>")
|
||||
|
|
|
@ -103,7 +103,7 @@ func serveNotFound(writer http.ResponseWriter, request *http.Request) {
|
|||
}
|
||||
|
||||
func serveErrorPage(writer http.ResponseWriter, err string) {
|
||||
errorpage_tmpl.Execute(writer, map[string]interface{}{
|
||||
errorpageTmpl.Execute(writer, map[string]interface{}{
|
||||
"config": config,
|
||||
"ErrorTitle": "Error :c",
|
||||
// "ErrorImage": "/error/lol 404.gif",
|
||||
|
@ -241,7 +241,7 @@ func utilHandler(writer http.ResponseWriter, request *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
if err = post_edit_tmpl.Execute(writer, map[string]interface{}{
|
||||
if err = postEditTmpl.Execute(writer, map[string]interface{}{
|
||||
"config": config,
|
||||
"post": post,
|
||||
"referrer": request.Referer(),
|
||||
|
|
|
@ -145,6 +145,7 @@ func initDB(initFile string) error {
|
|||
for _, statement := range sqlArr {
|
||||
if statement != "" && statement != " " {
|
||||
if _, err := db.Exec(statement + ";"); err != nil {
|
||||
panic("Error with SQL statement:" + statement)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,14 +42,14 @@ var funcMap = template.FuncMap{
|
|||
},
|
||||
|
||||
// Array functions
|
||||
"getSlice": func(arr []interface{}, start, end int) []interface{} {
|
||||
slice := arr[start:end]
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
slice = make([]interface{}, 1)
|
||||
}
|
||||
}()
|
||||
return slice
|
||||
"getSlice": func(arr []interface{}, start, length int) []interface{} {
|
||||
if start < 0 {
|
||||
start = 0
|
||||
}
|
||||
if length > len(arr) {
|
||||
length = len(arr)
|
||||
}
|
||||
return arr[start:length]
|
||||
},
|
||||
"len": func(arr []interface{}) int {
|
||||
return len(arr)
|
||||
|
@ -290,19 +290,20 @@ var funcMap = template.FuncMap{
|
|||
}
|
||||
|
||||
var (
|
||||
banpage_tmpl *template.Template
|
||||
captcha_tmpl *template.Template
|
||||
catalog_tmpl *template.Template
|
||||
errorpage_tmpl *template.Template
|
||||
front_page_tmpl *template.Template
|
||||
img_boardpage_tmpl *template.Template
|
||||
img_threadpage_tmpl *template.Template
|
||||
img_post_form_tmpl *template.Template
|
||||
manage_bans_tmpl *template.Template
|
||||
manage_boards_tmpl *template.Template
|
||||
manage_config_tmpl *template.Template
|
||||
manage_header_tmpl *template.Template
|
||||
post_edit_tmpl *template.Template
|
||||
banpageTmpl *template.Template
|
||||
captchaTmpl *template.Template
|
||||
catalogTmpl *template.Template
|
||||
errorpageTmpl *template.Template
|
||||
frontPageTmpl *template.Template
|
||||
boardpageTmpl *template.Template
|
||||
threadpageTmpl *template.Template
|
||||
postFormTmpl *template.Template
|
||||
postEditTmpl *template.Template
|
||||
manageBansTmpl *template.Template
|
||||
manageBoardsTmpl *template.Template
|
||||
manageConfigTmpl *template.Template
|
||||
manageHeaderTmpl *template.Template
|
||||
jsTmpl *template.Template
|
||||
)
|
||||
|
||||
func loadTemplate(files ...string) (*template.Template, error) {
|
||||
|
@ -332,77 +333,83 @@ func initTemplates(which ...string) error {
|
|||
resetBoardSectionArrays()
|
||||
for _, t := range which {
|
||||
if buildAll || t == "banpage" {
|
||||
banpage_tmpl, err = loadTemplate("banpage.html", "global_footer.html")
|
||||
banpageTmpl, err = loadTemplate("banpage.html", "page_footer.html")
|
||||
if err != nil {
|
||||
return templateError("banpage.html", err)
|
||||
}
|
||||
}
|
||||
if buildAll || t == "captcha" {
|
||||
captcha_tmpl, err = loadTemplate("captcha.html")
|
||||
captchaTmpl, err = loadTemplate("captcha.html")
|
||||
if err != nil {
|
||||
return templateError("captcha.html", err)
|
||||
}
|
||||
}
|
||||
if buildAll || t == "catalog" {
|
||||
catalog_tmpl, err = loadTemplate("catalog.html", "img_header.html", "global_footer.html")
|
||||
catalogTmpl, err = loadTemplate("catalog.html", "page_header.html", "page_footer.html")
|
||||
if err != nil {
|
||||
return templateError("catalog.html", err)
|
||||
}
|
||||
}
|
||||
if buildAll || t == "error" {
|
||||
errorpage_tmpl, err = loadTemplate("error.html")
|
||||
errorpageTmpl, err = loadTemplate("error.html")
|
||||
if err != nil {
|
||||
return templateError("error.html", err)
|
||||
}
|
||||
}
|
||||
if buildAll || t == "front" {
|
||||
front_page_tmpl, err = loadTemplate("front.html", "front_intro.html", "img_header.html", "global_footer.html")
|
||||
frontPageTmpl, err = loadTemplate("front.html", "front_intro.html", "page_header.html", "page_footer.html")
|
||||
if err != nil {
|
||||
return templateError("front.html", err)
|
||||
}
|
||||
}
|
||||
if buildAll || t == "boardpage" {
|
||||
img_boardpage_tmpl, err = loadTemplate("img_boardpage.html", "img_header.html", "postbox.html", "global_footer.html")
|
||||
boardpageTmpl, err = loadTemplate("boardpage.html", "page_header.html", "postbox.html", "page_footer.html")
|
||||
if err != nil {
|
||||
return templateError("img_boardpage.html", err)
|
||||
return templateError("boardpage.html", err)
|
||||
}
|
||||
}
|
||||
if buildAll || t == "threadpage" {
|
||||
img_threadpage_tmpl, err = loadTemplate("img_threadpage.html", "img_header.html", "postbox.html", "global_footer.html")
|
||||
threadpageTmpl, err = loadTemplate("threadpage.html", "page_header.html", "postbox.html", "page_footer.html")
|
||||
if err != nil {
|
||||
return templateError("img_threadpage.html", err)
|
||||
return templateError("threadpage.html", err)
|
||||
}
|
||||
}
|
||||
if buildAll || t == "postedit" {
|
||||
post_edit_tmpl, err = loadTemplate("post_edit.html", "img_header.html", "global_footer.html")
|
||||
postEditTmpl, err = loadTemplate("post_edit.html", "page_header.html", "page_footer.html")
|
||||
if err != nil {
|
||||
return templateError("img_threadpage.html", err)
|
||||
return templateError("threadpage.html", err)
|
||||
}
|
||||
}
|
||||
if buildAll || t == "managebans" {
|
||||
manage_bans_tmpl, err = loadTemplate("manage_bans.html")
|
||||
manageBansTmpl, err = loadTemplate("manage_bans.html")
|
||||
if err != nil {
|
||||
return templateError("manage_bans.html", err)
|
||||
}
|
||||
}
|
||||
if buildAll || t == "manageboards" {
|
||||
manage_boards_tmpl, err = loadTemplate("manage_boards.html")
|
||||
manageBoardsTmpl, err = loadTemplate("manage_boards.html")
|
||||
if err != nil {
|
||||
return templateError("manage_boards.html", err)
|
||||
}
|
||||
}
|
||||
if buildAll || t == "manageconfig" {
|
||||
manage_config_tmpl, err = loadTemplate("manage_config.html")
|
||||
manageConfigTmpl, err = loadTemplate("manage_config.html")
|
||||
if err != nil {
|
||||
return templateError("manage_config.html", err)
|
||||
}
|
||||
}
|
||||
if buildAll || t == "manageheader" {
|
||||
manage_header_tmpl, err = loadTemplate("manage_header.html")
|
||||
manageHeaderTmpl, err = loadTemplate("manage_header.html")
|
||||
if err != nil {
|
||||
return templateError("manage_header.html", err)
|
||||
}
|
||||
}
|
||||
if buildAll || t == "js" {
|
||||
jsTmpl, err = loadTemplate("consts.js")
|
||||
if err != nil {
|
||||
return templateError("consts.js", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -5,14 +5,10 @@
|
|||
<link rel="shortcut icon" href="{{.config.SiteWebfolder}}favicon.png">
|
||||
<link rel="stylesheet" href="{{.config.SiteWebfolder}}css/global.css" />
|
||||
<link id="theme" rel="stylesheet" href="{{.config.SiteWebfolder}}css/{{.config.DefaultStyle}}" />
|
||||
<script type="text/javascript">
|
||||
var styles = [{{range $ii, $style := .config.Styles}}{{if gt $ii 0}}, {{end}}{Name: "{{$style.Name}}", Filename: "{{$style.Filename}}"}{{end}}];
|
||||
var defaultStyle = "{{.config.DefaultStyle}}";
|
||||
var webroot = "{{.config.SiteWebfolder}}"
|
||||
</script>
|
||||
<script type="text/javascript" src="/javascript/jquery-3.3.1.min.js"></script>
|
||||
<script type="text/javascript" src="/javascript/gochan.js"></script>
|
||||
<script type="text/javascript" src="/javascript/manage.js"></script>
|
||||
<script type="text/javascript" src="{{.config.SiteWebfolder}}javascript/consts.js"></script>
|
||||
<script type="text/javascript" src="{{.config.SiteWebfolder}}javascript/jquery-3.3.1.min.js"></script>
|
||||
<script type="text/javascript" src="{{.config.SiteWebfolder}}javascript/gochan.js"></script>
|
||||
<script type="text/javascript" src="{{.config.SiteWebfolder}}javascript/manage.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="top-pane">
|
||||
|
@ -51,4 +47,4 @@
|
|||
<img id="banpage-image" src="/banned.jpg" style="float:right; margin: 4px 8px 8px 4px"/><br />{{end}}
|
||||
{{end}}</div>
|
||||
</div>
|
||||
{{template "global_footer.html" .}}
|
||||
{{template "page_footer.html" .}}
|
|
@ -1,4 +1,4 @@
|
|||
{{template "img_header.html" .}}
|
||||
{{template "page_header.html" .}}
|
||||
<header>
|
||||
<h1 id="board-title">/{{$.board.Dir}}/ - {{$.board.Title}}</h1>
|
||||
<span id="board-subtitle">{{$.board.Subtitle}}</span>
|
||||
|
@ -79,4 +79,4 @@
|
|||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{{template "global_footer.html" .}}
|
||||
{{template "page_footer.html" .}}
|
|
@ -1,4 +1,4 @@
|
|||
{{template "img_header.html" .}}
|
||||
{{template "page_header.html" .}}
|
||||
<header>
|
||||
<h1>/{{$.board.Dir}}/ - {{$.board.Title}}</h1>
|
||||
<span id="board-subtitle">Catalog</span>
|
||||
|
@ -24,4 +24,4 @@
|
|||
{{$thread.MessageHTML}}
|
||||
</div>{{end}}{{end}}
|
||||
</div><hr />
|
||||
{{template "global_footer.html" .}}
|
||||
{{template "page_footer.html" .}}
|
||||
|
|
10
templates/consts.js
Normal file
10
templates/consts.js
Normal file
|
@ -0,0 +1,10 @@
|
|||
{{/*
|
||||
This will be used for storing configuration-dependent JS variables,
|
||||
instead of loading them on every HTML page.
|
||||
*/ -}}
|
||||
var styles = [{{range $ii, $style := .Styles -}}
|
||||
{{if gt $ii 0}}, {{end -}}
|
||||
{Name: "{{js $style.Name}}", Filename: "{{js $style.Filename}}"}
|
||||
{{- end}}];
|
||||
var defaultStyle = "{{.DefaultStyle}}";
|
||||
var webroot = "{{.SiteWebfolder}}";
|
|
@ -1,4 +1,4 @@
|
|||
{{template "img_header.html" .}}
|
||||
{{template "page_header.html" .}}
|
||||
<div id="top-pane">
|
||||
<span id="site-title">{{.config.SiteName}}</span><br />
|
||||
<span id="site-slogan">{{.config.SiteSlogan}}</span>
|
||||
|
@ -34,4 +34,4 @@
|
|||
{{truncateMessage (stripHTML $post.Message) 40 4}}</div>{{end}}</div>
|
||||
</div>{{end}}</div>
|
||||
</div>
|
||||
{{template "global_footer.html" .}}
|
||||
{{template "page_footer.html" .}}
|
||||
|
|
|
@ -11,16 +11,7 @@
|
|||
{{else}}<title>/{{$.board.Dir}}/ - {{$.board.Title}}</title>{{end}}
|
||||
{{else}}<title>{{.config.SiteName}}</title>{{end}}
|
||||
<script type="text/javascript" src="{{$.config.SiteWebfolder}}javascript/jquery-3.3.1.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
var styles = [{{range $ii, $style := .config.Styles}}{{if gt $ii 0}}, {{end}}{Name: "{{$style.Name}}", Filename: "{{$style.Filename}}"}{{end}}];
|
||||
var defaultStyle = "{{$.config.DefaultStyle}}";
|
||||
var webroot = "{{$.config.SiteWebfolder}}";
|
||||
var thread_type = "thread";
|
||||
|
||||
function changePage(sel) {
|
||||
window.location = webroot+"{{$.board.Dir}}/res/{{$.op.ID}}p"+sel.value+".html";
|
||||
}
|
||||
</script>
|
||||
<script type="text/javascript" src="{{$.config.SiteWebfolder}}javascript/consts.js"></script>
|
||||
<script type="text/javascript" src="{{$.config.SiteWebfolder}}javascript/gochan.js"></script>
|
||||
<script type="text/javascript" src="{{$.config.SiteWebfolder}}javascript/manage.js"></script>
|
||||
<link rel="stylesheet" href="{{.config.SiteWebfolder}}css/global.css" />
|
|
@ -1,4 +1,4 @@
|
|||
{{template "img_header.html" .}}
|
||||
{{template "page_header.html" .}}
|
||||
<header>
|
||||
<h1>Edit post</h1><br />
|
||||
<div class="subtitle"><a href="{{.referrer}}">Return</a></div>
|
||||
|
@ -17,4 +17,4 @@
|
|||
<tr><th class="postblock">Message</th><td><textarea rows="4" cols="48" name="editmsg" id="editmsg">{{.post.MessageText}}</textarea></td></tr>
|
||||
</table>
|
||||
</form><br />
|
||||
{{template "global_footer.html" .}}
|
||||
{{template "page_footer.html" .}}
|
|
@ -1,4 +1,4 @@
|
|||
{{template "img_header.html" .}}
|
||||
{{template "page_header.html" .}}
|
||||
<header>
|
||||
<h1 id="board-title">/{{$.board.Dir}}/ - {{$.board.Title}}</h1>
|
||||
<span id="board-subtitle">{{$.board.Subtitle}}</span>
|
||||
|
@ -84,4 +84,4 @@
|
|||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{{template "global_footer.html" .}}
|
||||
{{template "page_footer.html" .}}
|
Loading…
Add table
Add a link
Reference in a new issue