package main
import (
"bufio"
"fmt"
"html/template"
"net/http"
"net/http/cgi"
"os"
"os/exec"
"strings"
"time"
)
type Result struct {
Name string
Version string
URL string
Suite string
}
type ResultPage struct {
Query string
Release string
NumResults int
Time string
Results []Result
}
var resTempl = `
Devuan Package Information
{{.NumResults}} results for "{{.Query}}" in {{.Release}} (in {{.Time}})
This site is a cookie-free zone
`
var releaseMap = map[string]string{
"jessie": "index_jessie.txt",
"ascii": "index_ascii.txt",
"beowulf": "index_beowulf.txt",
"ceres": "index_ceres.txt",
"experimental": "index_experimental.txt",
"any": "index.txt"}
func printError(errCode int, errMsg string) {
fmt.Printf("Status:%d %s\r\n", errCode, errMsg)
fmt.Printf("Content-Type: text/plain\r\n")
fmt.Printf("\r\n%s\r\n", errMsg)
}
func parseLines(s string) []Result {
results := make([]Result, 0, 10)
scanner := bufio.NewScanner(strings.NewReader(s))
for scanner.Scan() {
URL := scanner.Text()
URLParts := strings.Split(URL, "/")[1:]
pkgNameVer := strings.Split(URLParts[len(URLParts)-1], ".html")[0]
Name := strings.Split(pkgNameVer, "_")[0]
Version := strings.Split(pkgNameVer, "_")[1]
Suite := URLParts[2]
results = append(results, Result{URL: URL, Name: Name, Version: Version, Suite: Suite})
}
//fmt.Printf("len(results): %d\n", resSize)
return results
}
func pipeComands(commands []*exec.Cmd) ([]byte, error) {
for i, command := range commands[:len(commands)-1] {
out, err := command.StdoutPipe()
if err != nil {
return nil, err
}
command.Start()
commands[i+1].Stdin = out
}
final, err := commands[len(commands)-1].Output()
if err != nil {
return nil, err
}
return final, nil
}
func getResults(req http.Request) (ResultPage, error) {
var res ResultPage
var release string
req.ParseForm()
searchQuery := req.Form["search"]
if len(searchQuery) < 1 {
printError(503, fmt.Sprintf("Something went wrong in parsing query...\r\n%s\r\n", req.Form))
os.Exit(0)
}
res.Query = searchQuery[0]
QueryTerms := strings.Split(res.Query, " ")
selectedRelease := req.Form["release"]
if len(selectedRelease) < 1 {
release = "any"
} else {
release = selectedRelease[0]
}
res.Release = release
fmt.Printf("QueryTerms: %s\n", QueryTerms)
startTime := time.Now()
commands := make([]*exec.Cmd, 0)
cmd := "grep"
args := []string{QueryTerms[0], releaseMap[release]}
commands = append(commands, exec.Command(cmd, args...))
for _, word := range QueryTerms[1:] {
args = []string{word}
fmt.Printf("word: %s\r\n", word)
commands = append(commands, exec.Command(cmd, args...))
}
//if cmdOut, err := exec.Command(cmd, args...).Output(); err != nil {
if cmdOut, err := pipeComands(commands); err != nil {
fmt.Printf("error executing command: %s", err)
res.Time = fmt.Sprintf("%s", time.Since(startTime))
return res, nil
} else {
res.Results = parseLines(string(cmdOut[:len(cmdOut)]))
res.NumResults = len(res.Results)
res.Time = fmt.Sprintf("%s", time.Since(startTime))
}
return res, nil
}
func printResults(results ResultPage) {
t, err := template.New("webpage").Parse(resTempl)
if err != nil {
printError(502, "Something went wrong...")
return
}
fmt.Printf("Status: 200 OK\r\n")
fmt.Printf("Content-Type: text/html\r\n")
t.Execute(os.Stdout, results)
}
func main() {
var req *http.Request
var err error
req, err = cgi.Request()
if err != nil {
printError(500, "cannot get requested resource"+err.Error())
return
}
res, err := getResults(*req)
if err != nil {
printError(404, fmt.Sprintf("%s", err))
} else {
printResults(res)
}
}