mirror of
https://github.com/Eggbertx/gochan.git
synced 2025-08-24 08:46:24 -07:00
Add support for PostgreSQL and SQLite
This commit is contained in:
parent
72774c48aa
commit
317f9d4ba0
19 changed files with 928 additions and 539 deletions
|
@ -7,6 +7,6 @@
|
|||
<h1>404: File not found</h1>
|
||||
<img src="/error/lol 404.gif" border="0" alt="">
|
||||
<p>The requested file could not be found on this server. Are you just typing random stuff in the address bar? If you followed a link from this site here, then post <a href="/site">here</a></p>
|
||||
<hr><address>http://gochan.org powered by Gochan v2.7.0</address>
|
||||
<hr><address>http://gochan.org powered by Gochan v2.8.0</address>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -7,6 +7,6 @@
|
|||
<h1>500: Internal Server error</h1>
|
||||
<img src="/error/derpy server.gif" border="0" alt="">
|
||||
<p>The server encountered an error while trying to serve the page, and we apologize for the inconvenience. The <a href="https://en.wikipedia.org/wiki/Idiot">system administrator</a> will try to fix things as soon has he/she/it can.</p>
|
||||
<hr><address>http://gochan.org powered by Gochan v2.7.0</address>
|
||||
<hr><address>http://gochan.org powered by Gochan v2.8.0</address>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -2,97 +2,94 @@
|
|||
-- DO NOT DELETE
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `DBPREFIXannouncements` (
|
||||
`id` SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`subject` VARCHAR(45) NOT NULL,
|
||||
`message` TEXT NOT NULL,
|
||||
`poster` VARCHAR(45) NOT NULL,
|
||||
`id` SERIAL,
|
||||
`subject` VARCHAR(45) NOT NULL DEFAULT '',
|
||||
`message` TEXT NOT NULL CHECK (message <> ''),
|
||||
`poster` VARCHAR(45) NOT NULL CHECK (poster <> ''),
|
||||
`timestamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
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,
|
||||
`id` SERIAL,
|
||||
`ban` INT(11) UNSIGNED NOT NULL CHECK (ban <> 0),
|
||||
`message` TEXT NOT NULL CHECK (message <> ''),
|
||||
`timestamp` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
`denied` TINYINT(1) NOT NULL DEFAULT '0',
|
||||
`staff_response` TEXT NOT NULL,
|
||||
`denied` BOOLEAN DEFAULT false,
|
||||
`staff_response` TEXT NOT NULL DEFAULT '',
|
||||
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',
|
||||
CREATE TABLE IF NOT EXISTS DBPREFIXbanlist (
|
||||
`id` SERIAL,
|
||||
`allow_read` BOOLEAN DEFAULT TRUE,
|
||||
`ip` VARCHAR(45) NOT NULL DEFAULT '',
|
||||
`name` VARCHAR(255) NOT NULL,
|
||||
`name_is_regex` TINYINT(1) DEFAULT '0',
|
||||
`name` VARCHAR(255) NOT NULL DEFAULT '',
|
||||
`name_is_regex` BOOLEAN DEFAULT FALSE,
|
||||
`filename` VARCHAR(255) NOT NULL DEFAULT '',
|
||||
`file_checksum` VARCHAR(255) NOT NULL DEFAULT '',
|
||||
`boards` VARCHAR(255) NOT NULL DEFAULT '',
|
||||
`staff` VARCHAR(50) NOT NULL,
|
||||
`boards` VARCHAR(255) NOT NULL DEFAULT '*',
|
||||
`staff` VARCHAR(50) NOT NULL DEFAULT '',
|
||||
`timestamp` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
`expires` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`permaban` TINYINT(1) NOT NULL DEFAULT '1',
|
||||
`reason` VARCHAR(255) NOT NULL,
|
||||
`type` TINYINT UNSIGNED NOT NULL DEFAULT '3',
|
||||
`staff_note` VARCHAR(255) NOT NULL,
|
||||
`permaban` BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
`reason` VARCHAR(255) NOT NULL DEFAULT '',
|
||||
`type` SMALLINT NOT NULL DEFAULT 3,
|
||||
`staff_note` VARCHAR(255) NOT NULL DEFAULT '',
|
||||
`appeal_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`can_appeal` TINYINT(1) NOT NULL DEFAULT '1',
|
||||
PRIMARY KEY (`id`)
|
||||
`can_appeal` BOOLEAN NOT NULL DEFAULT true,
|
||||
PRIMARY KEY (id)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
ALTER TABLE `DBPREFIXbanlist`
|
||||
CHANGE IF EXISTS `banned_by` `staff` VARCHAR(50) NOT NULL,
|
||||
CHANGE IF EXISTS `id` `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
CHANGE IF EXISTS `banned_by` `staff` VARCHAR(50) NOT NULL DEFAULT '',
|
||||
CHANGE IF EXISTS `id` `id` SERIAL,
|
||||
CHANGE IF EXISTS `expires` `expires` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
CHANGE IF EXISTS `boards` `boards` VARCHAR(255) NOT NULL DEFAULT '',
|
||||
ADD COLUMN IF NOT EXISTS `type` TINYINT UNSIGNED NOT NULL DEFAULT '3',
|
||||
ADD COLUMN IF NOT EXISTS `name_is_regex` TINYINT(1) DEFAULT '0',
|
||||
CHANGE IF EXISTS `boards` `boards` VARCHAR(255) NOT NULL DEFAULT '*',
|
||||
ADD COLUMN IF NOT EXISTS `type` TINYINT UNSIGNED NOT NULL DEFAULT 3,
|
||||
ADD COLUMN IF NOT EXISTS `name_is_regex` BOOLEAN DEFAULT FALSE,
|
||||
ADD COLUMN IF NOT EXISTS `filename` VARCHAR(255) NOT NULL DEFAULT '',
|
||||
ADD COLUMN IF NOT EXISTS `file_checksum` VARCHAR(255) NOT NULL DEFAULT '',
|
||||
ADD COLUMN IF NOT EXISTS `permaban` TINYINT(1) DEFAULT '0',
|
||||
ADD COLUMN IF NOT EXISTS `can_appeal` TINYINT(1) DEFAULT '1',
|
||||
ADD COLUMN IF NOT EXISTS `permaban` BOOLEAN DEFAULT FALSE,
|
||||
ADD COLUMN IF NOT EXISTS `can_appeal` BOOLEAN DEFAULT TRUE,
|
||||
DROP COLUMN IF EXISTS `message`;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `DBPREFIXbannedhashes` (
|
||||
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`checksum` VARCHAR(45) NOT NULL,
|
||||
`description` VARCHAR(45) NOT NULL,
|
||||
PRIMARY KEY(`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
DROP TABLE IF EXISTS `DBPREFIXbannedhashes`;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `DBPREFIXboards` (
|
||||
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`order` TINYINT UNSIGNED NOT NULL DEFAULT 0,
|
||||
`dir` VARCHAR(45) NOT NULL,
|
||||
`type` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`upload_type` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`title` VARCHAR(45) NOT NULL,
|
||||
`id` SERIAL,
|
||||
`list_order` TINYINT UNSIGNED NOT NULL DEFAULT 0,
|
||||
`dir` VARCHAR(45) NOT NULL CHECK (dir <> ''),
|
||||
`type` TINYINT UNSIGNED NOT NULL DEFAULT 0,
|
||||
`upload_type` TINYINT UNSIGNED NOT NULL DEFAULT 0,
|
||||
`title` VARCHAR(45) NOT NULL CHECK (title <> ''),
|
||||
`subtitle` VARCHAR(64) NOT NULL DEFAULT '',
|
||||
`description` VARCHAR(64) NOT NULL DEFAULT '',
|
||||
`section` VARCHAR(45) NOT NULL,
|
||||
`max_image_size` INT UNSIGNED NOT NULL DEFAULT 4718592,
|
||||
`section` INT NOT NULL DEFAULT 1,
|
||||
`max_file_size` INT UNSIGNED NOT NULL DEFAULT 4718592,
|
||||
`max_pages` TINYINT UNSIGNED NOT NULL DEFAULT 11,
|
||||
`default_style` VARCHAR(45) NOT NULL,
|
||||
`locked` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`locked` BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
`created_on` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`anonymous` VARCHAR(45) NOT NULL DEFAULT 'Anonymous',
|
||||
`forced_anon` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`forced_anon` BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
`max_age` INT(20) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`autosage_after` INT(5) UNSIGNED NOT NULL DEFAULT 200,
|
||||
`no_images_after` INT(5) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`max_message_length` INT(10) UNSIGNED NOT NULL DEFAULT 8192,
|
||||
`embeds_allowed` TINYINT(1) NOT NULL DEFAULT 1,
|
||||
`redirect_to_thread` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`require_file` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`enable_catalog` TINYINT(1) UNSIGNED NOT NULL DEFAULT 1,
|
||||
`embeds_allowed` BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
`redirect_to_thread` BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
`require_file` BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
`enable_catalog` BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE (`dir`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=0;
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
ALTER TABLE `DBPREFIXboards`
|
||||
CHANGE COLUMN IF EXISTS `order` `list_order` INT UNSIGNED NOT NULL DEFAULT 0,
|
||||
CHANGE COLUMN IF EXISTS `max_image_size` `max_file_size` INT UNSIGNED NOT NULL DEFAULT 4718592,
|
||||
DROP COLUMN IF EXISTS `locale`;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `DBPREFIXembeds` (
|
||||
`id` TINYINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`id` SERIAL,
|
||||
`filetype` VARCHAR(3) NOT NULL,
|
||||
`name` VARCHAR(45) NOT NULL,
|
||||
`video_url` VARCHAR(255) NOT NULL,
|
||||
|
@ -102,27 +99,7 @@ CREATE TABLE IF NOT EXISTS `DBPREFIXembeds` (
|
|||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `DBPREFIXfiletypes` (
|
||||
`id` TINYINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`filetype` VARCHAR(10) NOT NULL,
|
||||
`mime` VARCHAR(45) NOT NULL,
|
||||
`thumb_image` VARCHAR(255) NOT NULL,
|
||||
`image_w` INT UNSIGNED NOT NULL DEFAULT 0,
|
||||
`image_h` INT UNSIGNED NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `DBPREFIXfrontpage` (
|
||||
`id` SMALLINT(5) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`page` TINYINT(3) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`order` TINYINT(3) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`subject` VARCHAR(140) NOT NULL,
|
||||
`message` TEXT NOT NULL,
|
||||
`timestamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`poster` VARCHAR(45) NOT NULL,
|
||||
`email` VARCHAR(45) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
DROP TABLE IF EXISTS `DBPREFIXDBPREFIXfrontpage`;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `DBPREFIXinfo` (
|
||||
`name` VARCHAR(45) NOT NULL,
|
||||
|
@ -131,32 +108,21 @@ CREATE TABLE IF NOT EXISTS `DBPREFIXinfo` (
|
|||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `DBPREFIXlinks` (
|
||||
`id` TINYINT NOT NULL AUTO_INCREMENT,
|
||||
`id` SERIAL,
|
||||
`title` VARCHAR(45) NOT NULL,
|
||||
`url` VARCHAR(255) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `DBPREFIXloginattempts` (
|
||||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`ip` VARCHAR(45) NOT NULL,
|
||||
`timestamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `DBPREFIXpluginsettings` (
|
||||
`module` CHAR(32) NOT NULL,
|
||||
`key` VARCHAR(200) NOT NULL DEFAULT '',
|
||||
`value` TEXT NOT NULL,
|
||||
PRIMARY KEY(`module`,`key`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
DROP TABLE IF EXISTS DBPREFIXloginattempts;
|
||||
DROP TABLE IF EXISTS DBPREFIXpluginsettings;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `DBPREFIXposts` (
|
||||
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`id` SERIAL,
|
||||
`boardid` INT NOT NULL,
|
||||
`parentid` INT(10) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`name` VARCHAR(50) NOT NULL,
|
||||
`tripcode` CHAR(10) NOT NULL,
|
||||
`tripcode` VARCHAR(10) NOT NULL,
|
||||
`email` VARCHAR(50) NOT NULL,
|
||||
`subject` VARCHAR(100) NOT NULL,
|
||||
`message` TEXT NOT NULL,
|
||||
|
@ -173,72 +139,77 @@ CREATE TABLE IF NOT EXISTS `DBPREFIXposts` (
|
|||
`ip` VARCHAR(45) NOT NULL DEFAULT '',
|
||||
`tag` VARCHAR(5) NOT NULL DEFAULT '',
|
||||
`timestamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`autosage` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`autosage` BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
`deleted_timestamp` TIMESTAMP,
|
||||
`bumped` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`stickied` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`locked` TINYINT(1) NOT NULL DEFAULT 0,
|
||||
`reviewed` TINYINT(1) NOT NULL DEFAULT 0,
|
||||
`sillytag` TINYINT(1) NOT NULL DEFAULT 0,
|
||||
`stickied` BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
`locked` BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
`reviewed` BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
PRIMARY KEY (`boardid`,`id`),
|
||||
KEY `parentid` (`parentid`),
|
||||
KEY `bumped` (`bumped`),
|
||||
KEY `file_checksum` (`file_checksum`),
|
||||
KEY `stickied` (`stickied`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=1;
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
ALTER TABLE `DBPREFIXposts`
|
||||
DROP COLUMN IF EXISTS `sillytag`,
|
||||
DROP COLUMN IF EXISTS `poster_authority`;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `DBPREFIXreports` (
|
||||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`id` SERIAL,
|
||||
`board` VARCHAR(45) NOT NULL,
|
||||
`postid` INT(10) UNSIGNED NOT NULL,
|
||||
`timestamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`ip` VARCHAR(45) NOT NULL,
|
||||
`reason` VARCHAR(255) NOT NULL,
|
||||
`cleared` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`istemp` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`cleared` BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
`istemp` BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `DBPREFIXsections` (
|
||||
`id` TINYINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`order` TINYINT UNSIGNED NOT NULL DEFAULT 0,
|
||||
`hidden` TINYINT(1) UNSIGNED NOT NULL,
|
||||
`id` SERIAL,
|
||||
`list_order` INT UNSIGNED NOT NULL DEFAULT 0,
|
||||
`hidden` BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
`name` VARCHAR(45) NOT NULL,
|
||||
`abbreviation` VARCHAR(10) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
ALTER TABLE `DBPREFIXsections`
|
||||
CHANGE COLUMN IF EXISTS `order` `list_order` INT UNSIGNED NOT NULL DEFAULT 0;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `DBPREFIXsessions` (
|
||||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`key` CHAR(10) NOT NULL,
|
||||
`data` VARCHAR(45) NOT NULL,
|
||||
`id` SERIAL,
|
||||
`name` CHAR(16) NOT NULL,
|
||||
`sessiondata` VARCHAR(45) NOT NULL,
|
||||
`expires` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MEMORY DEFAULT CHARSET=utf8mb4;
|
||||
ALTER TABLE `DBPREFIXsessions`
|
||||
CHANGE IF EXISTS `key` `name` CHAR(16) NOT NULL,
|
||||
CHANGE IF EXISTS `data` `sessiondata` VARCHAR(45) NOT NULL;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `DBPREFIXstaff` (
|
||||
`id` SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`id` SERIAL,
|
||||
`username` VARCHAR(45) NOT NULL,
|
||||
`password_checksum` VARCHAR(120) NOT NULL,
|
||||
`salt` CHAR(3) NOT NULL,
|
||||
`rank` TINYINT(1) UNSIGNED NOT NULL,
|
||||
`boards` VARCHAR(128) NOT NULL DEFAULT 'all',
|
||||
`rank` TINYINT(1) UNSIGNED NOT NULL DEFAULT 2,
|
||||
`boards` VARCHAR(128) NOT NULL DEFAULT '*',
|
||||
`added_on` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`last_active` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE (`username`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
ALTER TABLE `DBPREFIXstaff`
|
||||
CHANGE IF EXISTS `boards` `boards` VARCHAR(128) NOT NULL DEFAULT '*';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `DBPREFIXwordfilters` (
|
||||
`id` SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`from` VARCHAR(75) NOT NULL,
|
||||
`to` VARCHAR(75) NOT NULL,
|
||||
`boards` TEXT NOT NULL,
|
||||
`regex` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`id` SERIAL,
|
||||
`search` VARCHAR(75) NOT NULL CHECK (search <> ''),
|
||||
`change_to` VARCHAR(75) NOT NULL DEFAULT '',
|
||||
`boards` VARCHAR(128) NOT NULL DEFAULT '*',
|
||||
`regex` BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
SET sql_notes=1;
|
177
initdb_postgres.sql
Normal file
177
initdb_postgres.sql
Normal file
|
@ -0,0 +1,177 @@
|
|||
-- Gochan PostgreSQL/SQLite startup/update script
|
||||
-- DO NOT DELETE
|
||||
|
||||
CREATE TABLE IF NOT EXISTS DBPREFIXannouncements (
|
||||
id SERIAL,
|
||||
subject VARCHAR(45) NOT NULL DEFAULT '',
|
||||
message TEXT NOT NULL CHECK (message <> ''),
|
||||
poster VARCHAR(45) NOT NULL CHECK (poster <> ''),
|
||||
timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS DBPREFIXappeals (
|
||||
id SERIAL,
|
||||
ban INT NOT NULL CHECK (ban <> 0),
|
||||
message TEXT NOT NULL CHECK (message <> ''),
|
||||
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
denied BOOLEAN DEFAULT FALSE,
|
||||
staff_response TEXT NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS DBPREFIXbanlist (
|
||||
id SERIAL,
|
||||
allow_read BOOLEAN DEFAULT TRUE,
|
||||
ip VARCHAR(45) NOT NULL DEFAULT '',
|
||||
name VARCHAR(255) NOT NULL DEFAULT '',
|
||||
name_is_regex BOOLEAN DEFAULT FALSE,
|
||||
filename VARCHAR(255) NOT NULL DEFAULT '',
|
||||
file_checksum VARCHAR(255) NOT NULL DEFAULT '',
|
||||
boards VARCHAR(255) NOT NULL DEFAULT '*',
|
||||
staff VARCHAR(50) NOT NULL DEFAULT '',
|
||||
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
expires TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
permaban BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
reason VARCHAR(255) NOT NULL DEFAULT '',
|
||||
type SMALLINT NOT NULL DEFAULT 3,
|
||||
staff_note VARCHAR(255) NOT NULL DEFAULT '',
|
||||
appeal_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
can_appeal BOOLEAN NOT NULL DEFAULT true,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS DBPREFIXboards (
|
||||
id SERIAL,
|
||||
list_order SMALLINT NOT NULL DEFAULT 0,
|
||||
dir VARCHAR(45) NOT NULL CHECK (dir <> ''),
|
||||
type SMALLINT NOT NULL DEFAULT 0,
|
||||
upload_type SMALLINT NOT NULL DEFAULT 0,
|
||||
title VARCHAR(45) NOT NULL CHECK (title <> ''),
|
||||
subtitle VARCHAR(64) NOT NULL DEFAULT '',
|
||||
description VARCHAR(64) NOT NULL DEFAULT '',
|
||||
section INT NOT NULL DEFAULT 1,
|
||||
max_file_size INT NOT NULL DEFAULT 4718592,
|
||||
max_pages SMALLINT NOT NULL DEFAULT 11,
|
||||
default_style VARCHAR(45) NOT NULL,
|
||||
locked BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
created_on TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
anonymous VARCHAR(45) NOT NULL DEFAULT 'Anonymous',
|
||||
forced_anon BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
max_age INT NOT NULL DEFAULT 0,
|
||||
autosage_after INT NOT NULL DEFAULT 200,
|
||||
no_images_after INT NOT NULL DEFAULT 0,
|
||||
max_message_length INT NOT NULL DEFAULT 8192,
|
||||
embeds_allowed BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
redirect_to_thread BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
require_file BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
enable_catalog BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE (dir)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS DBPREFIXembeds (
|
||||
id SERIAL,
|
||||
filetype VARCHAR(3) NOT NULL,
|
||||
name VARCHAR(45) NOT NULL,
|
||||
video_url VARCHAR(255) NOT NULL,
|
||||
width SMALLINT NOT NULL,
|
||||
height SMALLINT NOT NULL,
|
||||
embed_code TEXT NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS DBPREFIXinfo (
|
||||
name VARCHAR(45) NOT NULL,
|
||||
value TEXT NOT NULL,
|
||||
PRIMARY KEY (name)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS DBPREFIXlinks (
|
||||
id SERIAL,
|
||||
title VARCHAR(45) NOT NULL,
|
||||
url VARCHAR(255) NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS DBPREFIXposts (
|
||||
id SERIAL,
|
||||
boardid INT NOT NULL,
|
||||
parentid INT NOT NULL DEFAULT '0',
|
||||
name VARCHAR(50) NOT NULL,
|
||||
tripcode VARCHAR(10) NOT NULL,
|
||||
email VARCHAR(50) NOT NULL,
|
||||
subject VARCHAR(100) NOT NULL,
|
||||
message TEXT NOT NULL,
|
||||
message_raw TEXT NOT NULL,
|
||||
password VARCHAR(45) NOT NULL,
|
||||
filename VARCHAR(45) NOT NULL DEFAULT '',
|
||||
filename_original VARCHAR(255) NOT NULL DEFAULT '',
|
||||
file_checksum VARCHAR(45) NOT NULL DEFAULT '',
|
||||
filesize INT NOT NULL DEFAULT 0,
|
||||
image_w SMALLINT NOT NULL DEFAULT 0,
|
||||
image_h SMALLINT NOT NULL DEFAULT 0,
|
||||
thumb_w SMALLINT NOT NULL DEFAULT 0,
|
||||
thumb_h SMALLINT NOT NULL DEFAULT 0,
|
||||
ip VARCHAR(45) NOT NULL DEFAULT '',
|
||||
tag VARCHAR(5) NOT NULL DEFAULT '',
|
||||
timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
autosage BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
deleted_timestamp TIMESTAMP,
|
||||
bumped TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
stickied BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
locked BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
reviewed BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
PRIMARY KEY (boardid,id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS DBPREFIXreports (
|
||||
id SERIAL,
|
||||
board VARCHAR(45) NOT NULL,
|
||||
postid INT NOT NULL,
|
||||
timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
ip VARCHAR(45) NOT NULL,
|
||||
reason VARCHAR(255) NOT NULL,
|
||||
cleared BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
istemp BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS DBPREFIXsections (
|
||||
id SERIAL,
|
||||
list_order SMALLINT NOT NULL DEFAULT 0,
|
||||
hidden SMALLINT NOT NULL,
|
||||
name VARCHAR(45) NOT NULL,
|
||||
abbreviation VARCHAR(10) NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
CREATE TEMP TABLE IF NOT EXISTS DBPREFIXsessions (
|
||||
id SERIAL,
|
||||
name CHAR(16) NOT NULL,
|
||||
sessiondata VARCHAR(45) NOT NULL,
|
||||
expires TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS DBPREFIXstaff (
|
||||
id SERIAL,
|
||||
username VARCHAR(45) NOT NULL,
|
||||
password_checksum VARCHAR(120) NOT NULL,
|
||||
salt CHAR(3) NOT NULL,
|
||||
rank SMALLINT NOT NULL,
|
||||
boards VARCHAR(128) NOT NULL DEFAULT '*',
|
||||
added_on TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
last_active TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE (username)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS DBPREFIXwordfilters (
|
||||
id SERIAL,
|
||||
search VARCHAR(75) NOT NULL CHECK (search <> ''),
|
||||
change_to VARCHAR(75) NOT NULL DEFAULT '',
|
||||
boards VARCHAR(128) NOT NULL DEFAULT '*',
|
||||
regex BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
PRIMARY KEY (id)
|
||||
);
|
162
initdb_sqlite3.sql
Normal file
162
initdb_sqlite3.sql
Normal file
|
@ -0,0 +1,162 @@
|
|||
-- Gochan SQLite startup/update script
|
||||
-- DO NOT DELETE
|
||||
|
||||
CREATE TABLE IF NOT EXISTS DBPREFIXannouncements (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
subject VARCHAR(45) NOT NULL DEFAULT '',
|
||||
message TEXT NOT NULL CHECK (message <> ''),
|
||||
poster VARCHAR(45) NOT NULL CHECK (poster <> ''),
|
||||
timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS DBPREFIXappeals (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
ban INT NOT NULL CHECK (ban <> 0),
|
||||
message TEXT NOT NULL CHECK (message <> ''),
|
||||
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
denied BOOLEAN DEFAULT FALSE,
|
||||
staff_response TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS DBPREFIXbanlist (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
allow_read BOOLEAN DEFAULT TRUE,
|
||||
ip VARCHAR(45) NOT NULL DEFAULT '',
|
||||
name VARCHAR(255) NOT NULL DEFAULT '',
|
||||
name_is_regex BOOLEAN DEFAULT FALSE,
|
||||
filename VARCHAR(255) NOT NULL DEFAULT '',
|
||||
file_checksum VARCHAR(255) NOT NULL DEFAULT '',
|
||||
boards VARCHAR(255) NOT NULL DEFAULT '*',
|
||||
staff VARCHAR(50) NOT NULL DEFAULT '',
|
||||
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
expires TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
permaban BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
reason VARCHAR(255) NOT NULL DEFAULT '',
|
||||
type SMALLINT NOT NULL DEFAULT 3,
|
||||
staff_note VARCHAR(255) NOT NULL DEFAULT '',
|
||||
appeal_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
can_appeal BOOLEAN NOT NULL DEFAULT true
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS DBPREFIXboards (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
list_order SMALLINT NOT NULL DEFAULT 0,
|
||||
dir VARCHAR(45) UNIQUE NOT NULL CHECK (dir <> ''),
|
||||
type SMALLINT NOT NULL DEFAULT 0,
|
||||
upload_type SMALLINT NOT NULL DEFAULT 0,
|
||||
title VARCHAR(45) NOT NULL CHECK (title <> ''),
|
||||
subtitle VARCHAR(64) NOT NULL DEFAULT '',
|
||||
description VARCHAR(64) NOT NULL DEFAULT '',
|
||||
section INT NOT NULL DEFAULT 1,
|
||||
max_file_size INT NOT NULL DEFAULT 4718592,
|
||||
max_pages SMALLINT NOT NULL DEFAULT 11,
|
||||
default_style VARCHAR(45) NOT NULL,
|
||||
locked BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
created_on TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
anonymous VARCHAR(45) NOT NULL DEFAULT 'Anonymous',
|
||||
forced_anon BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
max_age INT NOT NULL DEFAULT 0,
|
||||
autosage_after INT NOT NULL DEFAULT 200,
|
||||
no_images_after INT NOT NULL DEFAULT 0,
|
||||
max_message_length INT NOT NULL DEFAULT 8192,
|
||||
embeds_allowed BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
redirect_to_thread BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
require_file BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
enable_catalog BOOLEAN NOT NULL DEFAULT TRUE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS DBPREFIXembeds (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
filetype VARCHAR(3) NOT NULL,
|
||||
name VARCHAR(45) NOT NULL,
|
||||
video_url VARCHAR(255) NOT NULL,
|
||||
width SMALLINT NOT NULL,
|
||||
height SMALLINT NOT NULL,
|
||||
embed_code TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS DBPREFIXinfo (
|
||||
name VARCHAR(45) PRIMARY KEY NOT NULL,
|
||||
value TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS DBPREFIXlinks (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
title VARCHAR(45) NOT NULL,
|
||||
url VARCHAR(255) NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS DBPREFIXposts (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
boardid INT NOT NULL,
|
||||
parentid INT NOT NULL DEFAULT '0',
|
||||
name VARCHAR(50) NOT NULL,
|
||||
tripcode VARCHAR(10) NOT NULL,
|
||||
email VARCHAR(50) NOT NULL,
|
||||
subject VARCHAR(100) NOT NULL,
|
||||
message TEXT NOT NULL,
|
||||
message_raw TEXT NOT NULL,
|
||||
password VARCHAR(45) NOT NULL,
|
||||
filename VARCHAR(45) NOT NULL DEFAULT '',
|
||||
filename_original VARCHAR(255) NOT NULL DEFAULT '',
|
||||
file_checksum VARCHAR(45) NOT NULL DEFAULT '',
|
||||
filesize INT NOT NULL DEFAULT 0,
|
||||
image_w SMALLINT NOT NULL DEFAULT 0,
|
||||
image_h SMALLINT NOT NULL DEFAULT 0,
|
||||
thumb_w SMALLINT NOT NULL DEFAULT 0,
|
||||
thumb_h SMALLINT NOT NULL DEFAULT 0,
|
||||
ip VARCHAR(45) NOT NULL DEFAULT '',
|
||||
tag VARCHAR(5) NOT NULL DEFAULT '',
|
||||
timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
autosage BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
deleted_timestamp TIMESTAMP,
|
||||
bumped TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
stickied BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
locked BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
reviewed BOOLEAN NOT NULL DEFAULT FALSE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS DBPREFIXreports (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
board VARCHAR(45) NOT NULL,
|
||||
postid INT NOT NULL,
|
||||
timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
ip VARCHAR(45) NOT NULL,
|
||||
reason VARCHAR(255) NOT NULL,
|
||||
cleared BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
istemp BOOLEAN NOT NULL DEFAULT FALSE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS DBPREFIXsections (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
list_order SMALLINT NOT NULL DEFAULT 0,
|
||||
hidden SMALLINT NOT NULL,
|
||||
name VARCHAR(45) NOT NULL,
|
||||
abbreviation VARCHAR(10) NOT NULL
|
||||
);
|
||||
|
||||
CREATE TEMP TABLE IF NOT EXISTS DBPREFIXsessions (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
name CHAR(16) NOT NULL,
|
||||
sessiondata VARCHAR(45) NOT NULL,
|
||||
expires TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS gc_staff (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
username VARCHAR(45) UNIQUE NOT NULL,
|
||||
password_checksum VARCHAR(120) NOT NULL,
|
||||
salt CHAR(3) NOT NULL,
|
||||
rank SMALLINT NOT NULL,
|
||||
boards VARCHAR(128) NOT NULL DEFAULT '*',
|
||||
added_on TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
last_active TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS DBPREFIXwordfilters (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
search VARCHAR(75) NOT NULL CHECK (search <> ''),
|
||||
change_to VARCHAR(75) NOT NULL DEFAULT '',
|
||||
boards VARCHAR(128) NOT NULL DEFAULT '*',
|
||||
regex BOOLEAN NOT NULL DEFAULT FALSE
|
||||
);
|
|
@ -15,7 +15,7 @@ func TestAPI(t *testing.T) {
|
|||
var api string
|
||||
var err error
|
||||
|
||||
if api, err = marshalAPI("colorsSlice", []Color{
|
||||
if api, err = marshalJSON("colorsSlice", []Color{
|
||||
Color{255, 0, 0},
|
||||
Color{0, 255, 0},
|
||||
Color{0, 0, 255},
|
||||
|
@ -24,7 +24,7 @@ func TestAPI(t *testing.T) {
|
|||
}
|
||||
fmt.Println("API slice: " + api)
|
||||
|
||||
if api, err = marshalAPI("colorsMap", map[string]Color{
|
||||
if api, err = marshalJSON("colorsMap", map[string]Color{
|
||||
"red": Color{255, 0, 0},
|
||||
"green": Color{0, 255, 0},
|
||||
"blue": Color{0, 0, 255},
|
||||
|
@ -33,12 +33,12 @@ func TestAPI(t *testing.T) {
|
|||
}
|
||||
fmt.Println("API map: " + api)
|
||||
|
||||
if api, err = marshalAPI("color", Color{255, 0, 0}, true); err != nil {
|
||||
if api, err = marshalJSON("color", Color{255, 0, 0}, true); err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
fmt.Println("API struct: " + api)
|
||||
|
||||
if api, err = marshalAPI("error", "Some error", false); err != nil {
|
||||
if api, err = marshalJSON("error", "Some error", false); err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
fmt.Println("API string: " + api)
|
||||
|
|
122
src/building.go
122
src/building.go
|
@ -13,8 +13,11 @@ import (
|
|||
)
|
||||
|
||||
// build front page using templates/front.html
|
||||
func buildFrontPage() (html string) {
|
||||
initTemplates()
|
||||
func buildFrontPage() string {
|
||||
err := initTemplates("front")
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
var recentPostsArr []interface{}
|
||||
|
||||
os.Remove(path.Join(config.DocumentRoot, "index.html"))
|
||||
|
@ -25,18 +28,25 @@ func buildFrontPage() (html string) {
|
|||
}
|
||||
|
||||
// get recent posts
|
||||
recentQueryStr := "SELECT `" + config.DBprefix + "posts`.`id`, " +
|
||||
"`" + config.DBprefix + "posts`.`parentid`, " +
|
||||
"`" + config.DBprefix + "boards`.`dir` AS boardname, " +
|
||||
"`" + config.DBprefix + "posts`.`boardid` AS boardid, " +
|
||||
"`name`, `tripcode`, `message`, `filename`, `thumb_w`, `thumb_h` " +
|
||||
"FROM `" + config.DBprefix + "posts`, `" + config.DBprefix + "boards` " +
|
||||
"WHERE `" + config.DBprefix + "posts`.`deleted_timestamp` = ? "
|
||||
recentQueryStr := "SELECT " +
|
||||
config.DBprefix + "posts.id, " +
|
||||
config.DBprefix + "posts.parentid, " +
|
||||
config.DBprefix + "boards.dir as boardname, " +
|
||||
config.DBprefix + "posts.boardid as boardid, " +
|
||||
config.DBprefix + "posts.name, " +
|
||||
config.DBprefix + "posts.tripcode, " +
|
||||
config.DBprefix + "posts.message, " +
|
||||
config.DBprefix + "posts.filename, " +
|
||||
config.DBprefix + "posts.thumb_w, " +
|
||||
config.DBprefix + "posts.thumb_h " +
|
||||
"FROM " + config.DBprefix + "posts, " + config.DBprefix + "boards " +
|
||||
"WHERE " + config.DBprefix + "posts.deleted_timestamp = ? "
|
||||
|
||||
if !config.RecentPostsWithNoFile {
|
||||
recentQueryStr += "AND `" + config.DBprefix + "posts`.`filename` != '' AND `" + config.DBprefix + "posts`.filename != 'deleted' "
|
||||
recentQueryStr += "AND " + config.DBprefix + "posts.filename != '' AND " + config.DBprefix + "posts.filename != 'deleted' "
|
||||
}
|
||||
recentQueryStr += "AND `boardid` = `" + config.DBprefix + "boards`.`id` " +
|
||||
"ORDER BY `timestamp` DESC LIMIT ?"
|
||||
recentQueryStr += "AND boardid = " + config.DBprefix + "boards.id " +
|
||||
"ORDER BY timestamp DESC LIMIT ?"
|
||||
|
||||
rows, err := querySQL(recentQueryStr, nilTimestamp, config.MaxRecentPosts)
|
||||
defer closeHandle(rows)
|
||||
|
@ -73,8 +83,8 @@ func buildFrontPage() (html string) {
|
|||
}
|
||||
|
||||
func buildBoardListJSON() (html string) {
|
||||
board_list_file, err := os.OpenFile(path.Join(config.DocumentRoot, "boards.json"), os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0777)
|
||||
defer closeHandle(board_list_file)
|
||||
boardListFile, err := os.OpenFile(path.Join(config.DocumentRoot, "boards.json"), os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0777)
|
||||
defer closeHandle(boardListFile)
|
||||
if err != nil {
|
||||
return handleError(1, "Failed opening board.json for writing: "+err.Error()) + "<br />\n"
|
||||
}
|
||||
|
@ -95,7 +105,7 @@ func buildBoardListJSON() (html string) {
|
|||
if err != nil {
|
||||
return handleError(1, "Failed marshal to JSON: "+err.Error()) + "<br />\n"
|
||||
}
|
||||
if _, err = board_list_file.Write(boardJSON); err != nil {
|
||||
if _, err = boardListFile.Write(boardJSON); err != nil {
|
||||
return handleError(1, "Failed writing boards.json file: "+err.Error()) + "<br />\n"
|
||||
}
|
||||
return "Board list JSON rebuilt successfully.<br />"
|
||||
|
@ -105,6 +115,10 @@ func buildBoardListJSON() (html string) {
|
|||
// `board` is a Board object representing the board to build archive pages for.
|
||||
// The return value is a string of HTML with debug information from the build process.
|
||||
func buildBoardPages(board *Board) (html string) {
|
||||
err := initTemplates("boardpage")
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
start_time := benchmarkTimer("buildBoard"+strconv.Itoa(board.ID), time.Now(), true)
|
||||
var current_page_file *os.File
|
||||
var threads []interface{}
|
||||
|
@ -132,9 +146,9 @@ func buildBoardPages(board *Board) (html string) {
|
|||
"boardid": board.ID,
|
||||
"parentid": 0,
|
||||
"deleted_timestamp": nilTimestamp,
|
||||
}, " ORDER BY `bumped` DESC")
|
||||
}, " ORDER BY bumped DESC")
|
||||
if err != nil {
|
||||
html += handleError(1, err.Error()) + "<br />"
|
||||
html += handleError(1, "Error getting OP posts for /%s/: %s", board.Dir, err.Error()) + "<br />\n"
|
||||
op_posts = nil
|
||||
return
|
||||
}
|
||||
|
@ -142,22 +156,29 @@ func buildBoardPages(board *Board) (html string) {
|
|||
// For each top level post, start building a Thread struct
|
||||
for _, op := range op_posts {
|
||||
var thread Thread
|
||||
var posts_in_thread []Post
|
||||
var postsInThread []Post
|
||||
|
||||
// Get the number of replies to this thread.
|
||||
if err = queryRowSQL("SELECT COUNT(*) FROM `"+config.DBprefix+"posts` WHERE `boardid` = ? AND `parentid` = ? AND `deleted_timestamp` = ?",
|
||||
queryStr := "SELECT COUNT(*) FROM " + config.DBprefix + "posts WHERE boardid = ? AND parentid = ? AND deleted_timestamp = ?"
|
||||
|
||||
if err = queryRowSQL(queryStr,
|
||||
[]interface{}{board.ID, op.ID, nilTimestamp},
|
||||
[]interface{}{&thread.NumReplies},
|
||||
); err != nil {
|
||||
html += err.Error() + "<br />\n"
|
||||
html += handleError(1,
|
||||
"Error getting replies to /%s/%d: %s",
|
||||
board.Dir, op.ID, err.Error()) + "<br />\n"
|
||||
}
|
||||
|
||||
// Get the number of image replies in this thread
|
||||
if err = queryRowSQL("SELECT COUNT(*) FROM `"+config.DBprefix+"posts` WHERE `boardid` = ? AND `parentid` = ? AND `deleted_timestamp` = ? AND `filesize` <> 0",
|
||||
[]interface{}{board.ID, op.ID, nilTimestamp},
|
||||
queryStr += " AND filesize <> 0"
|
||||
if err = queryRowSQL(queryStr,
|
||||
[]interface{}{board.ID, op.ID, op.DeletedTimestamp},
|
||||
[]interface{}{&thread.NumImages},
|
||||
); err != nil {
|
||||
html += err.Error() + "<br />\n"
|
||||
html += handleError(1,
|
||||
"Error getting number of image replies to /%s/%d: %s",
|
||||
board.Dir, op.ID, err.Error()) + "<br />\n"
|
||||
}
|
||||
|
||||
thread.OP = op
|
||||
|
@ -173,28 +194,30 @@ func buildBoardPages(board *Board) (html string) {
|
|||
numRepliesOnBoardPage = config.RepliesOnBoardPage
|
||||
}
|
||||
|
||||
posts_in_thread, err = getPostArr(map[string]interface{}{
|
||||
postsInThread, err = getPostArr(map[string]interface{}{
|
||||
"boardid": board.ID,
|
||||
"parentid": op.ID,
|
||||
"deleted_timestamp": nilTimestamp,
|
||||
}, fmt.Sprintf(" ORDER BY `id` DESC LIMIT %d", numRepliesOnBoardPage))
|
||||
}, fmt.Sprintf(" ORDER BY id DESC LIMIT %d", numRepliesOnBoardPage))
|
||||
if err != nil {
|
||||
html += err.Error() + "<br />"
|
||||
html += handleError(1,
|
||||
"Error getting posts in /%s/%d: %s",
|
||||
board.Dir, op.ID, err.Error()) + "<br />\n"
|
||||
}
|
||||
|
||||
var reversedPosts []Post
|
||||
for i := len(posts_in_thread); i > 0; i-- {
|
||||
reversedPosts = append(reversedPosts, posts_in_thread[i-1])
|
||||
for i := len(postsInThread); i > 0; i-- {
|
||||
reversedPosts = append(reversedPosts, postsInThread[i-1])
|
||||
}
|
||||
|
||||
if len(posts_in_thread) > 0 {
|
||||
if len(postsInThread) > 0 {
|
||||
// Store the posts to show on board page
|
||||
//thread.BoardReplies = posts_in_thread
|
||||
//thread.BoardReplies = postsInThread
|
||||
thread.BoardReplies = reversedPosts
|
||||
|
||||
// Count number of images on board page
|
||||
image_count := 0
|
||||
for _, reply := range posts_in_thread {
|
||||
for _, reply := range postsInThread {
|
||||
if reply.Filesize != 0 {
|
||||
image_count++
|
||||
}
|
||||
|
@ -222,7 +245,8 @@ func buildBoardPages(board *Board) (html string) {
|
|||
// Open board.html for writing to the first page.
|
||||
board_page_file, err := os.OpenFile(path.Join(config.DocumentRoot, board.Dir, "board.html"), os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0777)
|
||||
if err != nil {
|
||||
html += handleError(1, "Failed opening /"+board.Dir+"/board.html: "+err.Error()) + "<br />"
|
||||
html += handleError(1,
|
||||
"Failed opening /%s/board.html: %s", board.Dir, err.Error()) + "<br />"
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -347,31 +371,34 @@ func buildBoards(which ...int) (html string) {
|
|||
return
|
||||
}
|
||||
|
||||
func buildCatalog(which int) (html string) {
|
||||
func buildCatalog(which int) string {
|
||||
err := initTemplates("catalog")
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
board, err := getBoardFromID(which)
|
||||
if err != nil {
|
||||
html += handleError(1, err.Error())
|
||||
return handleError(1, err.Error())
|
||||
}
|
||||
catalogPath := path.Join(config.DocumentRoot, board.Dir, "catalog.html")
|
||||
catalogFile, err := os.OpenFile(catalogPath, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0777)
|
||||
if err != nil {
|
||||
html += handleError(1, "Failed opening /"+board.Dir+"/catalog.html: "+err.Error())
|
||||
return
|
||||
return handleError(1, "Failed opening /%s/catalog.html: %s", board.Dir, err.Error())
|
||||
}
|
||||
threadOPs, err := getPostArr(map[string]interface{}{
|
||||
"boardid": which,
|
||||
"parentid": 0,
|
||||
"deleted_timestamp": nilTimestamp,
|
||||
}, "ORDER BY `bumped` ASC")
|
||||
}, "ORDER BY bumped ASC")
|
||||
if err != nil {
|
||||
html += handleError(1, "Error building catalog for /%s/: %s", board.Dir, err.Error())
|
||||
return
|
||||
return handleError(1, "Error building catalog for /%s/: %s", board.Dir, err.Error())
|
||||
}
|
||||
var threadInterfaces []interface{}
|
||||
for _, thread := range threadOPs {
|
||||
threadInterfaces = append(threadInterfaces, thread)
|
||||
}
|
||||
threadPages := paginate(config.PostsPerThreadPage, threadInterfaces)
|
||||
|
||||
if err = catalog_tmpl.Execute(catalogFile, map[string]interface{}{
|
||||
"boards": allBoards,
|
||||
"config": config,
|
||||
|
@ -379,19 +406,22 @@ func buildCatalog(which int) (html string) {
|
|||
"sections": allSections,
|
||||
"threadPages": threadPages,
|
||||
}); err != nil {
|
||||
html += handleError(1, "Error building catalog for /%s/: %s", board.Dir, err.Error())
|
||||
return
|
||||
return handleError(1, "Error building catalog for /%s/: %s", board.Dir, err.Error())
|
||||
}
|
||||
html += fmt.Sprintf("Built catalog for /%s/ successfully", board.Dir)
|
||||
return
|
||||
return fmt.Sprintf("Built catalog for /%s/ successfully", board.Dir)
|
||||
}
|
||||
|
||||
// buildThreadPages builds the pages for a thread given by a Post object.
|
||||
func buildThreadPages(op *Post) (html string) {
|
||||
err := initTemplates("threadpage")
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
|
||||
var replies []Post
|
||||
var current_page_file *os.File
|
||||
board, err := getBoardFromID(op.BoardID)
|
||||
if err != nil {
|
||||
var board *Board
|
||||
if board, err = getBoardFromID(op.BoardID); err != nil {
|
||||
html += handleError(1, err.Error())
|
||||
}
|
||||
|
||||
|
@ -399,7 +429,7 @@ func buildThreadPages(op *Post) (html string) {
|
|||
"boardid": op.BoardID,
|
||||
"parentid": op.ID,
|
||||
"deleted_timestamp": nilTimestamp,
|
||||
}, "ORDER BY `id` ASC")
|
||||
}, "ORDER BY id ASC")
|
||||
if err != nil {
|
||||
html += handleError(1, "Error building thread "+strconv.Itoa(op.ID)+":"+err.Error())
|
||||
return
|
||||
|
|
|
@ -18,7 +18,7 @@ func main() {
|
|||
|
||||
printf(0, "Starting gochan v%s.%s, using verbosity level %d\n", versionStr, buildtimeString, config.Verbosity)
|
||||
println(0, "Loading and parsing templates...")
|
||||
if err := initTemplates(); err != nil {
|
||||
if err := initTemplates("all"); err != nil {
|
||||
handleError(0, customError(err))
|
||||
os.Exit(2)
|
||||
}
|
||||
|
|
190
src/manage.go
190
src/manage.go
|
@ -86,7 +86,7 @@ func getCurrentStaff(request *http.Request) (string, error) {
|
|||
key := sessionCookie.Value
|
||||
currentSession := new(LoginSession)
|
||||
if err := queryRowSQL(
|
||||
"SELECT `data` FROM `"+config.DBprefix+"sessions` WHERE `key` = ?",
|
||||
"SELECT sessiondata FROM "+config.DBprefix+"sessions WHERE name = ?",
|
||||
[]interface{}{key},
|
||||
[]interface{}{¤tSession.Data},
|
||||
); err != nil {
|
||||
|
@ -97,8 +97,7 @@ func getCurrentStaff(request *http.Request) (string, error) {
|
|||
|
||||
func getStaff(name string) (*Staff, error) {
|
||||
staff := new(Staff)
|
||||
err := queryRowSQL(
|
||||
"SELECT * FROM `"+config.DBprefix+"staff` WHERE `username` = ?",
|
||||
err := queryRowSQL("SELECT * FROM "+config.DBprefix+"staff WHERE username = ?",
|
||||
[]interface{}{name},
|
||||
[]interface{}{&staff.ID, &staff.Username, &staff.PasswordChecksum, &staff.Salt, &staff.Rank, &staff.Boards, &staff.AddedOn, &staff.LastActive},
|
||||
)
|
||||
|
@ -124,13 +123,13 @@ func getStaffRank(request *http.Request) int {
|
|||
}
|
||||
|
||||
func newStaff(username string, password string, rank int) error {
|
||||
_, err := execSQL("INSERT INTO `"+config.DBprefix+"staff` (`username`, `password_checksum`, `rank`) VALUES(?,?,?)",
|
||||
_, err := execSQL("INSERT INTO `"+config.DBprefix+"staff` (username, password_checksum, rank) VALUES(?,?,?)",
|
||||
&username, bcryptSum(password), &rank)
|
||||
return err
|
||||
}
|
||||
|
||||
func deleteStaff(username string) error {
|
||||
_, err := execSQL("DELETE FROM `"+config.DBprefix+"staff` WHERE `username` = ?", username)
|
||||
_, err := execSQL("DELETE FROM "+config.DBprefix+"staff WHERE username = ?", username)
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -164,16 +163,16 @@ func createSession(key string, username string, password string, request *http.R
|
|||
Domain: domain,
|
||||
MaxAge: 60 * 60 * 24 * 7,
|
||||
})
|
||||
|
||||
if _, err = execSQL(
|
||||
"INSERT INTO `"+config.DBprefix+"sessions` (`key`, `data`, `expires`) VALUES(?,?,?)",
|
||||
key, username, getSpecificSQLDateTime(time.Now().Add(time.Duration(time.Hour*730))),
|
||||
); err != nil {
|
||||
handleError(1, customError(err))
|
||||
"INSERT INTO "+config.DBprefix+"sessions (name,sessiondata,expires) VALUES(?,?,?)",
|
||||
key, username, getSpecificSQLDateTime(time.Now().Add(time.Duration(time.Hour*730)))); err != nil {
|
||||
handleError(0, customError(err))
|
||||
return 2
|
||||
}
|
||||
|
||||
if _, err = execSQL(
|
||||
"UPDATE `"+config.DBprefix+"staff` SET `last_active` = ? WHERE `username` = ?", getSQLDateTime(), username,
|
||||
"UPDATE "+config.DBprefix+"staff SET last_active = ? WHERE username = ?", getSQLDateTime(), username,
|
||||
); err != nil {
|
||||
handleError(1, customError(err))
|
||||
}
|
||||
|
@ -381,8 +380,8 @@ var manage_functions = map[string]ManageFunction{
|
|||
config.EnableQuickReply = (request.PostFormValue("EnableQuickReply") == "on")
|
||||
config.DateTimeFormat = request.PostFormValue("DateTimeFormat")
|
||||
AkismetAPIKey := request.PostFormValue("AkismetAPIKey")
|
||||
err = checkAkismetAPIKey(AkismetAPIKey)
|
||||
if err != nil {
|
||||
|
||||
if err = checkAkismetAPIKey(AkismetAPIKey); err != nil {
|
||||
status += err.Error() + "<br />"
|
||||
} else {
|
||||
config.AkismetAPIKey = AkismetAPIKey
|
||||
|
@ -437,7 +436,7 @@ var manage_functions = map[string]ManageFunction{
|
|||
Permissions: 3,
|
||||
Callback: func(writer http.ResponseWriter, request *http.Request) (html string) {
|
||||
html = "<img src=\"/css/purge.jpg\" />"
|
||||
rows, err := querySQL("SELECT `dir` FROM `" + config.DBprefix + "boards`")
|
||||
rows, err := querySQL("SELECT dir FROM " + config.DBprefix + "boards")
|
||||
defer closeHandle(rows)
|
||||
if err != nil {
|
||||
html += err.Error()
|
||||
|
@ -472,15 +471,17 @@ var manage_functions = map[string]ManageFunction{
|
|||
return
|
||||
}
|
||||
}
|
||||
if _, err = execSQL("TRUNCATE `" + config.DBprefix + "posts`"); err != nil {
|
||||
html += err.Error() + "<br />"
|
||||
handleError(1, customError(err))
|
||||
truncateSQL := "TRUNCATE " + config.DBprefix + "posts"
|
||||
if config.DBtype == "postgres" {
|
||||
truncateSQL += " RESTART IDENTITY"
|
||||
}
|
||||
if _, err = execSQL(truncateSQL); err != nil {
|
||||
html += handleError(0, err.Error()) + "<br />\n"
|
||||
return
|
||||
}
|
||||
|
||||
if _, err = execSQL("ALTER TABLE `" + config.DBprefix + "posts` AUTO_INCREMENT = 1"); err != nil {
|
||||
html += err.Error() + "<br />"
|
||||
handleError(1, customError(err))
|
||||
html += handleError(0, err.Error()) + "<br />\n"
|
||||
return
|
||||
}
|
||||
html += "<br />Everything purged, rebuilding all<br />" +
|
||||
|
@ -544,7 +545,7 @@ var manage_functions = map[string]ManageFunction{
|
|||
Callback: func(writer http.ResponseWriter, request *http.Request) (html string) {
|
||||
html = "<h1 class=\"manage-header\">Announcements</h1><br />"
|
||||
|
||||
rows, err := querySQL("SELECT `subject`,`message`,`poster`,`timestamp` FROM `" + config.DBprefix + "announcements` ORDER BY `id` DESC")
|
||||
rows, err := querySQL("SELECT subject,message,poster,timestamp FROM " + config.DBprefix + "announcements ORDER BY id DESC")
|
||||
defer closeHandle(rows)
|
||||
if err != nil {
|
||||
html += handleError(1, err.Error())
|
||||
|
@ -605,9 +606,16 @@ var manage_functions = map[string]ManageFunction{
|
|||
reason := html.EscapeString(request.FormValue("reason"))
|
||||
staffNote := html.EscapeString(request.FormValue("staffnote"))
|
||||
currentStaff, _ := getCurrentStaff(request)
|
||||
if _, err := execSQL("INSERT INTO `"+config.DBprefix+"banlist`"+
|
||||
"(`ip`,`name`,`name_is_regex`,`filename`,`file_checksum`,`boards`,`staff`,`expires`,`permaban`,`reason`,`type`,`staff_note`)"+
|
||||
"VALUES(?,?,?,?,?,?,?,?,?,?,?,?)",
|
||||
sqlStr := "INSERT INTO " + config.DBprefix + "banlist (ip,name,name_is_regex,filename,file_checksum,boards,staff,expires,permaban,reason,type,staff_note) VALUES("
|
||||
for i := 1; i <= 12; i++ {
|
||||
sqlStr += "?"
|
||||
if i < 12 {
|
||||
sqlStr += ","
|
||||
}
|
||||
}
|
||||
sqlStr += ")"
|
||||
println(1, sqlStr)
|
||||
if _, err := execSQL(sqlStr,
|
||||
ip.String(), name, nameIsRegex, filename, checksum, boards, currentStaff, expires, permaban, reason, bantype, staffNote,
|
||||
); err != nil {
|
||||
pageHTML += err.Error()
|
||||
|
@ -640,7 +648,7 @@ var manage_functions = map[string]ManageFunction{
|
|||
}
|
||||
post = posts[0]
|
||||
}
|
||||
rows, err := querySQL("SELECT `ip`,`name`,`reason`,`boards`,`staff`,`timestamp`,`expires`,`permaban`,`can_appeal` FROM `" + config.DBprefix + "banlist`")
|
||||
rows, err := querySQL("SELECT ip,name,reason,boards,staff,timestamp,expires,permaban,can_appeal FROM " + config.DBprefix + "banlist")
|
||||
defer closeHandle(rows)
|
||||
if err != nil {
|
||||
pageHTML += handleError(1, err.Error())
|
||||
|
@ -678,7 +686,7 @@ var manage_functions = map[string]ManageFunction{
|
|||
return
|
||||
}
|
||||
staff := new(Staff)
|
||||
if err := queryRowSQL("SELECT `rank`,`boards` FROM `"+config.DBprefix+"staff` WHERE `username` = ?",
|
||||
if err := queryRowSQL("SELECT rank,boards FROM "+config.DBprefix+"staff WHERE username = ?",
|
||||
[]interface{}{current_staff},
|
||||
[]interface{}{&staff.Rank, &staff.Boards},
|
||||
); err != nil {
|
||||
|
@ -694,7 +702,7 @@ var manage_functions = map[string]ManageFunction{
|
|||
do := request.FormValue("do")
|
||||
var done bool
|
||||
board := new(Board)
|
||||
var board_creation_status string
|
||||
var boardCreationStatus string
|
||||
var err error
|
||||
var rows *sql.Rows
|
||||
for !done {
|
||||
|
@ -702,30 +710,30 @@ var manage_functions = map[string]ManageFunction{
|
|||
case do == "add":
|
||||
board.Dir = request.FormValue("dir")
|
||||
if board.Dir == "" {
|
||||
board_creation_status = "Error: \"Directory\" cannot be blank"
|
||||
boardCreationStatus = "Error: \"Directory\" cannot be blank"
|
||||
do = ""
|
||||
continue
|
||||
}
|
||||
order_str := request.FormValue("order")
|
||||
board.Order, err = strconv.Atoi(order_str)
|
||||
orderStr := request.FormValue("order")
|
||||
board.ListOrder, err = strconv.Atoi(orderStr)
|
||||
if err != nil {
|
||||
board.Order = 0
|
||||
board.ListOrder = 0
|
||||
}
|
||||
board.Title = request.FormValue("title")
|
||||
if board.Title == "" {
|
||||
board_creation_status = "Error: \"Title\" cannot be blank"
|
||||
boardCreationStatus = "Error: \"Title\" cannot be blank"
|
||||
do = ""
|
||||
continue
|
||||
}
|
||||
board.Subtitle = request.FormValue("subtitle")
|
||||
board.Description = request.FormValue("description")
|
||||
section_str := request.FormValue("section")
|
||||
if section_str == "none" {
|
||||
section_str = "0"
|
||||
sectionStr := request.FormValue("section")
|
||||
if sectionStr == "none" {
|
||||
sectionStr = "0"
|
||||
}
|
||||
|
||||
board.CreatedOn = time.Now()
|
||||
board.Section, err = strconv.Atoi(section_str)
|
||||
board.Section, err = strconv.Atoi(sectionStr)
|
||||
if err != nil {
|
||||
board.Section = 0
|
||||
}
|
||||
|
@ -776,35 +784,35 @@ var manage_functions = map[string]ManageFunction{
|
|||
//actually start generating stuff
|
||||
if err = os.Mkdir(path.Join(config.DocumentRoot, board.Dir), 0666); err != nil {
|
||||
do = ""
|
||||
board_creation_status = handleError(1, "ERROR: directory /"+config.DocumentRoot+"/"+board.Dir+"/ already exists!")
|
||||
boardCreationStatus = handleError(1, "ERROR: directory /"+config.DocumentRoot+"/"+board.Dir+"/ already exists!")
|
||||
break
|
||||
}
|
||||
|
||||
if err = os.Mkdir(path.Join(config.DocumentRoot, board.Dir, "res"), 0666); err != nil {
|
||||
do = ""
|
||||
board_creation_status = handleError(1, "ERROR: directory /"+config.DocumentRoot+"/"+board.Dir+"/res/ already exists!")
|
||||
boardCreationStatus = handleError(1, "ERROR: directory /"+config.DocumentRoot+"/"+board.Dir+"/res/ already exists!")
|
||||
break
|
||||
}
|
||||
|
||||
if err = os.Mkdir(path.Join(config.DocumentRoot, board.Dir, "thumb"), 0666); err != nil {
|
||||
do = ""
|
||||
board_creation_status = handleError(1, "ERROR: directory /"+config.DocumentRoot+"/"+board.Dir+"/thumb/ already exists!")
|
||||
boardCreationStatus = handleError(1, "ERROR: directory /"+config.DocumentRoot+"/"+board.Dir+"/thumb/ already exists!")
|
||||
break
|
||||
}
|
||||
|
||||
if err = os.Mkdir(path.Join(config.DocumentRoot, board.Dir, "src"), 0666); err != nil {
|
||||
do = ""
|
||||
board_creation_status = handleError(1, "ERROR: directory /"+config.DocumentRoot+"/"+board.Dir+"/src/ already exists!")
|
||||
boardCreationStatus = handleError(1, "ERROR: directory /"+config.DocumentRoot+"/"+board.Dir+"/src/ already exists!")
|
||||
break
|
||||
}
|
||||
boardCreationTimestamp := getSpecificSQLDateTime(board.CreatedOn)
|
||||
if _, err := execSQL(
|
||||
"INSERT INTO `"+config.DBprefix+"boards` (`order`,`dir`,`type`,`upload_type`,`title`,`subtitle`,"+
|
||||
"`description`,`section`,`max_image_size`,`max_pages`,`default_style`,`locked`,`created_on`,"+
|
||||
"`anonymous`,`forced_anon`,`max_age`,`autosage_after`,`no_images_after`,`max_message_length`,`embeds_allowed`,"+
|
||||
"`redirect_to_thread`,`require_file`,`enable_catalog`) "+
|
||||
"INSERT INTO "+config.DBprefix+"boards (list_order,dir,type,upload_type,title,subtitle,"+
|
||||
"description,section,max_file_size,max_pages,default_style,locked,created_on,"+
|
||||
"anonymous,forced_anon,max_age,autosage_after,no_images_after,max_message_length,embeds_allowed,"+
|
||||
"redirect_to_thread,require_file,enable_catalog) "+
|
||||
"VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
|
||||
board.Order, board.Dir, board.Type, board.UploadType,
|
||||
board.ListOrder, board.Dir, board.Type, board.UploadType,
|
||||
board.Title, board.Subtitle, board.Description, board.Section,
|
||||
board.MaxFilesize, board.MaxPages, board.DefaultStyle,
|
||||
board.Locked, boardCreationTimestamp, board.Anonymous,
|
||||
|
@ -813,11 +821,11 @@ var manage_functions = map[string]ManageFunction{
|
|||
board.RedirectToThread, board.RequireFile, board.EnableCatalog,
|
||||
); err != nil {
|
||||
do = ""
|
||||
board_creation_status = handleError(1, "Error creating board: "+customError(err))
|
||||
boardCreationStatus = handleError(1, "Error creating board: "+customError(err))
|
||||
break
|
||||
} else {
|
||||
board_creation_status = "Board created successfully"
|
||||
println(2, board_creation_status)
|
||||
boardCreationStatus = "Board created successfully"
|
||||
println(2, boardCreationStatus)
|
||||
buildBoards()
|
||||
resetBoardSectionArrays()
|
||||
println(2, "Boards rebuilt successfully")
|
||||
|
@ -830,71 +838,21 @@ var manage_functions = map[string]ManageFunction{
|
|||
// resetBoardSectionArrays()
|
||||
default:
|
||||
// put the default column values in the text boxes
|
||||
rows, err = querySQL("SELECT `column_name`,`column_default` FROM `information_schema`.`columns` WHERE `table_name` = '" + config.DBprefix + "boards'")
|
||||
defer closeHandle(rows)
|
||||
if err != nil {
|
||||
html += handleError(1, "Error getting column names from boards table:"+err.Error())
|
||||
return
|
||||
}
|
||||
for rows.Next() {
|
||||
var columnName string
|
||||
var columnDefault string
|
||||
rows.Scan(&columnName, &columnDefault)
|
||||
columnDefaultInt, _ := strconv.Atoi(columnDefault)
|
||||
columnDefaultBool := (columnDefaultInt == 1)
|
||||
switch columnName {
|
||||
case "id":
|
||||
board.ID = columnDefaultInt
|
||||
case "order":
|
||||
board.Order = columnDefaultInt
|
||||
case "dir":
|
||||
board.Dir = columnDefault
|
||||
case "type":
|
||||
board.Type = columnDefaultInt
|
||||
case "upload_type":
|
||||
board.UploadType = columnDefaultInt
|
||||
case "title":
|
||||
board.Title = columnDefault
|
||||
case "subtitle":
|
||||
board.Subtitle = columnDefault
|
||||
case "description":
|
||||
board.Description = columnDefault
|
||||
case "section":
|
||||
board.Section = columnDefaultInt
|
||||
case "max_image_size":
|
||||
board.MaxFilesize = columnDefaultInt
|
||||
case "max_pages":
|
||||
board.MaxPages = columnDefaultInt
|
||||
case "default_style":
|
||||
board.DefaultStyle = columnDefault
|
||||
case "locked":
|
||||
board.Locked = columnDefaultBool
|
||||
case "anonymous":
|
||||
board.Anonymous = columnDefault
|
||||
case "forced_anon":
|
||||
board.ForcedAnon = columnDefaultBool
|
||||
case "max_age":
|
||||
board.MaxAge = columnDefaultInt
|
||||
case "autosage_after":
|
||||
board.AutosageAfter = columnDefaultInt
|
||||
case "no_images_after":
|
||||
board.NoImagesAfter = columnDefaultInt
|
||||
case "max_message_length":
|
||||
board.MaxMessageLength = columnDefaultInt
|
||||
case "embeds_allowed":
|
||||
board.EmbedsAllowed = columnDefaultBool
|
||||
case "redirect_to_thread":
|
||||
board.RedirectToThread = columnDefaultBool
|
||||
case "require_file":
|
||||
board.RequireFile = columnDefaultBool
|
||||
case "enable_catalog":
|
||||
board.EnableCatalog = columnDefaultBool
|
||||
}
|
||||
}
|
||||
board.Section = 1
|
||||
board.MaxFilesize = 4718592
|
||||
board.MaxPages = 11
|
||||
board.DefaultStyle = "pipes.css"
|
||||
board.Anonymous = "Anonymous"
|
||||
board.AutosageAfter = 200
|
||||
board.MaxMessageLength = 8192
|
||||
board.EmbedsAllowed = true
|
||||
board.EnableCatalog = true
|
||||
board.Worksafe = true
|
||||
board.ThreadsPerPage = config.ThreadsPerPage
|
||||
}
|
||||
|
||||
html = "<h1 class=\"manage-header\">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 = querySQL("SELECT `dir` FROM `" + config.DBprefix + "boards`")
|
||||
rows, err = querySQL("SELECT dir FROM " + config.DBprefix + "boards")
|
||||
defer closeHandle(rows)
|
||||
if err != nil {
|
||||
html += handleError(1, err.Error())
|
||||
|
@ -908,12 +866,12 @@ var manage_functions = map[string]ManageFunction{
|
|||
}
|
||||
|
||||
html += "</select> <input type=\"submit\" value=\"Edit\" /> <input type=\"submit\" value=\"Delete\" /></form><hr />" +
|
||||
"<h2 class=\"manage-header\">Create new board</h2>\n<span id=\"board-creation-message\">" + board_creation_status + "</span><br />"
|
||||
"<h2 class=\"manage-header\">Create new board</h2>\n<span id=\"board-creation-message\">" + boardCreationStatus + "</span><br />"
|
||||
|
||||
manageBoardsBuffer := bytes.NewBufferString("")
|
||||
allSections, _ = getSectionArr("")
|
||||
if len(allSections) == 0 {
|
||||
execSQL("INSERT INTO `" + config.DBprefix + "sections` (`hidden`,`name`,`abbreviation`) VALUES(0,'Main','main')")
|
||||
execSQL("INSERT INTO " + config.DBprefix + "sections (hidden,name,abbreviation) VALUES(0,'Main','main')")
|
||||
}
|
||||
allSections, _ = getSectionArr("")
|
||||
|
||||
|
@ -1027,7 +985,7 @@ var manage_functions = map[string]ManageFunction{
|
|||
"`"+config.DBprefix+"posts`. "+
|
||||
"`ip` AS ip, "+
|
||||
"`"+config.DBprefix+"posts`. "+
|
||||
"`timestamp` AS timestamp "+
|
||||
"`timestamp` AS timestamp "+
|
||||
"FROM `"+config.DBprefix+"posts`, `"+config.DBprefix+"boards` "+
|
||||
"WHERE `reviewed` = 0 "+
|
||||
"AND `"+config.DBprefix+"posts`.`deleted_timestamp` = ? "+
|
||||
|
@ -1068,11 +1026,11 @@ var manage_functions = map[string]ManageFunction{
|
|||
"dir": boardDir,
|
||||
}, "")
|
||||
if err != nil {
|
||||
jsonErr, _ := marshalAPI("error", err.Error(), false)
|
||||
jsonErr, _ := marshalJSON("error", err.Error(), false)
|
||||
return jsonErr
|
||||
}
|
||||
if len(boards) < 1 {
|
||||
jsonErr, _ := marshalAPI("error", "Board doesn't exist.", false)
|
||||
jsonErr, _ := marshalJSON("error", "Board doesn't exist.", false)
|
||||
return jsonErr
|
||||
}
|
||||
|
||||
|
@ -1081,14 +1039,14 @@ var manage_functions = map[string]ManageFunction{
|
|||
"boardid": boards[0].ID,
|
||||
}, "")
|
||||
if err != nil {
|
||||
jsonErr, _ := marshalAPI("error", err.Error(), false)
|
||||
jsonErr, _ := marshalJSON("error", err.Error(), false)
|
||||
return jsonErr
|
||||
}
|
||||
if len(posts) < 1 {
|
||||
jsonErr, _ := marshalAPI("eror", "Post doesn't exist.", false)
|
||||
jsonErr, _ := marshalJSON("eror", "Post doesn't exist.", false)
|
||||
return jsonErr
|
||||
}
|
||||
jsonStr, _ := marshalAPI("", posts[0], false)
|
||||
jsonStr, _ := marshalJSON("", posts[0], false)
|
||||
return jsonStr
|
||||
}},
|
||||
"staff": {
|
||||
|
|
|
@ -40,7 +40,7 @@ var (
|
|||
|
||||
// bumps the given thread on the given board and returns true if there were no errors
|
||||
func bumpThread(postID, boardID int) error {
|
||||
_, err := execSQL("UPDATE `"+config.DBprefix+"posts` SET `bumped` = ? WHERE `id` = ? AND `boardid` = ?",
|
||||
_, err := execSQL("UPDATE "+config.DBprefix+"posts SET bumped = ? WHERE id = ? AND boardid = ?",
|
||||
time.Now(), postID, boardID,
|
||||
)
|
||||
|
||||
|
@ -79,21 +79,21 @@ func getBannedStatus(request *http.Request) (BanInfo, error) {
|
|||
}
|
||||
|
||||
in := []interface{}{ip}
|
||||
query := "SELECT `id`,`ip`,`name`,`boards`,`timestamp`,`expires`,`permaban`,`reason`,`type`,`appeal_at`,`can_appeal` FROM `" + config.DBprefix + "banlist` WHERE `ip` = ? "
|
||||
query := "SELECT id,ip,name,boards,timestamp,expires,permaban,reason,type,appeal_at,can_appeal FROM " + config.DBprefix + "banlist WHERE ip = ? "
|
||||
|
||||
if tripcode != "" {
|
||||
in = append(in, tripcode)
|
||||
query += "OR `name` = ? "
|
||||
query += "OR name = ? "
|
||||
}
|
||||
if filename != "" {
|
||||
in = append(in, filename)
|
||||
query += "OR `filename` = ? "
|
||||
query += "OR filename = ? "
|
||||
}
|
||||
if checksum != "" {
|
||||
in = append(in, checksum)
|
||||
query += "OR `file_checksum` = ? "
|
||||
query += "OR file_checksum = ? "
|
||||
}
|
||||
query += " ORDER BY `id` DESC LIMIT 1"
|
||||
query += " ORDER BY id DESC LIMIT 1"
|
||||
|
||||
err = queryRowSQL(query, in, []interface{}{
|
||||
&banEntry.ID, &banEntry.IP, &banEntry.Name, &banEntry.Boards, &banEntry.Timestamp,
|
||||
|
@ -119,7 +119,7 @@ func isBanned(ban BanInfo, board string) bool {
|
|||
|
||||
func sinceLastPost(post *Post) int {
|
||||
var lastPostTime time.Time
|
||||
if err := queryRowSQL("SELECT `timestamp` FROM `"+config.DBprefix+"posts` WHERE `ip` = '?' ORDER BY `timestamp` DESC LIMIT 1",
|
||||
if err := queryRowSQL("SELECT timestamp FROM "+config.DBprefix+"posts WHERE ip = ? ORDER BY timestamp DESC LIMIT 1",
|
||||
[]interface{}{post.IP},
|
||||
[]interface{}{&lastPostTime},
|
||||
); err == sql.ErrNoRows {
|
||||
|
@ -243,31 +243,38 @@ func parseName(name string) map[string]string {
|
|||
}
|
||||
|
||||
// inserts prepared post object into the SQL table so that it can be rendered
|
||||
func insertPost(post Post, bump bool) (sql.Result, error) {
|
||||
result, err := execSQL(
|
||||
"INSERT INTO `"+config.DBprefix+"posts` "+
|
||||
"(`boardid`,`parentid`,`name`,`tripcode`,`email`,`subject`,`message`,`message_raw`,`password`,`filename`,`filename_original`,`file_checksum`,`filesize`,`image_w`,`image_h`,`thumb_w`,`thumb_h`,`ip`,`tag`,`timestamp`,`autosage`,`deleted_timestamp`,`bumped`,`stickied`,`locked`,`reviewed`)"+
|
||||
"VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
|
||||
func insertPost(post *Post, bump bool) error {
|
||||
queryStr := "INSERT INTO " + config.DBprefix + "posts " +
|
||||
"(boardid,parentid,name,tripcode,email,subject,message,message_raw,password,filename,filename_original,file_checksum,filesize,image_w,image_h,thumb_w,thumb_h,ip,tag,timestamp,autosage,deleted_timestamp,bumped,stickied,locked,reviewed)" +
|
||||
"VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"
|
||||
|
||||
result, err := execSQL(queryStr,
|
||||
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.Capcode,
|
||||
post.Timestamp, post.Autosage, post.DeletedTimestamp, post.Bumped,
|
||||
post.Stickied, post.Locked, post.Reviewed,
|
||||
)
|
||||
|
||||
post.Stickied, post.Locked, post.Reviewed)
|
||||
if err != nil {
|
||||
return result, err
|
||||
return err
|
||||
}
|
||||
|
||||
switch config.DBtype {
|
||||
case "mysql":
|
||||
var postID int64
|
||||
postID, err = result.LastInsertId()
|
||||
post.ID = int(postID)
|
||||
case "postgres":
|
||||
err = queryRowSQL("SELECT currval(pg_get_serial_sequence('"+config.DBprefix+"posts','id'))", nil, []interface{}{&post.ID})
|
||||
case "sqlite3":
|
||||
err = queryRowSQL("SELECT LAST_INSERT_ROWID()", nil, []interface{}{&post.ID})
|
||||
}
|
||||
|
||||
// Bump parent post if requested.
|
||||
if post.ParentID != 0 && bump {
|
||||
if err != nil && post.ParentID != 0 && bump {
|
||||
err = bumpThread(post.ParentID, post.BoardID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return result, err
|
||||
return err
|
||||
}
|
||||
|
||||
// called when a user accesses /post. Parse form data, then insert and build
|
||||
|
@ -310,7 +317,7 @@ func makePost(writer http.ResponseWriter, request *http.Request) {
|
|||
post.Subject = request.FormValue("postsubject")
|
||||
post.MessageText = strings.Trim(request.FormValue("postmsg"), "\r\n")
|
||||
|
||||
if err := queryRowSQL("SELECT `max_message_length` from `"+config.DBprefix+"boards` WHERE `id` = ?",
|
||||
if err := queryRowSQL("SELECT max_message_length from "+config.DBprefix+"boards WHERE id = ?",
|
||||
[]interface{}{post.BoardID},
|
||||
[]interface{}{&maxMessageLength},
|
||||
); err != nil {
|
||||
|
@ -377,6 +384,7 @@ func makePost(writer http.ResponseWriter, request *http.Request) {
|
|||
// no file was uploaded
|
||||
post.Filename = ""
|
||||
accessLog.Print("Receiving post from " + post.IP + ", referred from: " + request.Referer())
|
||||
accessLog.Printf("Receiving post from %s, referred from: %s", post.IP, request.Referer())
|
||||
} else {
|
||||
data, err := ioutil.ReadAll(file)
|
||||
if err != nil {
|
||||
|
@ -411,7 +419,7 @@ func makePost(writer http.ResponseWriter, request *http.Request) {
|
|||
post.FileChecksum = fmt.Sprintf("%x", md5.Sum(data))
|
||||
|
||||
var allowsVids bool
|
||||
if err = queryRowSQL("SELECT `embeds_allowed` FROM `"+config.DBprefix+"boards` WHERE `id` = ? LIMIT 1",
|
||||
if err = queryRowSQL("SELECT embeds_allowed FROM "+config.DBprefix+"boards WHERE id = ? LIMIT 1",
|
||||
[]interface{}{post.BoardID},
|
||||
[]interface{}{&allowsVids},
|
||||
); err != nil {
|
||||
|
@ -588,13 +596,10 @@ func makePost(writer http.ResponseWriter, request *http.Request) {
|
|||
}
|
||||
|
||||
post.Sanitize()
|
||||
result, err := insertPost(post, emailCommand != "sage")
|
||||
if err != nil {
|
||||
if err = insertPost(&post, emailCommand != "sage"); err != nil {
|
||||
serveErrorPage(writer, handleError(1, err.Error()))
|
||||
return
|
||||
}
|
||||
postid, _ := result.LastInsertId()
|
||||
post.ID = int(postid)
|
||||
|
||||
// rebuild the board page
|
||||
buildBoards(post.BoardID)
|
||||
|
@ -628,7 +633,7 @@ func formatMessage(message string) string {
|
|||
var boardDir string
|
||||
var linkParent int
|
||||
|
||||
if err = queryRowSQL("SELECT `dir`,`parentid` FROM "+config.DBprefix+"posts,"+config.DBprefix+"boards WHERE "+config.DBprefix+"posts.id = ?",
|
||||
if err = queryRowSQL("SELECT dir,parentid FROM "+config.DBprefix+"posts,"+config.DBprefix+"boards WHERE "+config.DBprefix+"posts.id = ?",
|
||||
[]interface{}{word[8:]},
|
||||
[]interface{}{&boardDir, &linkParent},
|
||||
); err != nil {
|
||||
|
@ -673,7 +678,7 @@ func banHandler(writer http.ResponseWriter, request *http.Request) {
|
|||
return
|
||||
}
|
||||
escapedMsg := html.EscapeString(appealMsg)
|
||||
if _, err = execSQL("INSERT INTO `"+config.DBprefix+"appeals` (`ban`,`message`) VALUES(?,?)",
|
||||
if _, err = execSQL("INSERT INTO "+config.DBprefix+"appeals (ban,message) VALUES(?,?)",
|
||||
banStatus.ID, escapedMsg,
|
||||
); err != nil {
|
||||
serveErrorPage(writer, err.Error())
|
||||
|
|
|
@ -225,7 +225,7 @@ func utilHandler(writer http.ResponseWriter, request *http.Request) {
|
|||
var post Post
|
||||
post.ID, _ = strconv.Atoi(postsArr[0])
|
||||
post.BoardID, _ = strconv.Atoi(boardid)
|
||||
if err = queryRowSQL("SELECT `parentid`,`name`,`tripcode`,`email`,`subject`,`password`,`message_raw` FROM `"+config.DBprefix+"posts` WHERE `id` = ? AND `boardid` = ? AND `deleted_timestamp` = ?",
|
||||
if err = queryRowSQL("SELECT parentid,name,tripcode,email,subject,password,message_raw FROM "+config.DBprefix+"posts WHERE id = ? AND boardid = ? AND deleted_timestamp = ?",
|
||||
[]interface{}{post.ID, post.BoardID, nilTimestamp},
|
||||
[]interface{}{
|
||||
&post.ParentID, &post.Name, &post.Tripcode, &post.Email, &post.Subject,
|
||||
|
@ -265,7 +265,7 @@ func utilHandler(writer http.ResponseWriter, request *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
if err = queryRowSQL("SELECT `password` FROM `"+config.DBprefix+"posts` WHERE `id` = ? AND `boardid` = ?",
|
||||
if err = queryRowSQL("SELECT password FROM "+config.DBprefix+"posts WHERE id = ? AND boardid = ?",
|
||||
[]interface{}{postid, boardid},
|
||||
[]interface{}{&postPassword},
|
||||
); err != nil {
|
||||
|
@ -284,8 +284,8 @@ func utilHandler(writer http.ResponseWriter, request *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
if _, err = execSQL("UPDATE `"+config.DBprefix+"posts` SET "+
|
||||
"`email` = ?, `subject` = ?, `message` = ?, `message_raw` = ? WHERE `id` = ? AND `boardid` = ?",
|
||||
if _, err = execSQL("UPDATE "+config.DBprefix+"posts SET "+
|
||||
"email = ?, subject = ?, message = ?, message_raw = ? WHERE id = ? AND boardid = ?",
|
||||
request.FormValue("editemail"), request.FormValue("editsubject"), formatMessage(request.FormValue("editmsg")), request.FormValue("editmsg"),
|
||||
postid, boardid,
|
||||
); err != nil {
|
||||
|
@ -323,8 +323,8 @@ func utilHandler(writer http.ResponseWriter, request *http.Request) {
|
|||
post.BoardID, _ = strconv.Atoi(boardid)
|
||||
|
||||
if err = queryRowSQL(
|
||||
"SELECT `parentid`, `filename`, `password` FROM `"+config.DBprefix+"posts` WHERE `id` = ? AND `boardid` = ? AND `deleted_timestamp` = ?",
|
||||
[]interface{}{&post.ID, &post.BoardID, nilTimestamp},
|
||||
"SELECT parentid, filename,password FROM "+config.DBprefix+"posts WHERE id = ? AND boardid = ? AND deleted_timestamp = ?",
|
||||
[]interface{}{post.ID, post.BoardID, nilTimestamp},
|
||||
[]interface{}{&post.ParentID, &post.Filename, &post.Password},
|
||||
); err == sql.ErrNoRows {
|
||||
//the post has already been deleted
|
||||
|
@ -337,7 +337,7 @@ func utilHandler(writer http.ResponseWriter, request *http.Request) {
|
|||
}
|
||||
|
||||
if err = queryRowSQL(
|
||||
"SELECT `id` FROM `"+config.DBprefix+"boards` WHERE `dir` = ?",
|
||||
"SELECT id FROM "+config.DBprefix+"boards WHERE dir = ?",
|
||||
[]interface{}{board},
|
||||
[]interface{}{&post.BoardID},
|
||||
); err != nil {
|
||||
|
@ -364,7 +364,7 @@ func utilHandler(writer http.ResponseWriter, request *http.Request) {
|
|||
os.Remove(path.Join(config.DocumentRoot, board, "/thumb/"+fileName+"c."+thumbType))
|
||||
|
||||
if _, err = execSQL(
|
||||
"UPDATE `"+config.DBprefix+"posts` SET `filename` = 'deleted' WHERE `id` = ? AND `boardid` = ?",
|
||||
"UPDATE "+config.DBprefix+"posts SET filename = deleted WHERE id = ? AND boardid = ?",
|
||||
post.ID, post.BoardID,
|
||||
); err != nil {
|
||||
serveErrorPage(writer, err.Error())
|
||||
|
@ -382,7 +382,7 @@ func utilHandler(writer http.ResponseWriter, request *http.Request) {
|
|||
} else {
|
||||
// delete the post
|
||||
if _, err = execSQL(
|
||||
"UPDATE `"+config.DBprefix+"posts` SET `deleted_timestamp` = ? WHERE `id` = ?",
|
||||
"UPDATE "+config.DBprefix+"posts SET deleted_timestamp = ? WHERE id = ?",
|
||||
getSQLDateTime(), post.ID,
|
||||
); err != nil {
|
||||
serveErrorPage(writer, err.Error())
|
||||
|
@ -395,7 +395,7 @@ func utilHandler(writer http.ResponseWriter, request *http.Request) {
|
|||
}
|
||||
|
||||
// if the deleted post is actually a thread, delete its posts
|
||||
if _, err = execSQL("UPDATE `"+config.DBprefix+"posts` SET `deleted_timestamp` = ? WHERE `parentID` = ?",
|
||||
if _, err = execSQL("UPDATE "+config.DBprefix+"posts SET deleted_timestamp = ? WHERE parentID = ?",
|
||||
getSQLDateTime(), post.ID,
|
||||
); err != nil {
|
||||
serveErrorPage(writer, err.Error())
|
||||
|
@ -405,7 +405,7 @@ func utilHandler(writer http.ResponseWriter, request *http.Request) {
|
|||
// delete the file
|
||||
var deletedFilename string
|
||||
if err = queryRowSQL(
|
||||
"SELECT `filename` FROM `"+config.DBprefix+"posts` WHERE `id` = ? AND `filename` != ''",
|
||||
"SELECT filename FROM "+config.DBprefix+"posts WHERE id = ? AND filename != ''",
|
||||
[]interface{}{post.ID},
|
||||
[]interface{}{&deletedFilename},
|
||||
); err == nil {
|
||||
|
@ -415,7 +415,7 @@ func utilHandler(writer http.ResponseWriter, request *http.Request) {
|
|||
}
|
||||
|
||||
if err = queryRowSQL(
|
||||
"SELECT `filename` FROM `"+config.DBprefix+"posts` WHERE `parentID` = ? AND `filename` != ''",
|
||||
"SELECT filename FROM "+config.DBprefix+"posts WHERE parentID = ? AND filename != ''",
|
||||
[]interface{}{post.ID},
|
||||
[]interface{}{&deletedFilename},
|
||||
); err == nil {
|
||||
|
|
127
src/sql.go
127
src/sql.go
|
@ -2,7 +2,7 @@ package main
|
|||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"regexp"
|
||||
|
@ -10,49 +10,73 @@ import (
|
|||
"time"
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
// _ "github.com/lib/pq"
|
||||
_ "github.com/lib/pq"
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
)
|
||||
|
||||
const (
|
||||
nilTimestamp = "0000-00-00 00:00:00"
|
||||
mysqlDatetimeFormat = "2006-01-02 15:04:05"
|
||||
mysqlDatetimeFormat = "2006-01-02 15:04:05"
|
||||
unsupportedSQLVersionMsg = `Received syntax error while preparing a SQL string.
|
||||
This means that either there is a bug in gochan's code (hopefully not) or that you are using an unsupported My/Postgre/SQLite version.
|
||||
Before reporting an error, make sure that you are using the up to date version of your selected SQL server.
|
||||
Error text: %s
|
||||
`
|
||||
)
|
||||
|
||||
var (
|
||||
db *sql.DB
|
||||
db *sql.DB
|
||||
nilTimestamp string
|
||||
)
|
||||
|
||||
func connectToSQLServer() {
|
||||
var err error
|
||||
|
||||
var connStr string
|
||||
println(0, "Initializing server...")
|
||||
db, err = sql.Open("mysql", config.DBusername+":"+config.DBpassword+"@"+config.DBhost+"/"+config.DBname+"?parseTime=true&collation=utf8mb4_unicode_ci")
|
||||
if err != nil {
|
||||
|
||||
switch config.DBtype {
|
||||
case "mysql":
|
||||
connStr = fmt.Sprintf("%s:%s@%s/%s?parseTime=true&collation=utf8mb4_unicode_ci",
|
||||
config.DBusername, config.DBpassword, config.DBhost, config.DBname)
|
||||
nilTimestamp = "0000-00-00 00:00:00"
|
||||
case "postgres":
|
||||
connStr = fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=verify-ca",
|
||||
config.DBusername, config.DBpassword, config.DBhost, config.DBname)
|
||||
nilTimestamp = "0001-01-01 00:00:00"
|
||||
case "sqlite3":
|
||||
connStr = config.DBhost
|
||||
nilTimestamp = "0001-01-01 00:00:00+00:00"
|
||||
default:
|
||||
handleError(0, "Invalid DBtype '%s' in gochan.json, valid values are 'mysql' and 'postgres'", config.DBtype)
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
nullTime, _ = time.Parse("2006-01-02 15:04:05", nilTimestamp)
|
||||
if db, err = sql.Open(config.DBtype, connStr); err != nil {
|
||||
handleError(0, "Failed to connect to the database: %s\n", customError(err))
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
if err = initDB(); err != nil {
|
||||
handleError(0, "Failed initializing DB: %s\n", customError(err))
|
||||
if err = initDB("initdb_" + config.DBtype + ".sql"); err != nil {
|
||||
println(0, "Failed initializing DB:", sqlVersionErr(err))
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
var sqlVersionStr string
|
||||
err = queryRowSQL("SELECT `value` FROM `"+config.DBprefix+"info` WHERE `name` = 'version'",
|
||||
err = queryRowSQL("SELECT value FROM "+config.DBprefix+"info WHERE name = 'version'",
|
||||
[]interface{}{}, []interface{}{&sqlVersionStr})
|
||||
|
||||
if err == sql.ErrNoRows {
|
||||
println(0, "\nThis looks like a new installation")
|
||||
|
||||
if _, err = db.Exec("INSERT INTO `" + config.DBname + "`.`" + config.DBprefix + "staff` " +
|
||||
"(`username`, `password_checksum`, `salt`, `rank`) " +
|
||||
if _, err = db.Exec("INSERT INTO " + config.DBprefix + "staff " +
|
||||
"(username, password_checksum, salt, rank) " +
|
||||
"VALUES ('admin', '" + bcryptSum("password") + "', 'abc', 3)",
|
||||
); err != nil {
|
||||
handleError(0, "Failed creating admin user with error: %s\n", customError(err))
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
_, err = execSQL("INSERT INTO `"+config.DBprefix+"info` (`name`,`value`) VALUES('version',?)", versionStr)
|
||||
_, err = execSQL("INSERT INTO "+config.DBprefix+"info (name,value) VALUES('version',?)", versionStr)
|
||||
return
|
||||
} else if err != nil {
|
||||
handleError(0, "failed: %s\n", customError(err))
|
||||
|
@ -64,18 +88,18 @@ func connectToSQLServer() {
|
|||
}
|
||||
if version.CompareString(sqlVersionStr) > 0 {
|
||||
printf(0, "Updating version in database from %s to %s\n", sqlVersionStr, version.String())
|
||||
execSQL("UPDATE `"+config.DBprefix+"info` SET `value` = ? WHERE `name` = 'version'", versionStr)
|
||||
execSQL("UPDATE "+config.DBprefix+"info SET value = ? WHERE name = 'version'", versionStr)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func initDB() error {
|
||||
func initDB(initFile string) error {
|
||||
var err error
|
||||
if _, err = os.Stat("initdb.sql"); err != nil {
|
||||
return errors.New("SQL database initialization file (initdb.sql) missing. Please reinstall gochan")
|
||||
if _, err = os.Stat(initFile); err != nil {
|
||||
return fmt.Errorf("SQL database initialization file (%s) missing. Please reinstall gochan", initFile)
|
||||
}
|
||||
|
||||
sqlBytes, err := ioutil.ReadFile("initdb.sql")
|
||||
sqlBytes, err := ioutil.ReadFile(initFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -97,15 +121,62 @@ func initDB() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// checks to see if the given error is a syntax error (used for built-in strings)
|
||||
func sqlVersionErr(err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
errText := err.Error()
|
||||
switch config.DBtype {
|
||||
case "mysql":
|
||||
if !strings.Contains(errText, "You have an error in your SQL syntax") {
|
||||
return err
|
||||
}
|
||||
case "postgres":
|
||||
if !strings.Contains(errText, "syntax error at or near") {
|
||||
return err
|
||||
}
|
||||
case "sqlite3":
|
||||
if !strings.Contains(errText, "Error: near ") {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return fmt.Errorf(unsupportedSQLVersionMsg, errText)
|
||||
}
|
||||
|
||||
// used for generating a prepared SQL statement formatted according to config.DBtype
|
||||
func prepareSQL(query string) (*sql.Stmt, error) {
|
||||
var preparedStr string
|
||||
switch config.DBtype {
|
||||
case "mysql":
|
||||
fallthrough
|
||||
case "sqlite3":
|
||||
preparedStr = query
|
||||
break
|
||||
case "postgres":
|
||||
arr := strings.Split(query, "?")
|
||||
for i := range arr {
|
||||
if i == len(arr)-1 {
|
||||
break
|
||||
}
|
||||
arr[i] += fmt.Sprintf("$%d", i+1)
|
||||
}
|
||||
preparedStr = strings.Join(arr, "")
|
||||
break
|
||||
}
|
||||
stmt, err := db.Prepare(preparedStr)
|
||||
return stmt, sqlVersionErr(err)
|
||||
}
|
||||
|
||||
/*
|
||||
* Automatically escapes the given values and caches the statement
|
||||
* Example:
|
||||
* var intVal int
|
||||
* var stringVal string
|
||||
* result, err := execSQL("INSERT INTO `tablename` (`intval`,`stringval`) VALUES(?,?)", intVal, stringVal)
|
||||
* result, err := execSQL("INSERT INTO tablename (intval,stringval) VALUES(?,?)", intVal, stringVal)
|
||||
*/
|
||||
func execSQL(query string, values ...interface{}) (sql.Result, error) {
|
||||
stmt, err := db.Prepare(query)
|
||||
stmt, err := prepareSQL(query)
|
||||
defer closeHandle(stmt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -120,13 +191,13 @@ func execSQL(query string, values ...interface{}) (sql.Result, error) {
|
|||
* id := 32
|
||||
* var intVal int
|
||||
* var stringVal string
|
||||
* err := queryRowSQL("SELECT `intval`,`stringval` FROM `table` WHERE `id` = ?",
|
||||
* err := queryRowSQL("SELECT intval,stringval FROM table WHERE id = ?",
|
||||
* []interface{}{&id},
|
||||
* []interface{}{&intVal, &stringVal}
|
||||
* )
|
||||
*/
|
||||
func queryRowSQL(query string, values []interface{}, out []interface{}) error {
|
||||
stmt, err := db.Prepare(query)
|
||||
stmt, err := prepareSQL(query)
|
||||
defer closeHandle(stmt)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -138,7 +209,7 @@ func queryRowSQL(query string, values []interface{}, out []interface{}) error {
|
|||
* Gets all rows from the db with the values in values[] and fills the respective pointers in out[]
|
||||
* Automatically escapes the given values and caches the query
|
||||
* Example:
|
||||
* rows, err := querySQL("SELECT * FROM `table`")
|
||||
* rows, err := querySQL("SELECT * FROM table")
|
||||
* if err == nil {
|
||||
* for rows.Next() {
|
||||
* var intVal int
|
||||
|
@ -149,7 +220,7 @@ func queryRowSQL(query string, values []interface{}, out []interface{}) error {
|
|||
* }
|
||||
*/
|
||||
func querySQL(query string, a ...interface{}) (*sql.Rows, error) {
|
||||
stmt, err := db.Prepare(query)
|
||||
stmt, err := prepareSQL(query)
|
||||
defer closeHandle(stmt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -164,9 +235,3 @@ func getSQLDateTime() string {
|
|||
func getSpecificSQLDateTime(t time.Time) string {
|
||||
return t.Format(mysqlDatetimeFormat)
|
||||
}
|
||||
|
||||
func checkTableExists(tableName string) bool {
|
||||
rows, err := querySQL("SELECT * FROM information_schema.tables WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ? LIMIT 1",
|
||||
config.DBname, tableName)
|
||||
return err == nil && rows.Next() == true
|
||||
}
|
||||
|
|
131
src/template.go
131
src/template.go
|
@ -1,7 +1,6 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"html"
|
||||
"os"
|
||||
|
@ -307,7 +306,7 @@ var (
|
|||
|
||||
func loadTemplate(files ...string) (*template.Template, error) {
|
||||
if len(files) == 0 {
|
||||
return nil, errors.New("No files named in call to loadTemplate")
|
||||
return nil, fmt.Errorf("No files named in call to loadTemplate")
|
||||
}
|
||||
var templates []string
|
||||
for i, file := range files {
|
||||
|
@ -323,65 +322,83 @@ func loadTemplate(files ...string) (*template.Template, error) {
|
|||
}
|
||||
|
||||
func templateError(name string, err error) error {
|
||||
return errors.New("Failed loading template \"" + config.TemplateDir + "/" + name + ": \"" + err.Error())
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("Failed loading template '%s/%s': %s", config.TemplateDir, name, err.Error())
|
||||
}
|
||||
|
||||
func initTemplates() error {
|
||||
func initTemplates(which ...string) error {
|
||||
var err error
|
||||
resetBoardSectionArrays()
|
||||
banpage_tmpl, err = loadTemplate("banpage.html", "global_footer.html")
|
||||
if err != nil {
|
||||
return templateError("banpage.html", err)
|
||||
}
|
||||
buildAll := len(which) == 0 || which[0] == "all"
|
||||
|
||||
catalog_tmpl, err = loadTemplate("catalog.html", "img_header.html", "global_footer.html")
|
||||
if err != nil {
|
||||
return templateError("catalog.html", err)
|
||||
}
|
||||
|
||||
errorpage_tmpl, err = loadTemplate("error.html")
|
||||
if err != nil {
|
||||
return templateError("error.html", err)
|
||||
}
|
||||
|
||||
img_boardpage_tmpl, err = loadTemplate("img_boardpage.html", "img_header.html", "postbox.html", "global_footer.html")
|
||||
if err != nil {
|
||||
return templateError("img_boardpage.html", err)
|
||||
}
|
||||
|
||||
img_threadpage_tmpl, err = loadTemplate("img_threadpage.html", "img_header.html", "postbox.html", "global_footer.html")
|
||||
if err != nil {
|
||||
return templateError("img_threadpage.html", err)
|
||||
}
|
||||
|
||||
post_edit_tmpl, err = loadTemplate("post_edit.html", "img_header.html", "global_footer.html")
|
||||
if err != nil {
|
||||
return templateError("img_threadpage.html", err)
|
||||
}
|
||||
|
||||
manage_bans_tmpl, err = loadTemplate("manage_bans.html")
|
||||
if err != nil {
|
||||
return templateError("manage_bans.html", err)
|
||||
}
|
||||
|
||||
manage_boards_tmpl, err = loadTemplate("manage_boards.html")
|
||||
if err != nil {
|
||||
return templateError("manage_boards.html", err)
|
||||
}
|
||||
|
||||
manage_config_tmpl, err = loadTemplate("manage_config.html")
|
||||
if err != nil {
|
||||
return templateError("manage_config.html", err)
|
||||
}
|
||||
|
||||
manage_header_tmpl, err = loadTemplate("manage_header.html")
|
||||
if err != nil {
|
||||
return templateError("manage_header.html", err)
|
||||
}
|
||||
|
||||
front_page_tmpl, err = loadTemplate("front.html", "front_intro.html", "img_header.html", "global_footer.html")
|
||||
if err != nil {
|
||||
return templateError("front.html", err)
|
||||
for _, t := range which {
|
||||
if buildAll || t == "banpage" {
|
||||
banpage_tmpl, err = loadTemplate("banpage.html", "global_footer.html")
|
||||
if err != nil {
|
||||
return templateError("banpage.html", err)
|
||||
}
|
||||
}
|
||||
if buildAll || t == "catalog" {
|
||||
catalog_tmpl, err = loadTemplate("catalog.html", "img_header.html", "global_footer.html")
|
||||
if err != nil {
|
||||
return templateError("catalog.html", err)
|
||||
}
|
||||
}
|
||||
if buildAll || t == "error" {
|
||||
errorpage_tmpl, err = loadTemplate("error.html")
|
||||
if err != nil {
|
||||
return templateError("error.html", err)
|
||||
}
|
||||
}
|
||||
if buildAll || t == "front" {
|
||||
front_page_tmpl, err = loadTemplate("front.html", "front_intro.html", "img_header.html", "global_footer.html")
|
||||
if err != nil {
|
||||
return templateError("front.html", err)
|
||||
}
|
||||
}
|
||||
if buildAll || t == "boardpage" {
|
||||
img_boardpage_tmpl, err = loadTemplate("img_boardpage.html", "img_header.html", "postbox.html", "global_footer.html")
|
||||
if err != nil {
|
||||
return templateError("img_boardpage.html", err)
|
||||
}
|
||||
}
|
||||
if buildAll || t == "threadpage" {
|
||||
img_threadpage_tmpl, err = loadTemplate("img_threadpage.html", "img_header.html", "postbox.html", "global_footer.html")
|
||||
if err != nil {
|
||||
return templateError("img_threadpage.html", err)
|
||||
}
|
||||
}
|
||||
if buildAll || t == "postedit" {
|
||||
post_edit_tmpl, err = loadTemplate("post_edit.html", "img_header.html", "global_footer.html")
|
||||
if err != nil {
|
||||
return templateError("img_threadpage.html", err)
|
||||
}
|
||||
}
|
||||
if buildAll || t == "managebans" {
|
||||
manage_bans_tmpl, err = loadTemplate("manage_bans.html")
|
||||
if err != nil {
|
||||
return templateError("manage_bans.html", err)
|
||||
}
|
||||
}
|
||||
if buildAll || t == "manageboards" {
|
||||
manage_boards_tmpl, err = loadTemplate("manage_boards.html")
|
||||
if err != nil {
|
||||
return templateError("manage_boards.html", err)
|
||||
}
|
||||
}
|
||||
if buildAll || t == "manageconfig" {
|
||||
manage_config_tmpl, err = loadTemplate("manage_config.html")
|
||||
if err != nil {
|
||||
return templateError("manage_config.html", err)
|
||||
}
|
||||
}
|
||||
if buildAll || t == "manageheader" {
|
||||
manage_header_tmpl, err = loadTemplate("manage_header.html")
|
||||
if err != nil {
|
||||
return templateError("manage_header.html", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
24
src/types.go
24
src/types.go
|
@ -87,7 +87,7 @@ func (a *BanAppeal) GetBan() (BanInfo, error) {
|
|||
var ban BanInfo
|
||||
var err error
|
||||
|
||||
err = queryRowSQL("SELECT * FROM `"+config.DBprefix+"banlist` WHERE `id` = ? LIMIT 1",
|
||||
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,
|
||||
|
@ -123,9 +123,9 @@ type BannedHash struct {
|
|||
|
||||
type Board struct {
|
||||
ID int `json:"-"`
|
||||
CurrentPage int `json:`
|
||||
CurrentPage int `json:"-"`
|
||||
NumPages int `json:"pages"`
|
||||
Order int `json:"-"`
|
||||
ListOrder int `json:"-"`
|
||||
Dir string `json:"board"`
|
||||
Type int `json:"-"`
|
||||
UploadType int `json:"-"`
|
||||
|
@ -159,7 +159,7 @@ type Board struct {
|
|||
|
||||
type BoardSection struct {
|
||||
ID int
|
||||
Order int
|
||||
ListOrder int
|
||||
Hidden bool
|
||||
Name string
|
||||
Abbreviation string
|
||||
|
@ -191,7 +191,7 @@ type Post struct {
|
|||
IP string `json:"-"`
|
||||
Capcode string `json:"capcode"`
|
||||
Timestamp time.Time `json:"time"`
|
||||
Autosage int `json:"-"`
|
||||
Autosage bool `json:"-"`
|
||||
DeletedTimestamp time.Time `json:"-"`
|
||||
Bumped time.Time `json:"last_modified"`
|
||||
Stickied bool `json:"-"`
|
||||
|
@ -242,6 +242,7 @@ type Report struct {
|
|||
|
||||
type LoginSession struct {
|
||||
ID uint
|
||||
Name string
|
||||
Data string
|
||||
Expires string
|
||||
}
|
||||
|
@ -291,13 +292,12 @@ type GochanConfig struct {
|
|||
TemplateDir string
|
||||
LogDir string
|
||||
|
||||
DBtype string
|
||||
DBhost string
|
||||
DBname string
|
||||
DBusername string
|
||||
DBpassword string
|
||||
DBprefix string
|
||||
DBkeepalive bool
|
||||
DBtype string
|
||||
DBhost string
|
||||
DBname string
|
||||
DBusername string
|
||||
DBpassword string
|
||||
DBprefix string
|
||||
|
||||
Lockdown bool `description:"Disables posting." default:"unchecked"`
|
||||
LockdownMessage string `description:"Message displayed when someone tries to post while the site is on lockdown."`
|
||||
|
|
108
src/util.go
108
src/util.go
|
@ -25,7 +25,7 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
nullTime, _ = time.Parse("2006-01-02 15:04:05", "0000-00-00 00:00:00")
|
||||
nullTime time.Time
|
||||
errEmptyDurationString = errors.New("Empty Duration string")
|
||||
errInvalidDurationString = errors.New("Invalid Duration string")
|
||||
durationRegexp = regexp.MustCompile(`^((\d+)\s?ye?a?r?s?)?\s?((\d+)\s?mon?t?h?s?)?\s?((\d+)\s?we?e?k?s?)?\s?((\d+)\s?da?y?s?)?\s?((\d+)\s?ho?u?r?s?)?\s?((\d+)\s?mi?n?u?t?e?s?)?\s?((\d+)\s?s?e?c?o?n?d?s?)?$`)
|
||||
|
@ -91,11 +91,7 @@ func byteByByteReplace(input, from, to string) string {
|
|||
}
|
||||
|
||||
// for easier defer cleaning
|
||||
type Closeable interface {
|
||||
Close() error
|
||||
}
|
||||
|
||||
func closeHandle(handle Closeable) {
|
||||
func closeHandle(handle io.Closer) {
|
||||
if handle != nil && !reflect.ValueOf(handle).IsNil() {
|
||||
handle.Close()
|
||||
}
|
||||
|
@ -120,10 +116,10 @@ func deleteMatchingFiles(root, match string) (filesDeleted int, err error) {
|
|||
return filesDeleted, err
|
||||
}
|
||||
|
||||
// getBoardArr performs a query against the database, and returns an array of BoardsTables along with an error value.
|
||||
// getBoardArr performs a query against the database, and returns an array of Boards along with an error value.
|
||||
// If specified, the string where is added to the query, prefaced by WHERE. An example valid value is where = "id = 1".
|
||||
func getBoardArr(parameterList map[string]interface{}, extra string) (boards []Board, err error) {
|
||||
queryString := "SELECT * FROM `" + config.DBprefix + "boards` "
|
||||
queryString := "SELECT * FROM " + config.DBprefix + "boards "
|
||||
numKeys := len(parameterList)
|
||||
var parameterValues []interface{}
|
||||
if numKeys > 0 {
|
||||
|
@ -131,7 +127,7 @@ func getBoardArr(parameterList map[string]interface{}, extra string) (boards []B
|
|||
}
|
||||
|
||||
for key, value := range parameterList {
|
||||
queryString += fmt.Sprintf("`%s` = ? AND ", key)
|
||||
queryString += fmt.Sprintf("%s = ? AND ", key)
|
||||
parameterValues = append(parameterValues, value)
|
||||
}
|
||||
|
||||
|
@ -140,7 +136,7 @@ func getBoardArr(parameterList map[string]interface{}, extra string) (boards []B
|
|||
queryString = queryString[:len(queryString)-4]
|
||||
}
|
||||
|
||||
queryString += fmt.Sprintf(" %s ORDER BY `order`", extra)
|
||||
queryString += fmt.Sprintf(" %s ORDER BY list_order", extra)
|
||||
|
||||
rows, err := querySQL(queryString, parameterValues...)
|
||||
defer closeHandle(rows)
|
||||
|
@ -149,13 +145,13 @@ func getBoardArr(parameterList map[string]interface{}, extra string) (boards []B
|
|||
return
|
||||
}
|
||||
|
||||
// For each row in the results from the database, populate a new BoardsTable instance,
|
||||
// For each row in the results from the database, populate a new Board instance,
|
||||
// then append it to the boards array we are going to return
|
||||
for rows.Next() {
|
||||
board := new(Board)
|
||||
if err = rows.Scan(
|
||||
&board.ID,
|
||||
&board.Order,
|
||||
&board.ListOrder,
|
||||
&board.Dir,
|
||||
&board.Type,
|
||||
&board.UploadType,
|
||||
|
@ -189,14 +185,13 @@ func getBoardArr(parameterList map[string]interface{}, extra string) (boards []B
|
|||
|
||||
func getBoardFromID(id int) (*Board, error) {
|
||||
board := new(Board)
|
||||
err := queryRowSQL(
|
||||
"SELECT `order`,`dir`,`type`,`upload_type`,`title`,`subtitle`,`description`,`section`,"+
|
||||
"`max_image_size`,`max_pages`,`default_style`,`locked`,`created_on`,`anonymous`,`forced_anon`,`max_age`,"+
|
||||
"`autosage_after`,`no_images_after`,`max_message_length`,`embeds_allowed`,`redirect_to_thread`,`require_file`,"+
|
||||
"`enable_catalog` FROM `"+config.DBprefix+"boards` WHERE `id` = ?",
|
||||
err := queryRowSQL("SELECT list_order,dir,type,upload_type,title,subtitle,description,section,"+
|
||||
"max_file_size,max_pages,default_style,locked,created_on,anonymous,forced_anon,max_age,"+
|
||||
"autosage_after,no_images_after,max_message_length,embeds_allowed,redirect_to_thread,require_file,"+
|
||||
"enable_catalog FROM "+config.DBprefix+"boards WHERE id = ?",
|
||||
[]interface{}{id},
|
||||
[]interface{}{
|
||||
&board.Order, &board.Dir, &board.Type, &board.UploadType, &board.Title,
|
||||
&board.ListOrder, &board.Dir, &board.Type, &board.UploadType, &board.Title,
|
||||
&board.Subtitle, &board.Description, &board.Section, &board.MaxFilesize,
|
||||
&board.MaxPages, &board.DefaultStyle, &board.Locked, &board.CreatedOn,
|
||||
&board.Anonymous, &board.ForcedAnon, &board.MaxAge, &board.AutosageAfter,
|
||||
|
@ -210,7 +205,7 @@ func getBoardFromID(id int) (*Board, error) {
|
|||
|
||||
// if parameterList is nil, ignore it and treat extra like a whole SQL query
|
||||
func getPostArr(parameterList map[string]interface{}, extra string) (posts []Post, err error) {
|
||||
queryString := "SELECT * FROM `" + config.DBprefix + "posts` "
|
||||
queryString := "SELECT * FROM " + config.DBprefix + "posts "
|
||||
numKeys := len(parameterList)
|
||||
var parameterValues []interface{}
|
||||
if numKeys > 0 {
|
||||
|
@ -218,7 +213,7 @@ func getPostArr(parameterList map[string]interface{}, extra string) (posts []Pos
|
|||
}
|
||||
|
||||
for key, value := range parameterList {
|
||||
queryString += fmt.Sprintf("`%s` = ? AND ", key)
|
||||
queryString += fmt.Sprintf("%s = ? AND ", key)
|
||||
parameterValues = append(parameterValues, value)
|
||||
}
|
||||
|
||||
|
@ -235,7 +230,7 @@ func getPostArr(parameterList map[string]interface{}, extra string) (posts []Pos
|
|||
return
|
||||
}
|
||||
|
||||
// For each row in the results from the database, populate a new PostTable instance,
|
||||
// For each row in the results from the database, populate a new Post instance,
|
||||
// then append it to the posts array we are going to return
|
||||
for rows.Next() {
|
||||
var post Post
|
||||
|
@ -257,18 +252,18 @@ func getPostArr(parameterList map[string]interface{}, extra string) (posts []Pos
|
|||
// TODO: replace where with a map[string]interface{} like getBoardsArr()
|
||||
func getSectionArr(where string) (sections []BoardSection, err error) {
|
||||
if where == "" {
|
||||
where = "1"
|
||||
where = "1 = 1"
|
||||
}
|
||||
rows, err := querySQL("SELECT * FROM `" + config.DBprefix + "sections` WHERE " + where + " ORDER BY `order`")
|
||||
rows, err := querySQL("SELECT * FROM " + config.DBprefix + "sections WHERE " + where + " ORDER BY list_order")
|
||||
defer closeHandle(rows)
|
||||
if err != nil {
|
||||
errorLog.Print(err.Error())
|
||||
handleError(0, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
for rows.Next() {
|
||||
var section BoardSection
|
||||
if err = rows.Scan(§ion.ID, §ion.Order, §ion.Hidden, §ion.Name, §ion.Abbreviation); err != nil {
|
||||
if err = rows.Scan(§ion.ID, §ion.ListOrder, §ion.Hidden, §ion.Name, §ion.Abbreviation); err != nil {
|
||||
handleError(1, customError(err))
|
||||
return
|
||||
}
|
||||
|
@ -326,7 +321,7 @@ func getMetaInfo(stackOffset int) (string, int, string) {
|
|||
|
||||
func customError(err error) string {
|
||||
if err != nil {
|
||||
file, line, _ := getMetaInfo(1)
|
||||
file, line, _ := getMetaInfo(2)
|
||||
return fmt.Sprintf("[ERROR] %s:%d: %s\n", file, line, err.Error())
|
||||
}
|
||||
return ""
|
||||
|
@ -360,14 +355,14 @@ func getThumbnailPath(thumbType string, img string) string {
|
|||
}
|
||||
|
||||
// paginate returns a 2d array of a specified interface from a 1d array passed in,
|
||||
// with a specified number of values per array in the 2d array.
|
||||
// interface_length is the number of interfaces per array in the 2d array (e.g, threads per page)
|
||||
// with a specified number of values per array in the 2d array.
|
||||
// interfaceLength is the number of interfaces per array in the 2d array (e.g, threads per page)
|
||||
// interf is the array of interfaces to be split up.
|
||||
func paginate(interfaceLength int, interf []interface{}) [][]interface{} {
|
||||
// paginated_interfaces = the finished interface array
|
||||
// num_arrays = the current number of arrays (before remainder overflow)
|
||||
// interfaces_remaining = if greater than 0, these are the remaining interfaces
|
||||
// that will be added to the super-interface
|
||||
// paginatedInterfaces = the finished interface array
|
||||
// numArrays = the current number of arrays (before remainder overflow)
|
||||
// interfacesRemaining = if greater than 0, these are the remaining interfaces
|
||||
// that will be added to the super-interface
|
||||
|
||||
var paginatedInterfaces [][]interface{}
|
||||
numArrays := len(interf) / interfaceLength
|
||||
|
@ -478,15 +473,15 @@ func checkPostForSpam(userIP string, userAgent string, referrer string,
|
|||
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 {
|
||||
handleError(1, err.Error())
|
||||
return "other_failure"
|
||||
}
|
||||
defer func() {
|
||||
if resp != nil && resp.Body != nil {
|
||||
resp.Body.Close()
|
||||
}
|
||||
}()
|
||||
if err != nil {
|
||||
handleError(1, err.Error())
|
||||
return "other_failure"
|
||||
}
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
handleError(1, err.Error())
|
||||
|
@ -508,33 +503,25 @@ func checkPostForSpam(userIP string, userAgent string, referrer string,
|
|||
return "other_failure"
|
||||
}
|
||||
|
||||
func marshalAPI(tag string, data interface{}, indent bool) (string, error) {
|
||||
var apiMap map[string]interface{}
|
||||
var apiBytes []byte
|
||||
func marshalJSON(tag string, data interface{}, indent bool) (string, error) {
|
||||
var jsonBytes []byte
|
||||
var err error
|
||||
|
||||
if tag != "" {
|
||||
data = map[string]interface{}{
|
||||
tag: data,
|
||||
}
|
||||
}
|
||||
if indent {
|
||||
if tag == "" {
|
||||
apiBytes, err = json.MarshalIndent(data, "", " ")
|
||||
} else {
|
||||
apiMap = make(map[string]interface{})
|
||||
apiMap[tag] = data
|
||||
apiBytes, err = json.MarshalIndent(apiMap, "", " ")
|
||||
}
|
||||
jsonBytes, err = json.MarshalIndent(data, "", " ")
|
||||
} else {
|
||||
if tag == "" {
|
||||
apiBytes, err = json.Marshal(data)
|
||||
} else {
|
||||
apiMap := make(map[string]interface{})
|
||||
apiMap[tag] = data
|
||||
apiBytes, err = json.Marshal(apiMap)
|
||||
}
|
||||
jsonBytes, err = json.Marshal(data)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
apiBytes, _ = json.Marshal(map[string]string{
|
||||
"error": err.Error(),
|
||||
})
|
||||
jsonBytes, _ = json.Marshal(map[string]string{"error": err.Error()})
|
||||
}
|
||||
return string(apiBytes), err
|
||||
return string(jsonBytes), err
|
||||
}
|
||||
|
||||
func limitArraySize(arr []string, maxSize int) []string {
|
||||
|
@ -546,9 +533,10 @@ func limitArraySize(arr []string, maxSize int) []string {
|
|||
|
||||
func numReplies(boardid, threadid int) int {
|
||||
var num int
|
||||
if err := queryRowSQL("SELECT COUNT(*) FROM `"+config.DBprefix+"posts` WHERE `boardid` = ? AND `parentid` = ?",
|
||||
[]interface{}{boardid, threadid}, []interface{}{&num},
|
||||
); err != nil {
|
||||
|
||||
if err := queryRowSQL(
|
||||
"SELECT COUNT(*) FROM "+config.DBprefix+"posts WHERE boardid = ? AND parentid = ?",
|
||||
[]interface{}{boardid, threadid}, []interface{}{&num}); err != nil {
|
||||
return 0
|
||||
}
|
||||
return num
|
||||
|
|
|
@ -3,10 +3,12 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
{{with $.op.Subject}}{{if ne $.op.Subject ""}}<title>/{{$.board.Dir}}/ - {{truncateString $.op.Subject 20 true}}</title>
|
||||
{{else if ne $.op.MessageHTML ""}}<title>/{{$.board.Dir}}/ - {{truncateString $.op.MessageText 20 true}}</title>
|
||||
{{end}}{{else}}{{with $.recent_posts}}<title>{{$.config.SiteName}}</title>
|
||||
{{else}}<title>/{{.board.Dir}}/ - {{.board.Title}}</title>{{end}}{{end}}
|
||||
{{with .board}}
|
||||
{{with $.op}}
|
||||
{{if ne $.op.Subject ""}}<title>/{{$.board.Dir}}/ - {{truncateString $.op.Subject 20 true}}</title>
|
||||
{{else if ne $.op.MessageHTML ""}}<title>/{{$.board.Dir}}/ - {{truncateString $.op.MessageText 20 true}}</title>{{end}}
|
||||
{{else}}<title>/{{$.board.Dir}}/ - {{$.board.Title}}</title>{{end}}
|
||||
{{else}}<title>{{.config.SiteName}}</title>{{end}}
|
||||
<script type="text/javascript" src="{{$.config.SiteWebfolder}}javascript/jquery-3.3.1.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
var styles = [{{range $ii, $style := .config.Styles}}{{if gt $ii 0}}, {{end}}{Name: "{{$style.Name}}", Filename: "{{$style.Filename}}"}{{end}}];
|
||||
|
|
|
@ -7,13 +7,13 @@
|
|||
<option value="{{$section.ID}}">{{$section.Name}}</option>{{end}}
|
||||
</select></td></tr>
|
||||
<tr><td>Order</td><td><input type="text" name="order" value="0" /></td></tr>
|
||||
<tr><td>Title</td><td><input type="text" name="title" value="" /></td></tr>
|
||||
<tr><td>Subtitle</td><td><input type="text" name="subtitle" value="" /></td></tr>
|
||||
<tr><td>Description</td><td><input type="text" name="description" value="" /></td></tr>
|
||||
<tr><td>Max image size</td><td><input type="text" name="maximagesize" value="4718592" /></td></tr>
|
||||
<tr><td>Max pages</td><td><input type="text" name="maxpages" value="11" /></td></tr>
|
||||
<tr><td>Title</td><td><input type="text" name="title" value="{{$.board.Title}}" /></td></tr>
|
||||
<tr><td>Subtitle</td><td><input type="text" name="subtitle" value="{{$.board.Subtitle}}" /></td></tr>
|
||||
<tr><td>Description</td><td><input type="text" name="description" value="{{$.board.Description}}" /></td></tr>
|
||||
<tr><td>Max image size</td><td><input type="text" name="maximagesize" value="{{$.board.MaxFilesize}}" /></td></tr>
|
||||
<tr><td>Max pages</td><td><input type="text" name="maxpages" value="{{$.board.MaxPages}}" /></td></tr>
|
||||
<tr><td>Default style</td><td><select name="defaultstyle">{{range $_, $style := $.config.Styles}}
|
||||
<option value="{{$style}}">{{$style}}</option>{{end}}
|
||||
<option value="{{$style.Filename}}">{{$style.Name}} ({{$style.Filename}})</option>{{end}}
|
||||
</select></td></tr>
|
||||
<tr><td>Locked</td><td><input type="checkbox" name="locked" {{if $.board.Locked}}checked{{end}}/></td></tr>
|
||||
<tr><td>Forced anonymity</td><td><input type="checkbox" name="forcedanon" {{if .board.ForcedAnon}}checked{{end}}/></td></tr>
|
||||
|
|
|
@ -4,55 +4,47 @@
|
|||
set -euo pipefail
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
export DBTYPE=mysql
|
||||
export DBTYPE=postgresql
|
||||
|
||||
apt-get -y update && apt-get -y upgrade
|
||||
|
||||
if [ "$DBTYPE" == "mysql" ]; then
|
||||
# Using MySQL (stable)
|
||||
apt-get -y install mariadb-server mariadb-client
|
||||
# Make sure any imported database is utf8mb4
|
||||
# http://mathiasbynens.be/notes/mysql-utf8mb4
|
||||
# Put in /etc/mysql/conf.d/local.cnf
|
||||
cat << EOF >/etc/mysql/conf.d/local.cnf
|
||||
[client]
|
||||
default-character-set = utf8mb4
|
||||
|
||||
[mysql]
|
||||
default-character-set = utf8mb4
|
||||
|
||||
[mysqld]
|
||||
character-set-client-handshake = FALSE
|
||||
character-set-server = utf8mb4
|
||||
collation-server = utf8mb4_unicode_ci
|
||||
default-storage-engine = innodb
|
||||
EOF
|
||||
|
||||
mysql -uroot -e "CREATE DATABASE IF NOT EXISTS gochan; \
|
||||
GRANT USAGE ON *.* TO gochan IDENTIFIED BY ''; \
|
||||
GRANT ALL PRIVILEGES ON gochan.* TO gochan; \
|
||||
SET PASSWORD FOR 'gochan'@'%' = PASSWORD('gochan');
|
||||
FLUSH PRIVILEGES;"
|
||||
|
||||
cat << EOF >/etc/mysql/conf.d/open.cnf
|
||||
[mysqld]
|
||||
bind-address = 0.0.0.0
|
||||
EOF
|
||||
systemctl enable mysql
|
||||
systemctl start mysql &
|
||||
wait
|
||||
elif [ "$DBTYPE" == "postgresql" ]; then
|
||||
# apt-get -y install postgresql postgresql-contrib
|
||||
# useradd gochan
|
||||
# passwd -d gochan
|
||||
# sudo -u postgres createuser -d gochan
|
||||
echo "PostgreSQL not supported yet"
|
||||
exit 1
|
||||
# using PostgreSQL (mostly stable)
|
||||
apt-get -y install postgresql postgresql-contrib
|
||||
|
||||
sudo -u postgres psql -f - << EOF
|
||||
CREATE USER gochan PASSWORD 'gochan';
|
||||
CREATE DATABASE gochan;
|
||||
GRANT ALL PRIVILEGES ON DATABASE gochan TO gochan;
|
||||
EOF
|
||||
echo "127.0.0.1:5432:gochan:gochan:gochan" > /home/vagrant/.pgpass
|
||||
chown vagrant:vagrant /home/vagrant/.pgpass
|
||||
chmod 0600 /home/vagrant/.pgpass
|
||||
systemctl enable postgresql
|
||||
systemctl start postgresql &
|
||||
wait
|
||||
elif [ "$DBTYPE" == "sqlite3" ]; then
|
||||
# using SQLite (mostly stable)
|
||||
apt-get -y install sqlite3
|
||||
elif [ "$DBTYPE" == "mssql" ]; then
|
||||
echo "Microsoft SQL Server not supported yet";
|
||||
exit 1
|
||||
elif [ "$DBTYPE" == "sqlite" ]; then
|
||||
echo "SQLite not supported yet"
|
||||
exit 1
|
||||
# using Microsoft SQL Server (currently unsupported)
|
||||
echo "Microsoft SQL Server not supported yet";
|
||||
exit 1
|
||||
else
|
||||
echo "Invalid DB type: $DBTYPE"
|
||||
exit 1
|
||||
echo "Invalid DB type: $DBTYPE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
apt-get -y install git subversion mercurial golang-1.10 nginx ffmpeg
|
||||
|
@ -69,13 +61,13 @@ systemctl disable nginx
|
|||
sed -i 's/WantedBy=multi-user.target/WantedBy=vagrant.mount/' /lib/systemd/system/nginx.service
|
||||
systemctl daemon-reload
|
||||
systemctl enable nginx
|
||||
|
||||
systemctl restart nginx mysql &
|
||||
systemctl restart nginx &
|
||||
wait
|
||||
|
||||
mkdir -p /vagrant/lib
|
||||
cd /vagrant
|
||||
su - vagrant
|
||||
|
||||
export GOCHAN_PATH=/home/vagrant/gochan
|
||||
export GOPATH=/vagrant/lib
|
||||
mkdir /home/vagrant/bin
|
||||
|
@ -88,19 +80,28 @@ function changePerms {
|
|||
}
|
||||
|
||||
function makeLink {
|
||||
ln -sf /vagrant/$1 $GOCHAN_PATH/$1
|
||||
ln -sf /vagrant/$1 $GOCHAN_PATH/
|
||||
}
|
||||
|
||||
cat << EOF >>/home/vagrant/.bashrc
|
||||
export GOPATH=/vagrant/lib
|
||||
export GOCHAN_PATH=/home/vagrant/gochan
|
||||
export GOPATH=$GOPATH
|
||||
export GOCHAN_PATH=$GOCHAN_PATH
|
||||
export DBTYPE=$DBTYPE
|
||||
EOF
|
||||
|
||||
# a couple convenience shell scripts, since they're nice to have
|
||||
cat << EOF >/home/vagrant/dbconnect.sh
|
||||
#!/usr/bin/env bash
|
||||
|
||||
mysql -s -t -u gochan -D gochan -pgochan
|
||||
if [ "$DBTYPE" = "mysql" ] || [ -z "$DBTYPE" ]; then
|
||||
mysql -stu gochan -D gochan -pgochan
|
||||
elif [ "$DBTYPE" = "postgresql" ]; then
|
||||
psql -U gochan -h 127.0.0.1 gochan
|
||||
elif [ "$DBTYPE" = "sqlite3" ]; then
|
||||
sqlite3 ~/gochan/gochan.db
|
||||
else
|
||||
echo "DB type '$DBTYPE' not supported"
|
||||
fi
|
||||
EOF
|
||||
|
||||
cat << EOF >/home/vagrant/buildgochan.sh
|
||||
|
@ -120,18 +121,19 @@ go get \
|
|||
golang.org/x/net/html \
|
||||
github.com/aquilax/tripcode \
|
||||
golang.org/x/crypto/bcrypt \
|
||||
github.com/frustra/bbcode
|
||||
github.com/frustra/bbcode \
|
||||
github.com/mattn/go-sqlite3
|
||||
make debug
|
||||
|
||||
rm -f $GOCHAN_PATH/gochan
|
||||
rm -f $GOCHAN_PATH/initdb.sql
|
||||
rm -f $GOCHAN_PATH/initdb*.sql
|
||||
|
||||
install -m 775 -o vagrant -g vagrant -d $GOCHAN_PATH
|
||||
makeLink html
|
||||
makeLink log
|
||||
makeLink gochan
|
||||
makeLink templates
|
||||
makeLink initdb.sql
|
||||
ln -sf /vagrant/initdb*.sql $GOCHAN_PATH/
|
||||
changePerms $GOCHAN_PATH
|
||||
|
||||
mkdir -p /home/vagrant/.config/systemd/user/
|
||||
|
@ -144,7 +146,19 @@ sed /vagrant/gochan.example.json \
|
|||
-e 's/"DBpassword": ""/"DBpassword": "gochan"/' \
|
||||
-e 's/"RandomSeed": ""/"RandomSeed": "abc123"/' \
|
||||
-e 's/"Verbosity": 0/"Verbosity": 1/' \
|
||||
-e w\ $GOCHAN_PATH/gochan.json
|
||||
-e "w $GOCHAN_PATH/gochan.json"
|
||||
|
||||
if [ "$DBTYPE" = "postgresql" ]; then
|
||||
sed \
|
||||
-e 's/"DBtype": ".*",/"DBtype": "postgres",/' \
|
||||
-e 's/"DBhost": ".*",/"DBhost": "127.0.0.1",/' \
|
||||
-i $GOCHAN_PATH/gochan.json
|
||||
elif [ "$DBTYPE" = "sqlite3" ]; then
|
||||
sed \
|
||||
-e 's/"DBtype": ".*",/"DBtype": "sqlite3",/' \
|
||||
-e 's/"DBhost": ".*",/"DBhost": "gochan.db",/' \
|
||||
-i $GOCHAN_PATH/gochan.json
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "Server set up, please run \"vagrant ssh\" on your host machine and"
|
||||
|
|
2
version
2
version
|
@ -1 +1 @@
|
|||
2.7.0
|
||||
2.8.0
|
Loading…
Add table
Add a link
Reference in a new issue