Merge pull request 'Verify File Manifest Prior to Profile Images Downloads (+remove Android specific checks)' (#506) from code-fixes into master
continuous-integration/drone/push Build is pending
Details
continuous-integration/drone/push Build is pending
Details
Reviewed-on: #506 Reviewed-by: Dan Ballard <dan@openprivacy.ca>
This commit is contained in:
commit
3967cceb83
|
@ -181,17 +181,24 @@ func (om *OverlayMessage) ShouldAutoDL() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Functionality) VerifyOrResumeDownload(profile peer.CwtchPeer, conversation int, fileKey string) {
|
func (f *Functionality) VerifyOrResumeDownload(profile peer.CwtchPeer, conversation int, fileKey string, size uint64) error {
|
||||||
if manifestFilePath, exists := profile.GetScopedZonedAttribute(attr.LocalScope, attr.FilesharingZone, fmt.Sprintf("%s.manifest", fileKey)); exists {
|
if manifestFilePath, exists := profile.GetScopedZonedAttribute(attr.LocalScope, attr.FilesharingZone, fmt.Sprintf("%s.manifest", fileKey)); exists {
|
||||||
if downloadfilepath, exists := profile.GetScopedZonedAttribute(attr.LocalScope, attr.FilesharingZone, fmt.Sprintf("%s.path", fileKey)); exists {
|
if downloadfilepath, exists := profile.GetScopedZonedAttribute(attr.LocalScope, attr.FilesharingZone, fmt.Sprintf("%s.path", fileKey)); exists {
|
||||||
log.Debugf("resuming %s", fileKey)
|
manifest, err := files.LoadManifest(manifestFilePath)
|
||||||
f.DownloadFile(profile, conversation, downloadfilepath, manifestFilePath, fileKey, files.MaxManifestSize*files.DefaultChunkSize)
|
if err == nil {
|
||||||
} else {
|
// Assert the filename...this is technically not necessary, but is here for completeness
|
||||||
log.Errorf("found manifest path but not download path for %s", fileKey)
|
manifest.FileName = downloadfilepath
|
||||||
|
if manifest.VerifyFile() == nil {
|
||||||
|
// File is verified and there is nothing else to do...
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
// Kick off another Download...
|
||||||
|
return f.DownloadFile(profile, conversation, downloadfilepath, manifestFilePath, fileKey, size)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
log.Errorf("no stored manifest path found for %s", fileKey)
|
|
||||||
}
|
}
|
||||||
|
return errors.New("file download metadata does not exist, or is corrupted")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Functionality) CheckDownloadStatus(profile peer.CwtchPeer, fileKey string) {
|
func (f *Functionality) CheckDownloadStatus(profile peer.CwtchPeer, fileKey string) {
|
||||||
|
@ -254,18 +261,16 @@ func (f *Functionality) DownloadFile(profile peer.CwtchPeer, conversationID int,
|
||||||
return errors.New("download path or manifest path is empty")
|
return errors.New("download path or manifest path is empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
// We write to a temp file for Android...
|
// Don't download files if the download file directory does not exist
|
||||||
if runtime.GOOS != "android" {
|
if _, err := os.Stat(path.Dir(downloadFilePath)); os.IsNotExist(err) {
|
||||||
// Don't download files if the download file directory does not exist
|
return errors.New("download directory does not exist")
|
||||||
if _, err := os.Stat(path.Dir(downloadFilePath)); os.IsNotExist(err) {
|
|
||||||
return errors.New("download directory does not exist")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't download files if the manifest file directory does not exist
|
|
||||||
if _, err := os.Stat(path.Dir(manifestFilePath)); os.IsNotExist(err) {
|
|
||||||
return errors.New("manifest directory does not exist")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Don't download files if the manifest file directory does not exist
|
||||||
|
if _, err := os.Stat(path.Dir(manifestFilePath)); os.IsNotExist(err) {
|
||||||
|
return errors.New("manifest directory does not exist")
|
||||||
|
}
|
||||||
|
|
||||||
// Store local.filesharing.filekey.manifest as the location of the manifest
|
// Store local.filesharing.filekey.manifest as the location of the manifest
|
||||||
profile.SetScopedZonedAttribute(attr.LocalScope, attr.FilesharingZone, fmt.Sprintf("%s.manifest", key), manifestFilePath)
|
profile.SetScopedZonedAttribute(attr.LocalScope, attr.FilesharingZone, fmt.Sprintf("%s.manifest", key), manifestFilePath)
|
||||||
|
|
||||||
|
|
|
@ -89,26 +89,32 @@ func (i *ImagePreviewsFunctionality) OnContactRequestValue(profile peer.CwtchPee
|
||||||
func (i *ImagePreviewsFunctionality) OnContactReceiveValue(profile peer.CwtchPeer, conversation model.Conversation, path attr.ScopedZonedPath, value string, exists bool) {
|
func (i *ImagePreviewsFunctionality) OnContactReceiveValue(profile peer.CwtchPeer, conversation model.Conversation, path attr.ScopedZonedPath, value string, exists bool) {
|
||||||
if profile.IsFeatureEnabled(constants.FileSharingExperiment) && profile.IsFeatureEnabled(constants.ImagePreviewsExperiment) {
|
if profile.IsFeatureEnabled(constants.FileSharingExperiment) && profile.IsFeatureEnabled(constants.ImagePreviewsExperiment) {
|
||||||
_, zone, path := path.GetScopeZonePath()
|
_, zone, path := path.GetScopeZonePath()
|
||||||
if zone == attr.ProfileZone && path == constants.CustomProfileImageKey {
|
if exists && zone == attr.ProfileZone && path == constants.CustomProfileImageKey {
|
||||||
fileKey := value
|
// We only download from accepted conversations
|
||||||
|
|
||||||
if conversation.Accepted {
|
if conversation.Accepted {
|
||||||
fsf := FunctionalityGate()
|
fileKey := value
|
||||||
basepath := i.downloadFolder
|
basepath := i.downloadFolder
|
||||||
|
fsf := FunctionalityGate()
|
||||||
|
// We always overwrite profile image files...
|
||||||
fp, mp := GenerateDownloadPath(basepath, fileKey, true)
|
fp, mp := GenerateDownloadPath(basepath, fileKey, true)
|
||||||
|
|
||||||
|
// If we have marked this file as complete...
|
||||||
if value, exists := profile.GetScopedZonedAttribute(attr.LocalScope, attr.FilesharingZone, fmt.Sprintf("%s.complete", fileKey)); exists && value == event.True {
|
if value, exists := profile.GetScopedZonedAttribute(attr.LocalScope, attr.FilesharingZone, fmt.Sprintf("%s.complete", fileKey)); exists && value == event.True {
|
||||||
if _, err := os.Stat(fp); err == nil {
|
if _, err := os.Stat(fp); err == nil {
|
||||||
// file is marked as completed downloaded and exists...
|
// file is marked as completed downloaded and exists...
|
||||||
} else {
|
if fsf.VerifyOrResumeDownload(profile, conversation.ID, fileKey, constants.ImagePreviewMaxSizeInBytes) == nil {
|
||||||
// the user probably deleted the file, mark completed as false...
|
return
|
||||||
profile.SetScopedZonedAttribute(attr.LocalScope, attr.FilesharingZone, fmt.Sprintf("%s.complete", fileKey), event.False)
|
}
|
||||||
|
// Otherwise we fall through...
|
||||||
}
|
}
|
||||||
|
// Something went wrong...the file is marked as complete but either doesn't exist, or is corrupted such that we can't continue...
|
||||||
|
// So mark complete as false...
|
||||||
|
profile.SetScopedZonedAttribute(attr.LocalScope, attr.FilesharingZone, fmt.Sprintf("%s.complete", fileKey), event.False)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we have reached this point then we need to download the file again...
|
||||||
log.Debugf("Downloading Profile Image %v %v %v", fp, mp, fileKey)
|
log.Debugf("Downloading Profile Image %v %v %v", fp, mp, fileKey)
|
||||||
// ev.Event.Data[event.FilePath] = fp
|
fsf.DownloadFile(profile, conversation.ID, fp, mp, fileKey, constants.ImagePreviewMaxSizeInBytes)
|
||||||
fsf.DownloadFile(profile, conversation.ID, fp, mp, value, constants.ImagePreviewMaxSizeInBytes)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -265,12 +265,21 @@ func (e *engine) eventHandler() {
|
||||||
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]
|
title := ev.Data[event.NameSuggestion]
|
||||||
// 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
|
// Another optimistic check here. Technically Cwtch profile should not request manifest on a download files
|
||||||
// contacts
|
// but if they do then we should check if it exists up front. If it does then announce that the download
|
||||||
for _, message := range e.filesharingSubSystem.CompileChunkRequests(key, serializedManifest, tempFile, title) {
|
// is complete.
|
||||||
if err := e.sendPeerMessage(handle, message); err != nil {
|
if _, filePath, success := e.filesharingSubSystem.VerifyFile(key); success {
|
||||||
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()}))
|
log.Debugf("file verified and downloaded!")
|
||||||
|
e.eventManager.Publish(event.NewEvent(event.FileDownloaded, map[event.Field]string{event.FileKey: key, event.FilePath: filePath, event.TempFile: tempFile}))
|
||||||
|
} else {
|
||||||
|
// 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
|
||||||
|
// contacts
|
||||||
|
for _, message := range e.filesharingSubSystem.CompileChunkRequests(key, serializedManifest, tempFile, title) {
|
||||||
|
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()}))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case event.ProtocolEngineShutdown:
|
case event.ProtocolEngineShutdown:
|
||||||
|
|
|
@ -231,7 +231,7 @@ func (m *Manifest) GetChunkRequest() ChunkSpec {
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrepareDownload creates an empty file of the expected size of the file described by the manifest
|
// PrepareDownload creates an empty file of the expected size of the file described by the manifest
|
||||||
// If the file already exists it assume it is the correct file and that it is resuming from when it left off.
|
// If the file already exists it assumes it is the correct file and that it is resuming from when it left off.
|
||||||
func (m *Manifest) PrepareDownload() error {
|
func (m *Manifest) PrepareDownload() error {
|
||||||
m.lock.Lock()
|
m.lock.Lock()
|
||||||
defer m.lock.Unlock()
|
defer m.lock.Unlock()
|
||||||
|
|
Loading…
Reference in New Issue