summaryrefslogtreecommitdiff
path: root/main.go
diff options
context:
space:
mode:
Diffstat (limited to 'main.go')
-rw-r--r--main.go86
1 files changed, 75 insertions, 11 deletions
diff --git a/main.go b/main.go
index 12389af..ec07e82 100644
--- a/main.go
+++ b/main.go
@@ -1,24 +1,25 @@
package main
import (
+ "bufio"
"crypto/md5"
- "mime"
- "io/ioutil"
- "io"
"encoding/json"
- "sync"
"flag"
"fmt"
"html/template"
+ "io"
+ "io/ioutil"
"log"
- "strconv"
+ "mime"
"net/http"
"os"
"path"
+ "strconv"
"strings"
+ "sync"
"github.com/jmoiron/sqlx"
- _"github.com/lib/pq"
+ "github.com/lib/pq"
)
type Config struct {
@@ -32,6 +33,8 @@ type Config struct {
MaxPages uint `json:"max_pages"`
}
+type cmdFunction func (w http.ResponseWriter, r *http.Request, args []string)
+
type Server struct {
mux *http.ServeMux
conf *Config
@@ -39,6 +42,8 @@ type Server struct {
fslock sync.RWMutex
filestore map[string][]string
+
+ cmds map[string]cmdFunction
}
type note struct {
@@ -103,6 +108,10 @@ func NewServer(conf *Config) *Server {
s.filestore = map[string][]string{}
+ s.cmds = map[string]cmdFunction{}
+ s.addCmd("a", s.cmdCreateNode)
+ s.addCmd("c", s.cmdChangeLoc)
+
return s
}
@@ -154,6 +163,7 @@ func (s *Server) httpLog(r *http.Request, format string, args... interface{}) {
}
func (s *Server) Error(w http.ResponseWriter, r *http.Request, err string, code int) {
+ // Do not leak internal errors
if code < 500 {
http.Error(w, err, code)
} else {
@@ -163,10 +173,14 @@ func (s *Server) Error(w http.ResponseWriter, r *http.Request, err string, code
s.httpLog(r, "ERR: %s", err)
}
-func (s *Server) httpCreateNode(w http.ResponseWriter, r *http.Request) {
+func (s *Server) cmdCreateNode(w http.ResponseWriter, r *http.Request, args []string) {
+ if len(args) < 3 {
+ s.Error(w, r, "Please specify both name and location", http.StatusBadRequest)
+ return
+ }
var (
- name = r.FormValue("name")
- location = r.FormValue("location")
+ name = args[1]
+ location = args[2]
)
hash := fmt.Sprintf("%x", md5.Sum([]byte(name)))[0:4]
@@ -196,6 +210,56 @@ func (s *Server) httpCreateNode(w http.ResponseWriter, r *http.Request) {
</html>`, name, location, hash, ref.String())
}
+func (s *Server) cmdChangeLoc(w http.ResponseWriter, r *http.Request, args []string) {
+ argc := len(args)
+ if argc < 3 {
+ s.Error(w, r, "Please specify both id and new location", http.StatusBadRequest)
+ return
+ }
+
+ var (
+ hashes = args[1:argc-1]
+ loc = args[argc-1]
+ )
+
+ _, err := s.db.ExecContext(r.Context(), `
+ UPDATE notes SET location = $1 WHERE hash = ANY($2)`,
+ loc, pq.Array(hashes))
+ if err != nil {
+ s.Error(w, r, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ http.Redirect(w, r, "/", http.StatusSeeOther)
+}
+
+func (s *Server) addCmd(name string, f cmdFunction) {
+ s.cmds[name] = f
+}
+
+func (s *Server) httpRunCmd(w http.ResponseWriter, r *http.Request) {
+ cmd := r.FormValue("cmd")
+
+ scanner := bufio.NewScanner(strings.NewReader(cmd))
+ scanner.Split(bufio.ScanWords)
+ var words []string
+ for scanner.Scan() {
+ words = append(words, scanner.Text())
+ }
+ if err := scanner.Err(); err != nil {
+ s.Error(w, r, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ cmd = strings.ToLower(words[0])
+ f, ok := s.cmds[cmd]
+ if !ok {
+ s.Error(w, r, fmt.Sprintf("No such command '%s'", cmd), http.StatusBadRequest)
+ return
+ }
+ f(w, r, words)
+}
+
func (s *Server) httpRoot(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/" {
w.WriteHeader(http.StatusNotFound)
@@ -203,7 +267,7 @@ func (s *Server) httpRoot(w http.ResponseWriter, r *http.Request) {
}
if r.Method == "POST" {
- s.httpCreateNode(w, r)
+ s.httpRunCmd(w, r)
return
}
@@ -217,7 +281,7 @@ func (s *Server) httpRoot(w http.ResponseWriter, r *http.Request) {
page.Root = s.conf.Root
err := s.db.SelectContext(r.Context(), &page.Notes, `
- SELECT hash, name, location FROM notes WHERE available = True`)
+ SELECT hash, name, location FROM notes WHERE available = True ORDER BY name`)
if err != nil {
s.Error(w, r, err.Error(), http.StatusInternalServerError)
return