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

Finish (mostly) ban page displaying contents according to the database

This commit is contained in:
Joshua Merrell 2018-10-05 15:21:36 -07:00
parent ad9d0989b2
commit 87628a8d92
14 changed files with 163 additions and 84 deletions

BIN
html/hittheroad.mp3 Normal file

Binary file not shown.

BIN
html/hittheroad.ogg Normal file

Binary file not shown.

BIN
html/hittheroad.wav Normal file

Binary file not shown.

BIN
html/permabanned.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

View file

@ -12,22 +12,34 @@ CREATE TABLE IF NOT EXISTS `DBPREFIXannouncements` (
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS `DBPREFIXappeals` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`ban` INT(11) UNSIGNED NOT NULL,
`message` TEXT NOT NULL,
`timestamp` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`denied` TINYINT(1) NOT NULL DEFAULT '0',
`staff_response` TEXT NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS `DBPREFIXbanlist` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`allow_read` TINYINT(1) DEFAULT '1',
`ip` VARCHAR(45) NOT NULL DEFAULT '',
`name` VARCHAR(255) NOT NULL,
`tripcode` CHAR(10) NOT NULL,
`message` TEXT NOT NULL,
`silent_ban` TINYINT(1) DEFAULT '0',
`name_is_regex` TINYINT(1) DEFAULT '0',
`filename` VARCHAR(255) NOT NULL DEFAULT '',
`file_checksum` VARCHAR(255) NOT NULL DEFAULT '',
`boards` VARCHAR(255) NOT NULL DEFAULT '*',
`banned_by` VARCHAR(50) NOT NULL,
`staff` VARCHAR(50) NOT NULL,
`timestamp` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`expires` TIMESTAMP NULL,
`permaban` TINYINT(1) NOT NULL DEFAULT '0',
`reason` VARCHAR(255) NOT NULL,
`type` TINYINT UNSIGNED NOT NULL DEFAULT '3',
`staff_note` VARCHAR(255) NOT NULL,
`appeal_message` VARCHAR(255) NOT NULL,
`appeal_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`can_appeal` TINYINT(1) NOT NULL DEFAULT '1',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;

View file

@ -569,17 +569,17 @@ var manage_functions = map[string]ManageFunction{
"bans": {
Permissions: 1,
Callback: func(writer http.ResponseWriter, request *http.Request) (html string) {
rows, err := querySQL("SELECT `ip`,`name`,`tripcode`,`reason`,`boards`,`banned_by`,`timestamp`,`expires` FROM `" + config.DBprefix + "banlist`")
rows, err := querySQL("SELECT `ip`,`name`,`reason`,`boards`,`staff`,`timestamp`,`expires` FROM `" + config.DBprefix + "banlist`")
defer closeRows(rows)
if err != nil {
html += "<hr />" + handleError(1, err.Error())
html += handleError(1, err.Error())
return
}
var banlist []BanlistTable
for rows.Next() {
var ban BanlistTable
rows.Scan(&ban.IP, &ban.Name, &ban.Tripcode, &ban.Reason, &ban.Boards, &ban.BannedBy, &ban.Timestamp, &ban.Expires)
rows.Scan(&ban.IP, &ban.Name, &ban.Reason, &ban.Boards, &ban.Staff, &ban.Timestamp, &ban.Expires)
banlist = append(banlist, ban)
}
manageBansBuffer := bytes.NewBufferString("")

View file

@ -564,12 +564,16 @@ func bumpThread(postID, boardID int) error {
// Checks check poster's name/tripcode/file checksum (from PostTable post) for banned status
// returns ban table if the user is banned or errNotBanned if they aren't
func getBannedStatus(post *PostTable, writer http.ResponseWriter) (BanlistTable, error) {
func getBannedStatus(post *PostTable) (BanlistTable, error) {
var banEntry BanlistTable
err := queryRowSQL("SELECT `ip`, `name`, `reason`, `boards`, `timestamp`, `expires`, `appeal_at` FROM `"+config.DBprefix+"banlist` WHERE `ip` = ? ORDER BY `id` DESC LIMIT 1",
[]interface{}{&post.IP},
[]interface{}{&banEntry.IP, &banEntry.Name, &banEntry.Reason, &banEntry.Boards, &banEntry.Timestamp, &banEntry.Expires, &banEntry.AppealAt},
err := queryRowSQL("SELECT `ip`,`name`,`boards`,`timestamp`,`expires`,`permaban`,`reason`,`type`,`appeal_at`,`can_appeal` FROM `"+config.DBprefix+"banlist` WHERE `ip` = ? OR `name` = ? OR `filename` = ? OR `file_checksum` = ? ORDER BY `id` DESC LIMIT 1",
[]interface{}{&post.IP, &post.Name, &post.Filename, &post.FileChecksum},
[]interface{}{
&banEntry.IP, &banEntry.Name, &banEntry.Boards, &banEntry.Timestamp,
&banEntry.Expires, &banEntry.Permaban, &banEntry.Reason, &banEntry.Type,
&banEntry.AppealAt, &banEntry.CanAppeal},
)
println(1, banEntry.Timestamp)
return banEntry, err
}
@ -1016,13 +1020,12 @@ func makePost(writer http.ResponseWriter, request *http.Request) {
}
}
banStatus, err := getBannedStatus(&post, writer)
banStatus, err := getBannedStatus(&post)
if err != nil && err != sql.ErrNoRows {
handleError(1, "Error in getBannedStatus: "+err.Error())
serveErrorPage(writer, err.Error())
return
}
if banStatus.IsBanned() {
var banpage_buffer bytes.Buffer
var banpage_html string

View file

@ -144,7 +144,7 @@ func initServer() {
server.AddNamespace("util", utilHandler)
server.AddNamespace("example", func(writer http.ResponseWriter, request *http.Request) {
if writer != nil {
_, _ = writer.Write([]byte("hahahaha"))
http.Redirect(writer, request, "https://www.youtube.com/watch?v=dQw4w9WgXcQ", http.StatusFound)
}
})
@ -183,7 +183,6 @@ func validReferrer(request *http.Request) bool {
// register /util handler
func utilHandler(writer http.ResponseWriter, request *http.Request) {
//writer.Header().Add("Content-Type", "text/css")
action := request.FormValue("action")
password := request.FormValue("password")
board := request.FormValue("board")
@ -377,7 +376,7 @@ func utilHandler(writer http.ResponseWriter, request *http.Request) {
buildThreadPages(&postBoard)
writer.Header().Add("refresh", "4;url="+request.Referer())
fmt.Fprintf(writer, "Attached image from %d deleted successfully\n", post.ID) //<br />\n<meta http-equiv=\"refresh\" content=\"1;url=/"+board+"/\">", post.ID)
fmt.Fprintf(writer, "Attached image from %d deleted successfully\n", post.ID)
} else {
// delete the post
if _, err = execSQL(

View file

@ -87,7 +87,7 @@ func connectToSQLServer() {
os.Exit(2)
}
}
checkDeprecatedSchema()
println(0, "complete.")
}
@ -158,3 +158,52 @@ func getSQLDateTime() string {
func getSpecificSQLDateTime(t time.Time) string {
return t.Format(mysqlDatetimeFormat)
}
// checkDeprecatedSchema checks the tables for outdated columns and column values
// and causes gochan to quit with an error message specific to the needed change
func checkDeprecatedSchema() {
var hasColumn int
var err error
execSQL("ALTER TABLE `"+config.DBprefix+"banlist` CHANGE COLUMN `id` `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT", nil)
if err = queryRowSQL(
"SELECT COUNT(*) FROM information_schema.COlUMNS WHERE `TABLE_SCHEMA` = '"+config.DBname+"' AND TABLE_NAME = '"+config.DBprefix+"banlist' AND COLUMN_NAME = 'appeal_message'",
[]interface{}{}, []interface{}{&hasColumn},
); err != nil {
println(0, "error checking for deprecated column: "+err.Error())
os.Exit(2)
return
}
if hasColumn > 0 {
// Running them one at a time, in case we get errors from individual queries
execSQL("ALTER TABLE `"+config.DBprefix+"banlist` CHANGE COLUMN `banned_by` `staff` VARCHAR(50) NOT NULL", nil)
execSQL("ALTER TABLE `"+config.DBprefix+"banlist` ADD COLUMN `type` TINYINT UNSIGNED NOT NULL DEFAULT '3'", nil)
execSQL("ALTER TABLE `"+config.DBprefix+"banlist` ADD COLUMN `name_is_regex` TINYINT(1) DEFAULT '0'", nil)
execSQL("ALTER TABLE `"+config.DBprefix+"banlist` ADD COLUMN `filename` VARCHAR(255) NOT NULL DEFAULT ''", nil)
execSQL("ALTER TABLE `"+config.DBprefix+"banlist` ADD COLUMN `file_checksum` VARCHAR(255) NOT NULL DEFAULT ''", nil)
execSQL("ALTER TABLE `"+config.DBprefix+"banlist` ADD COLUMN `permaban` TINYINT(1) DEFAULT '0'", nil)
execSQL("ALTER TABLE `"+config.DBprefix+"banlist` ADD COLUMN `can_appeal` TINYINT(1) DEFAULT '1'", nil)
execSQL("ALTER TABLE `"+config.DBprefix+"banlist` DROP COLUMN `message`", nil)
println(0, "The column `appeal_message` in table "+config.DBprefix+"banlist is deprecated. A new table , `"+config.DBprefix+"appeals` has been created for it, and the banlist table will be modified accordingly.")
println(0, "Just to be safe, you may want to check both tables to make sure everything is good.")
rows, err := querySQL("SELECT `id`,`appeal_message` FROM `" + config.DBprefix + "banlist`")
if err != nil {
println(0, "Error updating banlist schema: "+err.Error())
os.Exit(2)
return
}
for rows.Next() {
var id int
var appeal_message string
rows.Scan(&id, &appeal_message)
if appeal_message != "" {
execSQL("INSERT INTO `"+config.DBprefix+"appeals` (`ban`,`message`) VALUES(?,?)", &id, &appeal_message)
}
execSQL("ALTER TABLE `" + config.DBprefix + "banlist` DROP COLUMN `appeal_message`")
}
}
}

