aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFChannel <>2021-07-22 19:03:28 -0700
committerFChannel <>2021-07-22 19:03:28 -0700
commit16b4165e5102fc9b4766e1bd1204ca9cf23199aa (patch)
tree0a491330799a37558a4d85648f29c45b5311ef59
parent213683bf7245a05aa734ac2bb26fba60705ba5ee (diff)
added banning media by saving hash in database
-rw-r--r--client.go2
-rw-r--r--databaseschema.psql7
-rw-r--r--main.go107
-rw-r--r--outboxPost.go41
-rw-r--r--static/posts.html9
5 files changed, 149 insertions, 17 deletions
diff --git a/client.go b/client.go
index f47ca52..002fc40 100644
--- a/client.go
+++ b/client.go
@@ -641,7 +641,7 @@ func MediaProxy(url string) string {
func ParseContent(db *sql.DB, board Actor, op string, content string, thread ObjectBase) template.HTML {
var nContent = content
- re := regexp.MustCompile(`(>>https?://[A-Za-z0-9_.\-~]+\/[A-Za-z0-9_.\-~]+\/\w+)`)
+ re := regexp.MustCompile(`(>>https?://[A-Za-z0-9_.:\-~]+\/[A-Za-z0-9_.\-~]+\/\w+)`)
match := re.FindAllStringSubmatch(nContent, -1)
//add url to each matched reply
diff --git a/databaseschema.psql b/databaseschema.psql
index 954aa2e..67681cd 100644
--- a/databaseschema.psql
+++ b/databaseschema.psql
@@ -232,4 +232,9 @@ id serial primary key,
regex varchar(200)
);
-ALTER TABLE actor ADD COLUMN IF NOT EXISTS autosubscribe boolean default false; \ No newline at end of file
+ALTER TABLE actor ADD COLUMN IF NOT EXISTS autosubscribe boolean default false;
+
+CREATE TABLE IF NOT EXISTS bannedmedia(
+id serial primary key,
+hash varchar(200)
+); \ No newline at end of file
diff --git a/main.go b/main.go
index 9ef9873..f219a2d 100644
--- a/main.go
+++ b/main.go
@@ -272,7 +272,7 @@ func main() {
auth := CreateTripCode(verify.Code)
auth = CreateTripCode(auth)
-
+
if CreateTripCode(auth) == code {
w.WriteHeader(http.StatusOK)
} else {
@@ -336,8 +336,8 @@ func main() {
}
if(r.FormValue("inReplyTo") == "" && file == nil) {
- w.Write([]byte("Media is required for new posts"))
- return
+ w.Write([]byte("Media is required for new posts"))
+ return
}
@@ -502,7 +502,7 @@ func main() {
}
}
- //follow all of boards followers
+ //follow all of boards followers
} else if followers.MatchString(follow){
followersActor := FingerActor(follow)
col := GetActorCollection(followersActor.Followers)
@@ -521,7 +521,7 @@ func main() {
}
}
- //do a normal follow to a single board
+ //do a normal follow to a single board
} else {
followActivity := MakeFollowActivity(db, actorId, follow)
@@ -603,7 +603,7 @@ func main() {
} else if admin || actor.Id == Domain {
t := template.Must(template.New("").Funcs(template.FuncMap{
"sub": func (i, j int) int { return i - j }}).ParseFiles("./static/main.html", "./static/nadmin.html"))
-
+
actor := GetActor(Domain)
follow := GetActorCollection(actor.Following).Items
follower := GetActorCollection(actor.Followers).Items
@@ -771,7 +771,91 @@ func main() {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("404 no path"))
}
- })
+ })
+
+ http.HandleFunc("/banmedia", func(w http.ResponseWriter, r *http.Request) {
+ id := r.URL.Query().Get("id")
+ board := r.URL.Query().Get("board")
+
+ _, auth := GetPasswordFromSession(r)
+
+ if id == "" || auth == "" {
+ w.WriteHeader(http.StatusBadRequest)
+ w.Write([]byte(""))
+ return
+ }
+
+ col := GetCollectionFromID(id)
+
+ if len(col.OrderedItems) > 0 {
+
+ actor := col.OrderedItems[0].Actor
+
+ if !HasAuth(db, auth, actor) {
+ w.WriteHeader(http.StatusBadRequest)
+ w.Write([]byte(""))
+ return
+ }
+
+ if len(col.OrderedItems[0].Attachment) > 0 {
+ re := regexp.MustCompile(Domain)
+ file := re.ReplaceAllString(col.OrderedItems[0].Attachment[0].Href, "")
+
+ f, err := os.Open("." + file)
+ CheckError(err, "could not open attachment for ban media")
+
+ defer f.Close()
+ bytes, err := ioutil.ReadAll(f)
+ CheckError(err, "could not get attachment bytes for ban media")
+
+ if !IsMediaBanned(db, f) {
+ query := `insert into bannedmedia (hash) values ($1)`
+
+ _, err := db.Exec(query, HashBytes(bytes))
+
+ CheckError(err, "error inserting banend media into db")
+
+ }
+
+ var obj ObjectBase
+ obj.Id = id
+ obj.Actor = actor
+
+ isOP := CheckIfObjectOP(db, obj.Id)
+
+ var OP string
+ if len(col.OrderedItems[0].InReplyTo) > 0 {
+ OP = col.OrderedItems[0].InReplyTo[0].Id
+ }
+
+ if !isOP {
+ TombstoneObject(db, id)
+ } else {
+ TombstoneObjectAndReplies(db, id)
+ }
+
+ if IsIDLocal(db, id){
+ go DeleteObjectRequest(db, id)
+ }
+
+
+ if !isOP {
+ if (!IsIDLocal(db, id)){
+ http.Redirect(w, r, "/" + board + "/" + remoteShort(OP), http.StatusSeeOther)
+ return
+ } else {
+ http.Redirect(w, r, OP, http.StatusSeeOther)
+ return
+ }
+ } else {
+ http.Redirect(w, r, "/" + board, http.StatusSeeOther)
+ return
+ }
+ }
+ }
+ w.WriteHeader(http.StatusBadRequest)
+ w.Write([]byte(""))
+ })
http.HandleFunc("/delete", func(w http.ResponseWriter, r *http.Request){
id := r.URL.Query().Get("id")
@@ -1377,7 +1461,6 @@ func CreateTripCode(input string) string {
return code[0]
}
-
func GetActorFromPath(db *sql.DB, location string, prefix string) Actor {
pattern := fmt.Sprintf("%s([^/\n]+)(/.+)?", prefix)
re := regexp.MustCompile(pattern)
@@ -1891,7 +1974,7 @@ func MakeCaptchas(db *sql.DB, total int) {
}
func GetFileContentType(out multipart.File) (string, error) {
-
+
buffer := make([]byte, 512)
_, err := out.Read(buffer)
@@ -2697,6 +2780,12 @@ func HashMedia(media string) string {
return hex.EncodeToString(h.Sum(nil))
}
+func HashBytes(media []byte) string {
+ h:= sha256.New()
+ h.Write(media)
+ return hex.EncodeToString(h.Sum(nil))
+}
+
func RouteImages(w http.ResponseWriter, media string) {
req, err := http.NewRequest("GET", MediaHashs[media], nil)
diff --git a/outboxPost.go b/outboxPost.go
index 356647e..a827e21 100644
--- a/outboxPost.go
+++ b/outboxPost.go
@@ -7,6 +7,7 @@ import _ "github.com/lib/pq"
import "encoding/json"
import "reflect"
import "io/ioutil"
+import "mime/multipart"
import "os"
import "regexp"
import "strings"
@@ -24,6 +25,8 @@ func ParseOutboxRequest(w http.ResponseWriter, r *http.Request, db *sql.DB) {
r.ParseMultipartForm(5 << 20)
if(BoardHasAuthType(db, actor.Name, "captcha") && CheckCaptcha(db, r.FormValue("captcha"))) {
f, header, _ := r.FormFile("file")
+ defer f.Close()
+
if(header != nil) {
if(header.Size > (7 << 20)){
w.WriteHeader(http.StatusRequestEntityTooLarge)
@@ -31,6 +34,12 @@ func ParseOutboxRequest(w http.ResponseWriter, r *http.Request, db *sql.DB) {
return
}
+ if(IsMediaBanned(db, f)) {
+ fmt.Println("media banned")
+ http.Redirect(w, r, Domain, http.StatusSeeOther)
+ return
+ }
+
contentType, _ := GetFileContentType(f)
if(!SupportedMIMEType(contentType)) {
@@ -39,7 +48,7 @@ func ParseOutboxRequest(w http.ResponseWriter, r *http.Request, db *sql.DB) {
return
}
}
-
+
var nObj = CreateObject("Note")
nObj = ObjectFromForm(r, db, nObj)
@@ -339,7 +348,6 @@ func ObjectFromForm(r *http.Request, db *sql.DB, obj ObjectBase) ObjectBase {
err := cmd.Run()
CheckError(err, "error with removing exif data from image")
-
}
obj.Preview = CreatePreviewObject(obj.Attachment[0])
@@ -617,3 +625,32 @@ func MakeActivityFollowingReq(w http.ResponseWriter, r *http.Request, activity A
return false
}
+
+func IsMediaBanned(db *sql.DB, f multipart.File) bool {
+ f.Seek(0, 0)
+
+ fileBytes, _ := ioutil.ReadAll(f)
+
+ hash := HashBytes(fileBytes)
+
+ f.Seek(0, 0)
+
+ query := `select hash from bannedmedia where hash=$1`
+
+ rows, err := db.Query(query, hash)
+
+ CheckError(err, "could not get hash from banned media in db")
+
+ var h string
+
+ defer rows.Close()
+
+ rows.Next()
+ rows.Scan(&h)
+
+ if h == hash {
+ return true
+ }
+
+ return false
+}
diff --git a/static/posts.html b/static/posts.html
index b638a10..d7f46b9 100644
--- a/static/posts.html
+++ b/static/posts.html
@@ -12,7 +12,8 @@
<a href="/delete?id={{ .Id }}&board={{ $board.Actor.Name }}">[Delete Post]</a>
{{ end }}
{{ if .Attachment }}
- {{ if eq $board.ModCred $board.Domain $board.Actor.Id }}
+ {{ if eq $board.ModCred $board.Domain $board.Actor.Id }}
+ <a href="/banmedia?id={{ .Id }}&board={{ $board.Actor.Name }}">[Ban Media]</a>
<a href="/deleteattach?id={{ .Id }}&board={{ $board.Actor.Name }}">[Delete Attachment]</a>
<a href="/marksensitive?id={{ .Id }}&board={{ $board.Actor.Name }}">[Mark Sensitive]</a>
{{ end }}
@@ -41,7 +42,6 @@
sensitive.style = "display: block"
media.style = "display: none;"
}
-
</script>
{{ end }}
<span style="color: #0f0c5d;"><b>{{ .Name }}</b></span><span style="color: #117743;"><b>{{ if .AttributedTo }} {{.AttributedTo }} {{ else }} Anonymous {{ end }}</b></span><span class="tripcode"> {{ .TripCode }} </span><span>{{ .Published }} <a id="{{ .Id }}-anchor" href="/{{ $board.Name }}/{{ short $board.Actor.Outbox $opId }}#{{ short $board.Actor.Outbox .Id }}">No.</a> <a id="{{ .Id }}-link" title="{{ .Id }}" href="javascript:quote('{{ $board.Actor.Id }}', '{{ $opId }}', '{{ .Id }}')">{{ short $board.Actor.Outbox .Id }}</a> {{ if ne .Type "Tombstone" }}<a href="javascript:report('{{ $board.Actor.Id }}', '{{ .Id }}')">[Report]</a>{{ end }}</span>
@@ -62,9 +62,10 @@
<a href="/delete?id={{ .Id }}&board={{ $board.Actor.Name }}">[Delete Post]</a>
{{ end }}
{{ if .Attachment }}
- {{ if eq $board.ModCred $board.Domain $board.Actor.Id }}
+ {{ if eq $board.ModCred $board.Domain $board.Actor.Id }}
+ <a href="/banmedia?id={{ .Id }}&board={{ $board.Actor.Name }}">[Ban Media]</a>
<a href="/deleteattach?id={{ .Id }}&board={{ $board.Actor.Name }}">[Delete Attachment]</a>
- <a href="/marksensitive?id={{ .Id }}&board={{ $board.Actor.Name }}">[Mark Sensitive]</a>
+ <a href="/marksensitive?id={{ .Id }}&board={{ $board.Actor.Name }}">[Mark Sensitive]</a>
{{ end }}
<span style="display: block;">File <a id="{{ .Id }}-img" href="{{ proxy (index .Attachment 0).Href}}">{{ (index .Attachment 0).Name }}</a> <span id="{{ .Id }}-size">({{ (index .Attachment 0).Size }})</span></span>
<div id="hide-{{ .Id }}" style="display: none;">[Hide]</div>