diff --git a/functionality/filesharing/filesharing_functionality.go b/functionality/filesharing/filesharing_functionality.go index 2cdd7c5..c1d7e76 100644 --- a/functionality/filesharing/filesharing_functionality.go +++ b/functionality/filesharing/filesharing_functionality.go @@ -181,17 +181,24 @@ func (om *OverlayMessage) ShouldAutoDL() bool { 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 downloadfilepath, exists := profile.GetScopedZonedAttribute(attr.LocalScope, attr.FilesharingZone, fmt.Sprintf("%s.path", fileKey)); exists { - log.Debugf("resuming %s", fileKey) - f.DownloadFile(profile, conversation, downloadfilepath, manifestFilePath, fileKey, files.MaxManifestSize*files.DefaultChunkSize) - } else { - log.Errorf("found manifest path but not download path for %s", fileKey) + manifest, err := files.LoadManifest(manifestFilePath) + if err == nil { + // Assert the filename...this is technically not necessary, but is here for completeness + 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) { @@ -254,18 +261,16 @@ func (f *Functionality) DownloadFile(profile peer.CwtchPeer, conversationID int, return errors.New("download path or manifest path is empty") } - // We write to a temp file for Android... - if runtime.GOOS != "android" { - // Don't download files if the download file 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 download file 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") + } + // Store local.filesharing.filekey.manifest as the location of the manifest profile.SetScopedZonedAttribute(attr.LocalScope, attr.FilesharingZone, fmt.Sprintf("%s.manifest", key), manifestFilePath) diff --git a/functionality/filesharing/image_previews.go b/functionality/filesharing/image_previews.go index d294b88..106d32b 100644 --- a/functionality/filesharing/image_previews.go +++ b/functionality/filesharing/image_previews.go @@ -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) { if profile.IsFeatureEnabled(constants.FileSharingExperiment) && profile.IsFeatureEnabled(constants.ImagePreviewsExperiment) { _, zone, path := path.GetScopeZonePath() - if zone == attr.ProfileZone && path == constants.CustomProfileImageKey { - fileKey := value - + if exists && zone == attr.ProfileZone && path == constants.CustomProfileImageKey { + // We only download from accepted conversations if conversation.Accepted { - fsf := FunctionalityGate() + fileKey := value basepath := i.downloadFolder + fsf := FunctionalityGate() + // We always overwrite profile image files... 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 _, err := os.Stat(fp); err == nil { // file is marked as completed downloaded and exists... - } else { - // the user probably deleted the file, mark completed as false... - profile.SetScopedZonedAttribute(attr.LocalScope, attr.FilesharingZone, fmt.Sprintf("%s.complete", fileKey), event.False) + if fsf.VerifyOrResumeDownload(profile, conversation.ID, fileKey, constants.ImagePreviewMaxSizeInBytes) == nil { + return + } + // 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) - // ev.Event.Data[event.FilePath] = fp - fsf.DownloadFile(profile, conversation.ID, fp, mp, value, constants.ImagePreviewMaxSizeInBytes) + fsf.DownloadFile(profile, conversation.ID, fp, mp, fileKey, constants.ImagePreviewMaxSizeInBytes) } } } diff --git a/protocol/files/manifest.go b/protocol/files/manifest.go index 5478211..3ffaa6a 100644 --- a/protocol/files/manifest.go +++ b/protocol/files/manifest.go @@ -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 -// 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 { m.lock.Lock() defer m.lock.Unlock()