nemunaire
8f7de926d3
We are now able, depending on configuration, to retrieve files from either WebDAV or local file system.
156 lines
4.8 KiB
Go
156 lines
4.8 KiB
Go
package main
|
|
|
|
import (
|
|
"flag"
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
"net/url"
|
|
"os"
|
|
"path"
|
|
"path/filepath"
|
|
"strings"
|
|
"text/template"
|
|
|
|
"srs.epita.fr/fic-server/admin/api"
|
|
"srs.epita.fr/fic-server/admin/sync"
|
|
"srs.epita.fr/fic-server/libfic"
|
|
"srs.epita.fr/fic-server/settings"
|
|
)
|
|
|
|
var PKIDir string
|
|
var StaticDir string
|
|
|
|
type ResponseWriterPrefix struct {
|
|
real http.ResponseWriter
|
|
prefix string
|
|
}
|
|
|
|
func (r ResponseWriterPrefix) Header() http.Header {
|
|
return r.real.Header()
|
|
}
|
|
|
|
func (r ResponseWriterPrefix) WriteHeader(s int) {
|
|
if v, exists := r.real.Header()["Location"]; exists {
|
|
r.real.Header().Set("Location", r.prefix + v[0])
|
|
}
|
|
r.real.WriteHeader(s)
|
|
}
|
|
|
|
func (r ResponseWriterPrefix) Write(z []byte) (int, error) {
|
|
return r.real.Write(z)
|
|
}
|
|
|
|
func StripPrefix(prefix string, h http.Handler) http.Handler {
|
|
if prefix == "" {
|
|
return h
|
|
}
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if prefix != "/" && r.URL.Path == "/" {
|
|
http.Redirect(w, r, prefix + "/", http.StatusFound)
|
|
} else if p := strings.TrimPrefix(r.URL.Path, prefix); len(p) < len(r.URL.Path) {
|
|
r2 := new(http.Request)
|
|
*r2 = *r
|
|
r2.URL = new(url.URL)
|
|
*r2.URL = *r.URL
|
|
r2.URL.Path = p
|
|
h.ServeHTTP(ResponseWriterPrefix{w, prefix}, r2)
|
|
} else {
|
|
h.ServeHTTP(w, r)
|
|
}
|
|
})
|
|
}
|
|
|
|
func main() {
|
|
// Read paremeters from environment
|
|
if v, exists := os.LookupEnv("FICCLOUD_URL"); exists {
|
|
sync.CloudDAVBase = v
|
|
}
|
|
if v, exists := os.LookupEnv("FICCLOUD_USER"); exists {
|
|
sync.CloudUsername = v
|
|
}
|
|
if v, exists := os.LookupEnv("FICCLOUD_PASS"); exists {
|
|
sync.CloudPassword = v
|
|
}
|
|
|
|
// Read parameters from command line
|
|
var bind = flag.String("bind", "127.0.0.1:8081", "Bind port/socket")
|
|
var dsn = flag.String("dsn", fic.DSNGenerator(), "DSN to connect to the MySQL server")
|
|
var baseURL = flag.String("baseurl", "/", "URL prepended to each URL")
|
|
flag.StringVar(&PKIDir, "pki", "./pki/", "Base directory where found PKI scripts")
|
|
flag.StringVar(&StaticDir, "static", "./htdocs-admin/", "Directory containing static files")
|
|
flag.StringVar(&api.TeamsDir, "teams", "./TEAMS", "Base directory where save teams JSON files")
|
|
flag.StringVar(&settings.SettingsDir, "settings", settings.SettingsDir, "Base directory where load and save settings")
|
|
flag.StringVar(&fic.FilesDir, "files", fic.FilesDir, "Base directory where found challenges files, local part")
|
|
flag.StringVar(&sync.CloudDAVBase, "clouddav", sync.CloudDAVBase,
|
|
"Base directory where found challenges files, cloud part")
|
|
flag.StringVar(&sync.CloudUsername, "clouduser", sync.CloudUsername, "Username used to sync")
|
|
flag.StringVar(&sync.CloudPassword, "cloudpass", sync.CloudPassword, "Password used to sync")
|
|
flag.BoolVar(&fic.OptionalDigest, "optionaldigest", fic.OptionalDigest, "Is the digest required when importing files?")
|
|
flag.BoolVar(&fic.StrongDigest, "strongdigest", fic.StrongDigest, "Are BLAKE2b digests required instead of SHA-1 or BLAKE2b?")
|
|
flag.Parse()
|
|
|
|
log.SetPrefix("[admin] ")
|
|
|
|
// Sanitize options
|
|
var err error
|
|
log.Println("Checking paths...")
|
|
if StaticDir, err = filepath.Abs(StaticDir); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
if fic.FilesDir, err = filepath.Abs(fic.FilesDir); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
if PKIDir, err = filepath.Abs(PKIDir); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
if api.TeamsDir, err = filepath.Abs(api.TeamsDir); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
if settings.SettingsDir, err = filepath.Abs(settings.SettingsDir); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
if fic.FilesDir, err = filepath.Abs(fic.FilesDir); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
if *baseURL != "/" {
|
|
tmp := path.Clean(*baseURL)
|
|
baseURL = &tmp
|
|
} else {
|
|
tmp := ""
|
|
baseURL = &tmp
|
|
}
|
|
|
|
// Initialize contents
|
|
if err := os.Chdir(PKIDir); err != nil {
|
|
log.Fatal("Unable to enter PKI directory at: ", err)
|
|
}
|
|
|
|
log.Println("Opening database...")
|
|
if err := fic.DBInit(*dsn); err != nil {
|
|
log.Fatal("Cannot open the database: ", err)
|
|
}
|
|
defer fic.DBClose()
|
|
|
|
log.Println("Creating database...")
|
|
if err := fic.DBCreate(); err != nil {
|
|
log.Fatal("Cannot create database: ", err)
|
|
}
|
|
|
|
// Update base URL on main page
|
|
log.Println("Changing base URL to", *baseURL + "/", "...")
|
|
if file, err := os.OpenFile(path.Join(StaticDir, "index.html"), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.FileMode(0644)); err != nil {
|
|
log.Println("Unable to open index.html: ", err)
|
|
} else if indexTmpl, err := template.New("index").Parse(indextpl); err != nil {
|
|
log.Println("Cannot create template: ", err)
|
|
} else if err := indexTmpl.Execute(file, map[string]string{"urlbase": path.Clean(path.Join(*baseURL + "/", "nuke"))[:len(path.Clean(path.Join(*baseURL + "/", "nuke"))) - 4]}); err != nil {
|
|
log.Println("An error occurs during template execution: ", err)
|
|
}
|
|
|
|
// Serve content
|
|
log.Println(fmt.Sprintf("Ready, listening on %s", *bind))
|
|
if err := http.ListenAndServe(*bind, StripPrefix(*baseURL, api.Router())); err != nil {
|
|
log.Fatal("Unable to listen and serve: ", err)
|
|
}
|
|
}
|