From 0f31132a8ac982a03921201045985cdecc2dc9bc Mon Sep 17 00:00:00 2001 From: Zack Scholl Date: Mon, 28 Mar 2016 19:29:30 -0400 Subject: [PATCH 1/6] Don't need this password checking now Former-commit-id: 1951dfcb6292d6a9bad533f2cfb28a97e108eb8b [formerly cb098a5f59a9a4c00a3b6db270fea0716d7d5c60] [formerly b4f9bee32bc08a279397a714af9c2230070c00fc [formerly 725abe4412fb4aa7f116c6fc45842c0030a5cd52 [formerly 600dd685f14c9c1e6dfe1544684cce9b59d25079]]] Former-commit-id: c1fbbb182163aee133d42475f14dc0ac207b49ad [formerly 465d4f43772c7146419e2a4bd4ef13ec1567ec01] Former-commit-id: d39d6f868cbeae584c105bc50ad8b7df3172e833 Former-commit-id: 80d4772b7f34b557c7029cb5e690534e0af7d92a --- main.go | 9 ++------- routes.go | 52 +++++++++++++++++++++++----------------------------- 2 files changed, 25 insertions(+), 36 deletions(-) diff --git a/main.go b/main.go index cccab19..6946657 100644 --- a/main.go +++ b/main.go @@ -109,10 +109,6 @@ Options:`) r.GET("/:title", editNote) r.PUT("/:title", func(c *gin.Context) { filename := c.Param("title") - fmt.Println(filename) - fmt.Println(c.Request.Body) - fmt.Println(c.Request.ContentLength) - fmt.Println(c.Request.Header) contentLength := c.Request.ContentLength var reader io.Reader reader = c.Request.Body @@ -154,10 +150,9 @@ Options:`) buf := new(bytes.Buffer) buf.ReadFrom(reader) fmt.Println("---------------") - fmt.Println(buf.String()) + fmt.Println(filename) fmt.Println("---------------") - fmt.Println(c.ContentType()) - fmt.Println(c.Request.Header) + fmt.Println(buf.String()) fmt.Println("---------------") p := WikiData{filename, "", []string{}, []string{}, false, ""} p.save(buf.String()) diff --git a/routes.go b/routes.go index d471c28..8ce9b6b 100644 --- a/routes.go +++ b/routes.go @@ -158,37 +158,31 @@ func editNote(c *gin.Context) { } else if strings.ToLower(title) == "help" { //}&& strings.Contains(AllowedIPs, c.ClientIP()) != true { c.Redirect(302, "/Help/view") } else { - locked, _ := hasPassword(title) - if locked { + version := c.DefaultQuery("version", "-1") + versionNum, _ := strconv.Atoi(version) + currentText, versions, currentVersion, totalTime, encrypted, locked := getCurrentText(title, versionNum) + if encrypted || len(locked) > 0 { c.Redirect(302, "/"+title+"/view") - } else { - version := c.DefaultQuery("version", "-1") - versionNum, _ := strconv.Atoi(version) - currentText, versions, currentVersion, totalTime, encrypted, locked := getCurrentText(title, versionNum) - if encrypted || len(locked) > 0 { - c.Redirect(302, "/"+title+"/view") - } - if strings.Contains(currentText, "self-destruct\n") || strings.Contains(currentText, "\nself-destruct") { - c.Redirect(302, "/"+title+"/view") - } - numRows := len(strings.Split(currentText, "\n")) + 10 - totalTimeString := totalTime.String() - if totalTime.Seconds() < 1 { - totalTimeString = "< 1 s" - } - c.HTML(http.StatusOK, "index.tmpl", gin.H{ - "Title": title, - "WikiName": RuntimeArgs.WikiName, - "ExternalIP": RuntimeArgs.ExternalIP, - "CurrentText": currentText, - "NumRows": numRows, - "Versions": versions, - "TotalTime": totalTimeString, - "SocketType": RuntimeArgs.Socket, - "NoEdit": !currentVersion, - }) - } + if strings.Contains(currentText, "self-destruct\n") || strings.Contains(currentText, "\nself-destruct") { + c.Redirect(302, "/"+title+"/view") + } + numRows := len(strings.Split(currentText, "\n")) + 10 + totalTimeString := totalTime.String() + if totalTime.Seconds() < 1 { + totalTimeString = "< 1 s" + } + c.HTML(http.StatusOK, "index.tmpl", gin.H{ + "Title": title, + "WikiName": RuntimeArgs.WikiName, + "ExternalIP": RuntimeArgs.ExternalIP, + "CurrentText": currentText, + "NumRows": numRows, + "Versions": versions, + "TotalTime": totalTimeString, + "SocketType": RuntimeArgs.Socket, + "NoEdit": !currentVersion, + }) } } From b4e36280088957aeabe770c411fc2e3e196e727f Mon Sep 17 00:00:00 2001 From: Zack Scholl Date: Mon, 28 Mar 2016 19:29:48 -0400 Subject: [PATCH 2/6] Removed haspassword Former-commit-id: 4670fa4a1dc343c501f8f76421fa51b54d450cd3 [formerly e3b56e6823a77a388881b388f8f7fff348c04cba] [formerly e8bd41425d5b0a377d0ff687fcead01cab38c98c [formerly a4b29de724db196efc8505bff0b990b469bce019 [formerly 4ffcc1abd5338b0253db15b222afb9ac10a64991]]] Former-commit-id: 0850667d5b0245328ca38933359006101d14e9d6 [formerly e7643ddbfe5ec74936760a4b6ffbaeeb71a93275] Former-commit-id: be2765befe8951bc772c0c04a0583911446c8bb7 Former-commit-id: f12d53de63112af8f5132f3f90736f0f450d178e --- db.go | 37 ------------------------------------- 1 file changed, 37 deletions(-) diff --git a/db.go b/db.go index 0f243da..4d31bb8 100644 --- a/db.go +++ b/db.go @@ -43,43 +43,6 @@ type WikiData struct { Locked string } -func hasPassword(title string) (bool, error) { - title = strings.ToLower(title) - if !open { - Open(RuntimeArgs.DatabaseLocation) - defer Close() - } - hasPassword := false - err := db.View(func(tx *bolt.Tx) error { - var err error - b := tx.Bucket([]byte("datas")) - if b == nil { - return fmt.Errorf("db must be opened before loading") - } - k := []byte(title) - val := b.Get(k) - if val == nil { - return nil - } - var p WikiData - err = p.decode(val) - if err != nil { - return err - } - for _, line := range strings.Split(p.CurrentText, "\n") { - if strings.Contains(line, "<") == true && strings.Contains(line, ">") == true && strings.Contains(line, "user") == true && strings.Contains(line, "password") == true && strings.Contains(line, "public") == true { - hasPassword = true - } - } - return nil - }) - if err != nil { - fmt.Printf("Could not get WikiData: %s", err) - return false, err - } - return hasPassword, nil -} - func getCurrentText(title string, version int) (string, []versionsInfo, bool, time.Duration, bool, string) { Open(RuntimeArgs.DatabaseLocation) defer Close() From 8ebe02f4326bef58d0ad2f344597dc42ed3a4d8d Mon Sep 17 00:00:00 2001 From: Zack Scholl Date: Mon, 28 Mar 2016 19:55:25 -0400 Subject: [PATCH 3/6] curl upload/download Former-commit-id: 31707169c9c4d67f4b53a4d1f075eadf76502475 [formerly 05b4e61848391ab3a2e3a0821bff1a77643ea350] [formerly 9f6dff7e3dd94dbde69fadaa59fe97139defef79 [formerly f2d4ab4c265dd0b748bffdbdbb76936d628cf592 [formerly f6c287ba24dbbd6c270fc0b74260e02f281195eb]]] Former-commit-id: 010fc8f14ddbd3e68a315336dcbafdfe1c07ab94 [formerly 8cedec66735b36c0bf9468383d111b22c770ce69] Former-commit-id: 02b4b823c8bbf01f46782c4411e3fce319d053ca Former-commit-id: 360ad6773be388fc3cf721e63eb44134ef092371 --- main.go | 54 +------------------------------------------------ routes.go | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 53 deletions(-) diff --git a/main.go b/main.go index 6946657..cdcebb3 100644 --- a/main.go +++ b/main.go @@ -1,12 +1,9 @@ package main import ( - "bytes" "flag" "fmt" - "io" "io/ioutil" - "log" "os" "path" @@ -107,56 +104,7 @@ Options:`) r.GET("/", newNote) r.HEAD("/", func(c *gin.Context) { c.Status(200) }) r.GET("/:title", editNote) - r.PUT("/:title", func(c *gin.Context) { - filename := c.Param("title") - contentLength := c.Request.ContentLength - var reader io.Reader - reader = c.Request.Body - if contentLength == -1 { - // queue file to disk, because s3 needs content length - var err error - var f io.Reader - - f = reader - - var b bytes.Buffer - - n, err := io.CopyN(&b, f, _24K+1) - if err != nil && err != io.EOF { - log.Printf("%s", err.Error()) - } - - if n > _24K { - file, err := ioutil.TempFile("./", "transfer-") - if err != nil { - log.Printf("%s", err.Error()) - } - - defer file.Close() - - n, err = io.Copy(file, io.MultiReader(&b, f)) - if err != nil { - os.Remove(file.Name()) - log.Printf("%s", err.Error()) - } - - reader, err = os.Open(file.Name()) - } else { - reader = bytes.NewReader(b.Bytes()) - } - - contentLength = n - } - buf := new(bytes.Buffer) - buf.ReadFrom(reader) - fmt.Println("---------------") - fmt.Println(filename) - fmt.Println("---------------") - fmt.Println(buf.String()) - fmt.Println("---------------") - p := WikiData{filename, "", []string{}, []string{}, false, ""} - p.save(buf.String()) - }) + r.PUT("/:title", putFile) r.GET("/:title/*option", everythingElse) r.POST("/:title/*option", encryptionRoute) r.DELETE("/listitem", deleteListItem) diff --git a/routes.go b/routes.go index 8ce9b6b..71153fd 100644 --- a/routes.go +++ b/routes.go @@ -1,9 +1,12 @@ package main import ( + "bytes" "fmt" "html/template" + "io" "io/ioutil" + "log" "net/http" "os" "path" @@ -18,6 +21,57 @@ import ( "github.com/russross/blackfriday" ) +func putFile(c *gin.Context) { + filename := c.Param("title") + contentLength := c.Request.ContentLength + var reader io.Reader + reader = c.Request.Body + if contentLength == -1 { + // queue file to disk, because s3 needs content length + var err error + var f io.Reader + + f = reader + + var b bytes.Buffer + + n, err := io.CopyN(&b, f, _24K+1) + if err != nil && err != io.EOF { + log.Printf("%s", err.Error()) + } + + if n > _24K { + file, err := ioutil.TempFile("./", "transfer-") + if err != nil { + log.Printf("%s", err.Error()) + } + + defer file.Close() + + n, err = io.Copy(file, io.MultiReader(&b, f)) + if err != nil { + os.Remove(file.Name()) + log.Printf("%s", err.Error()) + } + + reader, err = os.Open(file.Name()) + } else { + reader = bytes.NewReader(b.Bytes()) + } + + contentLength = n + } + buf := new(bytes.Buffer) + buf.ReadFrom(reader) + // p := WikiData{filename, "", []string{}, []string{}, false, ""} + // p.save(buf.String()) + var p WikiData + p.load(strings.ToLower(filename)) + p.save(buf.String()) + fmt.Println(c.ClientIP()) + c.Data(200, "text/plain", []byte("File uploaded to http://"+RuntimeArgs.ExternalIP+"/"+filename)) +} + type EncryptionPost struct { Text string `form:"text" json:"text" binding:"required"` Password string `form:"password" json:"password" binding:"required"` @@ -161,11 +215,17 @@ func editNote(c *gin.Context) { version := c.DefaultQuery("version", "-1") versionNum, _ := strconv.Atoi(version) currentText, versions, currentVersion, totalTime, encrypted, locked := getCurrentText(title, versionNum) + if strings.Contains(c.Request.Header.Get("User-Agent"), "curl/") { + c.Data(200, "text/plain", []byte(currentText)) + return + } if encrypted || len(locked) > 0 { c.Redirect(302, "/"+title+"/view") + return } if strings.Contains(currentText, "self-destruct\n") || strings.Contains(currentText, "\nself-destruct") { c.Redirect(302, "/"+title+"/view") + return } numRows := len(strings.Split(currentText, "\n")) + 10 totalTimeString := totalTime.String() From 041d674ddc6b240ecc9606dfdc82497e28665e83 Mon Sep 17 00:00:00 2001 From: Zack Scholl Date: Mon, 28 Mar 2016 20:19:13 -0400 Subject: [PATCH 4/6] CLI support! You can use curl (only curl at the moment) to PUT files into the database. Former-commit-id: 9c6d499403675cb28eb76676a73304e3acd2cc48 [formerly b30cad27b172756fdfcbf55d1e4c7542d90ca710] [formerly f2d936c586cb11525e36421c235bd1eb8909af3a [formerly efc27e723e7ffae0a898e8a59344fba9be0b4fd8 [formerly bd59a69f2841b1f8c79b4069f4d4b36090b64f2a]]] Former-commit-id: c8f9d721fe83366a7545df693bbec7cdf376bf1b [formerly c97362f33772b2fc391d4705cc3d6eaf0f78f26b] Former-commit-id: 31366a03506e761af053625496c662f675dfeb8d Former-commit-id: 920ba22309df9ca3d9c16bdab90257b91252cbd1 --- README.md | 19 ++++++++++++++++++- main.go | 5 ++--- ratelimiter.go | 29 +++++++++++++++++++++++++++++ routes.go | 10 +++++++++- 4 files changed, 58 insertions(+), 5 deletions(-) create mode 100755 ratelimiter.go diff --git a/README.md b/README.md index 27a5ffc..9d62782 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ # [cowyo.com](http://cowyo.com/) -[![Version 0.94](https://img.shields.io/badge/version-0.94-brightgreen.svg)]() [![Go Report Card](https://goreportcard.com/badge/github.com/schollz/cowyo)](https://goreportcard.com/report/github.com/schollz/cowyo) [![Join the chat at https://gitter.im/schollz/cowyo](https://badges.gitter.im/schollz/cowyo.svg)](https://gitter.im/schollz/cowyo?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![Version 0.95](https://img.shields.io/badge/version-0.94-brightgreen.svg)]() [![Go Report Card](https://goreportcard.com/badge/github.com/schollz/cowyo)](https://goreportcard.com/report/github.com/schollz/cowyo) [![Join the chat at https://gitter.im/schollz/cowyo](https://badges.gitter.im/schollz/cowyo.svg)](https://gitter.im/schollz/cowyo?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) This is a self-contained notepad webserver that makes sharing easy and _fast_. The most important feature here is *simplicity*. There are many other features as well including versioning, page locking, self-destructing messages, encryption, math support, and listifying. Read on to learn more about the features. @@ -44,6 +44,23 @@ This is a self-contained notepad webserver that makes sharing easy and _fast_. T
+**CLI support**. Want to upload/download from a server? Its super easy. Upload/download files like this: +```bash +$ echo "Hello, world!" > hi.txt +$ curl --upload-file hi.txt cowyo.com + File uploaded to http://cowyo.com/hi.txt +$ curl cowyo.com/test.txt + Hello, world! +``` +or just skip the file-creation step, +```bash +$ echo "Wow, so easy" | curl --upload-file "-" cowyo.com + File uploaded to http://cowyo.com/CautiousCommonLoon +$ curl cowyo.com/CautiousCommonLoon + Wow, so easy +``` + +
**Keyboard Shortcuts**. Quickly transition between Edit/View/List by using `Ctl+Shift+E` to Edit, `Ctl+Shift+Z` to View, and `Ctl+Shift+L` to Listify. diff --git a/main.go b/main.go index cdcebb3..6663546 100644 --- a/main.go +++ b/main.go @@ -35,10 +35,8 @@ var RuntimeArgs struct { } var VersionNum string -const _24K = (1 << 20) * 24 - func main() { - VersionNum = "0.94" + VersionNum = "0.95" // _, executableFile, _, _ := runtime.Caller(0) // get full path of this file cwd, _ := os.Getwd() databaseFile := path.Join(cwd, "data.db") @@ -105,6 +103,7 @@ Options:`) r.HEAD("/", func(c *gin.Context) { c.Status(200) }) r.GET("/:title", editNote) r.PUT("/:title", putFile) + r.PUT("/", putFile) r.GET("/:title/*option", everythingElse) r.POST("/:title/*option", encryptionRoute) r.DELETE("/listitem", deleteListItem) diff --git a/ratelimiter.go b/ratelimiter.go new file mode 100755 index 0000000..a01e268 --- /dev/null +++ b/ratelimiter.go @@ -0,0 +1,29 @@ +package main + +import ( + "fmt" + "time" +) + +var bannedIPs []string + +func init() { + go clearBannedIPs() +} + +func clearBannedIPs() { + for { + fmt.Println("CLEARING IPS!!") + bannedIPs = []string{} + time.Sleep(3 * time.Minute) + } +} + +func isIPBanned(ip string) bool { + if stringInSlice(ip, bannedIPs) { + return true + } else { + bannedIPs = append(bannedIPs, ip) + return false + } +} diff --git a/routes.go b/routes.go index 71153fd..6b44aa3 100644 --- a/routes.go +++ b/routes.go @@ -21,8 +21,17 @@ import ( "github.com/russross/blackfriday" ) +const _24K = (1 << 20) * 24 + func putFile(c *gin.Context) { + if isIPBanned(c.ClientIP()) { + c.Data(200, "text/plain", []byte("You are rate limited to 20 requests/hour.")) + return + } filename := c.Param("title") + if len(filename) == 0 { + filename = randomAlliterateCombo() + } contentLength := c.Request.ContentLength var reader io.Reader reader = c.Request.Body @@ -68,7 +77,6 @@ func putFile(c *gin.Context) { var p WikiData p.load(strings.ToLower(filename)) p.save(buf.String()) - fmt.Println(c.ClientIP()) c.Data(200, "text/plain", []byte("File uploaded to http://"+RuntimeArgs.ExternalIP+"/"+filename)) } From 380707cbe647da18540e9e7317819a8d9894ec13 Mon Sep 17 00:00:00 2001 From: Zack Scholl Date: Mon, 28 Mar 2016 20:20:47 -0400 Subject: [PATCH 5/6] Bumped version, updated README Former-commit-id: 28b93329d92d3d7d01ebdbb42b7d1c20f5fd0518 [formerly a70573f0f01d5151b5288bd289b399e098317c92] [formerly 33bc07777f90f36c3f9829f9e4971a5e3119cc55 [formerly c2f9c23bb1e6ba22aece91739d79d1f405465941 [formerly a0c57004a84f040357b4d4933588c52788ded482]]] Former-commit-id: 570e2d901d8732cfc71ffbe95f18a91570e0d00a [formerly 52a740c2799400a2c12dcc1080cb60ca134ba6eb] Former-commit-id: 7536551aa08126c773bad299754194c8f148adfb Former-commit-id: 4d34638b8198338e0b3cfae685deeda6051d56f3 --- README.md | 2 +- templates/aboutpage.md | 20 +++++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9d62782..5551905 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ # [cowyo.com](http://cowyo.com/) -[![Version 0.95](https://img.shields.io/badge/version-0.94-brightgreen.svg)]() [![Go Report Card](https://goreportcard.com/badge/github.com/schollz/cowyo)](https://goreportcard.com/report/github.com/schollz/cowyo) [![Join the chat at https://gitter.im/schollz/cowyo](https://badges.gitter.im/schollz/cowyo.svg)](https://gitter.im/schollz/cowyo?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![Version 0.95](https://img.shields.io/badge/version-0.95-brightgreen.svg)]() [![Go Report Card](https://goreportcard.com/badge/github.com/schollz/cowyo)](https://goreportcard.com/report/github.com/schollz/cowyo) [![Join the chat at https://gitter.im/schollz/cowyo](https://badges.gitter.im/schollz/cowyo.svg)](https://gitter.im/schollz/cowyo?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) This is a self-contained notepad webserver that makes sharing easy and _fast_. The most important feature here is *simplicity*. There are many other features as well including versioning, page locking, self-destructing messages, encryption, math support, and listifying. Read on to learn more about the features. diff --git a/templates/aboutpage.md b/templates/aboutpage.md index e83432f..c988814 100644 --- a/templates/aboutpage.md +++ b/templates/aboutpage.md @@ -2,7 +2,7 @@ # CowYo ## Collections of Organized Words You Open -![Version 0.94](https://img.shields.io/badge/version-0.94-brightgreen.svg) +![Version 0.95](https://img.shields.io/badge/version-0.95-brightgreen.svg) This is a self-contained wiki webserver that makes sharing easy and _fast_. The most important feature here is *simplicity*. There are many other features as well including versioning, page locking, self-destructing messages, encryption, math support, and listifying. Read on to learn more about the features. **CowYo** is also [Open Source](https://github.com/schollz/cowyo). @@ -45,6 +45,24 @@ This is a self-contained wiki webserver that makes sharing easy and _fast_. The
+**CLI support**. Want to upload/download from a server? Its super easy. Upload/download files like this: +```bash +$ echo "Hello, world!" > hi.txt +$ curl --upload-file hi.txt cowyo.com + File uploaded to http://cowyo.com/hi.txt +$ curl cowyo.com/test.txt + Hello, world! +``` +or just skip the file-creation step, +```bash +$ echo "Wow, so easy" | curl --upload-file "-" cowyo.com + File uploaded to http://cowyo.com/CautiousCommonLoon +$ curl cowyo.com/CautiousCommonLoon + Wow, so easy +``` + +
+ **Keyboard Shortcuts**. Quickly transition between Edit/View/List by using `Ctl+Shift+E` to Edit, `Ctl+Shift+Z` to View, and `Ctl+Shift+L` to Listify. **Admin controls**. The Admin can view/delete all the documents by setting the `-a YourAdminKey` when starting the program. Then the admin has access to the `/ls/YourAdminKey` to view and delete any of the pages. From 0f34d342d83f22848f74df1a6770fc923a843f84 Mon Sep 17 00:00:00 2001 From: Zack Scholl Date: Mon, 28 Mar 2016 20:21:06 -0400 Subject: [PATCH 6/6] Removed extraneous fmt. Former-commit-id: e14a3f63333e04d7dd36445af59971bf4483e38c [formerly 0d230b0ee7017a88627c3829cb3e25723ce16909] [formerly 448638670a680e4e7d69b43ee8024a9cb09dc743 [formerly 83cc0422e5bbc0f4ee0e5c5d7ca7697a31382549 [formerly 3f3cc1f41a1aaed1ef924a591fd2cad367085ed2]]] Former-commit-id: e8c31b3325d1b75a4b18bb9bcf842a00f5cf6ee8 [formerly 52fba3f6529f7271ed2f3ab3f9c7174acb8276c7] Former-commit-id: 1db89f1ce6fe1d62f73c71baabb01500b9ec0117 Former-commit-id: e9f97aa384c58861f990574c844c6274234e60a2 --- ratelimiter.go | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/ratelimiter.go b/ratelimiter.go index a01e268..35b070f 100755 --- a/ratelimiter.go +++ b/ratelimiter.go @@ -1,9 +1,6 @@ package main -import ( - "fmt" - "time" -) +import "time" var bannedIPs []string @@ -13,7 +10,6 @@ func init() { func clearBannedIPs() { for { - fmt.Println("CLEARING IPS!!") bannedIPs = []string{} time.Sleep(3 * time.Minute) } @@ -23,7 +19,7 @@ func isIPBanned(ip string) bool { if stringInSlice(ip, bannedIPs) { return true } else { - bannedIPs = append(bannedIPs, ip) + bannedIPs = append(bannedIPs, ip) return false } }