Overhaul.
This commit is contained in:
parent
44aede482b
commit
235e9bb643
12
common.go
12
common.go
@ -5,6 +5,8 @@ import (
|
|||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
|
||||||
|
"git.tcp.direct/tcp.direct/tcp.ac/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
type EntryType uint8
|
type EntryType uint8
|
||||||
@ -75,7 +77,7 @@ func (p *Post) Log(l zerolog.Logger) *zerolog.Logger {
|
|||||||
|
|
||||||
func validateKey(rKey string) bool {
|
func validateKey(rKey string) bool {
|
||||||
// if it doesn't match the key size or it isn't alphanumeric - throw it out
|
// if it doesn't match the key size or it isn't alphanumeric - throw it out
|
||||||
if len(rKey) != keySize || !valid.IsAlphanumeric(rKey) {
|
if len(rKey) != config.DeleteKeySize || !valid.IsAlphanumeric(rKey) {
|
||||||
log.Warn().Str("rKey", rKey).
|
log.Warn().Str("rKey", rKey).
|
||||||
Msg("delete request failed sanity check!")
|
Msg("delete request failed sanity check!")
|
||||||
return false
|
return false
|
||||||
@ -85,9 +87,9 @@ func validateKey(rKey string) bool {
|
|||||||
|
|
||||||
func (p *Post) URLString() string {
|
func (p *Post) URLString() string {
|
||||||
var keyurl string = ""
|
var keyurl string = ""
|
||||||
url := baseURL + p.TypeCode() + "/" + string(p.UID())
|
url := config.BaseURL + p.TypeCode() + "/" + string(p.UID())
|
||||||
if p.DelKey() != "" {
|
if p.DelKey() != "" {
|
||||||
keyurl = baseURL + "d/" + p.TypeCode() + "/" + p.DelKey()
|
keyurl = config.BaseURL + "d/" + p.TypeCode() + "/" + p.DelKey()
|
||||||
}
|
}
|
||||||
|
|
||||||
p.Log(log.Logger).Info().Msg("success")
|
p.Log(log.Logger).Info().Msg("success")
|
||||||
@ -100,9 +102,9 @@ func (p *Post) URLString() string {
|
|||||||
|
|
||||||
func (p *Post) Serve(c *gin.Context) {
|
func (p *Post) Serve(c *gin.Context) {
|
||||||
var keyurl string = ""
|
var keyurl string = ""
|
||||||
url := baseURL + p.TypeCode() + "/" + string(p.UID())
|
url := config.BaseURL + p.TypeCode() + "/" + string(p.UID())
|
||||||
if p.DelKey() != "" {
|
if p.DelKey() != "" {
|
||||||
keyurl = baseURL + "d/" + p.TypeCode() + "/" + p.DelKey()
|
keyurl = config.BaseURL + "d/" + p.TypeCode() + "/" + p.DelKey()
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info().
|
log.Info().
|
||||||
|
74
config.go
74
config.go
@ -1,74 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/rs/zerolog"
|
|
||||||
"github.com/rs/zerolog/log"
|
|
||||||
"github.com/spf13/viper"
|
|
||||||
)
|
|
||||||
|
|
||||||
// //////////// global declarations
|
|
||||||
var (
|
|
||||||
// config directives
|
|
||||||
debugBool bool
|
|
||||||
baseURL string
|
|
||||||
webPort string
|
|
||||||
webIP string
|
|
||||||
dbDir string
|
|
||||||
logDir string
|
|
||||||
uidSize int
|
|
||||||
keySize int
|
|
||||||
txtPort string
|
|
||||||
maxSize int
|
|
||||||
|
|
||||||
// utilitarian globals
|
|
||||||
err error
|
|
||||||
fn string
|
|
||||||
s string
|
|
||||||
i int
|
|
||||||
f *os.File
|
|
||||||
)
|
|
||||||
|
|
||||||
func configRead() {
|
|
||||||
// name of the file
|
|
||||||
// and the extension
|
|
||||||
viper.SetConfigName("config")
|
|
||||||
viper.SetConfigType("toml")
|
|
||||||
|
|
||||||
// potential config paths
|
|
||||||
viper.AddConfigPath("/etc/tcpac/")
|
|
||||||
viper.AddConfigPath("../")
|
|
||||||
viper.AddConfigPath("./")
|
|
||||||
|
|
||||||
// this should be replaced with more intelligent handling
|
|
||||||
err = viper.ReadInConfig()
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Errorf("Fatal error reading config file: %s \n", err))
|
|
||||||
}
|
|
||||||
|
|
||||||
// read config
|
|
||||||
debugBool = viper.GetBool("global.debug") // we need to load the debug boolean first
|
|
||||||
if debugBool {
|
|
||||||
zerolog.SetGlobalLevel(zerolog.DebugLevel)
|
|
||||||
log.Debug().Msg("Debug mode enabled")
|
|
||||||
} else {
|
|
||||||
zerolog.SetGlobalLevel(zerolog.InfoLevel)
|
|
||||||
}
|
|
||||||
|
|
||||||
baseURL = viper.GetString("http.baseurl")
|
|
||||||
|
|
||||||
i := viper.GetInt("http.port")
|
|
||||||
webPort = strconv.Itoa(i)
|
|
||||||
|
|
||||||
webIP = viper.GetString("http.bindip")
|
|
||||||
dbDir = viper.GetString("files.data")
|
|
||||||
logDir = viper.GetString("files.logs")
|
|
||||||
uidSize = viper.GetInt("global.uidsize")
|
|
||||||
keySize = viper.GetInt("global.delkeysize")
|
|
||||||
txtPort = viper.GetString("txt.port")
|
|
||||||
maxSize = viper.GetInt("files.maxuploadsize")
|
|
||||||
//
|
|
||||||
}
|
|
36
config.toml
36
config.toml
@ -1,20 +1,24 @@
|
|||||||
title = "tcp.ac config"
|
[data]
|
||||||
|
directory = '.data'
|
||||||
[global]
|
max_key_size_mb = 10
|
||||||
debug = true
|
max_value_size_mb = 20
|
||||||
uidsize = 5
|
|
||||||
delkeysize = 12
|
|
||||||
|
|
||||||
[http]
|
[http]
|
||||||
baseurl = "http://127.0.0.1:8080/"
|
bind_addr = '127.0.0.1'
|
||||||
bindip = "127.0.0.1"
|
bind_port = '8080'
|
||||||
port = 8080
|
unix_socket_path = '/var/run/tcp.ac'
|
||||||
|
unix_socket_permissions = 420
|
||||||
|
use_unix_socket = false
|
||||||
|
|
||||||
[txt]
|
[logger]
|
||||||
# string: port to listen on for termbin clone
|
debug = true
|
||||||
port = "9988"
|
directory = '.logs'
|
||||||
|
nocolor = false
|
||||||
|
trace = false
|
||||||
|
use_date_filename = true
|
||||||
|
|
||||||
|
[other]
|
||||||
|
delete_key_size = 12
|
||||||
|
termbin_listen = '127.0.0.1:9999'
|
||||||
|
uid_size = 5
|
||||||
|
|
||||||
[files]
|
|
||||||
data = "./data/"
|
|
||||||
logs = "./logs/"
|
|
||||||
sizelimit = 48
|
|
||||||
|
101
config/config.go
101
config/config.go
@ -7,7 +7,6 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
@ -20,20 +19,24 @@ const (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
// Version roughly represents the applications current version.
|
// Version roughly represents the applications current version.
|
||||||
Version = runtime.
|
Version = "asdf"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
BaseURL, WebPort, WebIP, DBDir, LogDir, TxtPort string
|
BaseURL, HTTPPort, HTTPBind, DBDir, LogDir,
|
||||||
UIDSize, KeySize, MaxSize int
|
TermbinListen, UnixSocketPath string
|
||||||
|
UIDSize, DeleteKeySize, KVMaxKeySizeMB,
|
||||||
|
KVMaxValueSizeMB int
|
||||||
|
UnixSocketPermissions uint32
|
||||||
|
UseUnixSocket bool
|
||||||
)
|
)
|
||||||
|
|
||||||
var usage = []string{
|
var usage = []string{
|
||||||
"\n" + Title + " v" + Version + " Usage\n",
|
"\n" + Title + " v" + Version + " Usage\n",
|
||||||
"-c <config.toml> - Specify config file",
|
"-c <toml> - Specify config file",
|
||||||
"--nocolor - disable color and banner ",
|
"--nocolor - disable color and banner ",
|
||||||
"--banner - show banner + version and exit",
|
"--banner - show banner + version and exit",
|
||||||
"--genconfig - write default config to 'config.toml' then exit",
|
"--genconfig - write default config to 'toml' then exit",
|
||||||
}
|
}
|
||||||
|
|
||||||
func printUsage() {
|
func printUsage() {
|
||||||
@ -44,6 +47,12 @@ func printUsage() {
|
|||||||
var (
|
var (
|
||||||
forceDebug = false
|
forceDebug = false
|
||||||
forceTrace = false
|
forceTrace = false
|
||||||
|
genConfig = false
|
||||||
|
noColorForce = false
|
||||||
|
customconfig = false
|
||||||
|
home string
|
||||||
|
prefConfigLocation string
|
||||||
|
snek *viper.Viper
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: should probably just make a proper CLI with flags or something
|
// TODO: should probably just make a proper CLI with flags or something
|
||||||
@ -53,35 +62,23 @@ func argParse() {
|
|||||||
case "-h":
|
case "-h":
|
||||||
printUsage()
|
printUsage()
|
||||||
case "--genconfig":
|
case "--genconfig":
|
||||||
GenConfig = true
|
genConfig = true
|
||||||
case "--debug", "-v":
|
case "--debug", "-v":
|
||||||
forceDebug = true
|
forceDebug = true
|
||||||
case "--trace", "-vv":
|
case "--trace", "-vv":
|
||||||
forceTrace = true
|
forceTrace = true
|
||||||
case "--nocolor":
|
case "--nocolor":
|
||||||
noColorForce = true
|
noColorForce = true
|
||||||
case "--banner":
|
|
||||||
BannerOnly = true
|
|
||||||
case "-c", "--config":
|
case "-c", "--config":
|
||||||
if len(os.Args) <= i-1 {
|
if len(os.Args) <= i-1 {
|
||||||
panic("syntax error! expected file after -c")
|
panic("syntax error! expected file after -c")
|
||||||
}
|
}
|
||||||
loadCustomConfig(os.Args[i+1])
|
|
||||||
default:
|
default:
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// generic vars
|
|
||||||
var (
|
|
||||||
noColorForce = false
|
|
||||||
customconfig = false
|
|
||||||
home string
|
|
||||||
prefConfigLocation string
|
|
||||||
snek *viper.Viper
|
|
||||||
)
|
|
||||||
|
|
||||||
// exported generic vars
|
// exported generic vars
|
||||||
var (
|
var (
|
||||||
// Trace is the value of our trace (extra verbose) on/off toggle as per the current configuration.
|
// Trace is the value of our trace (extra verbose) on/off toggle as per the current configuration.
|
||||||
@ -92,11 +89,6 @@ var (
|
|||||||
Filename string
|
Filename string
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
|
||||||
prefConfigLocation = home + "/.config/" + Title
|
|
||||||
snek = viper.New()
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeConfig() {
|
func writeConfig() {
|
||||||
var err error
|
var err error
|
||||||
//goland:noinspection GoBoolExpressions
|
//goland:noinspection GoBoolExpressions
|
||||||
@ -119,7 +111,7 @@ func writeConfig() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
newconfig := prefConfigLocation + "/" + "config.toml"
|
newconfig := prefConfigLocation + "/" + "toml"
|
||||||
if err = snek.SafeWriteConfigAs(newconfig); err != nil {
|
if err = snek.SafeWriteConfigAs(newconfig); err != nil {
|
||||||
fmt.Println("Failed to write new configuration file: " + err.Error())
|
fmt.Println("Failed to write new configuration file: " + err.Error())
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
@ -130,11 +122,19 @@ func writeConfig() {
|
|||||||
|
|
||||||
// Init will initialize our toml configuration engine and define our default configuration values which can be written to a new configuration file if desired
|
// Init will initialize our toml configuration engine and define our default configuration values which can be written to a new configuration file if desired
|
||||||
func Init() {
|
func Init() {
|
||||||
|
argParse()
|
||||||
|
prefConfigLocation = home + "/.config/" + Title
|
||||||
|
snek = viper.New()
|
||||||
|
|
||||||
|
if genConfig {
|
||||||
|
setDefaults()
|
||||||
|
println("config file generated at: " + Filename)
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
snek.SetConfigType("toml")
|
snek.SetConfigType("toml")
|
||||||
snek.SetConfigName("config")
|
snek.SetConfigName("config")
|
||||||
|
|
||||||
argParse()
|
|
||||||
|
|
||||||
if customconfig {
|
if customconfig {
|
||||||
associateExportedVariables()
|
associateExportedVariables()
|
||||||
return
|
return
|
||||||
@ -146,7 +146,7 @@ func Init() {
|
|||||||
snek.AddConfigPath(loc)
|
snek.AddConfigPath(loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = snek.MergeInConfig(); err != nil {
|
if err := snek.MergeInConfig(); err != nil {
|
||||||
println("Error reading configuration file: " + err.Error())
|
println("Error reading configuration file: " + err.Error())
|
||||||
println("Writing new configuration file...")
|
println("Writing new configuration file...")
|
||||||
writeConfig()
|
writeConfig()
|
||||||
@ -171,7 +171,8 @@ func getConfigPaths() (paths []string) {
|
|||||||
|
|
||||||
func loadCustomConfig(path string) {
|
func loadCustomConfig(path string) {
|
||||||
/* #nosec */
|
/* #nosec */
|
||||||
if f, err = os.Open(path); err != nil {
|
f, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
println("Error opening specified config file: " + path)
|
println("Error opening specified config file: " + path)
|
||||||
println(err.Error())
|
println(err.Error())
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
@ -212,59 +213,47 @@ func processOpts() {
|
|||||||
stringOpt := map[string]*string{
|
stringOpt := map[string]*string{
|
||||||
"http.bind_addr": &HTTPBind,
|
"http.bind_addr": &HTTPBind,
|
||||||
"http.bind_port": &HTTPPort,
|
"http.bind_port": &HTTPPort,
|
||||||
|
"http.unix_socket_path": &UnixSocketPath,
|
||||||
"logger.directory": &LogDir,
|
"logger.directory": &LogDir,
|
||||||
"deception.server_name": &FakeServerName,
|
"other.termbin_listen": &TermbinListen,
|
||||||
}
|
|
||||||
// string slice options and their exported variables
|
|
||||||
strSliceOpt := map[string]*[]string{
|
|
||||||
"http.router.paths": &Paths,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// bool options and their exported variables
|
// bool options and their exported variables
|
||||||
boolOpt := map[string]*bool{
|
boolOpt := map[string]*bool{
|
||||||
"performance.restrict_concurrency": &RestrictConcurrency,
|
|
||||||
"http.use_unix_socket": &UseUnixSocket,
|
"http.use_unix_socket": &UseUnixSocket,
|
||||||
"logger.debug": &Debug,
|
"logger.debug": &Debug,
|
||||||
"logger.trace": &Trace,
|
"logger.trace": &Trace,
|
||||||
"logger.nocolor": &NoColor,
|
"logger.nocolor": &noColorForce,
|
||||||
"http.router.makerobots": &MakeRobots,
|
|
||||||
"http.router.catchall": &CatchAll,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// integer options and their exported variables
|
// integer options and their exported variables
|
||||||
intOpt := map[string]*int{
|
intOpt := map[string]*int{
|
||||||
"performance.max_workers": &MaxWorkers,
|
"data.max_key_size": &KVMaxKeySizeMB,
|
||||||
|
"data.max_value_size": &KVMaxValueSizeMB,
|
||||||
|
"other.uid_size": &UIDSize,
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32Opt := map[string]*uint32{
|
||||||
|
"http.unix_socket_permissions": &UnixSocketPermissions,
|
||||||
}
|
}
|
||||||
|
|
||||||
for key, opt := range stringOpt {
|
for key, opt := range stringOpt {
|
||||||
*opt = snek.GetString(key)
|
*opt = snek.GetString(key)
|
||||||
}
|
}
|
||||||
for key, opt := range strSliceOpt {
|
|
||||||
*opt = snek.GetStringSlice(key)
|
|
||||||
}
|
|
||||||
for key, opt := range boolOpt {
|
for key, opt := range boolOpt {
|
||||||
*opt = snek.GetBool(key)
|
*opt = snek.GetBool(key)
|
||||||
}
|
}
|
||||||
for key, opt := range intOpt {
|
for key, opt := range intOpt {
|
||||||
*opt = snek.GetInt(key)
|
*opt = snek.GetInt(key)
|
||||||
}
|
}
|
||||||
|
for key, opt := range uint32Opt {
|
||||||
|
*opt = snek.GetUint32(key)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func associateExportedVariables() {
|
func associateExportedVariables() {
|
||||||
processOpts()
|
processOpts()
|
||||||
|
|
||||||
if noColorForce {
|
|
||||||
NoColor = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if UseUnixSocket {
|
|
||||||
UnixSocketPath = snek.GetString("http.unix_socket_path")
|
|
||||||
parsedPermissions, err := strconv.ParseUint(snek.GetString("http.unix_socket_permissions"), 8, 32)
|
|
||||||
if err == nil {
|
|
||||||
UnixSocketPermissions = uint32(parsedPermissions)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We set exported variables here so that it tracks when accessed from other packages.
|
// We set exported variables here so that it tracks when accessed from other packages.
|
||||||
|
|
||||||
if Debug || forceDebug {
|
if Debug || forceDebug {
|
||||||
zerolog.SetGlobalLevel(zerolog.DebugLevel)
|
zerolog.SetGlobalLevel(zerolog.DebugLevel)
|
||||||
Debug = true
|
Debug = true
|
||||||
|
60
config/defaults.go
Normal file
60
config/defaults.go
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
configSections = []string{"logger", "http", "data", "other"}
|
||||||
|
defNoColor = false
|
||||||
|
)
|
||||||
|
|
||||||
|
var defOpts = map[string]map[string]interface{}{
|
||||||
|
"logger": {
|
||||||
|
"directory": ".logs",
|
||||||
|
"debug": true,
|
||||||
|
"trace": false,
|
||||||
|
"nocolor": defNoColor,
|
||||||
|
"use_date_filename": true,
|
||||||
|
},
|
||||||
|
"http": {
|
||||||
|
"use_unix_socket": false,
|
||||||
|
"unix_socket_path": "/var/run/tcp.ac",
|
||||||
|
"unix_socket_permissions": uint32(0644),
|
||||||
|
"bind_addr": "127.0.0.1",
|
||||||
|
"bind_port": "8080",
|
||||||
|
},
|
||||||
|
"data": {
|
||||||
|
"directory": ".data",
|
||||||
|
"max_key_size_mb": 10,
|
||||||
|
"max_value_size_mb": 20,
|
||||||
|
},
|
||||||
|
"other": {
|
||||||
|
"uid_size": 5,
|
||||||
|
"delete_key_size": 12,
|
||||||
|
"termbin_listen": "127.0.0.1:9999",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func setDefaults() {
|
||||||
|
//goland:noinspection GoBoolExpressions
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
snek.SetDefault("logger.directory", "./logs/")
|
||||||
|
defNoColor = true
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, def := range configSections {
|
||||||
|
snek.SetDefault(def, defOpts[def])
|
||||||
|
}
|
||||||
|
|
||||||
|
if genConfig {
|
||||||
|
if err := snek.SafeWriteConfigAs("./config.toml"); err != nil {
|
||||||
|
fmt.Println(err.Error())
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
14
db.go
14
db.go
@ -1,8 +1,9 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
prologic "git.tcp.direct/Mirrors/bitcask-mirror"
|
|
||||||
"git.tcp.direct/tcp.direct/database/bitcask"
|
"git.tcp.direct/tcp.direct/database/bitcask"
|
||||||
|
|
||||||
|
"git.tcp.direct/tcp.direct/tcp.ac/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
var stores = []string{"hsh", "key", "img", "txt", "url"}
|
var stores = []string{"hsh", "key", "img", "txt", "url"}
|
||||||
@ -10,11 +11,16 @@ var megabyte = float64(1024 * 1024)
|
|||||||
|
|
||||||
var db *bitcask.DB
|
var db *bitcask.DB
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
bitcask.SetDefaultBitcaskOptions(
|
||||||
|
bitcask.WithMaxKeySize(uint32(config.KVMaxKeySizeMB*int(megabyte))),
|
||||||
|
bitcask.WithMaxValueSize(uint64(config.KVMaxValueSizeMB*int(megabyte))),
|
||||||
|
)
|
||||||
|
}
|
||||||
func dbInit() error {
|
func dbInit() error {
|
||||||
db = bitcask.OpenDB(dbDir)
|
db = bitcask.OpenDB(config.DBDir)
|
||||||
var bitcaskopts = []prologic.Option{prologic.WithMaxValueSize(uint64(maxSize) * uint64(megabyte))}
|
|
||||||
for _, st := range stores {
|
for _, st := range stores {
|
||||||
if err := db.Init(st, bitcaskopts...); err != nil {
|
if err := db.Init(st); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
2
go.mod
2
go.mod
@ -3,7 +3,6 @@ module git.tcp.direct/tcp.direct/tcp.ac
|
|||||||
go 1.18
|
go 1.18
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.tcp.direct/Mirrors/bitcask-mirror v0.0.0-20220228092422-1ec4297c7e34
|
|
||||||
git.tcp.direct/kayos/putxt v0.0.0-20220707194005-5bc828145cc4
|
git.tcp.direct/kayos/putxt v0.0.0-20220707194005-5bc828145cc4
|
||||||
git.tcp.direct/tcp.direct/database v0.0.0-20220610180603-058d36edd7f0
|
git.tcp.direct/tcp.direct/database v0.0.0-20220610180603-058d36edd7f0
|
||||||
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d
|
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d
|
||||||
@ -19,6 +18,7 @@ require (
|
|||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
git.tcp.direct/Mirrors/bitcask-mirror v0.0.0-20220228092422-1ec4297c7e34 // indirect
|
||||||
github.com/abcum/lcp v0.0.0-20201209214815-7a3f3840be81 // indirect
|
github.com/abcum/lcp v0.0.0-20201209214815-7a3f3840be81 // indirect
|
||||||
github.com/dsoprea/go-exif v0.0.0-20190901173045-3ce78807c90f // indirect
|
github.com/dsoprea/go-exif v0.0.0-20190901173045-3ce78807c90f // indirect
|
||||||
github.com/dsoprea/go-jpeg-image-structure v0.0.0-20190422055009-d6f9ba25cf48 // indirect
|
github.com/dsoprea/go-jpeg-image-structure v0.0.0-20190422055009-d6f9ba25cf48 // indirect
|
||||||
|
12
img.go
12
img.go
@ -17,6 +17,8 @@ import (
|
|||||||
exifremove "github.com/scottleedavis/go-exif-remove"
|
exifremove "github.com/scottleedavis/go-exif-remove"
|
||||||
"github.com/twharmon/gouid"
|
"github.com/twharmon/gouid"
|
||||||
"golang.org/x/crypto/blake2b"
|
"golang.org/x/crypto/blake2b"
|
||||||
|
|
||||||
|
"git.tcp.direct/tcp.direct/tcp.ac/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
var fExt string
|
var fExt string
|
||||||
@ -89,7 +91,7 @@ func imgView(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if it doesn't match the key size or it isn't alphanumeric - throw it out
|
// if it doesn't match the key size or it isn't alphanumeric - throw it out
|
||||||
if !valid.IsAlphanumeric(rUid) || len(rUid) != uidSize {
|
if !valid.IsAlphanumeric(rUid) || len(rUid) != config.UIDSize {
|
||||||
slog.Warn().
|
slog.Warn().
|
||||||
Str("remoteaddr", c.ClientIP()).
|
Str("remoteaddr", c.ClientIP()).
|
||||||
Msg("request discarded as invalid")
|
Msg("request discarded as invalid")
|
||||||
@ -135,17 +137,17 @@ func imgView(c *gin.Context) {
|
|||||||
func newUIDandKey() (uid string, key string) {
|
func newUIDandKey() (uid string, key string) {
|
||||||
slog := log.With().Str("caller", "newUIDandKey").Logger()
|
slog := log.With().Str("caller", "newUIDandKey").Logger()
|
||||||
// generate new uid and delete key
|
// generate new uid and delete key
|
||||||
uid = gouid.String(uidSize, gouid.MixedCaseAlphaNum)
|
uid = gouid.String(config.UIDSize, gouid.MixedCaseAlphaNum)
|
||||||
key = gouid.String(keySize, gouid.MixedCaseAlphaNum)
|
key = gouid.String(config.DeleteKeySize, gouid.MixedCaseAlphaNum)
|
||||||
|
|
||||||
// lets make sure that we don't clash even though its highly unlikely
|
// lets make sure that we don't clash even though its highly unlikely
|
||||||
for db.With("img").Has([]byte(uid)) {
|
for db.With("img").Has([]byte(uid)) {
|
||||||
slog.Warn().Msg(" uid already exists! generating new...")
|
slog.Warn().Msg(" uid already exists! generating new...")
|
||||||
uid = gouid.String(uidSize, gouid.MixedCaseAlphaNum)
|
uid = gouid.String(config.UIDSize, gouid.MixedCaseAlphaNum)
|
||||||
}
|
}
|
||||||
for db.With("key").Has([]byte(key)) {
|
for db.With("key").Has([]byte(key)) {
|
||||||
slog.Warn().Msg(" delete key already exists! generating new...")
|
slog.Warn().Msg(" delete key already exists! generating new...")
|
||||||
key = gouid.String(keySize, gouid.MixedCaseAlphaNum)
|
key = gouid.String(config.DeleteKeySize, gouid.MixedCaseAlphaNum)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
94
main.go
94
main.go
@ -6,64 +6,40 @@ import (
|
|||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/muesli/termenv"
|
"github.com/muesli/termenv"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
|
||||||
|
"git.tcp.direct/tcp.direct/tcp.ac/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
var Banner string = "CiAgLGQgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogIDg4ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKTU04OE1NTSAsYWRQUFliYSwgOGIsZFBQWWJhLCAgICAgICxhZFBQWVliYSwgICxhZFBQWWJhLCAgCiAgODggICBhOCIgICAgICIiIDg4UCcgICAgIjhhICAgICAiIiAgICAgYFk4IGE4IiAgICAgIiIgIAogIDg4ICAgOGIgICAgICAgICA4OCAgICAgICBkOCAgICAgLGFkUFBQUFA4OCA4YiAgICAgICAgICAKICA4OCwgICI4YSwgICAsYWEgODhiLCAgICxhOCIgODg4IDg4LCAgICAsODggIjhhLCAgICxhYSAgCiAgIlk4ODggYCJZYmJkOCInIDg4YFliYmRQIicgIDg4OCBgIjhiYmRQIlk4ICBgIlliYmQ4IicgIAogICAgICAgICAgICAgICAgICA4OCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgODggICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCg=="
|
var Banner string = "CiAgLGQgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogIDg4ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKTU04OE1NTSAsYWRQUFliYSwgOGIsZFBQWWJhLCAgICAgICxhZFBQWVliYSwgICxhZFBQWWJhLCAgCiAgODggICBhOCIgICAgICIiIDg4UCcgICAgIjhhICAgICAiIiAgICAgYFk4IGE4IiAgICAgIiIgIAogIDg4ICAgOGIgICAgICAgICA4OCAgICAgICBkOCAgICAgLGFkUFBQUFA4OCA4YiAgICAgICAgICAKICA4OCwgICI4YSwgICAsYWEgODhiLCAgICxhOCIgODg4IDg4LCAgICAsODggIjhhLCAgICxhYSAgCiAgIlk4ODggYCJZYmJkOCInIDg4YFliYmRQIicgIDg4OCBgIjhiYmRQIlk4ICBgIlliYmQ4IicgIAogICAgICAgICAgICAgICAgICA4OCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgODggICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCg=="
|
||||||
|
|
||||||
func init() {
|
func makeDirectories() {
|
||||||
|
log.Trace().Msgf("establishing log directory presence at %s...", config.LogDir)
|
||||||
|
err := os.MkdirAll(config.LogDir, 0o644)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal().
|
||||||
|
Str("directory", config.LogDir).
|
||||||
|
Err(err).Msg("failed to open log directory")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Trace().Msgf("establishing data directory presence at %s...", config.DBDir)
|
||||||
|
err = os.MkdirAll(config.DBDir, 0o644)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal().
|
||||||
|
Str("directory", config.DBDir).
|
||||||
|
Err(err).Msg("failed to open directory")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func printBanner() {
|
||||||
out := termenv.String(b64d(Banner))
|
out := termenv.String(b64d(Banner))
|
||||||
p := termenv.ColorProfile()
|
p := termenv.ColorProfile()
|
||||||
out = out.Foreground(p.Color("#948DB8"))
|
out = out.Foreground(p.Color("#948DB8"))
|
||||||
|
|
||||||
fmt.Println(out)
|
fmt.Println(out)
|
||||||
|
|
||||||
// initialize the logger before the config: that way we can output debug lines
|
|
||||||
// pertaining to the parsing of the configuration init
|
|
||||||
|
|
||||||
// ////////// init logging ////////////
|
|
||||||
|
|
||||||
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
|
|
||||||
consoleWriter := zerolog.ConsoleWriter{Out: os.Stdout}
|
|
||||||
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
|
|
||||||
log.Info().Msg("Initializing...")
|
|
||||||
|
|
||||||
// see config.go
|
|
||||||
configRead()
|
|
||||||
|
|
||||||
if !debugBool {
|
|
||||||
gin.SetMode(gin.ReleaseMode)
|
|
||||||
}
|
|
||||||
|
|
||||||
// now that we know where to put the log file, we can start output (replace logger)
|
|
||||||
|
|
||||||
err := os.MkdirAll(logDir, 0o755)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal().Str("directory", logDir).Str("intent", "logDir").Err(err).Msg("failed to open directory")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = os.MkdirAll(dbDir, 0o755)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal().Str("directory", dbDir).Str("intent", "dbDir").Err(err).Msg("failed to open directory")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
lf, err := os.OpenFile(logDir+"tcpac.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0o666)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal().Str("logDir", logDir).Err(err).Msg("Error opening log file!")
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
|
|
||||||
multi := zerolog.MultiLevelWriter(consoleWriter, lf)
|
|
||||||
log.Logger = zerolog.New(multi).With().Timestamp().Logger()
|
|
||||||
err = dbInit()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal().Err(err).Msg("bitcask failure")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func catchSignal() {
|
func catchSignal() {
|
||||||
@ -83,9 +59,27 @@ func catchSignal() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
printBanner()
|
||||||
|
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
|
||||||
|
consoleWriter := zerolog.ConsoleWriter{Out: os.Stdout}
|
||||||
|
log.Logger = log.Output(consoleWriter).With().Timestamp().Logger()
|
||||||
|
log.Info().Msg("Initializing...")
|
||||||
|
config.Init()
|
||||||
|
makeDirectories()
|
||||||
|
log.Debug().Msg("debug enabled")
|
||||||
|
log.Trace().Msg("trace enabled")
|
||||||
|
lf, err := os.OpenFile(config.LogDir+"tcpac.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0o666)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal().Str("config.LogDir", config.LogDir).Err(err).Msg("Error opening log file!")
|
||||||
|
}
|
||||||
|
multi := zerolog.MultiLevelWriter(consoleWriter, lf)
|
||||||
|
log.Logger = zerolog.New(multi).With().Timestamp().Logger()
|
||||||
|
err = dbInit()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal().Err(err).Msg("bitcask failure")
|
||||||
|
}
|
||||||
defer db.SyncAndCloseAll()
|
defer db.SyncAndCloseAll()
|
||||||
go catchSignal()
|
|
||||||
go serveTermbin()
|
go serveTermbin()
|
||||||
// see router.go
|
go httpRouter()
|
||||||
httpRouter()
|
catchSignal()
|
||||||
}
|
}
|
||||||
|
10
router.go
10
router.go
@ -10,6 +10,8 @@ import (
|
|||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
|
||||||
|
"git.tcp.direct/tcp.direct/tcp.ac/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
var favicon string = "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"
|
var favicon string = "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"
|
||||||
@ -30,7 +32,7 @@ func urlPost(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func httpRouter() {
|
func httpRouter() {
|
||||||
if !debugBool {
|
if !config.Debug {
|
||||||
gin.SetMode(gin.ReleaseMode)
|
gin.SetMode(gin.ReleaseMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,6 +81,8 @@ func httpRouter() {
|
|||||||
delR.GET("/i/:key", imgDel)
|
delR.GET("/i/:key", imgDel)
|
||||||
delR.GET("/t/:key", txtDel)
|
delR.GET("/t/:key", txtDel)
|
||||||
|
|
||||||
log.Info().Str("webIP", webIP).Str("webPort", webPort).Msg("done; tcp.ac is live.")
|
log.Info().Str("Host", config.HTTPBind).
|
||||||
router.Run(webIP + ":" + webPort)
|
Str("Port", config.HTTPPort).
|
||||||
|
Msg("done; tcp.ac is live.")
|
||||||
|
router.Run(config.HTTPBind + ":" + config.HTTPPort)
|
||||||
}
|
}
|
||||||
|
27
txt.go
27
txt.go
@ -2,6 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
valid "github.com/asaskevich/govalidator"
|
valid "github.com/asaskevich/govalidator"
|
||||||
@ -11,6 +12,8 @@ import (
|
|||||||
"golang.org/x/crypto/blake2b"
|
"golang.org/x/crypto/blake2b"
|
||||||
|
|
||||||
termbin "git.tcp.direct/kayos/putxt"
|
termbin "git.tcp.direct/kayos/putxt"
|
||||||
|
|
||||||
|
"git.tcp.direct/tcp.direct/tcp.ac/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -19,7 +22,6 @@ func init() {
|
|||||||
|
|
||||||
func incoming() {
|
func incoming() {
|
||||||
var msg termbin.Message
|
var msg termbin.Message
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case msg = <-termbin.Msg:
|
case msg = <-termbin.Msg:
|
||||||
switch msg.Type {
|
switch msg.Type {
|
||||||
@ -74,31 +76,31 @@ func termPost(b []byte) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// generate new uid and delete key
|
// generate new uid and delete key
|
||||||
uid := gouid.String(uidSize, gouid.MixedCaseAlphaNum)
|
uid := gouid.String(config.UIDSize, gouid.MixedCaseAlphaNum)
|
||||||
key := gouid.String(keySize, gouid.MixedCaseAlphaNum)
|
key := gouid.String(config.DeleteKeySize, gouid.MixedCaseAlphaNum)
|
||||||
|
|
||||||
// lets make sure that we don't clash even though its highly unlikely
|
// lets make sure that we don't clash even though its highly unlikely
|
||||||
for uidRef, _ := db.With("txt").Get([]byte(uid)); uidRef != nil; {
|
for uidRef, _ := db.With("txt").Get([]byte(uid)); uidRef != nil; {
|
||||||
slog.Info().Msg(" uid already exists! generating new...")
|
slog.Info().Msg(" uid already exists! generating new...")
|
||||||
uid = gouid.String(uidSize, gouid.MixedCaseAlphaNum)
|
uid = gouid.String(config.UIDSize, gouid.MixedCaseAlphaNum)
|
||||||
}
|
}
|
||||||
for keyRef, _ := db.With("key").Get([]byte(key)); keyRef != nil; {
|
for keyRef, _ := db.With("key").Get([]byte(key)); keyRef != nil; {
|
||||||
slog.Info().Msg(" delete key already exists! generating new...")
|
slog.Info().Msg(" delete key already exists! generating new...")
|
||||||
key = gouid.String(keySize, gouid.MixedCaseAlphaNum)
|
key = gouid.String(config.DeleteKeySize, gouid.MixedCaseAlphaNum)
|
||||||
}
|
}
|
||||||
|
|
||||||
db.With("hsh").Put(hash, []byte(uid))
|
db.With("hsh").Put(hash, []byte(uid))
|
||||||
|
|
||||||
uid = gouid.String(uidSize, gouid.MixedCaseAlphaNum)
|
uid = gouid.String(config.UIDSize, gouid.MixedCaseAlphaNum)
|
||||||
key = gouid.String(keySize, gouid.MixedCaseAlphaNum)
|
key = gouid.String(config.DeleteKeySize, gouid.MixedCaseAlphaNum)
|
||||||
|
|
||||||
for uidRef, _ := db.With("txt").Get([]byte(uid)); uidRef != nil; {
|
for uidRef, _ := db.With("txt").Get([]byte(uid)); uidRef != nil; {
|
||||||
slog.Info().Msg(" uid already exists! generating new...")
|
slog.Info().Msg(" uid already exists! generating new...")
|
||||||
uid = gouid.String(uidSize, gouid.MixedCaseAlphaNum)
|
uid = gouid.String(config.UIDSize, gouid.MixedCaseAlphaNum)
|
||||||
}
|
}
|
||||||
for keyRef, _ := db.With("key").Get([]byte(key)); keyRef != nil; {
|
for keyRef, _ := db.With("key").Get([]byte(key)); keyRef != nil; {
|
||||||
slog.Info().Msg(" delete key already exists! generating new...")
|
slog.Info().Msg(" delete key already exists! generating new...")
|
||||||
key = gouid.String(keySize, gouid.MixedCaseAlphaNum)
|
key = gouid.String(config.DeleteKeySize, gouid.MixedCaseAlphaNum)
|
||||||
}
|
}
|
||||||
|
|
||||||
db.With("hsh").Put([]byte(hash), []byte(uid))
|
db.With("hsh").Put([]byte(hash), []byte(uid))
|
||||||
@ -129,7 +131,7 @@ func termPost(b []byte) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func txtView(c *gin.Context) {
|
func txtView(c *gin.Context) {
|
||||||
raddr, _ := c.RemoteIP()
|
raddr := net.ParseIP(c.RemoteIP())
|
||||||
if termbin.Rater.Check(&termbin.Identity{Actual: raddr}) {
|
if termbin.Rater.Check(&termbin.Identity{Actual: raddr}) {
|
||||||
errThrow(c, 429, errors.New("ratelimitted"), "too many requests")
|
errThrow(c, 429, errors.New("ratelimitted"), "too many requests")
|
||||||
return
|
return
|
||||||
@ -148,7 +150,7 @@ func txtView(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if it doesn't match the key size or it isn't alphanumeric - throw it out
|
// if it doesn't match the key size or it isn't alphanumeric - throw it out
|
||||||
if !valid.IsAlphanumeric(rUid) || len(rUid) != uidSize {
|
if !valid.IsAlphanumeric(rUid) || len(rUid) != config.UIDSize {
|
||||||
errThrow(c, 400, errors.New("request discarded as invalid"), "400")
|
errThrow(c, 400, errors.New("request discarded as invalid"), "400")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -218,7 +220,8 @@ func serveTermbin() {
|
|||||||
incoming()
|
incoming()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
err := termbin.Listen("", txtPort)
|
split := strings.Split(config.TermbinListen, ":")
|
||||||
|
err := termbin.Listen(split[0], split[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
println(err.Error())
|
println(err.Error())
|
||||||
return
|
return
|
||||||
|
Loading…
Reference in New Issue
Block a user