1
0
Fork 0
mirror of https://github.com/Eggbertx/gochan.git synced 2025-08-24 08:46:24 -07:00

streamline row/stmt/file closing and error handling/printing

This commit is contained in:
Joshua Merrell 2018-02-17 19:21:22 -08:00
parent f39f55eda6
commit 9986bc8a6f
11 changed files with 490 additions and 666 deletions

View file

@ -28,20 +28,19 @@ func callManageFunction(w http.ResponseWriter, r *http.Request, data interface{}
staffRank := getStaffRank()
var managePageBuffer bytes.Buffer
mangePageHTML := ""
var err error
if action == "" {
action = "announcements"
}
err := global_header_tmpl.Execute(&managePageBuffer, config)
if err != nil {
if err = global_header_tmpl.Execute(&managePageBuffer, config); err != nil {
fmt.Fprintf(writer, mangePageHTML+err.Error()+"\n</body>\n</html>")
return
}
err = manage_header_tmpl.Execute(&managePageBuffer, config)
if err != nil {
fmt.Println(mangePageHTML)
if err = manage_header_tmpl.Execute(&managePageBuffer, config); err != nil {
println(0, mangePageHTML)
fmt.Fprintf(writer, mangePageHTML+err.Error()+"\n</body>\n</html>")
return
}
@ -79,8 +78,7 @@ func getCurrentStaff() (string, error) {
row := db.QueryRow("SELECT `data` FROM `" + config.DBprefix + "sessions` WHERE `key` = '" + key + "'")
current_session := new(SessionsTable)
err := row.Scan(&current_session.Data)
if err != nil {
if err := row.Scan(&current_session.Data); err != nil {
return "", err
}
return current_session.Data, nil
@ -104,7 +102,7 @@ func getStaffRank() int {
staff, err := getStaff(staffname)
if err != nil {
errorLog.Print(err.Error())
handleError(1, err.Error())
return 0
}
return staff.Rank
@ -123,8 +121,7 @@ func createSession(key string, username string, password string, request *http.R
}
staff, err := getStaff(username)
if err != nil {
fmt.Println(err.Error())
errorLog.Print(err.Error())
handleError(1, err.Error())
return 1
} else {
success := bcrypt.CompareHashAndPassword([]byte(staff.PasswordChecksum), []byte(password))
@ -138,12 +135,12 @@ func createSession(key string, username string, password string, request *http.R
http.SetCookie(*writer, cookie)
_, err := db.Exec("INSERT INTO `" + config.DBprefix + "sessions` (`key`, `data`, `expires`) VALUES('" + key + "','" + username + "', '" + getSpecificSQLDateTime(time.Now().Add(time.Duration(time.Hour*730))) + "')")
if err != nil {
errorLog.Print(err.Error())
handleError(1, err.Error())
return 2
}
_, err = db.Exec("UPDATE `" + config.DBprefix + "staff` SET `last_active` ='" + getSQLDateTime() + "' WHERE `username` = '" + username + "';")
if err != nil {
errorLog.Print(err.Error())
handleError(1, err.Error())
}
return 0
}
@ -177,7 +174,7 @@ var manage_functions = map[string]ManageFunction{
tableRows.Scan(&table)
_, err = db.Exec("OPTIMIZE TABLE " + table)
if err != nil {
html += err.Error()
html += handleError(1, err.Error()) + "<br />"
return
}
}
@ -209,9 +206,8 @@ var manage_functions = map[string]ManageFunction{
}
manageConfigBuffer := bytes.NewBufferString("")
err := renderTemplate(manage_config_tmpl, "manage_config", manageConfigBuffer)
if err != nil {
html += err.Error()
if err := renderTemplate(manage_config_tmpl, "manage_config", manageConfigBuffer); err != nil {
html += handleError(1, err.Error())
return
}
html += manageConfigBuffer.String()
@ -223,40 +219,34 @@ var manage_functions = map[string]ManageFunction{
html = "<img src=\"/css/purge.jpg\" />"
rows, err := db.Query("SELECT `dir` FROM `" + config.DBprefix + "boards`")
if err != nil {
html += err.Error()
html += handleError(1, err.Error())
return
}
var board string
for rows.Next() {
err = rows.Scan(&board)
if err != nil {
html += err.Error()
if err = rows.Scan(&board); err != nil {
html += handleError(1, err.Error())
return
}
_, err = deleteMatchingFiles(path.Join(config.DocumentRoot, board), ".html")
if err != nil {
html += err.Error()
if _, err = deleteMatchingFiles(path.Join(config.DocumentRoot, board), ".html"); err != nil {
html += handleError(1, err.Error())
return
}
_, err = deleteMatchingFiles(path.Join(config.DocumentRoot, board, "res"), ".*")
if err != nil {
html += err.Error()
if _, err = deleteMatchingFiles(path.Join(config.DocumentRoot, board, "res"), ".*"); err != nil {
html += handleError(1, err.Error())
return
}
_, err = deleteMatchingFiles(path.Join(config.DocumentRoot, board, "src"), ".*")
if err != nil {
html += err.Error()
if _, err = deleteMatchingFiles(path.Join(config.DocumentRoot, board, "src"), ".*"); err != nil {
html += handleError(1, err.Error())
return
}
_, err = deleteMatchingFiles(path.Join(config.DocumentRoot, board, "thumb"), ".*")
if err != nil {
html += err.Error()
if _, err = deleteMatchingFiles(path.Join(config.DocumentRoot, board, "thumb"), ".*"); err != nil {
html += handleError(1, err.Error())
return
}
}
_, err = db.Exec("TRUNCATE `" + config.DBprefix + "posts`")
if err != nil {
html += err.Error() + "<br />"
if _, err = db.Exec("TRUNCATE `" + config.DBprefix + "posts`"); err != nil {
html += handleError(1, err.Error()) + "<br />"
return
}
db.Exec("ALTER TABLE `" + config.DBprefix + "posts` AUTO_INCREMENT = 1")
@ -277,9 +267,7 @@ var manage_functions = map[string]ManageFunction{
println(1, &result)
if sqlerr != nil {
errortext := sqlerr.Error()
html += errortext
println(1, errortext)
html += handleError(1, sqlerr.Error())
} else {
html += "Statement esecuted successfully."
}
@ -345,8 +333,7 @@ var manage_functions = map[string]ManageFunction{
rows, err := db.Query("SELECT `subject`,`message`,`poster`,`timestamp` FROM `" + config.DBprefix + "announcements` ORDER BY `id` DESC;")
if err != nil {
errorLog.Print(err.Error())
html += err.Error()
html += handleError(1, err.Error())
return
}
iterations := 0
@ -354,7 +341,7 @@ var manage_functions = map[string]ManageFunction{
announcement := new(AnnouncementsTable)
err = rows.Scan(&announcement.Subject, &announcement.Message, &announcement.Poster, &announcement.Timestamp)
if err != nil {
html += err.Error()
html += handleError(1, err.Error())
} else {
html += "<div class=\"section-block\">\n" +
"<div class=\"section-title-block\"><b>" + announcement.Subject + "</b> by " + announcement.Poster + " at " + humanReadableTime(announcement.Timestamp) + "</div>\n" +
@ -381,14 +368,13 @@ var manage_functions = map[string]ManageFunction{
ban_which = "both"
}
// if none of these are true, we can assume that the page was loaded without sending anything
fmt.Println(ban_which)
println(0, "ban_which"+ban_which)
if ban_which == "user" {
//var banned_tripcode string
banned_ip := request.PostFormValue("ip")
if banned_ip != "" {
fmt.Println(banned_ip)
println(0, banned_ip)
}
}
@ -397,14 +383,13 @@ var manage_functions = map[string]ManageFunction{
rows, err := db.Query("SELECT `dir` FROM `" + config.DBprefix + "boards`;")
if err != nil {
html += "<hr />" + err.Error()
html += "<hr />" + handleError(1, err.Error())
return
}
var board_dir string
for rows.Next() {
err = rows.Scan(&board_dir)
if err != nil {
html += "<hr />" + err.Error()
if err = rows.Scan(&board_dir); err != nil {
html += "<hr />" + handleError(1, err.Error())
}
boards_list_html += " <label>/" + board_dir + "/ <input type=\"checkbox\" id=\"" + board_dir + "\" class=\"board-check\"/></label>&nbsp;&nbsp;\n"
}
@ -450,8 +435,7 @@ var manage_functions = map[string]ManageFunction{
rows, err = db.Query("SELECT * FROM `" + config.DBprefix + "banlist`")
if err != nil {
html += "</table><br />" + err.Error()
errorLog.Print(err.Error())
html += "</table><br />" + handleError(1, err.Error())
return
}
var ban BanlistTable
@ -459,14 +443,12 @@ var manage_functions = map[string]ManageFunction{
num_rows := 0
for rows.Next() {
if num_rows == 0 {
html += "<table width=\"100%%\" border=\"1\">\n" +
"<tr><th>IP</th><th>Name/Tripcode</th><th>Message</th><th>Date added</th><th>Added by</th><th>Reason</th><th>Expires/expired</th><th></th></tr>"
}
err = rows.Scan(&ban.ID, &ban.AllowRead, &ban.IP, &ban.Name, &ban.Tripcode, &ban.Message, &ban.SilentBan, &ban.Boards, &ban.BannedBy, &ban.Timestamp, &ban.Expires, &ban.Reason, &ban.StaffNote, &ban.AppealMessage, &ban.AppealAt)
if err != nil {
html += "</table><br />" + err.Error()
errorLog.Print(err.Error())
html += "</table><br />" + handleError(1, err.Error())
return
}
ban_name := ""
@ -475,7 +457,7 @@ var manage_functions = map[string]ManageFunction{
}
html += "<tr><td>" + ban.IP + "</td><td>" + ban_name + "</td><td>" + ban.Message + "</td><td>" + humanReadableTime(ban.Timestamp) + "</td><td>" + ban.BannedBy + "</td><td>" + ban.Reason + "</td><td>" + humanReadableTime(ban.Expires) + "</td><td>Delete</td></tr>"
num_rows += 1
num_rows++
}
if num_rows == 0 {
html += "No banned IPs"
@ -504,11 +486,8 @@ var manage_functions = map[string]ManageFunction{
}
row := db.QueryRow("SELECT `rank`,`boards` FROM `" + config.DBprefix + "staff` WHERE `username` = '" + current_staff + "'")
staff := new(StaffTable)
err = row.Scan(&staff.Rank, &staff.Boards)
if err != nil {
errorLog.Print("Error getting staff list: " + err.Error())
println(1, "Error getting staff list: "+err.Error())
html += err.Error()
if err = row.Scan(&staff.Rank, &staff.Boards); err != nil {
html += handleError(1, "Error getting staff list: "+err.Error())
return
}
html = current_staff + ";" + strconv.Itoa(staff.Rank) + ";" + staff.Boards
@ -599,31 +578,27 @@ var manage_functions = map[string]ManageFunction{
board.EnableCatalog = (request.FormValue("enablecatalog") == "on")
//actually start generating stuff
err = os.Mkdir(path.Join(config.DocumentRoot, board.Dir), 0777)
if err != nil {
if err = os.Mkdir(path.Join(config.DocumentRoot, board.Dir), 0777); err != nil {
do = ""
board_creation_status = "ERROR: directory /" + config.DocumentRoot + "/" + board.Dir + "/ already exists!"
board_creation_status = handleError(1, "ERROR: directory /"+config.DocumentRoot+"/"+board.Dir+"/ already exists!")
break
}
err = os.Mkdir(path.Join(config.DocumentRoot, board.Dir, "res"), 0777)
if err != nil {
if err = os.Mkdir(path.Join(config.DocumentRoot, board.Dir, "res"), 0777); err != nil {
do = ""
board_creation_status = "ERROR: directory /" + config.DocumentRoot + "/" + board.Dir + "/res/ already exists!"
board_creation_status = handleError(1, "ERROR: directory /"+config.DocumentRoot+"/"+board.Dir+"/res/ already exists!")
break
}
err = os.Mkdir(path.Join(config.DocumentRoot, board.Dir, "thumb"), 0777)
if err != nil {
if err = os.Mkdir(path.Join(config.DocumentRoot, board.Dir, "thumb"), 0777); err != nil {
do = ""
board_creation_status = "ERROR: directory /" + config.DocumentRoot + "/" + board.Dir + "/thumb/ already exists!"
board_creation_status = handleError(1, "ERROR: directory /"+config.DocumentRoot+"/"+board.Dir+"/thumb/ already exists!")
break
}
err = os.Mkdir(path.Join(config.DocumentRoot, board.Dir, "src"), 0777)
if err != nil {
if err = os.Mkdir(path.Join(config.DocumentRoot, board.Dir, "src"), 0777); err != nil {
do = ""
board_creation_status = "ERROR: directory /" + config.DocumentRoot + "/" + board.Dir + "/src/ already exists!"
board_creation_status = handleError(1, "ERROR: directory /"+config.DocumentRoot+"/"+board.Dir+"/src/ already exists!")
break
}
stmt, err := db.Prepare(
@ -632,21 +607,16 @@ var manage_functions = map[string]ManageFunction{
"`anonymous`,`forced_anon`,`max_age`,`autosage_after`,`no_images_after`,`max_message_length`,`embeds_allowed`," +
"`redirect_to_thread`,`require_file`,`enable_catalog`) " +
"VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)")
defer func() {
if stmt != nil {
stmt.Close()
}
}()
if err != nil {
do = ""
board_creation_status = err.Error()
board_creation_status = handleError(1, err.Error())
break
}
defer closeStatement(stmt)
boardCreationTimestamp := getSpecificSQLDateTime(board.CreatedOn)
_, err = stmt.Exec(
if _, err = stmt.Exec(
&board.Order, &board.Dir, &board.Type, &board.UploadType,
&board.Title, &board.Subtitle, &board.Description, &board.Section,
&board.MaxImageSize, &board.MaxPages, &board.Locale, &board.DefaultStyle,
@ -654,18 +624,17 @@ var manage_functions = map[string]ManageFunction{
&board.ForcedAnon, &board.MaxAge, &board.AutosageAfter,
&board.NoImagesAfter, &board.MaxMessageLength, &board.EmbedsAllowed,
&board.RedirectToThread, &board.RequireFile, &board.EnableCatalog,
)
if err != nil {
); err != nil {
do = ""
board_creation_status = err.Error()
println(1, "Error creating board: "+board_creation_status)
handleError(1, "Error creating board: "+board_creation_status)
break
} else {
board_creation_status = "Board created successfully"
println(1, board_creation_status)
println(2, board_creation_status)
buildBoards(true, 0)
resetBoardSectionArrays()
println(1, "Boards rebuilt successfully")
println(2, "Boards rebuilt successfully")
done = true
break
}
@ -677,17 +646,10 @@ var manage_functions = map[string]ManageFunction{
default:
// put the default column values in the text boxes
rows, err = db.Query("SELECT `column_name`,`column_default` FROM `information_schema`.`columns` WHERE `table_name` = '" + config.DBprefix + "boards'")
defer func() {
if rows != nil {
rows.Close()
}
}()
if err != nil {
html += err.Error()
println(1, "Error getting column names from boards table:"+err.Error())
html += handleError(1, "Error getting column names from boards table:"+err.Error())
return
}
for rows.Next() {
var column_name string
var column_default string
@ -750,14 +712,17 @@ var manage_functions = map[string]ManageFunction{
html = "<h1>Manage boards</h1>\n<form action=\"/manage?action=boards\" method=\"POST\">\n<input type=\"hidden\" name=\"do\" value=\"existing\" /><select name=\"boardselect\">\n<option>Select board...</option>\n"
rows, err = db.Query("SELECT `dir` FROM `" + config.DBprefix + "boards`;")
if err != nil {
html += err.Error()
html += handleError(1, err.Error())
return
}
var board_dir string
defer closeRows(rows)
for rows.Next() {
var board_dir string
rows.Scan(&board_dir)
html += "<option>" + board_dir + "</option>\n"
}
html += "</select> <input type=\"submit\" value=\"Edit\" /> <input type=\"submit\" value=\"Delete\" /></form><hr />" +
"<h2>Create new board</h2>\n<span id=\"board-creation-message\">" + board_creation_status + "</span><br />"
@ -768,12 +733,11 @@ var manage_functions = map[string]ManageFunction{
}
all_sections, _ = getSectionArr("")
err := renderTemplate(manage_boards_tmpl, "manage_boards", manageBoardsBuffer,
if err := renderTemplate(manage_boards_tmpl, "manage_boards", manageBoardsBuffer,
&Wrapper{IName: "board", Data: []interface{}{board}},
&Wrapper{IName: "section_arr", Data: all_sections},
)
if err != nil {
html += err.Error()
); err != nil {
html += handleError(1, err.Error())
return
}
html += manageBoardsBuffer.String()
@ -810,7 +774,6 @@ var manage_functions = map[string]ManageFunction{
"<a href=\"javascript:void(0)\" id=\"recentposts\" class=\"staffmenu-item\">Recent posts</a><br />\n" +
"<a href=\"javascript:void(0)\" id=\"searchip\" class=\"staffmenu-item\">Search posts by IP</a><br />\n"
}
return
}},
"rebuildfront": {
@ -848,14 +811,11 @@ var manage_functions = map[string]ManageFunction{
post := postInter.(PostTable)
stmt, err := db.Prepare("UPDATE `" + config.DBprefix + "posts` SET `message` = ? WHERE `id` = ? AND `boardid` = ?")
if err != nil {
html += err.Error() + "<br />"
html += handleError(1, err.Error()) + "<br />"
return
}
defer func() {
if stmt != nil {
stmt.Close()
}
}()
defer closeStatement(stmt)
stmt.Exec(formatMessage(post.MessageText), post.ID, post.BoardID)
}
html += "Done reparsing HTML<hr />" +
@ -889,16 +849,18 @@ var manage_functions = map[string]ManageFunction{
"AND `boardid` = `" + config.DBprefix + "boards`.`id` " +
"ORDER BY `timestamp` DESC LIMIT " + limit + ";")
if err != nil {
html += "<tr><td>" + err.Error() + "</td></tr></table>"
html += "<tr><td>" + handleError(1, err.Error()) + "</td></tr></table>"
return
}
defer closeRows(rows)
for rows.Next() {
recentpost := new(RecentPost)
err = rows.Scan(&recentpost.BoardName, &recentpost.BoardID, &recentpost.PostID, &recentpost.ParentID, &recentpost.Message, &recentpost.IP, &recentpost.Timestamp)
if err != nil {
errorLog.Print(err.Error())
return err.Error()
if err = rows.Scan(&recentpost.BoardName, &recentpost.BoardID,
&recentpost.PostID, &recentpost.ParentID, &recentpost.Message,
&recentpost.IP, &recentpost.Timestamp,
); err != nil {
return handleError(1, err.Error())
}
html += "<tr><td><b>Post:</b> <a href=\"" + path.Join(config.SiteWebfolder, recentpost.BoardName, "/res/", strconv.Itoa(recentpost.ParentID)+".html#"+strconv.Itoa(recentpost.PostID)) + "\">" + recentpost.BoardName + "/" + strconv.Itoa(recentpost.PostID) + "</a><br /><b>IP:</b> " + recentpost.IP + "</td><td>" + recentpost.Message + "</td><td>" + recentpost.Timestamp.Format("01/02/06, 15:04") + "</td></tr>"
}
@ -920,16 +882,16 @@ var manage_functions = map[string]ManageFunction{
"<tr><td><b>Username</b></td><td><b>Rank</b></td><td><b>Boards</b></td><td><b>Added on</b></td><td><b>Action</b></td></tr>\n"
rows, err := db.Query("SELECT `username`,`rank`,`boards`,`added_on` FROM `" + config.DBprefix + "staff`;")
if err != nil {
html += "<tr><td>" + err.Error() + "</td></tr></table>"
html += "<tr><td>" + handleError(1, err.Error()) + "</td></tr></table>"
return
}
defer closeRows(rows)
iter := 1
for rows.Next() {
staff := new(StaffTable)
err = rows.Scan(&staff.Username, &staff.Rank, &staff.Boards, &staff.AddedOn)
if err != nil {
errorLog.Print(err.Error())
if err = rows.Scan(&staff.Username, &staff.Rank, &staff.Boards, &staff.AddedOn); err != nil {
handleError(1, err.Error())
return err.Error()
}
@ -938,30 +900,22 @@ var manage_functions = map[string]ManageFunction{
new_password := request.FormValue("password")
new_rank := request.FormValue("rank")
stmt, err := db.Prepare("INSERT INTO `" + config.DBprefix + "staff` (`username`, `password_checksum`, `rank`) VALUES(?,?,?)")
defer func() {
if stmt != nil {
stmt.Close()
}
}()
if err != nil {
serveErrorPage(writer, err.Error())
serveErrorPage(writer, handleError(1, err.Error()))
}
defer closeStatement(stmt)
_, err = stmt.Exec(&new_username, bcryptSum(new_password), &new_rank)
if err != nil {
serveErrorPage(writer, err.Error())
if _, err = stmt.Exec(&new_username, bcryptSum(new_password), &new_rank); err != nil {
serveErrorPage(writer, handleError(1, err.Error()))
}
} else if request.FormValue("do") == "del" && request.FormValue("username") != "" {
stmt, err := db.Prepare("DELETE FROM `" + config.DBprefix + "staff` WHERE `username` = ?")
defer func() {
if stmt != nil {
stmt.Close()
}
}()
if err != nil {
serveErrorPage(writer, err.Error())
serveErrorPage(writer, handleError(1, err.Error()))
}
defer closeStatement(stmt)
_, err = stmt.Exec(request.FormValue("username"))
}
@ -975,7 +929,7 @@ var manage_functions = map[string]ManageFunction{
rank = "janitor"
}
html += "<tr><td>" + staff.Username + "</td><td>" + rank + "</td><td>" + staff.Boards + "</td><td>" + humanReadableTime(staff.AddedOn) + "</td><td><a href=\"/manage?action=staff&amp;do=del&amp;username=" + staff.Username + "\" style=\"float:right;color:red;\">X</a></td></tr>\n"
iter += 1
iter++
}
html += "</table>\n\n<hr />\n<h2>Add new staff</h2>\n\n" +
"<form action=\"/manage?action=staff\" onsubmit=\"return makeNewStaff();\" method=\"POST\">\n" +

View file

@ -133,13 +133,9 @@ func buildBoardPages(board *BoardsTable) (html string) {
if err != nil {
html += err.Error() + "<br />\n"
}
defer func() {
if stmt != nil {
stmt.Close()
}
}()
err = stmt.QueryRow(board.ID, op_post.ID, nil_timestamp).Scan(&thread.NumReplies)
if err != nil {
defer closeStatement(stmt)
if err = stmt.QueryRow(board.ID, op_post.ID, nil_timestamp).Scan(&thread.NumReplies); err != nil {
html += err.Error() + "<br />\n"
}
@ -148,8 +144,7 @@ func buildBoardPages(board *BoardsTable) (html string) {
if err != nil {
html += err.Error() + "<br />\n"
}
err = stmt.QueryRow(board.ID, op_post.ID, nil_timestamp).Scan(&thread.NumImages)
if err != nil {
if err = stmt.QueryRow(board.ID, op_post.ID, nil_timestamp).Scan(&thread.NumImages); err != nil {
html += err.Error() + "<br />\n"
}
@ -204,6 +199,7 @@ func buildBoardPages(board *BoardsTable) (html string) {
printf(2, "Number of files deleted: %d\n", num)
// Order the threads, stickied threads first, then nonstickied threads.
threads = append(stickied_threads, nonstickied_threads...)
// If there are no posts on the board
if len(threads) == 0 {
board.CurrentPage = 0
@ -222,19 +218,43 @@ func buildBoardPages(board *BoardsTable) (html string) {
// Render board page template to the file,
// packaging the board/section list, threads, and board info
err = renderTemplate(img_boardpage_tmpl, "boardpage", board_page_file,
if err = renderTemplate(img_header_tmpl, "img_header", board_page_file,
&Wrapper{IName: "boards_", Data: all_boards},
&Wrapper{IName: "sections_w", Data: all_sections},
&Wrapper{IName: "posts_w", Data: []interface{}{
PostTable{BoardID: board.ID},
}},
&Wrapper{IName: "op", Data: []interface{}{PostTable{}}},
&Wrapper{IName: "board", Data: []interface{}{board}},
); err != nil {
errortext = fmt.Sprintf("Failed building /%s/res/%d.html: %s", board.Dir, 0, err.Error())
html += errortext + "<br />\n"
println(1, errortext)
errorLog.Print(errortext)
return
}
if err = renderTemplate(img_boardpage_tmpl, "boardpage", board_page_file,
&Wrapper{IName: "boards", Data: all_boards},
&Wrapper{IName: "sections", Data: all_sections},
&Wrapper{IName: "threads", Data: threads},
&Wrapper{IName: "boardinfo", Data: boardinfo_i},
)
if err != nil {
); err != nil {
errortext = "Failed building /" + board.Dir + "/: " + err.Error()
html += errortext + "<br />\n"
errorLog.Print(errortext)
println(1, errortext)
return
}
if err = renderTemplate(global_footer_tmpl, "global_footer", board_page_file); err != nil {
errortext = "Failed building /" + board.Dir + "/: " + err.Error()
html += errortext + "<br />\n"
errorLog.Print(errortext)
println(1, errortext)
return
}
html += "/" + board.Dir + "/ built successfully, no threads to build.\n"
//benchmarkTimer("buildBoard"+strconv.Itoa(board.ID), start_time, false)
return
@ -248,12 +268,6 @@ func buildBoardPages(board *BoardsTable) (html string) {
var pages_obj []BoardPageJSON
catalog_json_file, err := os.OpenFile(path.Join(config.DocumentRoot, board.Dir, "catalog.json"), os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0777)
defer func() {
if catalog_json_file != nil {
catalog_json_file.Close()
}
}()
if err != nil {
errortext = "Failed opening /" + board.Dir + "/catalog.json: " + err.Error()
html += errortext + "<br />\n"
@ -261,6 +275,7 @@ func buildBoardPages(board *BoardsTable) (html string) {
errorLog.Print(errortext)
return
}
defer closeFile(catalog_json_file)
for page_num, page_threads := range thread_pages {
// Package up board info for the template to use.
@ -284,14 +299,38 @@ func buildBoardPages(board *BoardsTable) (html string) {
println(1, errortext)
continue
}
// Render the boardpage template, given boards, sections, threads, and board info
err = renderTemplate(img_boardpage_tmpl, "boardpage", current_page_file,
if err = renderTemplate(img_header_tmpl, "img_header", current_page_file,
&Wrapper{IName: "boards_", Data: all_boards},
&Wrapper{IName: "sections_w", Data: all_sections},
&Wrapper{IName: "posts_w", Data: []interface{}{
PostTable{BoardID: board.ID},
}},
&Wrapper{IName: "op", Data: []interface{}{PostTable{}}},
&Wrapper{IName: "board", Data: []interface{}{board}},
); err != nil {
errortext = fmt.Sprintf("Failed building /%s/res/%d.html: %s", board.Dir, 0, err.Error())
html += errortext + "<br />\n"
println(1, errortext)
errorLog.Print(errortext)
return
}
if err = renderTemplate(img_boardpage_tmpl, "boardpage", current_page_file,
&Wrapper{IName: "boards", Data: all_boards},
&Wrapper{IName: "sections", Data: all_sections},
&Wrapper{IName: "threads", Data: page_threads},
&Wrapper{IName: "boardinfo", Data: boardinfo_i},
)
if err != nil {
); err != nil {
errortext = "Failed building /" + board.Dir + "/: " + err.Error()
html += errortext + "<br />\n"
errorLog.Print(errortext)
println(1, errortext)
return
}
if err = renderTemplate(global_footer_tmpl, "global_footer", current_page_file); err != nil {
errortext = "Failed building /" + board.Dir + "/: " + err.Error()
html += errortext + "<br />\n"
errorLog.Print(errortext)
@ -334,7 +373,6 @@ func buildBoardPages(board *BoardsTable) (html string) {
}
catalog_json, err := json.Marshal(pages_obj)
if err != nil {
errortext = "Failed to marshal to JSON: " + err.Error()
errorLog.Println(errortext)
@ -343,19 +381,15 @@ func buildBoardPages(board *BoardsTable) (html string) {
return
}
_, err = catalog_json_file.Write(catalog_json)
if err != nil {
if _, err = catalog_json_file.Write(catalog_json); err != nil {
errortext = "Failed writing /" + board.Dir + "/catalog.json: " + err.Error()
errorLog.Println(errortext)
println(1, errortext)
html += errortext + "<br />\n"
return
}
html += "/" + board.Dir + "/ built successfully.\n"
}
//benchmarkTimer("buildBoard"+strconv.Itoa(board.ID), start_time, false)
return
}
@ -411,8 +445,7 @@ func buildThreadPages(op *PostTable) (html string) {
return
}
err = stmt.QueryRow(op.BoardID).Scan(&boardDir, &anonymous)
if err != nil {
if err = stmt.QueryRow(op.BoardID).Scan(&boardDir, &anonymous); err != nil {
errortext = "Failed getting board directory and board's anonymous setting from post: " + err.Error()
html += errortext + "<br />\n"
errorLog.Println(errortext)
@ -458,14 +491,32 @@ func buildThreadPages(op *PostTable) (html string) {
return
}
// render main page
err = renderTemplate(img_threadpage_tmpl, "threadpage", current_page_file,
if err = renderTemplate(img_header_tmpl, "img_header", current_page_file,
&Wrapper{IName: "boards_", Data: all_boards},
&Wrapper{IName: "sections_w", Data: all_sections},
&Wrapper{IName: "posts_w", Data: append([]interface{}{op}, replies...)},
)
); err != nil {
errortext = fmt.Sprintf("Failed building /%s/res/%d.html: %s", boardDir, op.ID, err.Error())
html += errortext + "<br />\n"
println(1, errortext)
errorLog.Print(errortext)
return
}
if err != nil {
fmt.Sprintf("Failed building /%s/res/%d.html: %s", boardDir, op.ID, err.Error())
if err = renderTemplate(img_threadpage_tmpl, "threadpage", current_page_file,
&Wrapper{IName: "boards_", Data: all_boards},
&Wrapper{IName: "sections_w", Data: all_sections},
&Wrapper{IName: "posts_w", Data: append([]interface{}{op}, replies...)},
); err != nil {
errortext = fmt.Sprintf("Failed building /%s/res/%d.html: %s", boardDir, op.ID, err.Error())
html += errortext + "<br />\n"
println(1, errortext)
errorLog.Print(errortext)
return
}
if err = renderTemplate(global_footer_tmpl, "global_footer", current_page_file); err != nil {
errortext = fmt.Sprintf("Failed building /%s/res/%d.html: %s", boardDir, op.ID, err.Error())
html += errortext + "<br />\n"
println(1, errortext)
errorLog.Print(errortext)
@ -474,11 +525,6 @@ func buildThreadPages(op *PostTable) (html string) {
// Put together the thread JSON
threadJSONFile, err := os.OpenFile(path.Join(config.DocumentRoot, boardDir, "res", strconv.Itoa(op.ID)+".json"), os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0777)
defer func() {
if threadJSONFile != nil {
threadJSONFile.Close()
}
}()
if err != nil {
errortext = fmt.Sprintf("Failed opening /%s/res/%d.json: %s", boardDir, op.ID, err.Error())
html += errortext + "<br />\n"
@ -486,6 +532,8 @@ func buildThreadPages(op *PostTable) (html string) {
errorLog.Print(errortext)
return
}
defer closeFile(threadJSONFile)
// Create the wrapper object
thread_json_wrapper := new(ThreadJSONWrapper)
@ -510,8 +558,7 @@ func buildThreadPages(op *PostTable) (html string) {
return
}
_, err = threadJSONFile.Write(threadJSON)
if err != nil {
if _, err = threadJSONFile.Write(threadJSON); err != nil {
errortext = fmt.Sprintf("Failed writing /%s/res/%d.json: %s", boardDir, op.ID, err.Error())
errorLog.Println(errortext)
println(1, errortext)
@ -525,35 +572,36 @@ func buildThreadPages(op *PostTable) (html string) {
for page_num, page_posts := range thread_pages {
op.CurrentPage = page_num
current_page_filepath := path.Join(config.DocumentRoot, boardDir, "res", strconv.Itoa(op.ID)+"p"+strconv.Itoa(op.CurrentPage+1)+".html")
current_page_file, err = os.OpenFile(current_page_filepath, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0777)
if err != nil {
errortext = "Failed opening " + current_page_filepath + ": " + err.Error()
html += errortext + "<br />\n"
println(1, errortext)
errorLog.Println(errortext)
html += handleError(1, "Failed opening "+current_page_filepath+": "+err.Error()) + "<br />\n"
return
}
// var postsSanitized []interface{}
// for i := 0; i < len(page_posts); i++ {
// postsSanitized = append(postsSanitized, sanitizePost(page_posts[i].(PostTable)))
// }
err = renderTemplate(img_threadpage_tmpl, "threadpage", current_page_file,
if err = renderTemplate(img_header_tmpl, "img_header", current_page_file,
&Wrapper{IName: "boards_", Data: all_boards},
&Wrapper{IName: "sections_w", Data: all_sections},
//&Wrapper{IName: "posts_w", Data: postsSanitized},
&Wrapper{IName: "posts_w", Data: page_posts},
)
if err != nil {
errortext = fmt.Sprintf("Failed building /%s/%d: %s", boardDir, op.ID, err.Error())
html += errortext + "<br />\n"
println(1, errortext)
errorLog.Print(errortext)
&Wrapper{IName: "posts_w", Data: append([]interface{}{op}, replies...)},
); err != nil {
html += handleError(1, fmt.Sprintf("Failed building /%s/%d: %s", boardDir, op.ID, err.Error()))
return
}
if err = renderTemplate(img_threadpage_tmpl, "threadpage", current_page_file,
&Wrapper{IName: "boards_", Data: all_boards},
&Wrapper{IName: "sections_w", Data: all_sections},
&Wrapper{IName: "posts_w", Data: page_posts},
); err != nil {
html += handleError(1, fmt.Sprintf("Failed building /%s/%d: %s", boardDir, op.ID, err.Error()))
return
}
if err = renderTemplate(global_footer_tmpl, "global_footer", current_page_file); err != nil {
html += handleError(1, fmt.Sprintf("Failed building /%s/%d: %s", boardDir, op.ID, err.Error()))
return
}
success_text := fmt.Sprintf("Built /%s/%dp%d successfully", boardDir, op.ID, op.CurrentPage+1)
html += success_text + "<br />\n"
println(2, success_text)
@ -566,35 +614,24 @@ func buildFrontPage() (html string) {
var front_arr []interface{}
var recent_posts_arr []interface{}
var errortext string
os.Remove(path.Join(config.DocumentRoot, "index.html"))
front_file, err := os.OpenFile(path.Join(config.DocumentRoot, "index.html"), os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0777)
defer func() {
if front_file != nil {
front_file.Close()
}
}()
if err != nil {
errortext = "Failed opening front page for writing: " + err.Error()
errorLog.Println(errortext)
return errortext + "<br />\n"
return handleError(1, "Failed opening front page for writing: "+err.Error()) + "<br />\n"
}
defer closeFile(front_file)
// get front pages
rows, err := db.Query("SELECT * FROM `" + config.DBprefix + "frontpage`")
if err != nil {
errortext = "Failed getting front page rows: " + err.Error()
errorLog.Print(errortext)
return errortext + "<br />"
return handleError(1, "Failed getting front page rows: "+err.Error())
}
for rows.Next() {
frontpage := new(FrontTable)
frontpage.IName = "front page"
err = rows.Scan(&frontpage.ID, &frontpage.Page, &frontpage.Order, &frontpage.Subject, &frontpage.Message, &frontpage.Timestamp, &frontpage.Poster, &frontpage.Email)
if err != nil {
errorLog.Print(err.Error())
println(1, err.Error())
return err.Error()
if err = rows.Scan(&frontpage.ID, &frontpage.Page, &frontpage.Order, &frontpage.Subject,
&frontpage.Message, &frontpage.Timestamp, &frontpage.Poster, &frontpage.Email); err != nil {
return handleError(1, err.Error()) + "<br />"
}
front_arr = append(front_arr, frontpage)
}
@ -610,63 +647,41 @@ func buildFrontPage() (html string) {
"WHERE `" + config.DBprefix + "posts`.`deleted_timestamp` = ? " +
"AND `boardid` = `" + config.DBprefix + "boards`.`id` " +
"ORDER BY `timestamp` DESC LIMIT ?")
defer func() {
if stmt != nil {
stmt.Close()
}
}()
if err != nil {
errorLog.Print(err.Error())
println(1, err.Error())
return err.Error() + "<br />\n"
return handleError(1, err.Error()) + "<br />"
}
defer closeStatement(stmt)
rows, err = stmt.Query(nil_timestamp, config.MaxRecentPosts)
if err != nil {
errortext = "Failed getting list of recent posts for front page: " + err.Error()
errorLog.Print(errortext)
println(1, errortext)
return errortext + "<br />\n"
return handleError(1, "Failed getting list of recent posts for front page: "+err.Error()) + "<br />"
}
for rows.Next() {
recent_post := new(RecentPost)
err = rows.Scan(&recent_post.PostID, &recent_post.ParentID, &recent_post.BoardName, &recent_post.BoardID, &recent_post.Name, &recent_post.Tripcode, &recent_post.Message, &recent_post.Filename, &recent_post.ThumbW, &recent_post.ThumbH)
if err != nil {
errortext = "Failed getting list of recent posts for front page: " + err.Error()
errorLog.Print(errortext)
println(1, errortext)
return errortext + "<br />\n"
return handleError(1, "Failed getting list of recent posts for front page: "+err.Error()) + "<br />"
}
recent_posts_arr = append(recent_posts_arr, recent_post)
}
err = renderTemplate(front_page_tmpl, "frontpage", front_file,
if err = renderTemplate(front_page_tmpl, "frontpage", front_file,
&Wrapper{IName: "fronts", Data: front_arr},
&Wrapper{IName: "boards", Data: all_boards},
&Wrapper{IName: "sections", Data: all_sections},
&Wrapper{IName: "recent posts", Data: recent_posts_arr},
)
if err != nil {
errortext = "Failed executing front page template: " + err.Error()
errorLog.Println(errortext)
println(1, errortext)
return errortext + "<br />\n"
); err != nil {
return handleError(1, "Failed executing front page template: "+err.Error()) + "<br />"
}
return "Front page rebuilt successfully.<br />"
}
func buildBoardListJSON() (html string) {
var errortext string
board_list_file, err := os.OpenFile(path.Join(config.DocumentRoot, "boards.json"), os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0777)
defer func() {
if board_list_file != nil {
board_list_file.Close()
}
}()
if err != nil {
errortext = "Failed opening board.json for writing: " + err.Error()
errorLog.Println(errortext)
return errortext + "<br />\n"
return handleError(1, "Failed opening board.json for writing: "+err.Error()) + "<br />\n"
}
defer closeFile(board_list_file)
board_list_wrapper := new(BoardJSONWrapper)
@ -686,20 +701,11 @@ func buildBoardListJSON() (html string) {
}
boardJSON, err := json.Marshal(board_list_wrapper)
if err != nil {
errortext = "Failed marshal to JSON: " + err.Error()
errorLog.Println(errortext)
println(1, errortext)
return errortext + "<br />\n"
return handleError(1, "Failed marshal to JSON: "+err.Error()) + "<br />\n"
}
_, err = board_list_file.Write(boardJSON)
if err != nil {
errortext = "Failed writing boards.json file: " + err.Error()
errorLog.Println(errortext)
println(1, errortext)
return errortext + "<br />\n"
if _, err = board_list_file.Write(boardJSON); err != nil {
return handleError(1, "Failed writing boards.json file: "+err.Error()) + "<br />\n"
}
return "Board list JSON rebuilt successfully.<br />"
}
@ -711,14 +717,9 @@ func bumpThread(postID, boardID int) error {
if err != nil {
return err
}
defer func() {
if stmt != nil {
stmt.Close()
}
}()
defer closeStatement(stmt)
_, err = stmt.Exec(time.Now(), postID, boardID)
if err != nil {
if _, err = stmt.Exec(time.Now(), postID, boardID); err != nil {
return err
}
return nil
@ -733,19 +734,13 @@ func checkBannedStatus(post *PostTable, writer *http.ResponseWriter) ([]interfac
// var count int
// var search string
stmt, err := db.Prepare("SELECT `ip`, `name`, `tripcode`, `message`, `boards`, `timestamp`, `expires`, `appeal_at` FROM `" + config.DBprefix + "banlist` WHERE `ip` = ?")
defer func() {
if stmt != nil {
stmt.Close()
}
}()
if err != nil {
errortext := "Error checking banned status: " + err.Error()
println(1, errortext)
errorLog.Print(errortext)
return interfaces, nil
handleError(1, "Error checking banned status: "+err.Error())
return interfaces, err
}
err = stmt.QueryRow(&post.IP).Scan(&ban_entry.IP, &ban_entry.Name, &ban_entry.Tripcode, &ban_entry.Message, &ban_entry.Boards, &ban_entry.Timestamp, &ban_entry.Expires, &ban_entry.AppealAt)
defer closeStatement(stmt)
err = stmt.QueryRow(&post.IP).Scan(&ban_entry.IP, &ban_entry.Name, &ban_entry.Tripcode, &ban_entry.Message, &ban_entry.Boards, &ban_entry.Timestamp, &ban_entry.Expires, &ban_entry.AppealAt)
if err != nil {
if err == sql.ErrNoRows {
// the user isn't banned
@ -780,15 +775,12 @@ func checkBannedStatus(post *PostTable, writer *http.ResponseWriter) ([]interfac
}
func sinceLastPost(post *PostTable) int {
var oldpost PostTable
err := db.QueryRow("SELECT `timestamp` FROM `" + config.DBprefix + "posts` WHERE `ip` = '" + post.IP + "' ORDER BY `timestamp` DESC LIMIT 1").Scan(&oldpost.Timestamp)
since := time.Since(oldpost.Timestamp)
if err == sql.ErrNoRows {
var lastPostTime time.Time
if err := db.QueryRow("SELECT `timestamp` FROM `" + config.DBprefix + "posts` WHERE `ip` = '" + post.IP + "' ORDER BY `timestamp` DESC LIMIT 1").Scan(&lastPostTime); err == sql.ErrNoRows {
// no posts by that IP.
return -1
} else {
return int(since.Seconds())
return int(time.Since(lastPostTime).Seconds())
}
return -1
}
@ -849,7 +841,6 @@ func getVideoInfo(path string) (map[string]int, error) {
}
}
}
return vidInfo, err
}
@ -907,11 +898,8 @@ func insertPost(post PostTable, bump bool) (sql.Result, error) {
if err != nil {
return nil, err
}
defer func() {
if stmt != nil {
stmt.Close()
}
}()
defer closeStatement(stmt)
result, err = stmt.Exec(
post.BoardID, post.ParentID, post.Name, post.Tripcode,
post.Email, post.Subject, post.MessageHTML, post.MessageText,
@ -941,7 +929,6 @@ func makePost(w http.ResponseWriter, r *http.Request, data interface{}) {
request = *r
writer = w
var maxMessageLength int
var errorText string
var post PostTable
domain := r.Host
var formName string
@ -991,17 +978,13 @@ func makePost(w http.ResponseWriter, r *http.Request, data interface{}) {
if err != nil {
serveErrorPage(w, "Error getting board info.")
errorLog.Print("Error getting board info: " + err.Error())
return
}
defer func() {
if stmt != nil {
stmt.Close()
}
}()
err = stmt.QueryRow(post.BoardID).Scan(&maxMessageLength)
defer closeStatement(stmt)
if err != nil {
serveErrorPage(w, "Requested board does not exist.")
errorLog.Print("requested board does not exist. Error: " + err.Error())
if err = stmt.QueryRow(post.BoardID).Scan(&maxMessageLength); err != nil {
serveErrorPage(w, handleError(1, "Requested board does not exist."))
return
}
if len(post.MessageText) > maxMessageLength {
@ -1048,6 +1031,11 @@ func makePost(w http.ResponseWriter, r *http.Request, data interface{}) {
}
file, handler, err := request.FormFile("imagefile")
defer func() {
if file != nil {
file.Close()
}
}()
if err != nil {
// no file was uploaded
post.Filename = ""
@ -1055,12 +1043,11 @@ func makePost(w http.ResponseWriter, r *http.Request, data interface{}) {
} else {
data, err := ioutil.ReadAll(file)
if err != nil {
serveErrorPage(w, "Couldn't read file: "+err.Error())
serveErrorPage(w, handleError(1, "Couldn't read file: "+err.Error()))
} else {
post.FilenameOriginal = html.EscapeString(handler.Filename)
filetype := getFileExtension(post.FilenameOriginal)
thumbFiletype := filetype
if thumbFiletype == "gif" || thumbFiletype == "webm" {
thumbFiletype = "jpg"
}
@ -1069,20 +1056,16 @@ func makePost(w http.ResponseWriter, r *http.Request, data interface{}) {
boardArr, _ := getBoardArr(map[string]interface{}{"id": request.FormValue("boardid")}, "")
if len(boardArr) == 0 {
serveErrorPage(w, "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))
err := ioutil.WriteFile(filePath, data, 0777)
if err != nil {
errorText = "Couldn't write file \"" + post.Filename + "\"" + err.Error()
println(0, errorText)
errorLog.Println(errorText)
if err := ioutil.WriteFile(filePath, data, 0777); err != nil {
handleError(0, "Couldn't write file \""+post.Filename+"\""+err.Error())
serveErrorPage(w, "Couldn't write file \""+post.FilenameOriginal+"\"")
return
}
@ -1093,25 +1076,13 @@ func makePost(w http.ResponseWriter, r *http.Request, data interface{}) {
var allowsVids bool
vidStmt, err := db.Prepare("SELECT `embeds_allowed` FROM `" + config.DBprefix + "boards` WHERE `id` = ? LIMIT 1")
if err != nil {
errortext := err.Error()
errorLog.Println(errorText)
serveErrorPage(w, "Couldn't get board info: "+errorText)
println(1, errortext)
serveErrorPage(w, handleError(1, "Couldn't get board info: "+err.Error()))
return
}
defer closeStatement(vidStmt)
defer func() {
if vidStmt != nil {
vidStmt.Close()
}
}()
err = vidStmt.QueryRow(post.BoardID).Scan(&allowsVids)
if err != nil {
errortext := err.Error()
errorLog.Println(errorText)
serveErrorPage(w, "Couldn't get board info: "+errorText)
println(1, errortext)
if err = vidStmt.QueryRow(post.BoardID).Scan(&allowsVids); err != nil {
serveErrorPage(w, handleError(1, "Couldn't get board info: "+err.Error()))
return
}
@ -1126,31 +1097,25 @@ func makePost(w http.ResponseWriter, r *http.Request, data interface{}) {
if post.ParentID == 0 {
err := createVideoThumbnail(filePath, thumbPath, config.ThumbWidth)
if err != nil {
serveErrorPage(w, err.Error())
printf(1, err.Error())
serveErrorPage(w, handleError(1, err.Error()))
return
}
} else {
err := createVideoThumbnail(filePath, thumbPath, config.ThumbWidth_reply)
if err != nil {
serveErrorPage(w, err.Error())
printf(1, err.Error())
serveErrorPage(w, handleError(1, err.Error()))
return
}
}
err := createVideoThumbnail(filePath, catalogThumbPath, config.ThumbWidth_catalog)
if err != nil {
serveErrorPage(w, err.Error())
printf(1, err.Error())
if err := createVideoThumbnail(filePath, catalogThumbPath, config.ThumbWidth_catalog); err != nil {
serveErrorPage(w, handleError(1, err.Error()))
return
}
outputBytes, err := exec.Command("ffprobe", "-v", "quiet", "-show_format", "-show_streams", filePath).CombinedOutput()
if err != nil {
errortext := "Error getting video info: " + err.Error()
serveErrorPage(w, errortext)
printf(1, errortext)
serveErrorPage(w, handleError(1, "Error getting video info: "+err.Error()))
return
}
if err == nil && outputBytes != nil {
@ -1181,20 +1146,15 @@ func makePost(w http.ResponseWriter, r *http.Request, data interface{}) {
// Attempt to load uploaded file with imaging library
img, err := imaging.Open(filePath)
if err != nil {
errorText = "Couldn't open uploaded file \"" + post.Filename + "\"" + err.Error()
errorLog.Println(errorText)
println(1, errorText)
os.Remove(filePath)
handleError(1, "Couldn't open uploaded file \""+post.Filename+"\""+err.Error())
serveErrorPage(w, "Upload filetype not supported")
return
} else {
// Get image filesize
stat, err := os.Stat(filePath)
if err != nil {
errortext := "Couldn't get image filesize: " + err.Error()
errorLog.Println(errortext)
println(1, errortext)
serveErrorPage(w, errortext)
serveErrorPage(w, handleError(1, "Couldn't get image filesize: "+err.Error()))
return
} else {
post.Filesize = int(stat.Size())
@ -1213,8 +1173,7 @@ func makePost(w http.ResponseWriter, r *http.Request, data interface{}) {
if request.FormValue("spoiler") == "on" {
// If spoiler is enabled, symlink thumbnail to spoiler image
_, err := os.Stat(path.Join(config.DocumentRoot, "spoiler.png"))
if err != nil {
if _, err := os.Stat(path.Join(config.DocumentRoot, "spoiler.png")); err != nil {
serveErrorPage(w, "missing /spoiler.png")
return
} else {
@ -1228,8 +1187,7 @@ func makePost(w http.ResponseWriter, r *http.Request, data interface{}) {
// If image fits in thumbnail size, symlink thumbnail to original
post.ThumbW = img.Bounds().Max.X
post.ThumbH = img.Bounds().Max.Y
err := syscall.Symlink(filePath, thumbPath)
if err != nil {
if err := syscall.Symlink(filePath, thumbPath); err != nil {
serveErrorPage(w, err.Error())
return
}
@ -1241,21 +1199,15 @@ func makePost(w http.ResponseWriter, r *http.Request, data interface{}) {
thumbnail = createImageThumbnail(img, "op")
catalogThumbnail = createImageThumbnail(img, "catalog")
println(1, catalogThumbPath)
err = imaging.Save(catalogThumbnail, catalogThumbPath)
if err != nil {
errorLog.Println("Couldn't generate catalog thumbnail: " + err.Error())
serveErrorPage(w, "Couldn't generate catalog thumbnail: "+err.Error())
if err = imaging.Save(catalogThumbnail, catalogThumbPath); err != nil {
serveErrorPage(w, handleError(1, "Couldn't generate catalog thumbnail: "+err.Error()))
return
}
} else {
thumbnail = createImageThumbnail(img, "reply")
}
err = imaging.Save(thumbnail, thumbPath)
if err != nil {
errortext := "Couldn't save thumbnail: " + err.Error()
println(0, errortext)
errorLog.Println(errortext)
serveErrorPage(w, errortext)
if err = imaging.Save(thumbnail, thumbPath); err != nil {
serveErrorPage(w, handleError(1, "Couldn't save thumbnail: "+err.Error()))
return
}
}
@ -1285,10 +1237,8 @@ func makePost(w http.ResponseWriter, r *http.Request, data interface{}) {
isBanned, err := checkBannedStatus(&post, &w)
if err != nil {
errorText = "Error in checkBannedStatus: " + err.Error()
handleError(1, "Error in checkBannedStatus: "+err.Error())
serveErrorPage(w, err.Error())
errorLog.Println(errorText)
println(1, errorText)
return
}
@ -1296,11 +1246,8 @@ func makePost(w http.ResponseWriter, r *http.Request, data interface{}) {
var banpage_buffer bytes.Buffer
var banpage_html string
banpage_buffer.Write([]byte(""))
err = renderTemplate(banpage_tmpl, "banpage", &banpage_buffer, &Wrapper{IName: "bans", Data: isBanned})
if err != nil {
fmt.Fprintf(writer, banpage_html+err.Error()+"\n</body>\n</html>")
println(1, err.Error())
errorLog.Println(err.Error())
if err = renderTemplate(banpage_tmpl, "banpage", &banpage_buffer, &Wrapper{IName: "bans", Data: isBanned}); err != nil {
fmt.Fprintf(writer, banpage_html+handleError(1, err.Error())+"\n</body>\n</html>")
return
}
fmt.Fprintf(w, banpage_buffer.String())
@ -1310,7 +1257,7 @@ func makePost(w http.ResponseWriter, r *http.Request, data interface{}) {
post = sanitizePost(post)
result, err := insertPost(post, emailCommand != "sage")
if err != nil {
serveErrorPage(w, err.Error())
serveErrorPage(w, handleError(1, err.Error()))
return
}
postid, _ := result.LastInsertId()
@ -1346,8 +1293,7 @@ func formatMessage(message string) string {
for w, word := range lineWords {
if strings.LastIndex(word, gt+gt) == 0 {
//word is a backlink
_, err := strconv.Atoi(word[8:])
if err == nil {
if _, err := strconv.Atoi(word[8:]); err == nil {
// the link is in fact, a valid int
var boardDir string
var linkParent int

View file

@ -127,7 +127,7 @@ func (s GochanServer) ServeHTTP(writer http.ResponseWriter, request *http.Reques
func initServer() {
listener, err := net.Listen("tcp", config.ListenIP+":"+strconv.Itoa(config.Port))
if err != nil {
fmt.Printf("Failed listening on %s:%d, see log for details", config.ListenIP, config.Port)
printf(0, "Failed listening on %s:%d, see log for details", config.ListenIP, config.Port)
errorLog.Fatal(err.Error())
}
server = new(GochanServer)
@ -182,7 +182,9 @@ func utilHandler(writer http.ResponseWriter, request *http.Request, data interfa
fileOnly := request.FormValue("fileonly") == "on"
deleteBtn := request.PostFormValue("delete_btn")
reportBtn := request.PostFormValue("report_btn")
if action == "" && deleteBtn != "Delete" && reportBtn != "Report" {
editBtn := request.PostFormValue("edit_btn")
if action == "" && deleteBtn != "Delete" && reportBtn != "Report" && editBtn != "Edit" {
http.Redirect(writer, request, path.Join(config.SiteWebfolder, "/"), http.StatusFound)
return
}
@ -192,6 +194,19 @@ func utilHandler(writer http.ResponseWriter, request *http.Request, data interfa
postsArr = append(postsArr, key[5:])
}
}
if editBtn == "Edit" {
if len(postsArr) == 0 {
serveErrorPage(writer, "You need to select one post to edit.")
return
} else if len(postsArr) > 1 {
serveErrorPage(writer, "You can only edit one post at a time.")
return
} else {
}
}
if deleteBtn == "Delete" {
// Delete a post or thread
passwordMD5 := md5Sum(password)
@ -213,17 +228,13 @@ func utilHandler(writer http.ResponseWriter, request *http.Request, data interfa
post.ID, _ = strconv.Atoi(checkedPostID)
stmt, err := db.Prepare("SELECT `parentID`, `filename`, `password` FROM `" + config.DBprefix + "posts` WHERE `id` = ? AND `deleted_timestamp` = ?")
defer func() {
if stmt != nil {
stmt.Close()
}
}()
if err != nil {
errorLog.Print(err.Error())
println(1, err.Error())
serveErrorPage(writer, err.Error())
}
defer closeStatement(stmt)
err = stmt.QueryRow(&post.ID, nil_timestamp).Scan(&post.ParentID, &post.Filename, &post.Password)
if err == sql.ErrNoRows {
@ -279,7 +290,7 @@ func utilHandler(writer http.ResponseWriter, request *http.Request, data interfa
// delete the post
_, err = db.Exec("UPDATE `" + config.DBprefix + "posts` SET `deleted_timestamp` = '" + getSQLDateTime() + "' WHERE `id` = " + strconv.Itoa(post.ID))
if post.ParentID == 0 {
err = os.Remove(path.Join(config.DocumentRoot, board, "/res/"+strconv.Itoa(post.ID)+".html"))
os.Remove(path.Join(config.DocumentRoot, board, "/res/"+strconv.Itoa(post.ID)+".html"))
} else {
_board, _ := getBoardArr(map[string]interface{}{"id": post.BoardID}, "") // getBoardArr("`id` = " + strconv.Itoa(boardid))
buildBoardPages(&_board[0])

View file

@ -33,7 +33,7 @@ func connectToSQLServer() {
// get the number of tables in the database. If the number > 1, we can assume that initial setup has already been run
var num_rows int
err = db.QueryRow("SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = '" + config.DBname + "';").Scan(&num_rows)
err = db.QueryRow("SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = '" + config.DBname + "'").Scan(&num_rows)
if err == sql.ErrNoRows {
num_rows = 0
} else if err != nil {
@ -50,8 +50,7 @@ func connectToSQLServer() {
return
} else {
// check if initialsetupdb.sql still exists
_, err := os.Stat("initialsetupdb.sql")
if err != nil {
if _, err := os.Stat("initialsetupdb.sql"); err != nil {
println(0, "Initial setup file (initialsetupdb.sql) missing. Please reinstall gochan")
errorLog.Fatal("Initial setup file (initialsetupdb.sql) missing. Please reinstall gochan")
}
@ -73,8 +72,7 @@ func connectToSQLServer() {
for _, statement := range initial_sql_arr {
if statement != "" {
_, err := db.Exec(statement)
if err != nil {
if _, err := db.Exec(statement); err != nil {
println(0, "failed, see log for details.")
errorLog.Fatal("Error executing initialsetupdb.sql: " + err.Error())
return

View file

@ -1,14 +1,12 @@
package main
import (
"bytes"
"fmt"
"html"
"io"
"io/ioutil"
"net/http"
"os"
"path"
"strconv"
"strings"
"text/template"
@ -115,7 +113,10 @@ var funcMap = template.FuncMap{
return style != config.DefaultStyle_img
},
"getElement": func(in []interface{}, element int) interface{} {
return in[element]
if len(in) > element {
return in[element]
}
return nil
},
"getInterface": func(in []interface{}, index int) interface{} {
var nope interface{}
@ -197,177 +198,119 @@ var funcMap = template.FuncMap{
var (
footer_data = FooterData{version, float32(0)}
banpage_tmpl_str string
banpage_tmpl *template.Template
global_footer_tmpl_str string
global_footer_tmpl *template.Template
global_header_tmpl_str string
global_header_tmpl *template.Template
img_boardpage_tmpl_str string
img_boardpage_tmpl *template.Template
img_threadpage_tmpl_str string
img_threadpage_tmpl *template.Template
manage_header_tmpl_str string
manage_header_tmpl *template.Template
manage_boards_tmpl_str string
manage_boards_tmpl *template.Template
manage_config_tmpl_str string
manage_config_tmpl *template.Template
front_page_tmpl_str string
banpage_tmpl *template.Template
global_footer_tmpl *template.Template
global_header_tmpl *template.Template
img_header_tmpl *template.Template
img_boardpage_tmpl *template.Template
img_threadpage_tmpl *template.Template
img_post_form_tmpl *template.Template
manage_header_tmpl *template.Template
manage_boards_tmpl *template.Template
manage_config_tmpl *template.Template
front_page_tmpl *template.Template
template_buffer bytes.Buffer
starting_time int
)
func initTemplates() {
resetBoardSectionArrays()
banpage_tmpl_bytes, tmpl_err := ioutil.ReadFile(config.TemplateDir + "/banpage.html")
if tmpl_err != nil {
fmt.Println("Failed loading template \"" + config.TemplateDir + "/banpage.html\": " + tmpl_err.Error())
os.Exit(2)
}
banpage_tmpl_str = "{{$config := getInterface .Data 0}}" +
"{{$ban := getInterface .Data 1}}" +
string(banpage_tmpl_bytes)
banpage_tmpl, tmpl_err = template.New("banpage_tmpl").Funcs(funcMap).Parse(string(banpage_tmpl_str))
if tmpl_err != nil {
fmt.Println("Failed loading template \"" + config.TemplateDir + "/banpage.html\": " + tmpl_err.Error())
os.Exit(2)
}
global_footer_tmpl_bytes, tmpl_err := ioutil.ReadFile(config.TemplateDir + "/global_footer.html")
if tmpl_err != nil {
fmt.Println("Failed loading template \"" + config.TemplateDir + "/global_footer.html\": " + tmpl_err.Error())
os.Exit(2)
}
global_footer_tmpl_str = string(global_footer_tmpl_bytes)
global_footer_tmpl, tmpl_err = template.New("global_footer_tmpl").Funcs(funcMap).Parse(string(global_footer_tmpl_str))
if tmpl_err != nil {
fmt.Println("Failed loading template \"" + config.TemplateDir + "/global_footer.html\": " + tmpl_err.Error())
os.Exit(2)
}
global_header_tmpl_bytes, tmpl_err := ioutil.ReadFile(config.TemplateDir + "/global_header.html")
if tmpl_err != nil {
fmt.Println("Failed loading template \"" + config.TemplateDir + "/global_header.html\": " + tmpl_err.Error())
os.Exit(2)
}
global_header_tmpl_str = string(global_header_tmpl_bytes)
global_header_tmpl, tmpl_err = template.New("global_header_tmpl").Funcs(funcMap).Parse(string(global_header_tmpl_str))
if tmpl_err != nil {
fmt.Println("Failed loading template \"" + config.TemplateDir + "/global_header.html\": " + tmpl_err.Error())
os.Exit(2)
}
img_boardpage_tmpl_bytes, _ := ioutil.ReadFile(path.Join(config.TemplateDir, "img_boardpage.html"))
if tmpl_err != nil {
fmt.Println("Failed loading template \"" + config.TemplateDir + "/img_boardpage.html\": " + tmpl_err.Error())
os.Exit(2)
}
img_boardpage_tmpl_str = "{{$config := getInterface .Data 0}}" +
"{{$board_arr := (getInterface .Data 1).Data}}" +
"{{$section_arr := (getInterface .Data 2).Data}}" +
"{{$thread_arr := (getInterface .Data 3).Data}}" +
"{{$board_info := (getInterface .Data 4).Data}}" +
"{{$board := getInterface $board_info 0}}" +
string(img_boardpage_tmpl_bytes)
img_boardpage_tmpl, tmpl_err = template.New("img_boardpage_tmpl").Funcs(funcMap).Parse(img_boardpage_tmpl_str)
if tmpl_err != nil {
fmt.Println("Failed loading template \"" + config.TemplateDir + "/img_boardpage.html: \"" + tmpl_err.Error())
os.Exit(2)
}
img_threadpage_tmpl_bytes, _ := ioutil.ReadFile(path.Join(config.TemplateDir, "img_threadpage.html"))
if tmpl_err != nil {
fmt.Println("Failed loading template \"" + config.TemplateDir + "/img_threadpage.html\": " + tmpl_err.Error())
os.Exit(2)
}
img_threadpage_tmpl_str = "{{$config := getInterface .Data 0}}" +
"{{$board_arr := (getInterface .Data 1).Data}}" +
"{{$section_arr := (getInterface .Data 2).Data}}" +
"{{$post_arr := (getInterface .Data 3).Data}}" +
"{{$op := getElement $post_arr 0}}" +
"{{$board := getElement $board_arr (subtract $op.BoardID 1)}}" +
string(img_threadpage_tmpl_bytes)
img_threadpage_tmpl, tmpl_err = template.New("img_threadpage_tmpl").Funcs(funcMap).Parse(img_threadpage_tmpl_str)
if tmpl_err != nil {
fmt.Println("Failed loading template \"" + config.TemplateDir + "/img_threadpage.html: \"" + tmpl_err.Error())
os.Exit(2)
}
manage_header_tmpl_bytes, err := ioutil.ReadFile(config.TemplateDir + "/manage_header.html")
func loadTemplate(name string, filename string, before string) (*template.Template, error) {
tmplBytes, err := ioutil.ReadFile(config.TemplateDir + "/" + filename)
if err != nil {
fmt.Println(err.Error())
}
manage_header_tmpl_str = string(manage_header_tmpl_bytes)
manage_header_tmpl, tmpl_err = template.New("manage_header_tmpl").Funcs(funcMap).Parse(manage_header_tmpl_str)
if tmpl_err != nil {
fmt.Println("Failed loading template \"" + config.TemplateDir + "/manage_header.html\": " + tmpl_err.Error())
os.Exit(2)
}
manage_boards_tmpl_bytes, err := ioutil.ReadFile(config.TemplateDir + "/manage_boards.html")
if err != nil {
fmt.Println(err.Error())
}
manage_boards_tmpl_str = "{{$config := getInterface .Data 0}}" +
"{{$board := getInterface (getInterface .Data 1).Data 0}}" +
"{{$section_arr := (getInterface .Data 2).Data}}" +
string(manage_boards_tmpl_bytes)
manage_boards_tmpl, tmpl_err = template.New("manage_boards_tmpl").Funcs(funcMap).Parse(manage_boards_tmpl_str)
if tmpl_err != nil {
fmt.Println("Failed loading template \"" + config.TemplateDir + "/manage_boards.html\": " + tmpl_err.Error())
os.Exit(2)
}
manage_config_tmpl_bytes, err := ioutil.ReadFile(config.TemplateDir + "/manage_config.html")
if err != nil {
fmt.Println(err.Error())
}
manage_config_tmpl_str = "{{$config := getInterface .Data 0}}" +
string(manage_config_tmpl_bytes)
manage_config_tmpl, tmpl_err = template.New("manage_config_tmpl").Funcs(funcMap).Parse(manage_config_tmpl_str)
if tmpl_err != nil {
fmt.Println("Failed loading template \"" + config.TemplateDir + "/manage_config.html\": " + tmpl_err.Error())
os.Exit(2)
}
front_page_tmpl_bytes, err := ioutil.ReadFile(config.TemplateDir + "/front.html")
if err != nil {
fmt.Println(err.Error())
os.Exit(2)
}
front_page_tmpl_str = "{{$config := getInterface .Data 0}}" +
"{{$page_arr := getInterface .Data 1}}" +
"{{$board_arr := getInterface .Data 2}}" +
"{{$section_arr := getInterface .Data 3}}" +
"{{$recent_posts_arr := getInterface .Data 4}}" +
string(front_page_tmpl_bytes)
front_page_tmpl, tmpl_err = template.New("front_page_tmpl").Funcs(funcMap).Parse(front_page_tmpl_str)
if tmpl_err != nil {
fmt.Println("Failed loading template \"" + config.TemplateDir + "/front.html\": " + tmpl_err.Error())
os.Exit(2)
return nil, err
}
tmplStr := before + string(tmplBytes)
return template.New(name).Funcs(funcMap).Parse(tmplStr)
}
func getTemplateAsString(templ template.Template) (string, error) {
var buf bytes.Buffer
err := templ.Execute(&buf, config)
if err == nil {
return buf.String(), nil
func initTemplates() {
var err error
resetBoardSectionArrays()
banpage_tmpl, err = loadTemplate("banpage_tmpl", "banpage.html",
"{{$config := getInterface .Data 0}}"+
"{{$ban := getInterface .Data 1}}")
if err != nil {
println(0, "Failed loading template \""+config.TemplateDir+"/banpage.html: \""+err.Error())
os.Exit(2)
}
global_footer_tmpl, err = loadTemplate("global_footer_tmpl", "global_footer.html", "{{$config := getInterface .Data 0}}")
if err != nil {
println(0, "Failed loading template \""+config.TemplateDir+"/global_footer.html: \""+err.Error())
os.Exit(2)
}
global_header_tmpl, err = loadTemplate("global_header_tmpl", "global_header.html", "")
if err != nil {
println(0, "Failed loading template \""+config.TemplateDir+"/global_header.html: \""+err.Error())
os.Exit(2)
}
img_header_tmpl, err = loadTemplate("img_header_tmpl", "img_header.html",
"{{$config := getInterface .Data 0}}"+
"{{$board_arr := (getInterface .Data 1).Data}}"+
"{{$section_arr := (getInterface .Data 2).Data}}"+
"{{$post_arr := (getInterface .Data 3).Data}}"+
"{{$op := getElement $post_arr 0}}"+
"{{$board := getElement $board_arr (subtract $op.BoardID 1)}}")
if err != nil {
println(0, "Failed loading template \""+config.TemplateDir+"/img_header.html: \""+err.Error())
os.Exit(2)
}
img_boardpage_tmpl, err = loadTemplate("img_boardpage_tmpl", "img_boardpage.html",
"{{$config := getInterface .Data 0}}"+
"{{$board_arr := (getInterface .Data 1).Data}}"+
"{{$section_arr := (getInterface .Data 2).Data}}"+
"{{$thread_arr := (getInterface .Data 3).Data}}"+
"{{$board_info := (getInterface .Data 4).Data}}"+
"{{$board := getInterface $board_info 0}}")
if err != nil {
println(0, "Failed loading template \""+config.TemplateDir+"/img_boardpage.html: \""+err.Error())
os.Exit(2)
}
img_threadpage_tmpl, err = loadTemplate("img_threadpage_tmpl", "img_threadpage.html",
"{{$config := getInterface .Data 0}}"+
"{{$board_arr := (getInterface .Data 1).Data}}"+
"{{$section_arr := (getInterface .Data 2).Data}}"+
"{{$post_arr := (getInterface .Data 3).Data}}"+
"{{$op := getElement $post_arr 0}}"+
"{{$board := getElement $board_arr (subtract $op.BoardID 1)}}")
if err != nil {
println(0, "Failed loading template \""+config.TemplateDir+"/img_threadpage.html: \""+err.Error())
os.Exit(2)
}
manage_header_tmpl, err = loadTemplate("manage_header_tmpl", "manage_header.html", "")
if err != nil {
println(0, "Failed loading template \""+config.TemplateDir+"/manage_header.html: \""+err.Error())
os.Exit(2)
}
manage_boards_tmpl, err = loadTemplate("manage_boards_tmpl", "manage_boards.html",
"{{$config := getInterface .Data 0}}"+
"{{$board := getInterface (getInterface .Data 1).Data 0}}"+
"{{$section_arr := (getInterface .Data 2).Data}}")
if err != nil {
println(0, "Failed loading template \""+config.TemplateDir+"/manage_boards.html: \""+err.Error())
os.Exit(2)
}
manage_config_tmpl, err = loadTemplate("manage_config_tmpl", "manage_config.html", "{{$config := getInterface .Data 0}}")
if err != nil {
println(0, "Failed loading template \""+config.TemplateDir+"/manage_config.html: \""+err.Error())
os.Exit(2)
}
front_page_tmpl, err = loadTemplate("front_page_tmpl", "front.html",
"{{$config := getInterface .Data 0}}"+
"{{$page_arr := getInterface .Data 1}}"+
"{{$board_arr := getInterface .Data 2}}"+
"{{$section_arr := getInterface .Data 3}}"+
"{{$recent_posts_arr := getInterface .Data 4}}")
if err != nil {
println(0, "Failed loading template \""+config.TemplateDir+"/front.html\": "+err.Error())
os.Exit(2)
}
return "", err
}
func getStyleLinks(w http.ResponseWriter, stylesheet string) {
@ -376,9 +319,8 @@ func getStyleLinks(w http.ResponseWriter, stylesheet string) {
styles_map[i] = config.Styles_img[i]
}
err := manage_header_tmpl.Execute(w, config)
if err != nil {
fmt.Println(err.Error())
if err := manage_header_tmpl.Execute(w, config); err != nil {
println(0, err.Error())
os.Exit(2)
}
}

View file

@ -418,8 +418,7 @@ func initConfig() {
os.Exit(2)
}
err = json.Unmarshal(jfile, &config)
if err != nil {
if err = json.Unmarshal(jfile, &config); err != nil {
printf(0, "Error parsing \"gochan.json\": %s\n", err.Error())
os.Exit(2)
}

View file

@ -4,6 +4,7 @@ import (
"bytes"
"crypto/md5"
"crypto/sha1"
"database/sql"
"fmt"
"html"
"io"
@ -74,6 +75,25 @@ func byteByByteReplace(input, from, to string) string {
return input
}
// for easier defer cleaning
func closeFile(file *os.File) {
if file != nil {
file.Close()
}
}
func closeRows(rows *sql.Rows) {
if rows != nil {
rows.Close()
}
}
func closeStatement(stmt *sql.Stmt) {
if stmt != nil {
stmt.Close()
}
}
/*
Deletes files in a folder (root) that match a given regular expression.
Returns the number of files that were deleted, and any error encountered.
@ -166,23 +186,19 @@ func getBoardArr(parameterList map[string]interface{}, extra string) (boards []B
printf(2, "queryString@getBoardArr: %s\n", queryString)
stmt, err := db.Prepare(queryString)
defer func() {
if stmt != nil {
stmt.Close()
}
}()
if err != nil {
errorLog.Print(err.Error())
return
}
defer closeStatement(stmt)
rows, err := stmt.Query(parameterValues...)
// For each row in the results from the database, populate a new BoardsTable instance,
// then append it to the boards array we are going to return
for rows.Next() {
board := new(BoardsTable)
err = rows.Scan(
board.IName = "board"
if err = rows.Scan(
&board.ID,
&board.Order,
&board.Dir,
@ -208,11 +224,9 @@ func getBoardArr(parameterList map[string]interface{}, extra string) (boards []B
&board.RedirectToThread,
&board.RequireFile,
&board.EnableCatalog,
)
board.IName = "board"
if err != nil {
); err != nil {
errorLog.Print(err.Error())
fmt.Println(err.Error())
println(0, err.Error())
return
}
boards = append(boards, *board)
@ -243,16 +257,11 @@ func getPostArr(parameterList map[string]interface{}, extra string) (posts []int
printf(2, "queryString@getPostArr queryString: %s\n", queryString)
stmt, err := db.Prepare(queryString)
defer func() {
if stmt != nil {
stmt.Close()
}
}()
if err != nil {
errorLog.Print(err.Error())
return
}
defer closeStatement(stmt)
rows, err := stmt.Query(parameterValues...)
if err != nil {
@ -261,20 +270,22 @@ func getPostArr(parameterList map[string]interface{}, extra string) (posts []int
println(1, errortext)
return
}
defer closeRows(rows)
// For each row in the results from the database, populate a new PostTable instance,
// then append it to the posts array we are going to return
for rows.Next() {
var post PostTable
err = rows.Scan(&post.ID, &post.BoardID, &post.ParentID, &post.Name, &post.Tripcode,
post.IName = "post"
if err = rows.Scan(&post.ID, &post.BoardID, &post.ParentID, &post.Name, &post.Tripcode,
&post.Email, &post.Subject, &post.MessageHTML, &post.MessageText, &post.Password, &post.Filename,
&post.FilenameOriginal, &post.FileChecksum, &post.Filesize, &post.ImageW,
&post.ImageH, &post.ThumbW, &post.ThumbH, &post.IP, &post.Tag, &post.Timestamp,
&post.Autosage, &post.PosterAuthority, &post.DeletedTimestamp, &post.Bumped,
&post.Stickied, &post.Locked, &post.Reviewed, &post.Sillytag)
post.IName = "post"
if err != nil {
&post.Stickied, &post.Locked, &post.Reviewed, &post.Sillytag,
); err != nil {
errorLog.Print(err.Error())
fmt.Println(err.Error())
println(0, err.Error())
return
}
posts = append(posts, post)
@ -291,13 +302,13 @@ func getSectionArr(where string) (sections []interface{}, err error) {
errorLog.Print(err.Error())
return
}
defer closeRows(rows)
for rows.Next() {
section := new(BoardSectionsTable)
section.IName = "section"
err = rows.Scan(&section.ID, &section.Order, &section.Hidden, &section.Name, &section.Abbreviation)
if err != nil {
if err = rows.Scan(&section.ID, &section.Order, &section.Hidden, &section.Name, &section.Abbreviation); err != nil {
errorLog.Print(err.Error())
return
}
@ -367,13 +378,19 @@ func customError(v int, err error) (errored bool) {
if err != nil {
if config.Verbosity >= v {
file, line, _ := getMetaInfo(1)
fmt.Printf("[ERROR] %s:%d: %s\n", file, line, err.Error())
printf(v, "[ERROR] %s:%d: %s\n", file, line, err.Error())
}
return true
}
return false
}
func handleError(verbosity int, text string) string {
printf(verbosity, text)
errorLog.Println(text)
return text
}
func humanReadableTime(t time.Time) string {
return t.Format(config.DateTimeFormat)
}
@ -475,6 +492,9 @@ func bToA(b bool) string {
// Checks the validity of the Akismet API key given in the config file.
func checkAkismetAPIKey() {
resp, err := http.PostForm("https://rest.akismet.com/1.1/verify-key", url.Values{"key": {config.AkismetAPIKey}, "blog": {"http://" + config.SiteDomain}})
if err != nil {
handleError(1, err.Error())
}
defer func() {
if resp != nil && resp.Body != nil {
resp.Body.Close()
@ -482,7 +502,7 @@ func checkAkismetAPIKey() {
}()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
errorLog.Print(err.Error())
handleError(1, err.Error())
}
if string(body) == "invalid" {
// This should disable the Akismet checks if the API key is not valid.
@ -503,20 +523,20 @@ func checkPostForSpam(userIP string, userAgent string, referrer string,
req, err := http.NewRequest("POST", "https://"+config.AkismetAPIKey+".rest.akismet.com/1.1/comment-check",
strings.NewReader(data.Encode()))
if err != nil {
errorLog.Print(err.Error())
handleError(1, err.Error())
return "other_failure"
}
req.Header.Set("User-Agent", "gochan/1.0 | Akismet/0.1")
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
resp, err := client.Do(req)
if err != nil {
errorLog.Print(err.Error())
handleError(1, err.Error())
return "other_failure"
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
errorLog.Print(err.Error())
handleError(1, err.Error())
return "other_failure"
}
errorLog.Print("Response from Akismet: " + string(body))

View file

@ -1,7 +1,6 @@
<div id="footer">
<a href="/">Home</a> | <a href="http://127.0.0.1:8080/#boards">Boards</a> | <a href="http://127.0.0.1:8080/#rules">Rules</a> | <a href="http://127.0.0.1:8080/#faq">FAQ</a><br />
Powered by Gochan {{.Version}}<br />
Generated in over 9000 hours
<a href="{{$config.SiteWebfolder}}">Home</a> | <a href="{{$config.SiteWebfolder}}#boards">Boards</a> | <a href="{{$config.SiteWebfolder}}#rules">Rules</a> | <a href="{{$config.SiteWebfolder}}#faq">FAQ</a><br />
Powered by <a href="http://github.com/eggbertx/gochan/">Gochan {{$config.Version}}</a><br />
</div>
</body>
</html>

View file

@ -1,36 +1,6 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>/{{$board.Dir}}/ - {{$board.Title}}</title>
<script type="text/javascript" src="/javascript/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
var styles = [{{range $ii, $style := $config.Styles_img}}{{if gt $ii 0}}, {{end}}"{{$style}}"{{end}}];
var webroot = "{{$config.SiteWebfolder}}";
var thread_type = "board";
</script>
<script type="text/javascript" src="/javascript/gochan.js"></script>
<script type="text/javascript" src="/javascript/manage.js"></script>
<link rel="stylesheet" href="/css/global/img.css" />
{{range $i, $style := $config.Styles_img}}
<link rel="{{if isStyleNotDefault_img $style}}alternate {{end}}stylesheet" href="/css/{{$style}}/img.css" />{{end}}
<link rel="shortcut icon" href="/favicon.png" />
</head>
<body>
<div id="topbar">
{{range $i, $boardlink := $board_arr}}
<a href="/{{$boardlink.Dir}}/" class="topbar-item">/{{$boardlink.Dir}}/</a>
{{end}}
</div>
<div id="top-pane">
<span id="board-title">{{$board.Title}}</span><br />
<span id="board-subtitle">{{$board.Subtitle}}</span>
</div>
<hr />
<div id="right-sidelinks">
<a href="{{$config.SiteWebfolder}}{{$board.Dir}}/catalog.html">Board catalog</a><br />
</div>
<div id="postbox-area">
<form name="postform" action="/post" method="POST" enctype="multipart/form-data">
<input type="hidden" name="threadid" value="0" />
@ -81,16 +51,15 @@
{{end}}{{end}}
<div class="post-text">{{$reply.MessageHTML}}</div>
</div>
</div>
{{end}}
</div>{{end}}
</div>
<hr />
{{end}}
<hr />{{end}}
<div id="right-bottom-content">
<div id="report-delbox">
<input type="hidden" name="board" value="{{$board.Dir}}" />
<label>[<input type="checkbox" name="fileonly"/>File only]</label> <input type="password" size="10" name="password" id="delete-password" /> <input type="submit" name="delete_btn" value="Delete" onclick="return confirm('Are you sure you want to delete these posts?')" /><br />
Reason: <input type="text" size="10" name="reason" id="reason" /> <input type="submit" value="Report" />
Reason: <input type="text" size="10" name="reason" id="reason" /> <input type="submit" name="report_btn" value="Report" /><br />
Edit post <input type="submit" name="edit_btn" value="Edit" />
</div>
</div>
</form>
@ -117,10 +86,4 @@
[{{range $i, $boardlink := $board_arr}} {{if gt $i 0}}/{{end}} <a href="/{{$boardlink.Dir}}/">{{$boardlink.Dir}}</a> {{end}}]
</span>
</div>
</div>
<div id="footer">
<a href="{{$config.SiteWebfolder}}">Home</a> | <a href="{{$config.SiteWebfolder}}#boards">Boards</a> | <a href="{{$config.SiteWebfolder}}#rules">Rules</a> | <a href="{{$config.SiteWebfolder}}#faq">FAQ</a><br />
Powered by <a href="http://github.com/eggbertx/gochan/">Gochan {{$config.Version}}</a><br />
</div>
</body>
</html>
</div>

37
templates/img_header.html Normal file
View file

@ -0,0 +1,37 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
{{if stringNeq $op.Subject ""}}
<title>/{{$board.Dir}}/ - {{truncateString $op.Subject 20 true}}</title>
{{else}}{{if stringNeq $op.MessageHTML ""}}
<title>/{{$board.Dir}}/ - {{truncateString $op.MessageText 20 true}}</title>
{{end}}{{end}}
<title>/{{$board.Dir}} - {{$board.Title}}</title>
<script type="text/javascript" src="/javascript/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
var styles = [{{range $ii, $style := $config.Styles_img}}{{if gt $ii 0}}, {{end}}"{{$style}}"{{end}}];
var webroot = "{{$config.SiteWebfolder}}";
var thread_type = "thread";
function changePage(sel) {
window.location = webroot+"test/res/{{$op.ID}}p"+sel.value+".html";
}
</script>
<script type="text/javascript" src="/javascript/gochan.js"></script>
<script type="text/javascript" src="/javascript/manage.js"></script>
<link rel="stylesheet" href="/css/global/img.css" />
{{range $i, $style := $config.Styles_img}}
<link rel="{{if isStyleNotDefault_img $style}}alternate {{end}}stylesheet" href="/css/{{$style}}/img.css" />{{end}}
<link rel="shortcut icon" href="/favicon.png" />
</head>
<body>
<div id="topbar">
{{range $i, $board := $board_arr}}
<a href="/{{$board.Dir}}/" class="topbar-item">/{{$board.Dir}}/</a>
{{end}}
</div>
<div id="top-pane">
<span id="board-title">{{$board.Title}}</span><br />
<span id="board-subtitle">{{$board.Subtitle}}</span>
</div>
<hr />

View file

@ -1,40 +1,3 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
{{if stringNeq $op.Subject ""}}
<title>/{{$board.Dir}}/ - {{truncateString $op.Subject 20 true}}</title>
{{else}}{{if stringNeq $op.MessageHTML ""}}
<title>/{{$board.Dir}}/ - {{truncateString $op.MessageText 20 true}}</title>
{{end}}{{end}}
<title>/{{$board.Dir}} - {{$board.Title}}</title>
<script type="text/javascript" src="/javascript/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
var styles = [{{range $ii, $style := $config.Styles_img}}{{if gt $ii 0}}, {{end}}"{{$style}}"{{end}}];
var webroot = "{{$config.SiteWebfolder}}";
var thread_type = "thread";
function changePage(sel) {
window.location = webroot+"test/res/"+{{$op.ID}}+"p"+sel.value+".html";
}
</script>
<script type="text/javascript" src="/javascript/gochan.js"></script>
<script type="text/javascript" src="/javascript/manage.js"></script>
<link rel="stylesheet" href="/css/global/img.css" />
{{range $i, $style := $config.Styles_img}}
<link rel="{{if isStyleNotDefault_img $style}}alternate {{end}}stylesheet" href="/css/{{$style}}/img.css" />{{end}}
<link rel="shortcut icon" href="/favicon.png" />
</head>
<body>
<div id="topbar">
{{range $i, $board := $board_arr}}
<a href="/{{$board.Dir}}/" class="topbar-item">/{{$board.Dir}}/</a>
{{end}}
</div>
<div id="top-pane">
<span id="board-title">{{$board.Title}}</span><br />
<span id="board-subtitle">{{$board.Subtitle}}</span>
</div>
<hr />
<div id="threadlinks-top">
<a href="{{$config.SiteWebfolder}}{{$board.Dir}}/board.html" >Return</a><br />
<select id="changepage" onchange="changePage(this)">
@ -50,7 +13,6 @@
<div id="right-sidelinks">
<a href="{{$config.SiteWebfolder}}{{$board.Dir}}/catalog.html">Board catalog</a><br />
</div>
<div id="postbox-area">
<form name="postform" action="/post" method="POST" enctype="multipart/form-data">
<input type="hidden" name="threadid" value="{{$op.ID}}" />
@ -77,8 +39,7 @@
<a class="upload-container" href="{{$config.SiteWebfolder}}{{$board.Dir}}/src/{{$op.Filename}}"><img src="{{$config.SiteWebfolder}}{{$board.Dir}}/thumb/{{imageToThumbnailPath $op.Filename}}" width="{{$op.ThumbW}}" height="{{$op.ThumbH}}" class="upload" /></a>
{{else}}
<div class="file-deleted-box" style="text-align:center;">File removed</div>
{{end}}
{{end}}
{{end}}{{end}}
<input type="checkbox" id="check{{$op.ID}}" name="check{{$op.ID}}" /><label class="post-info" for="check{{$op.ID}}"> <span class="subject">{{$op.Subject}}</span> <span class="postername">{{if stringNeq $op.Email ""}}<a href="mailto:{{$op.Email}}">{{end}}{{if stringNeq $op.Name ""}}{{$op.Name}}{{else}}{{if stringEq $op.Tripcode ""}}{{$board.Anonymous}}{{end}}{{end}}{{if stringNeq $op.Email ""}}</a>{{end}}</span>{{if stringNeq $op.Tripcode ""}}<span class="tripcode">!{{$op.Tripcode}}</span>{{end}} {{formatTimestamp $op.Timestamp}} </label><a href="/{{$board.Dir}}/res/{{$op.ID}}.html#{{$op.ID}}">No.</a> <a href="javascript:quote({{$op.ID}})" class="backlink-click">{{$op.ID}}</a> <span class="post-links"> <span class="thread-ddown">[<a href="javascript:void(0)">&#9660;</a>]</span></span><br />
<div class="post-text">{{$op.MessageHTML}}</div>
</div>
@ -96,15 +57,15 @@
{{end}}{{end}}
<div class="post-text">{{$reply.MessageHTML}}</div>
</div>
</div>
{{end}}{{end}}
</div>{{end}}{{end}}
</div>
<hr />
<div id="right-bottom-content">
<div id="report-delbox">
<input type="hidden" name="board" value="{{$board.Dir}}" />
<label>[<input type="checkbox" name="fileonly"/>File only]</label> <input type="password" size="10" name="password" id="delete-password" /> <input type="submit" name="delete_btn" value="Delete" onclick="return confirm('Are you sure you want to delete these posts?')" /><br />
Reason: <input type="text" size="10" name="reason" id="reason" /> <input type="submit" value="Report" />
Reason: <input type="text" size="10" name="reason" id="reason" /> <input type="submit" name="report_btn" value="Report" /><br />
Edit post <input type="submit" name="edit_btn" value="Edit" />
</div>
</div>
</form>
@ -129,10 +90,4 @@
[{{range $i, $boardlink := $board_arr}} {{if gt $i 0}}/{{end}} <a href="/{{$boardlink.Dir}}/">{{$boardlink.Dir}}</a> {{end}}]
</span>
</div>
</div>
<div id="footer">
<a href="{{$config.SiteWebfolder}}">Home</a> | <a href="{{$config.SiteWebfolder}}#boards">Boards</a> | <a href="{{$config.SiteWebfolder}}#rules">Rules</a> | <a href="{{$config.SiteWebfolder}}#faq">FAQ</a><br />
Powered by <a href="http://github.com/eggbertx/gochan/">Gochan {{$config.Version}}</a><br />
</div>
</body>
</html>
</div>