2015-05-01 03:59:48 +03:00
|
|
|
package api
|
|
|
|
|
|
|
|
import (
|
2016-01-08 06:18:22 +03:00
|
|
|
"fmt"
|
2015-05-01 03:59:48 +03:00
|
|
|
"mime"
|
2016-02-26 19:48:55 +03:00
|
|
|
"net/http"
|
2015-05-01 03:59:48 +03:00
|
|
|
"path/filepath"
|
2016-01-08 06:18:22 +03:00
|
|
|
"strconv"
|
2016-02-19 06:17:31 +03:00
|
|
|
"strings"
|
2015-05-01 03:59:48 +03:00
|
|
|
|
|
|
|
"github.com/gin-gonic/gin"
|
2016-01-15 04:50:01 +03:00
|
|
|
|
|
|
|
"github.com/sosedoff/pgweb/pkg/shared"
|
2015-05-01 03:59:48 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
var extraMimeTypes = map[string]string{
|
|
|
|
".icon": "image-x-icon",
|
|
|
|
".ttf": "application/x-font-ttf",
|
|
|
|
".woff": "application/x-font-woff",
|
|
|
|
".eot": "application/vnd.ms-fontobject",
|
|
|
|
".svg": "image/svg+xml",
|
2015-05-03 04:10:14 +03:00
|
|
|
".html": "text/html; charset-utf-8",
|
2015-05-01 03:59:48 +03:00
|
|
|
}
|
|
|
|
|
2016-01-09 04:10:11 +03:00
|
|
|
// Paths that dont require database connection
|
|
|
|
var allowedPaths = map[string]bool{
|
|
|
|
"/api/sessions": true,
|
|
|
|
"/api/info": true,
|
|
|
|
"/api/connect": true,
|
|
|
|
"/api/bookmarks": true,
|
|
|
|
"/api/history": true,
|
|
|
|
}
|
|
|
|
|
2016-02-19 06:17:31 +03:00
|
|
|
// List of characters replaced by javascript code to make queries url-safe.
|
|
|
|
var base64subs = map[string]string{
|
|
|
|
"-": "+",
|
|
|
|
"_": "/",
|
|
|
|
".": "=",
|
|
|
|
}
|
|
|
|
|
2015-05-01 03:59:48 +03:00
|
|
|
type Error struct {
|
|
|
|
Message string `json:"error"`
|
|
|
|
}
|
|
|
|
|
2016-02-19 06:17:31 +03:00
|
|
|
func NewError(err error) Error {
|
|
|
|
return Error{err.Error()}
|
|
|
|
}
|
|
|
|
|
2016-02-19 07:18:07 +03:00
|
|
|
// Returns a clean query without any comment statements
|
|
|
|
func cleanQuery(query string) string {
|
|
|
|
lines := []string{}
|
|
|
|
|
|
|
|
for _, line := range strings.Split(query, "\n") {
|
|
|
|
line = strings.TrimSpace(line)
|
|
|
|
if strings.HasPrefix(line, "--") {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
lines = append(lines, line)
|
|
|
|
}
|
|
|
|
|
|
|
|
return strings.TrimSpace(strings.Join(lines, "\n"))
|
|
|
|
}
|
|
|
|
|
2016-02-19 06:17:31 +03:00
|
|
|
func desanitize64(query string) string {
|
|
|
|
// Before feeding the string into decoded, we must "reconstruct" the base64 data.
|
|
|
|
// Javascript replaces a few characters to be url-safe.
|
|
|
|
for olds, news := range base64subs {
|
|
|
|
query = strings.Replace(query, olds, news, -1)
|
|
|
|
}
|
|
|
|
|
|
|
|
return query
|
|
|
|
}
|
|
|
|
|
2016-02-26 19:48:55 +03:00
|
|
|
func getSessionId(req *http.Request) string {
|
|
|
|
id := req.Header.Get("x-session-id")
|
2016-01-09 04:10:11 +03:00
|
|
|
if id == "" {
|
2016-02-26 19:48:55 +03:00
|
|
|
id = req.URL.Query().Get("_session_id")
|
2016-01-09 04:10:11 +03:00
|
|
|
}
|
|
|
|
return id
|
|
|
|
}
|
|
|
|
|
2016-01-05 03:03:53 +03:00
|
|
|
func getQueryParam(c *gin.Context, name string) string {
|
|
|
|
result := ""
|
|
|
|
q := c.Request.URL.Query()
|
|
|
|
|
|
|
|
if len(q[name]) > 0 {
|
|
|
|
result = q[name][0]
|
|
|
|
}
|
|
|
|
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
2016-01-08 06:18:22 +03:00
|
|
|
func parseIntFormValue(c *gin.Context, name string, defValue int) (int, error) {
|
|
|
|
val := c.Request.FormValue(name)
|
|
|
|
|
|
|
|
if val == "" {
|
|
|
|
return defValue, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
num, err := strconv.Atoi(val)
|
|
|
|
if err != nil {
|
|
|
|
return defValue, fmt.Errorf("%s must be a number", name)
|
|
|
|
}
|
|
|
|
|
2016-01-08 23:16:53 +03:00
|
|
|
if num < 1 && defValue != 0 {
|
2016-04-15 13:51:28 +03:00
|
|
|
return defValue, fmt.Errorf("%s must be greater than 0", name)
|
2016-01-08 06:18:22 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return num, nil
|
|
|
|
}
|
|
|
|
|
2016-01-15 04:50:01 +03:00
|
|
|
func parseSshInfo(c *gin.Context) *shared.SSHInfo {
|
|
|
|
info := shared.SSHInfo{
|
|
|
|
Host: c.Request.FormValue("ssh_host"),
|
|
|
|
Port: c.Request.FormValue("ssh_port"),
|
|
|
|
User: c.Request.FormValue("ssh_user"),
|
|
|
|
Password: c.Request.FormValue("ssh_password"),
|
|
|
|
}
|
|
|
|
|
|
|
|
if info.Port == "" {
|
|
|
|
info.Port = "22"
|
|
|
|
}
|
|
|
|
|
|
|
|
return &info
|
|
|
|
}
|
|
|
|
|
2015-05-01 03:59:48 +03:00
|
|
|
func assetContentType(name string) string {
|
|
|
|
ext := filepath.Ext(name)
|
|
|
|
result := mime.TypeByExtension(ext)
|
|
|
|
|
|
|
|
if result == "" {
|
|
|
|
result = extraMimeTypes[ext]
|
|
|
|
}
|
|
|
|
|
|
|
|
if result == "" {
|
|
|
|
result = "text/plain; charset=utf-8"
|
|
|
|
}
|
|
|
|
|
|
|
|
return result
|
|
|
|
}
|