Add support for encrypted files
This commit is contained in:
parent
fa04323daf
commit
a9dff6da73
2
go.mod
2
go.mod
@ -21,7 +21,7 @@ require (
|
|||||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e
|
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e
|
||||||
gopkg.in/toast.v1 v1.0.0-20180812000517-0a84660828b2
|
gopkg.in/toast.v1 v1.0.0-20180812000517-0a84660828b2
|
||||||
gopkg.in/yaml.v2 v2.2.8
|
gopkg.in/yaml.v2 v2.2.8
|
||||||
maunium.net/go/mautrix v0.2.0-beta.4.0.20200428185931-73915bafb538
|
maunium.net/go/mautrix v0.2.0-beta.4.0.20200428234424-a14b55c5445f
|
||||||
maunium.net/go/mauview v0.1.0
|
maunium.net/go/mauview v0.1.0
|
||||||
maunium.net/go/tcell v0.1.0
|
maunium.net/go/tcell v0.1.0
|
||||||
)
|
)
|
||||||
|
2
go.sum
2
go.sum
@ -88,6 +88,8 @@ maunium.net/go/mautrix v0.2.0-beta.4.0.20200427215704-fe82e2b914c8 h1:xflYDdpEon
|
|||||||
maunium.net/go/mautrix v0.2.0-beta.4.0.20200427215704-fe82e2b914c8/go.mod h1:SkGZzch8CvU2qKtNpYxtzZ0sQxfVEJ3IsVVLSUBUx9Y=
|
maunium.net/go/mautrix v0.2.0-beta.4.0.20200427215704-fe82e2b914c8/go.mod h1:SkGZzch8CvU2qKtNpYxtzZ0sQxfVEJ3IsVVLSUBUx9Y=
|
||||||
maunium.net/go/mautrix v0.2.0-beta.4.0.20200428185931-73915bafb538 h1:E/6URkgRmxhNid8mA+PV25Bi8F/4Yg5nmsxIi/MWDrU=
|
maunium.net/go/mautrix v0.2.0-beta.4.0.20200428185931-73915bafb538 h1:E/6URkgRmxhNid8mA+PV25Bi8F/4Yg5nmsxIi/MWDrU=
|
||||||
maunium.net/go/mautrix v0.2.0-beta.4.0.20200428185931-73915bafb538/go.mod h1:SkGZzch8CvU2qKtNpYxtzZ0sQxfVEJ3IsVVLSUBUx9Y=
|
maunium.net/go/mautrix v0.2.0-beta.4.0.20200428185931-73915bafb538/go.mod h1:SkGZzch8CvU2qKtNpYxtzZ0sQxfVEJ3IsVVLSUBUx9Y=
|
||||||
|
maunium.net/go/mautrix v0.2.0-beta.4.0.20200428234424-a14b55c5445f h1:kYrIUjr2v6fuVZfs5QnzRJ2YzbZVH21aP77a5ynFHNk=
|
||||||
|
maunium.net/go/mautrix v0.2.0-beta.4.0.20200428234424-a14b55c5445f/go.mod h1:SkGZzch8CvU2qKtNpYxtzZ0sQxfVEJ3IsVVLSUBUx9Y=
|
||||||
maunium.net/go/mauview v0.1.0 h1:x2WdkKI2zdriJuPAB0CKlwmnHGE7W9xfM5z6RgG+IIg=
|
maunium.net/go/mauview v0.1.0 h1:x2WdkKI2zdriJuPAB0CKlwmnHGE7W9xfM5z6RgG+IIg=
|
||||||
maunium.net/go/mauview v0.1.0/go.mod h1:og9WbzmWe9SNYNyOFlCv8qa9zMcOvG2nzRJ5vYyud9U=
|
maunium.net/go/mauview v0.1.0/go.mod h1:og9WbzmWe9SNYNyOFlCv8qa9zMcOvG2nzRJ5vYyud9U=
|
||||||
maunium.net/go/tcell v0.1.0 h1:XzsEoGCvOw5nac+tlkSLzQcliLYTN4PrtA7ar2ptjSM=
|
maunium.net/go/tcell v0.1.0 h1:XzsEoGCvOw5nac+tlkSLzQcliLYTN4PrtA7ar2ptjSM=
|
||||||
|
@ -18,6 +18,7 @@ package ifc
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"maunium.net/go/mautrix"
|
"maunium.net/go/mautrix"
|
||||||
|
"maunium.net/go/mautrix/crypto/attachment"
|
||||||
"maunium.net/go/mautrix/event"
|
"maunium.net/go/mautrix/event"
|
||||||
"maunium.net/go/mautrix/id"
|
"maunium.net/go/mautrix/id"
|
||||||
|
|
||||||
@ -59,8 +60,8 @@ type MatrixContainer interface {
|
|||||||
GetRoom(roomID id.RoomID) *rooms.Room
|
GetRoom(roomID id.RoomID) *rooms.Room
|
||||||
GetOrCreateRoom(roomID id.RoomID) *rooms.Room
|
GetOrCreateRoom(roomID id.RoomID) *rooms.Room
|
||||||
|
|
||||||
Download(uri id.ContentURI) ([]byte, error)
|
Download(uri id.ContentURI, file *attachment.EncryptedFile) ([]byte, error)
|
||||||
DownloadToDisk(uri id.ContentURI, target string) (string, error)
|
DownloadToDisk(uri id.ContentURI, file *attachment.EncryptedFile, target string) (string, error)
|
||||||
GetDownloadURL(uri id.ContentURI) string
|
GetDownloadURL(uri id.ContentURI) string
|
||||||
GetCachePath(uri id.ContentURI) string
|
GetCachePath(uri id.ContentURI) string
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
package matrix
|
package matrix
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/gob"
|
"encoding/gob"
|
||||||
@ -38,6 +37,7 @@ import (
|
|||||||
|
|
||||||
"maunium.net/go/mautrix"
|
"maunium.net/go/mautrix"
|
||||||
"maunium.net/go/mautrix/crypto"
|
"maunium.net/go/mautrix/crypto"
|
||||||
|
"maunium.net/go/mautrix/crypto/attachment"
|
||||||
"maunium.net/go/mautrix/event"
|
"maunium.net/go/mautrix/event"
|
||||||
"maunium.net/go/mautrix/format"
|
"maunium.net/go/mautrix/format"
|
||||||
"maunium.net/go/mautrix/id"
|
"maunium.net/go/mautrix/id"
|
||||||
@ -1061,7 +1061,7 @@ func cp(src, dst string) error {
|
|||||||
return out.Close()
|
return out.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Container) DownloadToDisk(uri id.ContentURI, target string) (fullPath string, err error) {
|
func (c *Container) DownloadToDisk(uri id.ContentURI, file *attachment.EncryptedFile, target string) (fullPath string, err error) {
|
||||||
cachePath := c.GetCachePath(uri)
|
cachePath := c.GetCachePath(uri)
|
||||||
if target == "" {
|
if target == "" {
|
||||||
fullPath = cachePath
|
fullPath = cachePath
|
||||||
@ -1072,21 +1072,27 @@ func (c *Container) DownloadToDisk(uri id.ContentURI, target string) (fullPath s
|
|||||||
}
|
}
|
||||||
|
|
||||||
if _, statErr := os.Stat(cachePath); os.IsNotExist(statErr) {
|
if _, statErr := os.Stat(cachePath); os.IsNotExist(statErr) {
|
||||||
var file *os.File
|
|
||||||
file, err = os.OpenFile(cachePath, os.O_CREATE|os.O_WRONLY, 0600)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
|
|
||||||
var body io.ReadCloser
|
var body io.ReadCloser
|
||||||
body, err = c.client.Download(uri)
|
body, err = c.client.Download(uri)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer body.Close()
|
|
||||||
|
|
||||||
_, err = io.Copy(file, body)
|
var data []byte
|
||||||
|
data, err = ioutil.ReadAll(body)
|
||||||
|
_ = body.Close()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if file != nil {
|
||||||
|
data, err = file.Decrypt(data)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(cachePath, data, 0600)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -1106,7 +1112,7 @@ func (c *Container) DownloadToDisk(uri id.ContentURI, target string) (fullPath s
|
|||||||
// Download fetches the given Matrix content (mxc) URL and returns the data, homeserver, file ID and potential errors.
|
// Download fetches the given Matrix content (mxc) URL and returns the data, homeserver, file ID and potential errors.
|
||||||
//
|
//
|
||||||
// The file will be either read from the media cache (if found) or downloaded from the server.
|
// The file will be either read from the media cache (if found) or downloaded from the server.
|
||||||
func (c *Container) Download(uri id.ContentURI) (data []byte, err error) {
|
func (c *Container) Download(uri id.ContentURI, file *attachment.EncryptedFile) (data []byte, err error) {
|
||||||
cacheFile := c.GetCachePath(uri)
|
cacheFile := c.GetCachePath(uri)
|
||||||
var info os.FileInfo
|
var info os.FileInfo
|
||||||
if info, err = os.Stat(cacheFile); err == nil && !info.IsDir() {
|
if info, err = os.Stat(cacheFile); err == nil && !info.IsDir() {
|
||||||
@ -1116,7 +1122,7 @@ func (c *Container) Download(uri id.ContentURI) (data []byte, err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err = c.download(uri, cacheFile)
|
data, err = c.download(uri, file, cacheFile)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1124,21 +1130,25 @@ func (c *Container) GetDownloadURL(uri id.ContentURI) string {
|
|||||||
return c.client.GetDownloadURL(uri)
|
return c.client.GetDownloadURL(uri)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Container) download(uri id.ContentURI, cacheFile string) (data []byte, err error) {
|
func (c *Container) download(uri id.ContentURI, file *attachment.EncryptedFile, cacheFile string) (data []byte, err error) {
|
||||||
var body io.ReadCloser
|
var body io.ReadCloser
|
||||||
body, err = c.client.Download(uri)
|
body, err = c.client.Download(uri)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer body.Close()
|
|
||||||
|
|
||||||
var buf bytes.Buffer
|
data, err = ioutil.ReadAll(body)
|
||||||
_, err = io.Copy(&buf, body)
|
_ = body.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
data = buf.Bytes()
|
if file != nil {
|
||||||
|
data, err = file.Decrypt(data)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
err = ioutil.WriteFile(cacheFile, data, 0600)
|
err = ioutil.WriteFile(cacheFile, data, 0600)
|
||||||
return
|
return
|
||||||
|
@ -22,7 +22,7 @@ import (
|
|||||||
"image"
|
"image"
|
||||||
"image/color"
|
"image/color"
|
||||||
|
|
||||||
"maunium.net/go/gomuks/matrix/muksevt"
|
"maunium.net/go/mautrix/crypto/attachment"
|
||||||
"maunium.net/go/mautrix/event"
|
"maunium.net/go/mautrix/event"
|
||||||
"maunium.net/go/mautrix/id"
|
"maunium.net/go/mautrix/id"
|
||||||
"maunium.net/go/mauview"
|
"maunium.net/go/mauview"
|
||||||
@ -32,14 +32,19 @@ import (
|
|||||||
"maunium.net/go/gomuks/debug"
|
"maunium.net/go/gomuks/debug"
|
||||||
"maunium.net/go/gomuks/interface"
|
"maunium.net/go/gomuks/interface"
|
||||||
"maunium.net/go/gomuks/lib/ansimage"
|
"maunium.net/go/gomuks/lib/ansimage"
|
||||||
|
"maunium.net/go/gomuks/matrix/muksevt"
|
||||||
"maunium.net/go/gomuks/ui/messages/tstring"
|
"maunium.net/go/gomuks/ui/messages/tstring"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FileMessage struct {
|
type FileMessage struct {
|
||||||
Type event.MessageType
|
Type event.MessageType
|
||||||
Body string
|
Body string
|
||||||
URL id.ContentURI
|
|
||||||
Thumbnail id.ContentURI
|
URL id.ContentURI
|
||||||
|
File *attachment.EncryptedFile
|
||||||
|
Thumbnail id.ContentURI
|
||||||
|
ThumbnailFile *attachment.EncryptedFile
|
||||||
|
|
||||||
imageData []byte
|
imageData []byte
|
||||||
buffer []tstring.TString
|
buffer []tstring.TString
|
||||||
|
|
||||||
@ -49,14 +54,23 @@ type FileMessage struct {
|
|||||||
// NewFileMessage creates a new FileMessage object with the provided values and the default state.
|
// NewFileMessage creates a new FileMessage object with the provided values and the default state.
|
||||||
func NewFileMessage(matrix ifc.MatrixContainer, evt *muksevt.Event, displayname string) *UIMessage {
|
func NewFileMessage(matrix ifc.MatrixContainer, evt *muksevt.Event, displayname string) *UIMessage {
|
||||||
content := evt.Content.AsMessage()
|
content := evt.Content.AsMessage()
|
||||||
url, _ := content.URL.Parse()
|
var file, thumbnailFile *attachment.EncryptedFile
|
||||||
thumbnail, _ := content.GetInfo().ThumbnailURL.Parse()
|
if content.File != nil {
|
||||||
|
file = &content.File.EncryptedFile
|
||||||
|
content.URL = content.File.URL
|
||||||
|
}
|
||||||
|
if content.GetInfo().ThumbnailFile != nil {
|
||||||
|
thumbnailFile = &content.Info.ThumbnailFile.EncryptedFile
|
||||||
|
content.Info.ThumbnailURL = content.Info.ThumbnailFile.URL
|
||||||
|
}
|
||||||
return newUIMessage(evt, displayname, &FileMessage{
|
return newUIMessage(evt, displayname, &FileMessage{
|
||||||
Type: content.MsgType,
|
Type: content.MsgType,
|
||||||
Body: content.Body,
|
Body: content.Body,
|
||||||
URL: url,
|
URL: content.URL,
|
||||||
Thumbnail: thumbnail,
|
File: file,
|
||||||
matrix: matrix,
|
Thumbnail: content.GetInfo().ThumbnailURL,
|
||||||
|
ThumbnailFile: thumbnailFile,
|
||||||
|
matrix: matrix,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,17 +110,20 @@ func (msg *FileMessage) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (msg *FileMessage) DownloadPreview() {
|
func (msg *FileMessage) DownloadPreview() {
|
||||||
url := msg.Thumbnail
|
var url id.ContentURI
|
||||||
if url.IsEmpty() {
|
var file *attachment.EncryptedFile
|
||||||
if msg.Type == event.MsgImage && !msg.URL.IsEmpty() {
|
if !msg.Thumbnail.IsEmpty() {
|
||||||
msg.Thumbnail = msg.URL
|
url = msg.Thumbnail
|
||||||
url = msg.Thumbnail
|
file = msg.ThumbnailFile
|
||||||
} else {
|
} else if msg.Type == event.MsgImage && !msg.URL.IsEmpty() {
|
||||||
return
|
msg.Thumbnail = msg.URL
|
||||||
}
|
url = msg.URL
|
||||||
|
file = msg.File
|
||||||
|
} else {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
debug.Print("Loading file:", url)
|
debug.Print("Loading file:", url)
|
||||||
data, err := msg.matrix.Download(url)
|
data, err := msg.matrix.Download(url, file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
debug.Printf("Failed to download file %s: %v", url, err)
|
debug.Printf("Failed to download file %s: %v", url, err)
|
||||||
return
|
return
|
||||||
|
@ -20,13 +20,13 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"maunium.net/go/gomuks/debug"
|
|
||||||
"maunium.net/go/gomuks/matrix/muksevt"
|
|
||||||
"maunium.net/go/mautrix/event"
|
"maunium.net/go/mautrix/event"
|
||||||
"maunium.net/go/mautrix/id"
|
"maunium.net/go/mautrix/id"
|
||||||
"maunium.net/go/tcell"
|
"maunium.net/go/tcell"
|
||||||
|
|
||||||
|
"maunium.net/go/gomuks/debug"
|
||||||
"maunium.net/go/gomuks/interface"
|
"maunium.net/go/gomuks/interface"
|
||||||
|
"maunium.net/go/gomuks/matrix/muksevt"
|
||||||
"maunium.net/go/gomuks/matrix/rooms"
|
"maunium.net/go/gomuks/matrix/rooms"
|
||||||
"maunium.net/go/gomuks/ui/messages/html"
|
"maunium.net/go/gomuks/ui/messages/html"
|
||||||
"maunium.net/go/gomuks/ui/messages/tstring"
|
"maunium.net/go/gomuks/ui/messages/tstring"
|
||||||
|
@ -26,6 +26,7 @@ import (
|
|||||||
"github.com/kyokomi/emoji"
|
"github.com/kyokomi/emoji"
|
||||||
"github.com/mattn/go-runewidth"
|
"github.com/mattn/go-runewidth"
|
||||||
|
|
||||||
|
"maunium.net/go/mautrix/crypto/attachment"
|
||||||
"maunium.net/go/mauview"
|
"maunium.net/go/mauview"
|
||||||
"maunium.net/go/tcell"
|
"maunium.net/go/tcell"
|
||||||
|
|
||||||
@ -122,6 +123,10 @@ func NewRoomView(parent *MainView, room *rooms.Room) *RoomView {
|
|||||||
SetPressKeyUpAtStartFunc(view.EditPrevious).
|
SetPressKeyUpAtStartFunc(view.EditPrevious).
|
||||||
SetPressKeyDownAtEndFunc(view.EditNext)
|
SetPressKeyDownAtEndFunc(view.EditNext)
|
||||||
|
|
||||||
|
if room.Encrypted {
|
||||||
|
view.input.SetPlaceholder("Send an encrypted message...")
|
||||||
|
}
|
||||||
|
|
||||||
view.topic.
|
view.topic.
|
||||||
SetTextColor(tcell.ColorWhite).
|
SetTextColor(tcell.ColorWhite).
|
||||||
SetBackgroundColor(tcell.ColorDarkGreen)
|
SetBackgroundColor(tcell.ColorDarkGreen)
|
||||||
@ -202,7 +207,7 @@ func (view *RoomView) OnSelect(message *messages.UIMessage) {
|
|||||||
} else if view.selectReason == SelectDownload {
|
} else if view.selectReason == SelectDownload {
|
||||||
path = msg.Body
|
path = msg.Body
|
||||||
}
|
}
|
||||||
go view.Download(msg.URL, path, view.selectReason == SelectOpen)
|
go view.Download(msg.URL, msg.File, path, view.selectReason == SelectOpen)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
view.selecting = false
|
view.selecting = false
|
||||||
@ -624,8 +629,8 @@ func (view *RoomView) InputSubmit(text string) {
|
|||||||
view.SetInputText("")
|
view.SetInputText("")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *RoomView) Download(url id.ContentURI, filename string, openFile bool) {
|
func (view *RoomView) Download(url id.ContentURI, file *attachment.EncryptedFile, filename string, openFile bool) {
|
||||||
path, err := view.parent.matrix.DownloadToDisk(url, filename)
|
path, err := view.parent.matrix.DownloadToDisk(url, file, filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
view.AddServiceMessage(fmt.Sprintf("Failed to download media: %v", err))
|
view.AddServiceMessage(fmt.Sprintf("Failed to download media: %v", err))
|
||||||
view.parent.parent.Render()
|
view.parent.parent.Render()
|
||||||
|
Loading…
Reference in New Issue
Block a user