all repos — flounder @ 04c6d55b8d4967f11c4f7e795c7379469e0587d4

A small site builder for the Gemini protocol

main.go (view raw)

  1package main
  2
  3import (
  4	"database/sql"
  5	"flag"
  6	"fmt"
  7	"github.com/gorilla/sessions"
  8	"io/ioutil"
  9	"log"
 10	"os"
 11	"path"
 12	"path/filepath"
 13	"sort"
 14	"strings"
 15	"sync"
 16	"time"
 17)
 18
 19var c Config // global var to hold static configuration
 20
 21type File struct {
 22	Creator     string
 23	Name        string
 24	UpdatedTime time.Time
 25}
 26
 27func getUsers() ([]string, error) {
 28	rows, err := DB.Query(`SELECT username from user`)
 29	if err != nil {
 30		return nil, err
 31	}
 32	var users []string
 33	for rows.Next() {
 34		var user string
 35		err = rows.Scan(&user)
 36		if err != nil {
 37			return nil, err
 38		}
 39		users = append(users, user)
 40	}
 41	return users, nil
 42}
 43
 44/// Perform some checks to make sure the file is OK
 45func checkIfValidFile(filename string, fileBytes []byte) error {
 46	ext := strings.ToLower(path.Ext(filename))
 47	found := false
 48	for _, mimetype := range c.OkExtensions {
 49		if ext == mimetype {
 50			found = true
 51		}
 52	}
 53	if !found {
 54		return fmt.Errorf("Invalid file extension: %s", ext)
 55	}
 56	if len(fileBytes) > c.MaxFileSize {
 57		return fmt.Errorf("File too large. File was %s bytes, Max file size is %s", len(fileBytes), c.MaxFileSize)
 58	}
 59	return nil
 60}
 61
 62func getIndexFiles() ([]*File, error) { // cache this function
 63	result := []*File{}
 64	err := filepath.Walk(c.FilesDirectory, func(thepath string, info os.FileInfo, err error) error {
 65		if err != nil {
 66			log.Printf("Failure accessing a path %q: %v\n", thepath, err)
 67			return err // think about
 68		}
 69		// make this do what it should
 70		if !info.IsDir() {
 71			creatorFolder, _ := path.Split(thepath)
 72			result = append(result, &File{
 73				Name:        info.Name(),
 74				Creator:     path.Base(creatorFolder),
 75				UpdatedTime: info.ModTime(),
 76			})
 77		}
 78		return nil
 79	})
 80	if err != nil {
 81		return nil, err
 82	}
 83	// sort
 84	// truncate
 85	sort.Slice(result, func(i, j int) bool {
 86		return result[i].UpdatedTime.Before(result[j].UpdatedTime)
 87	})
 88	if len(result) > 50 {
 89		result = result[:50]
 90	}
 91	return result, nil
 92} // todo clean up paths
 93
 94func getUserFiles(user string) ([]*File, error) {
 95	result := []*File{}
 96	files, err := ioutil.ReadDir(path.Join(c.FilesDirectory, user))
 97	if err != nil {
 98		return nil, err
 99	}
100	for _, file := range files {
101		result = append(result, &File{
102			Name:        file.Name(),
103			Creator:     user,
104			UpdatedTime: file.ModTime(),
105		})
106	}
107	return result, nil
108}
109
110func main() {
111	configPath := flag.String("c", "flounder.toml", "path to config file")
112	var err error
113	c, err = getConfig(*configPath)
114	if err != nil {
115		log.Fatal(err)
116	}
117	SessionStore = sessions.NewCookieStore([]byte(c.CookieStoreKey))
118	DB, err = sql.Open("sqlite3", c.DBFile)
119	if err != nil {
120		log.Fatal(err)
121	}
122
123	wg := new(sync.WaitGroup)
124	wg.Add(2)
125	go func() {
126		runHTTPServer()
127		wg.Done()
128	}()
129	go func() {
130		runGeminiServer()
131		wg.Done()
132	}()
133	wg.Wait()
134}