redact filepath when sending manifests, and add original suggestion for android notifications
This commit is contained in:
parent
f690825c8d
commit
ae075ed3fe
|
@ -329,6 +329,7 @@ const (
|
||||||
SerializedManifest = Field("SerializedManifest")
|
SerializedManifest = Field("SerializedManifest")
|
||||||
TempFile = Field("TempFile")
|
TempFile = Field("TempFile")
|
||||||
FilePath = Field("FilePath")
|
FilePath = Field("FilePath")
|
||||||
|
NameSuggestion = Field("NameSuggestion")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Defining Common errors
|
// Defining Common errors
|
||||||
|
|
|
@ -81,7 +81,10 @@ func (f *Functionality) ShareFile(filepath string, profile peer.CwtchPeer, handl
|
||||||
|
|
||||||
// Store the size of the manifest (in chunks) as part of the public scope so contacts who we share the file with
|
// Store the size of the manifest (in chunks) as part of the public scope so contacts who we share the file with
|
||||||
// can fetch the manifest as if it were a file.
|
// can fetch the manifest as if it were a file.
|
||||||
profile.SetAttribute(attr.GetPublicScope(fmt.Sprintf("%s.manifest.size", key)), strconv.Itoa(int(math.Ceil(float64(len(serializedManifest))/float64(files.DefaultChunkSize)))))
|
// manifest.FileName gets redacted in filesharing_subsystem (to remove the system-specific file hierarchy),
|
||||||
|
// but we need to *store* the full path because the sender also uses it to locate the file
|
||||||
|
lenDiff := len(filepath) - len(path.Base(filepath))
|
||||||
|
profile.SetAttribute(attr.GetPublicScope(fmt.Sprintf("%s.manifest.size", key)), strconv.Itoa(int(math.Ceil(float64(len(serializedManifest)-lenDiff)/float64(files.DefaultChunkSize)))))
|
||||||
|
|
||||||
profile.ShareFile(key, string(serializedManifest))
|
profile.ShareFile(key, string(serializedManifest))
|
||||||
|
|
||||||
|
|
|
@ -846,6 +846,7 @@ func (cp *cwtchPeer) eventHandler() {
|
||||||
var manifest files.Manifest
|
var manifest files.Manifest
|
||||||
err := json.Unmarshal([]byte(serializedManifest), &manifest)
|
err := json.Unmarshal([]byte(serializedManifest), &manifest)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
manifest.Title = manifest.FileName
|
||||||
manifest.FileName = downloadFilePath
|
manifest.FileName = downloadFilePath
|
||||||
log.Debugf("saving manifest")
|
log.Debugf("saving manifest")
|
||||||
err = manifest.Save(manifestFilePath)
|
err = manifest.Save(manifestFilePath)
|
||||||
|
@ -862,6 +863,7 @@ func (cp *cwtchPeer) eventHandler() {
|
||||||
event.Handle: handle,
|
event.Handle: handle,
|
||||||
event.SerializedManifest: string(manifest.Serialize()),
|
event.SerializedManifest: string(manifest.Serialize()),
|
||||||
event.TempFile: tempFile,
|
event.TempFile: tempFile,
|
||||||
|
event.NameSuggestion: manifest.Title,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -214,10 +214,11 @@ func (e *engine) eventHandler() {
|
||||||
key := ev.Data[event.FileKey]
|
key := ev.Data[event.FileKey]
|
||||||
serializedManifest := ev.Data[event.SerializedManifest]
|
serializedManifest := ev.Data[event.SerializedManifest]
|
||||||
tempFile := ev.Data[event.TempFile]
|
tempFile := ev.Data[event.TempFile]
|
||||||
|
title := ev.Data[event.NameSuggestion]
|
||||||
// NOTE: for now there will probably only ever be a single chunk request. When we enable group
|
// NOTE: for now there will probably only ever be a single chunk request. When we enable group
|
||||||
// sharing and rehosting then this loop will serve as a a way of splitting the request among multiple
|
// sharing and rehosting then this loop will serve as a a way of splitting the request among multiple
|
||||||
// contacts
|
// contacts
|
||||||
for _, message := range e.filesharingSubSystem.CompileChunkRequests(key, serializedManifest, tempFile) {
|
for _, message := range e.filesharingSubSystem.CompileChunkRequests(key, serializedManifest, tempFile, title) {
|
||||||
if err := e.sendPeerMessage(handle, message); err != nil {
|
if err := e.sendPeerMessage(handle, message); err != nil {
|
||||||
e.eventManager.Publish(event.NewEvent(event.SendMessageToPeerError, map[event.Field]string{event.RemotePeer: ev.Data[event.RemotePeer], event.EventID: ev.EventID, event.Error: err.Error()}))
|
e.eventManager.Publish(event.NewEvent(event.SendMessageToPeerError, map[event.Field]string{event.RemotePeer: ev.Data[event.RemotePeer], event.EventID: ev.EventID, event.Error: err.Error()}))
|
||||||
}
|
}
|
||||||
|
@ -566,9 +567,9 @@ func (e *engine) handlePeerMessage(hostname string, eventID string, context stri
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if context == event.ContextSendFile {
|
} else if context == event.ContextSendFile {
|
||||||
fileKey, progress, totalChunks, _ := e.filesharingSubSystem.ProcessChunk(eventID, message)
|
fileKey, progress, totalChunks, _, title := e.filesharingSubSystem.ProcessChunk(eventID, message)
|
||||||
if len(fileKey) != 0 {
|
if len(fileKey) != 0 {
|
||||||
e.eventManager.Publish(event.NewEvent(event.FileDownloadProgressUpdate, map[event.Field]string{event.FileKey: fileKey, event.Progress: strconv.Itoa(int(progress)), event.FileSizeInChunks: strconv.Itoa(int(totalChunks))}))
|
e.eventManager.Publish(event.NewEvent(event.FileDownloadProgressUpdate, map[event.Field]string{event.FileKey: fileKey, event.Progress: strconv.Itoa(int(progress)), event.FileSizeInChunks: strconv.Itoa(int(totalChunks)), event.NameSuggestion: title}))
|
||||||
if progress == totalChunks {
|
if progress == totalChunks {
|
||||||
if tempFile, filePath, success := e.filesharingSubSystem.VerifyFile(fileKey); success {
|
if tempFile, filePath, success := e.filesharingSubSystem.VerifyFile(fileKey); success {
|
||||||
log.Debugf("file verified and downloaded!")
|
log.Debugf("file verified and downloaded!")
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"path"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -50,12 +51,13 @@ func (fsss *FileSharingSubSystem) FetchManifest(fileKey string, manifestSize uin
|
||||||
|
|
||||||
// CompileChunkRequests takes in a complete serializedManifest and returns a set of chunk request messages
|
// CompileChunkRequests takes in a complete serializedManifest and returns a set of chunk request messages
|
||||||
// TODO in the future we will want this to return the handles of contacts to request chunks from
|
// TODO in the future we will want this to return the handles of contacts to request chunks from
|
||||||
func (fsss *FileSharingSubSystem) CompileChunkRequests(fileKey, serializedManifest, tempFile string) []model.PeerMessage {
|
func (fsss *FileSharingSubSystem) CompileChunkRequests(fileKey, serializedManifest, tempFile, title string) []model.PeerMessage {
|
||||||
var manifest Manifest
|
var manifest Manifest
|
||||||
err := json.Unmarshal([]byte(serializedManifest), &manifest)
|
err := json.Unmarshal([]byte(serializedManifest), &manifest)
|
||||||
var messages []model.PeerMessage
|
var messages []model.PeerMessage
|
||||||
if err == nil {
|
if err == nil {
|
||||||
manifest.TempFileName = tempFile
|
manifest.TempFileName = tempFile
|
||||||
|
manifest.Title = title
|
||||||
err := manifest.PrepareDownload()
|
err := manifest.PrepareDownload()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
fsss.activeDownloads.Store(fileKey, &manifest)
|
fsss.activeDownloads.Store(fileKey, &manifest)
|
||||||
|
@ -78,9 +80,18 @@ func (fsss *FileSharingSubSystem) RequestManifestParts(fileKey string) []model.P
|
||||||
manifestI, exists := fsss.activeShares.Load(fileKey)
|
manifestI, exists := fsss.activeShares.Load(fileKey)
|
||||||
var messages []model.PeerMessage
|
var messages []model.PeerMessage
|
||||||
if exists {
|
if exists {
|
||||||
manifest := manifestI.(*Manifest)
|
oldManifest := manifestI.(*Manifest)
|
||||||
|
serializedOldManifest := oldManifest.Serialize()
|
||||||
|
log.Debugf("found serialized manifest: %s", serializedOldManifest)
|
||||||
|
|
||||||
|
// copy so we dont get threading issues by modifying the original
|
||||||
|
// and then redact the file path before sending
|
||||||
|
// nb: manifest.size has already been corrected elsewhere
|
||||||
|
var manifest Manifest
|
||||||
|
json.Unmarshal([]byte(serializedOldManifest), &manifest)
|
||||||
|
manifest.FileName = path.Base(manifest.FileName)
|
||||||
serializedManifest := manifest.Serialize()
|
serializedManifest := manifest.Serialize()
|
||||||
log.Debugf("found serialized manifest: %s", serializedManifest)
|
|
||||||
chunkID := 0
|
chunkID := 0
|
||||||
for i := 0; i < len(serializedManifest); i += DefaultChunkSize {
|
for i := 0; i < len(serializedManifest); i += DefaultChunkSize {
|
||||||
offset := i
|
offset := i
|
||||||
|
@ -173,7 +184,7 @@ func (fsss *FileSharingSubSystem) ProcessChunkRequest(fileKey string, serialized
|
||||||
// Always return the progress of a matched download if it exists along with the total number of chunks and the
|
// Always return the progress of a matched download if it exists along with the total number of chunks and the
|
||||||
// given chunk ID
|
// given chunk ID
|
||||||
// If not such active download exists then return an empty file key and ignore all further processing.
|
// If not such active download exists then return an empty file key and ignore all further processing.
|
||||||
func (fsss *FileSharingSubSystem) ProcessChunk(chunkKey string, chunk []byte) (fileKey string, progress uint64, totalChunks uint64, chunkID uint64) {
|
func (fsss *FileSharingSubSystem) ProcessChunk(chunkKey string, chunk []byte) (fileKey string, progress uint64, totalChunks uint64, chunkID uint64, title string) {
|
||||||
fileKeyParts := strings.Split(chunkKey, ".")
|
fileKeyParts := strings.Split(chunkKey, ".")
|
||||||
log.Debugf("got chunk for %s", fileKeyParts)
|
log.Debugf("got chunk for %s", fileKeyParts)
|
||||||
if len(fileKeyParts) == 3 { // fileKey is rootHash.nonce.chunk
|
if len(fileKeyParts) == 3 { // fileKey is rootHash.nonce.chunk
|
||||||
|
@ -181,16 +192,18 @@ func (fsss *FileSharingSubSystem) ProcessChunk(chunkKey string, chunk []byte) (f
|
||||||
fileKey = fmt.Sprintf("%s.%s", fileKeyParts[0], fileKeyParts[1])
|
fileKey = fmt.Sprintf("%s.%s", fileKeyParts[0], fileKeyParts[1])
|
||||||
derivedChunkID, err := strconv.Atoi(fileKeyParts[2])
|
derivedChunkID, err := strconv.Atoi(fileKeyParts[2])
|
||||||
if err == nil {
|
if err == nil {
|
||||||
log.Debugf("got chunk id %d", chunkID)
|
|
||||||
chunkID = uint64(derivedChunkID)
|
chunkID = uint64(derivedChunkID)
|
||||||
|
log.Debugf("got chunk id %d", chunkID)
|
||||||
manifestI, exists := fsss.activeDownloads.Load(fileKey)
|
manifestI, exists := fsss.activeDownloads.Load(fileKey)
|
||||||
if exists {
|
if exists {
|
||||||
manifest := manifestI.(*Manifest)
|
manifest := manifestI.(*Manifest)
|
||||||
totalChunks = uint64(len(manifest.Chunks))
|
totalChunks = uint64(len(manifest.Chunks))
|
||||||
|
title = manifest.Title
|
||||||
log.Debugf("found active manifest %v", manifest)
|
log.Debugf("found active manifest %v", manifest)
|
||||||
progress, err = manifest.StoreChunk(chunkID, chunk)
|
progress, err = manifest.StoreChunk(chunkID, chunk)
|
||||||
log.Debugf("attempts to store chunk %v %v", progress, err)
|
log.Debugf("attempts to store chunk %v %v", progress, err)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debugf("error storing chunk: %v", err)
|
||||||
// malicious contacts who share conversations can share random chunks
|
// malicious contacts who share conversations can share random chunks
|
||||||
// these will not match the chunk hash and as such will fail.
|
// these will not match the chunk hash and as such will fail.
|
||||||
// at this point we can't differentiate between a malicious chunk and failure to store a
|
// at this point we can't differentiate between a malicious chunk and failure to store a
|
||||||
|
|
|
@ -35,6 +35,7 @@ type Manifest struct {
|
||||||
FileSizeInBytes uint64
|
FileSizeInBytes uint64
|
||||||
ChunkSizeInBytes uint64
|
ChunkSizeInBytes uint64
|
||||||
TempFileName string `json:"-"`
|
TempFileName string `json:"-"`
|
||||||
|
Title string `json:"-"`
|
||||||
|
|
||||||
chunkComplete []bool
|
chunkComplete []bool
|
||||||
openFd *os.File
|
openFd *os.File
|
||||||
|
@ -45,7 +46,6 @@ type Manifest struct {
|
||||||
// CreateManifest takes in a file path and constructs a file sharing manifest of hashes along with
|
// CreateManifest takes in a file path and constructs a file sharing manifest of hashes along with
|
||||||
// other information necessary to download, reconstruct and verify the file.
|
// other information necessary to download, reconstruct and verify the file.
|
||||||
func CreateManifest(path string) (*Manifest, error) {
|
func CreateManifest(path string) (*Manifest, error) {
|
||||||
|
|
||||||
// Process file into Chunks
|
// Process file into Chunks
|
||||||
f, err := os.Open(path)
|
f, err := os.Open(path)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue