package main import ( "errors" "fmt" "git.openprivacy.ca/openprivacy/libricochet-go/log" "git.openprivacy.ca/sarah/kdb/citing" "github.com/nickng/bibtex" "html/template" "io/ioutil" "net/http" "os" "os/exec" "path" "path/filepath" "regexp" "strings" ) type Page struct { Title string Body template.HTML BodyOrig string Concept template.HTML References map[string]*bibtex.BibEntry } var templates = template.Must(template.ParseFiles("templates/view.html")) func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) { err := templates.ExecuteTemplate(w, tmpl+".html", p) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } } func (p *Page) save() error { filename := path.Join("data", p.Title+".kdb") return ioutil.WriteFile(filename, []byte(p.Body), 0600) } var validPath = regexp.MustCompile("^/(edit|save|view)/([a-zA-Z0-9\\-]+)(/?)$") func getTitle(w http.ResponseWriter, r *http.Request) (string, error) { m := validPath.FindStringSubmatch(r.URL.Path) if m == nil { http.NotFound(w, r) return "", errors.New("Invalid Page Title") } return m[2], nil // The title is the second subexpression. } func hasPage(word string) bool { if _, err := os.Stat(path.Join("data/", normalize(word)+".kdb")); err != nil { return false } return true } func loadPage(title string) (*Page, error) { filename := title + ".kdb" bodyb, err := ioutil.ReadFile(path.Join("data", filename)) if err != nil { return nil, err } body := template.HTMLEscapeString(string(bodyb)) concept := template.HTML(construct_graph(title)) linked := make(map[string]bool) references := make(map[string]*bibtex.BibEntry) for _, word := range strings.Fields(body) { if !linked[normalize(word)] { if hasPage(word) { body = strings.ReplaceAll(body, word, fmt.Sprintf("%v", normalize(word), normalize(word))) } if strings.HasPrefix(word, "cite;") { log.Infof("Extracting Citation") cite, link, img, rec := citing.ExtractPDF(word) if rec != nil { if references[rec.CiteName] == nil { references[rec.CiteName] = rec } } body = strings.ReplaceAll(body, word, fmt.Sprintf("[X]%v", cite, link, img)) } if strings.HasPrefix(word, "http") { body = strings.ReplaceAll(body, word, fmt.Sprintf("%v", word, word)) } if strings.HasPrefix(word, "data:image/png;base64,") { body = strings.ReplaceAll(body, word, fmt.Sprintf("", word)) } linked[normalize(word)] = true } } return &Page{Title: title, Body: template.HTML(body), BodyOrig: string(bodyb), Concept: concept, References: references}, nil } func normalize(word string) string { if strings.HasPrefix(word, "typeof:") { word = word[7:] } else if strings.HasPrefix(word, "subtype:") { word = word[8:] } else if strings.HasPrefix(word, "instance:") { word = word[9:] } word = strings.TrimSpace(word) return word } func viewHandler(w http.ResponseWriter, r *http.Request) { title, err := getTitle(w, r) if err != nil { return } p, err := loadPage(title) if err != nil { p = &Page{} p.Title = title } renderTemplate(w, "view", p) } func saveHandler(w http.ResponseWriter, r *http.Request) { title, err := getTitle(w, r) if err != nil { return } body := r.FormValue("body") p := &Page{Title: title, Body: template.HTML(body)} err = p.save() if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } http.Redirect(w, r, "/view/"+title, http.StatusFound) } func get_links(name string) (links []string) { filename := name + ".kdb" bodyb, err := ioutil.ReadFile(path.Join("data", filename)) if err != nil { return []string{} } body := template.HTMLEscapeString(string(bodyb)) for _, word := range strings.Fields(body) { if hasPage(word) { links = append(links, word) } } return } func construct_graph(word string) string { seen := make(map[string]bool) graph := "digraph {\n ratio=\"compress\";size=\"8,4!\";splines=true;\"" + word + "\";\n" graph = construct_graph_sub(graph, word, seen, 1) graph += "}" ioutil.WriteFile("tmp.dot", []byte(graph), 0640) subProcess := exec.Command("dot", "-Tsvg", "-otmp.svg", "-Nfontname=Chilanka", "tmp.dot") subProcess.Run() subProcess.Wait() data, _ := ioutil.ReadFile("tmp.svg") return "