View file

@ -225,6 +225,9 @@ var funcMap = template.FuncMap{
tableOut += "</table>\n"
return tableOut
},
"bannedForever": func(ban BanlistTable) bool {
return ban.Permaban && !ban.CanAppeal && ban.Type == 3 && ban.Boards == ""
},
}
var (

View file

@ -56,22 +56,44 @@ type AnnouncementsTable struct {
Timestamp time.Time
}
type BanlistTable struct {
ID uint
AllowRead bool
IP string
Name string
Tripcode string
type AppealsTable struct {
ID int
Ban int
Message string
SilentBan uint8
Boards string
BannedBy string
Timestamp time.Time
Expires time.Time
Reason string
StaffNote string
AppealMessage string
AppealAt time.Time
Denied bool
StaffResponse string
}
func (a *AppealsTable) GetBan() (BanlistTable, error) {
var ban BanlistTable
var err error
err = queryRowSQL("SELECT * FROM `"+config.DBprefix+"banlist` WHERE `id` = ? LIMIT 1",
[]interface{}{a.ID}, []interface{}{
&ban.ID, &ban.AllowRead, &ban.IP, &ban.Name, &ban.NameIsRegex, &ban.SilentBan,
&ban.Boards, &ban.Staff, &ban.Timestamp, &ban.Expires, &ban.Permaban, &ban.Reason,
&ban.StaffNote, &ban.AppealAt},
)
return ban, err
}
type BanlistTable struct {
ID uint
AllowRead bool
IP string
Name string
NameIsRegex bool
SilentBan uint8
Boards string
Staff string
Timestamp time.Time
Expires time.Time
Permaban bool
Reason string
Type int
StaffNote string
AppealAt time.Time
CanAppeal bool
}
func (bt *BanlistTable) IsBanned() bool {

View file

@ -582,20 +582,6 @@ func makePostJSON(post PostTable, anonymous string) (postObj PostJSON) {
return
}
func getBan(post PostTable) (*BanlistTable, error) {
ban := new(BanlistTable)
if err := queryRowSQL(
"SELECT `ip`, `name`, `tripcode`, `message`, `boards`, `banned_by`, `timestamp`, `expires`, `reason` FROM `"+config.DBprefix+"banlist` "+
"WHERE ? like `ip` OR ? REGEXP `name` OR ? REGEXP `tripcode`",
[]interface{}{post.IP, post.Name, post.Tripcode},
[]interface{}{&ban.IP, &ban.Name, &ban.Tripcode},
); err != nil {
return nil, err
}
return ban, nil
}
func ipMatch(newIP, existingIP string) bool {
if newIP == existingIP {
// both are single IPs and are the same

View file

@ -22,7 +22,7 @@
<br /><br />
<div class="section-block" style="margin: 0px 26px 0px 24px">
<div class="section-title-block">
<span class="section-title"><b>YOU ARE BANNED :(</b></span>
<span class="section-title"><b>{{if bannedForever .ban}}YOUR'E BANNED, IDIOT!{{else}}YOU ARE BANNED :({{end}}</b></span>
</div>
<div class="section-body" style="padding-top:8px">
<div id="ban-info" style="float:left">{{if eq $.ban.Boards ""}}
@ -30,22 +30,26 @@
You are banned from posting on <b>{{.ban.Boards}}</b> for the following reason:{{end}}
<br /><br />
<b>{{.ban.Reason}}</b>
<br /><br />{{$expires_timestamp := formatTimestamp .ban.Expires}}{{$appeal_timestamp := formatTimestamp .ban.AppealAt}}{{if eq $expires_timestamp "Mon, January 01, 0001 00:00 AM"}}
Your ban was placed on {{formatTimestamp .ban.Timestamp}} and will <b>not expire.</b><br />{{else}}
Your ban was placed on <b>{{formatTimestamp .ban.Timestamp}}</b> and will expire on <b>{{$expires_timestamp}}</b><br />{{end}}
<br />{{if eq $appeal_timestamp "Mon, January 01, 0001 00:00 AM"}}
You may not appeal this ban.{{else}}
You may appeal this ban on <b>{{$appeal_timestamp}}</b>.{{end}}
<br /><br />
<br /><br />{{$expires_timestamp := formatTimestamp .ban.Expires}}{{$appeal_timestamp := formatTimestamp .ban.AppealAt}}
Your ban was placed on {{formatTimestamp .ban.Timestamp}} and will
{{if .ban.Permaban}}<b>not expire</b>{{else}}expire on <b>{{$expires_timestamp}}</b>{{end}}.<br />
Your IP address is <b>{{.ban.IP}}</b>.<br /><br />
<form id="appeal-form">
<table id="postbox-static">
<tr><th class="postblock">Email</th><td><input type="email" name="email" /><input type="submit" value="Appeal" /></td></tr>
<tr><th class="postblock">Message</th><td><textarea rows="4" cols="48" name="postmsg" id="postmsg"></textarea></td></tr>
</table>
</form>
{{if .ban.CanAppeal}}You may appeal this ban:<br />
<form id="appeal-form">
<textarea rows="4" cols="48" name="postmsg" id="postmsg" placeholder="Appeal message"></textarea><br />
<input type="submit" value="Submit" /><br />
</form>{{else}}You may <b>not</b> appeal this ban.<br />{{end}}
</div>
{{if bannedForever .ban}}
<img id="banpage-image" src="/permabanned.jpg" style="float:right; margin: 4px 8px 8px 4px"/><br />
<audio id="jack" preload="auto" autobuffer loop>
<source src="{{.config.SiteWebfolder}}hittheroad.ogg" />
<source src="{{.config.SiteWebfolder}}hittheroad.wav" />
<source src="{{.config.SiteWebfolder}}hittheroad.mp3" />
</audio>
<script type="text/javascript">
document.getElementById("jack").play();
</script>{{else}}<img id="banpage-image" src="/banned.jpg" style="float:right; margin: 4px 8px 8px 4px"/><br />{{end}}
</div>
<img id="banpage-image" src="/banned.jpg" style="float:right; margin: 4px 8px 8px 4px"/><br />
</div>
</div>
{{template "global_footer.html" .}}

View file

@ -2,32 +2,33 @@
<form method="POST" action="/manage">
<input type="hidden" name="action" value="bans" />
<fieldset><legend>User filter</legend>
<b>IP address:</b> <input type="text" name="ip" /><br />
"192.168.1.36" will ban posts from that IP address<br />
"192.168" will block all IPs starting with 192.168<br /><hr />
<b>Name!Tripcode:</b> <input type="text" name="name" /><br />
<b>Ban filename:</b> <input type="text" name="filename" /><br />
<b>Ban file checksum: </b> <i>3bdffa672fefe458223629815d3b63e1</i> <input type="checkbox" />
</fieldset><br />
<b>User filter:</b><br />
<table>
<tr><th>IP address</th><td><input type="text" name="ip" /></td></tr>
<tr><th></th><td>"192.168.1.36" will ban posts from that IP address<br />
"192.168" will block all IPs starting with 192.168<br /></td></tr>
<tr><th>Name!Tripcode</th><td><input type="text" name="name" /> <label>Regex<input type="checkbox" name="nameregex" /></label></td></tr>
<tr><th>Ban filename</th><td><input type="text" name="filename" /></td></tr>
<tr><th>Ban file checksum</th><td>3bdffa672fefe458223629815d3b63e1 <input type="checkbox" /></td></tr>
</table><br /><hr />
<fieldset><legend>Ban info</legend>
<b>Duration:</b><sup title="e.g. '1y2mo3w4d5h6m7s', '1 year 2 months 3 weeks 4 days 5 hours 6 minutes 7 seconds' or 'forever', '0', or '' for a permaban">[?]</sup> <input type="text" name="ban-duration" /><br />
<b>Ban type:</b><br />
<label>Image ban <input type="checkbox" name="image-ban" /></label><br />
<label>Thread starting ban <input type="checkbox" name="thread-ban" /></label><br />
<label>Full ban (overrides the above) <input type="checkbox" name="full-ban" /></label><hr />
<table class="baninfotable">
<tr><td><b>Boards:</b><sup title="Comma-separated list of boards (e.g. board1,board2,board3) or blank for all boards">[?]</sup></td><td><input type="text" name="boards" /></td></tr>
<tr><td><b>Reason:</b></td><td><textarea name="reason" rows="5" cols="30"></textarea></td></tr>
<tr><td><b>Staff note:</b></td><td><input type="text" name="staff-note" /></td></tr>
</table>
</fieldset>
<b>Ban info</b><br />
<table>
<tr><th>Duration</th><td><input type="text" name="ban-duration" /></td></tr>
<tr><th></th><td>e.g. '1y2mo3w4d5h6m7s',<br />'1 year 2 months 3 weeks 4 days 5 hours 6 minutes 7 seconds',<br /> or 'forever', '0', or '' for a permaban</td></tr>
<tr><th>Ban type</th><td><label>Image ban <input type="checkbox" name="image-ban" /></label><br />
<label>Thread starting ban <input type="checkbox" name="thread-ban" /></label><br />
<label>Full ban (overrides the above) <input type="checkbox" name="full-ban" /></label></tr>
<tr><th>Boards</th><td><input type="text" name="boards" /></td></tr>
<tr><th></th><td>Comma-separated list of boards (e.g. board1,board2,board3) or blank for all boards</td></tr>
<tr><th>Reason</th><td><textarea name="reason" rows="5" cols="30"></textarea></td></tr>
<tr><th>Staff note</th><td><input type="text" name="staff-note" /></td></tr>
</table>
<h2>Banlist</h2>
<table>
<th>IP</th><th>Name!Tripcode</th><th>Reason</th><th>Boards</th><th>Staff</th><th>Set</th><th>Expires</th>
{{range $b, $ban := $.banlist}}<tr>
<td>{{$ban.IP}}</td><td>{{$ban.Name}}</td><td>{{$ban.Reason}}</td><td>{{$ban.Boards}}</td><td>{{$ban.BannedBy}}</td><td>{{$ban.Timestamp}}</td><td>{{$ban.Expires}}</td>
<td>{{$ban.IP}}</td><td>{{$ban.Name}}</td><td>{{$ban.Reason}}</td><td>{{if eq $ban.Boards ""}}<i>all boards</i>{{else}}{{$ban.Boards}}{{end}}</td><td>{{$ban.Staff}}</td><td>{{$ban.Timestamp}}</td><td>{{$ban.Expires}}</td>
</tr>{{end}}
</table>