@ -1,4 +1,4 @@
// Copyright (C) 2021-202 2 Leonid Maslakov.
// Copyright (C) 2021-202 3 Leonid Maslakov.
// This file is part of Lenpaste.
@ -21,6 +21,7 @@ package main
import (
"errors"
"flag"
"fmt"
"git.lcomrade.su/root/lenpaste/internal/apiv1"
"git.lcomrade.su/root/lenpaste/internal/config"
"git.lcomrade.su/root/lenpaste/internal/logger"
@ -38,7 +39,7 @@ import (
var Version = "unknown"
func backgroundJob ( cleanJobPeriod time . Duration , db storage . DB , log logger . Config ) {
func backgroundJob ( cleanJobPeriod time . Duration , db storage . DB , log logger . Logger ) {
for {
// Delete expired pastes
count , err := db . PasteDeleteExpired ( )
@ -72,7 +73,7 @@ func readFile(path string) (string, error) {
}
func exitOnError ( e error ) {
println ( "error:" , e . Error ( ) )
fmt . Fprintln ( os . Stderr , "error:" , e . Error ( ) )
os . Exit ( 1 )
}
@ -80,21 +81,39 @@ func printHelp(noErrors bool) {
println ( "Usage:" , os . Args [ 0 ] , "[-db-source] [OPTION]..." )
println ( "" )
println ( " -address ADDRESS:PORT (default: :80)" )
println ( )
println ( " -db-driver Currently supported drivers: 'sqlite3' and 'postgres' (default: sqlite3)" )
println ( " -db-source DB source." )
println ( " -db-max-open-conns Maximum number of connections to the database. (default: 25)" )
println ( " -db-max-idle-conns Maximum number of idle connections to the database. (default: 5)" )
println ( " -db-cleanup-period Interval at which the DB is cleared of expired but not yet deleted pastes. (default: 3h)" )
println ( )
println ( " -robots-disallow Prohibits search engine crawlers from indexing site using robots.txt file." )
println ( )
println ( " -title-max-length Maximum length of the paste title. If 0 disable title, if -1 disable length limit. (default: 100)" )
println ( " -body-max-length Maximum length of the paste body. If -1 disable length limit. Can't be -1. (default: 20000)" )
println ( " -max-paste-lifetime Maximum lifetime of the paste. Examples: 10m, 1h 30m, 12h, 1w, 30d, 365d. (default: unlimited)" )
println ( " -new-pastes-per-5min Maximum number of paste that can be created in 5 minutes from one IP. If 0 disable rate-limit. (default: 15)" )
println ( )
println ( " -get-pastes-per-5min Maximum number of pastes that can be VIEWED in 5 minutes from one IP. If 0 disable rate-limit. (default: 50)" )
println ( " -get-pastes-per-15min Maximum number of pastes that can be VIEWED in 15 minutes from one IP. If 0 disable rate-limit. (default: 100)" )
println ( " -get-pastes-per-1hour Maximum number of pastes that can be VIEWED in 1 hour from one IP. If 0 disable rate-limit. (default: 500)" )
println ( " -new-pastes-per-5min Maximum number of pastes that can be CREATED in 5 minutes from one IP. If 0 disable rate-limit. (default: 15)" )
println ( " -new-pastes-per-15min Maximum number of pastes that can be CREATED in 15 minutes from one IP. If 0 disable rate-limit. (default: 30)" )
println ( " -new-pastes-per-1hour Maximum number of pastes that can be CREATED in 1 hour from one IP. If 0 disable rate-limit. (default: 40)" )
println ( )
println ( " -server-about Path to the TXT file that contains the server description." )
println ( " -server-rules Path to the TXT file that contains the server rules." )
println ( " -server-terms Path to the TXT file that contains the server terms of use." )
println ( )
println ( " -admin-name Name of the administrator of this server." )
println ( " -admin-mail Email of the administrator of this server." )
println ( )
println ( " -ui-default-lifetime Lifetime of paste will be set by default in WEB interface. Examples: 10min, 1h, 1d, 2w, 6mon, 1y." )
println ( " -ui-default-theme Sets the default theme for the WEB interface. Examples: dark, light, my_theme. (default: dark)" )
println ( " -ui-themes-dir Loads external WEB interface themes from directory." )
println ( )
println ( " -lenpasswd-file File in LenPasswd format. If set, authorization will be required to create pastes." )
println ( )
println ( " -version Display version and exit." )
println ( " -help Display this help and exit." )
println ( )
@ -175,21 +194,39 @@ func main() {
flag . Usage = func ( ) { printHelp ( false ) }
flagAddress := flag . String ( "address" , ":80" , "" )
flagDbDriver := flag . String ( "db-driver" , "sqlite3" , "" )
flagDbSource := flag . String ( "db-source" , "" , "" )
flagDbMaxOpenConns := flag . Int ( "db-max-open-conns" , 25 , "" )
flagDbMaxIdleConns := flag . Int ( "db-max-idle-conns" , 5 , "" )
flagDbCleanupPeriod := flag . String ( "db-cleanup-period" , "3h" , "" )
flagRobotsDisallow := flag . Bool ( "robots-disallow" , false , "" )
flagTitleMaxLen := flag . Int ( "title-max-length" , 100 , "" )
flagBodyMaxLen := flag . Int ( "body-max-length" , 20000 , "" )
flagMaxLifetime := flag . String ( "max-paste-lifetime" , "unlimited" , "" )
flagNewPastesPer5Min := flag . Int ( "new-pastes-per-5min" , 15 , "" )
flagGetPastesPer5Min := flag . Uint ( "get-pastes-per-5min" , 50 , "" )
flagGetPastesPer15Min := flag . Uint ( "get-pastes-per-15min" , 100 , "" )
flagGetPastesPer1Hour := flag . Uint ( "get-pastes-per-1hour" , 500 , "" )
flagNewPastesPer5Min := flag . Uint ( "new-pastes-per-5min" , 15 , "" )
flagNewPastesPer15Min := flag . Uint ( "new-pastes-per-15min" , 30 , "" )
flagNewPastesPer1Hour := flag . Uint ( "new-pastes-per-1hour" , 40 , "" )
flagServerAbout := flag . String ( "server-about" , "" , "" )
flagServerRules := flag . String ( "server-rules" , "" , "" )
flagServerTerms := flag . String ( "server-terms" , "" , "" )
flagAdminName := flag . String ( "admin-name" , "" , "" )
flagAdminMail := flag . String ( "admin-mail" , "" , "" )
flagUiDefaultLifetime := flag . String ( "ui-default-lifetime" , "" , "" )
flagUiDefaultTheme := flag . String ( "ui-default-theme" , "dark" , "" )
flagUiThemesDir := flag . String ( "ui-themes-dir" , "" , "" )
flagLenPasswdFile := flag . String ( "lenpasswd-file" , "" , "" )
flagVersion := flag . Bool ( "version" , false , "" )
flagHelp := flag . Bool ( "help" , false , "" )
@ -270,19 +307,17 @@ func main() {
}
// Settings
db := storage . DB {
DriverName : * flagDbDriver ,
DataSourceName : * flagDbSource ,
}
log := logger . New ( "2006/01/02 15:04:05" )
log := logger . Config {
TimeFormat : "2006/01/02 15:04:05" ,
db , err := storage . NewPool ( * flagDbDriver , * flagDbSource , * flagDbMaxOpenConns , * flagDbMaxIdleConns )
if err != nil {
exitOnError ( err )
}
cfg := config . Config {
DB : db ,
Log : log ,
RateLimit : netshare . NewRateLimit ( * flagNewPastesPer5Min ) ,
RateLimitGet : netshare . NewRateLimitSystem ( * flagGetPastesPer5Min , * flagGetPastesPer15Min , * flagGetPastesPer1Hour ) ,
RateLimitNew : netshare . NewRateLimitSystem ( * flagNewPastesPer5Min , * flagNewPastesPer15Min , * flagNewPastesPer1Hour ) ,
Version : Version ,
TitleMaxLen : * flagTitleMaxLen ,
BodyMaxLen : * flagBodyMaxLen ,
@ -294,109 +329,36 @@ func main() {
AdminMail : * flagAdminMail ,
RobotsDisallow : * flagRobotsDisallow ,
UiDefaultLifetime : * flagUiDefaultLifetime ,
UiDefaultTheme : * flagUiDefaultTheme ,
UiThemesDir : * flagUiThemesDir ,
LenPasswdFile : * flagLenPasswdFile ,
}
apiv1Data := apiv1 . Load ( cfg)
apiv1Data := apiv1 . Load ( db, cfg)
rawData := raw . Load ( cfg)
rawData := raw . Load ( db, cfg)
// Init data base
err = db. InitDB ( )
err = storage. InitDB ( * flagDbDriver , * flagDbSource )
if err != nil {
exitOnError ( err )
}
// Load pages
webData , err := web . Load ( cfg)
webData , err := web . Load ( db, cfg)
if err != nil {
exitOnError ( err )
}
// Handlers
http . HandleFunc ( "/robots.txt" , func ( rw http . ResponseWriter , req * http . Request ) {
webData . RobotsTxtHand ( rw , req )
} )
if * flagRobotsDisallow == false {
http . HandleFunc ( "/sitemap.xml" , func ( rw http . ResponseWriter , req * http . Request ) {
webData . SitemapHand ( rw , req )
} )
}
http . HandleFunc ( "/style.css" , func ( rw http . ResponseWriter , req * http . Request ) {
webData . StyleCSSHand ( rw , req )
} )
http . HandleFunc ( "/" , func ( rw http . ResponseWriter , req * http . Request ) {
webData . MainHand ( rw , req )
} )
http . HandleFunc ( "/main.js" , func ( rw http . ResponseWriter , req * http . Request ) {
webData . MainJSHand ( rw , req )
} )
http . HandleFunc ( "/history.js" , func ( rw http . ResponseWriter , req * http . Request ) {
webData . HistoryJSHand ( rw , req )
} )
http . HandleFunc ( "/code.js" , func ( rw http . ResponseWriter , req * http . Request ) {
webData . CodeJSHand ( rw , req )
} )
http . HandleFunc ( "/paste.js" , func ( rw http . ResponseWriter , req * http . Request ) {
webData . PasteJSHand ( rw , req )
} )
http . HandleFunc ( "/settings" , func ( rw http . ResponseWriter , req * http . Request ) {
webData . SettingsHand ( rw , req )
webData . Handler ( rw , req )
} )
http . HandleFunc ( "/terms" , func ( rw http . ResponseWriter , req * http . Request ) {
webData . TermsOfUseHand ( rw , req )
} )
http . HandleFunc ( "/raw/" , func ( rw http . ResponseWriter , req * http . Request ) {
rawData . RawHand ( rw , req )
} )
http . HandleFunc ( "/dl/" , func ( rw http . ResponseWriter , req * http . Request ) {
webData . DlHand ( rw , req )
rawData . Hand ( rw , req )
} )
http . HandleFunc ( "/emb/" , func ( rw http . ResponseWriter , req * http . Request ) {
webData . EmbeddedHand ( rw , req )
} )
http . HandleFunc ( "/emb_help/" , func ( rw http . ResponseWriter , req * http . Request ) {
webData . EmbeddedHelpHand ( rw , req )
} )
http . HandleFunc ( "/about" , func ( rw http . ResponseWriter , req * http . Request ) {
webData . AboutHand ( rw , req )
} )
http . HandleFunc ( "/about/authors" , func ( rw http . ResponseWriter , req * http . Request ) {
webData . AuthorsHand ( rw , req )
} )
http . HandleFunc ( "/about/license" , func ( rw http . ResponseWriter , req * http . Request ) {
webData . LicenseHand ( rw , req )
} )
http . HandleFunc ( "/about/source_code" , func ( rw http . ResponseWriter , req * http . Request ) {
webData . SourceCodePageHand ( rw , req )
} )
http . HandleFunc ( "/docs" , func ( rw http . ResponseWriter , req * http . Request ) {
webData . DocsHand ( rw , req )
} )
http . HandleFunc ( "/docs/apiv1" , func ( rw http . ResponseWriter , req * http . Request ) {
webData . DocsApiV1Hand ( rw , req )
} )
http . HandleFunc ( "/docs/api_libs" , func ( rw http . ResponseWriter , req * http . Request ) {
webData . DocsApiLibsHand ( rw , req )
} )
http . HandleFunc ( "/api/" , func ( rw http . ResponseWriter , req * http . Request ) {
apiv1Data . MainHand ( rw , req )
} )
http . HandleFunc ( "/api/v1/new" , func ( rw http . ResponseWriter , req * http . Request ) {
apiv1Data . NewHand ( rw , req )
} )
http . HandleFunc ( "/api/v1/get" , func ( rw http . ResponseWriter , req * http . Request ) {
apiv1Data . GetHand ( rw , req )
} )
http . HandleFunc ( "/api/v1/getServerInfo" , func ( rw http . ResponseWriter , req * http . Request ) {
apiv1Data . GetServerInfoHand ( rw , req )
apiv1Data . Hand ( rw , req )
} )
// Run background job