package main import ( "html/template" "net/http" "strconv" "time" "github.com/gin-contrib/static" "github.com/gin-gonic/gin" ) func serve(port string) { router := gin.Default() router.LoadHTMLGlob("templates/*") router.Use(static.Serve("/static/", static.LocalFile("./static", true))) router.GET("/", func(c *gin.Context) { c.Redirect(302, "/"+randomAlliterateCombo()) }) router.GET("/:page", func(c *gin.Context) { page := c.Param("page") c.Redirect(302, "/"+page+"/edit") }) router.GET("/:page/:command", handlePageRequest) router.POST("/update", handlePageUpdate) router.POST("/prime", handlePrime) router.POST("/lock", handleLock) router.POST("/encrypt", handleEncrypt) router.Run(":" + port) } func handlePageRequest(c *gin.Context) { page := c.Param("page") command := c.Param("command") version := c.DefaultQuery("version", "ajksldfjl") p := Open(page) if p.IsPrimedForSelfDestruct && !p.IsLocked && !p.IsEncrypted { p.Update("*This page has now self-destructed.*\n\n" + p.Text.GetCurrent()) p.Erase() } if command == "erase" && !p.IsLocked { p.Erase() c.Redirect(302, "/"+page+"/edit") } rawText := p.Text.GetCurrent() rawHTML := p.RenderedPage // Check to see if an old version is requested versionInt, versionErr := strconv.Atoi(version) if versionErr == nil && versionInt > 0 { versionText, err := p.Text.GetPreviousByTimestamp(int64(versionInt)) if err == nil { rawText = versionText rawHTML = GithubMarkdownToHTML(rawText) } } versionsInt64 := p.Text.GetSnapshots() versionsText := make([]string, len(versionsInt64)) for i, v := range versionsInt64 { versionsText[i] = time.Unix(v/1000000000, 0).String() } if command == "raw" { c.Writer.Header().Set("Content-Type", contentType(p.Name)) c.Writer.Header().Set("Access-Control-Allow-Origin", "*") c.Writer.Header().Set("Access-Control-Max-Age", "86400") c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE") c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, X-Max") c.Writer.Header().Set("Access-Control-Allow-Credentials", "true") c.Data(200, contentType(p.Name), []byte(rawText)) return } c.HTML(http.StatusOK, "index.html", gin.H{ "EditPage": command == "edit", "ViewPage": command == "view", "ListPage": command == "list", "HistoryPage": command == "history", "Page": p.Name, "RenderedPage": template.HTML([]byte(rawHTML)), "RawPage": rawText, "Versions": versionsInt64, "VersionsText": versionsText, "IsLocked": p.IsLocked, "IsEncrypted": p.IsEncrypted, }) } func handlePageUpdate(c *gin.Context) { type QueryJSON struct { Page string `json:"page"` NewText string `json:"new_text"` } var json QueryJSON if c.BindJSON(&json) != nil { c.JSON(http.StatusOK, gin.H{"success": false, "message": "Wrong JSON"}) return } if len(json.NewText) > 100000 { c.JSON(http.StatusOK, gin.H{"success": false, "message": "Too much"}) return } log.Trace("Update: %v", json) p := Open(json.Page) var message string if p.IsLocked { message = "Locked" } else if p.IsEncrypted { message = "Encrypted" } else { p.Update(json.NewText) p.Save() message = "Saved" } c.JSON(http.StatusOK, gin.H{"success": false, "message": message}) } func handlePrime(c *gin.Context) { type QueryJSON struct { Page string `json:"page"` } var json QueryJSON if c.BindJSON(&json) != nil { c.String(http.StatusBadRequest, "Problem binding keys") return } log.Trace("Update: %v", json) p := Open(json.Page) if p.IsLocked { c.JSON(http.StatusOK, gin.H{"success": false, "message": "Locked"}) return } else if p.IsEncrypted { c.JSON(http.StatusOK, gin.H{"success": false, "message": "Encrypted"}) return } p.IsPrimedForSelfDestruct = true p.Save() c.JSON(http.StatusOK, gin.H{"success": true, "message": "Primed"}) } func handleLock(c *gin.Context) { type QueryJSON struct { Page string `json:"page"` Passphrase string `json:"passphrase"` } var json QueryJSON if c.BindJSON(&json) != nil { c.String(http.StatusBadRequest, "Problem binding keys") return } p := Open(json.Page) var message string if p.IsLocked { err2 := CheckPasswordHash(json.Passphrase, p.PassphraseToUnlock) if err2 != nil { c.JSON(http.StatusOK, gin.H{"success": false, "message": "Can't unlock"}) return } p.IsLocked = false message = "Unlocked" } else { p.IsLocked = true p.PassphraseToUnlock = HashPassword(json.Passphrase) message = "Locked" } p.Save() c.JSON(http.StatusOK, gin.H{"success": true, "message": message}) } func handleEncrypt(c *gin.Context) { type QueryJSON struct { Page string `json:"page"` Passphrase string `json:"passphrase"` } var json QueryJSON if c.BindJSON(&json) != nil { c.String(http.StatusBadRequest, "Problem binding keys") return } p := Open(json.Page) q := Open(json.Page) var message string if p.IsEncrypted { decrypted, err2 := DecryptString(p.Text.GetCurrent(), json.Passphrase) if err2 != nil { c.JSON(http.StatusOK, gin.H{"success": false, "message": "Wrong password"}) return } q.Erase() q = Open(json.Page) q.Update(decrypted) q.IsEncrypted = false q.IsLocked = p.IsLocked q.IsPrimedForSelfDestruct = p.IsPrimedForSelfDestruct message = "Decrypted" } else { currentText := p.Text.GetCurrent() encrypted, _ := EncryptString(currentText, json.Passphrase) q.Erase() q = Open(json.Page) q.Update(encrypted) q.IsEncrypted = true q.IsLocked = p.IsLocked q.IsPrimedForSelfDestruct = p.IsPrimedForSelfDestruct message = "Encrypted" } q.Save() c.JSON(http.StatusOK, gin.H{"success": true, "message": message}) }