diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index ffe97265..a18b2f23 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -6923,6 +6923,7 @@ void ContactsManager::add_user_photo_id(User *u, UserId user_id, int64 photo_id, file_source_id = it->second; user_profile_photo_file_source_ids_.erase(it); } else { + VLOG(file_references) << "Need to create new file source for " << photo_id << " of " << user_id; file_source_id = td_->file_reference_manager_->create_user_photo_file_source(user_id, photo_id); } for (auto &file_id : photo_file_ids) { diff --git a/td/telegram/MessageContent.cpp b/td/telegram/MessageContent.cpp index dd903088..cf775c70 100644 --- a/td/telegram/MessageContent.cpp +++ b/td/telegram/MessageContent.cpp @@ -2122,7 +2122,7 @@ tl_object_ptr get_input_media(const MessageContent *co } if (!was_uploaded) { auto file_reference = FileManager::extract_file_reference(input_media); - if (file_reference == FileReferenceView::invalid_file_reference()) { + if (!FileReferenceView(file_reference).has_upload()) { return nullptr; } } @@ -2132,7 +2132,7 @@ tl_object_ptr get_input_media(const MessageContent *co tl_object_ptr get_input_media(const MessageContent *content, Td *td, int32 ttl) { auto input_media = get_input_media(content, td, nullptr, nullptr, ttl); auto file_reference = FileManager::extract_file_reference(input_media); - if (file_reference == FileReferenceView::invalid_file_reference()) { + if (!FileReferenceView(file_reference).has_upload()) { return nullptr; } return input_media; diff --git a/td/telegram/Photo.cpp b/td/telegram/Photo.cpp index c6acc385..275345b3 100644 --- a/td/telegram/Photo.cpp +++ b/td/telegram/Photo.cpp @@ -481,9 +481,6 @@ Photo get_photo(FileManager *file_manager, tl_object_ptr && res.date = photo->date_; res.has_stickers = (photo->flags_ & telegram_api::photo::HAS_STICKERS_MASK) != 0; - auto file_reference = photo->file_reference_.as_slice().str(); - // TODO use file_reference - for (auto &size_ptr : photo->sizes_) { res.photos.push_back(get_photo_size(file_manager, FileType::Photo, photo->id_, photo->access_hash_, photo->file_reference_.as_slice().str(), owner_dialog_id, std::move(size_ptr), diff --git a/td/telegram/files/FileLocation.h b/td/telegram/files/FileLocation.h index bad7e69d..965a57c8 100644 --- a/td/telegram/files/FileLocation.h +++ b/td/telegram/files/FileLocation.h @@ -23,35 +23,30 @@ #include "td/utils/Variant.h" #include +#include namespace td { class FileReferenceView { public: - static Slice invalid_file_reference() { - return "#"; + static std::string create_invalid() { + return create_one(invalid_file_reference()); } static std::string create_one(Slice first) { unsigned char second_length = 255; return PSTRING() << static_cast(second_length) << first; } - static std::string create_two(Slice first, Slice second = {}) { + static std::string create_two(Slice first, Slice second) { if (second.size() >= 255) { LOG(ERROR) << "File reference is too big " << base64_encode(second); second = invalid_file_reference(); } - char second_length = narrow_cast(second.size()); + char second_length = static_cast(narrow_cast(second.size())); return PSTRING() << second_length << first << second; } - std::string create(Slice first, Slice second) const { - if (size() == 1) { - return create_one(first); - } - return create_two(first, second); - } + FileReferenceView(Slice data) { if (data.empty()) { - size_ = 1; return; } @@ -59,10 +54,9 @@ class FileReferenceView { if (second_size == 255) { first_ = data.substr(1); second_ = data.substr(1); - size_ = 1; } else { if (second_size > data.size() - 1) { - size_ = 1; + first_ = second_ = data; return; } auto first_size = data.size() - 1 - second_size; @@ -71,46 +65,54 @@ class FileReferenceView { size_ = 2; } } - size_t size() const { - return size_; - } - Slice first() const { + Slice upload() const { return first_; } - Slice second() const { + Slice download() const { return second_; } - bool has_first() const { - return first() != invalid_file_reference(); + bool has_upload() const { + return upload() != invalid_file_reference(); } - bool has_second() const { - return second() != invalid_file_reference(); + bool has_download() const { + return download() != invalid_file_reference(); } std::pair delete_file_reference(Slice bad_file_reference) const { if (bad_file_reference == FileReferenceView::invalid_file_reference()) { - return {"", false}; + return {string(), false}; } - auto first = this->first(); - auto second = this->second(); - bool changed = false; + auto first = first_; + auto second = second_; + bool is_changed = false; if (first == bad_file_reference) { first = invalid_file_reference(); - changed = true; + is_changed = true; } if (second == bad_file_reference) { second = invalid_file_reference(); - changed = true; + is_changed = true; } - if (!changed) { - return {"", false}; + if (!is_changed) { + return {string(), false}; } return {create(first, second), true}; } private: + static Slice invalid_file_reference() { + return Slice("#"); + } + + std::string create(Slice first, Slice second) const { + if (size_ == 1) { + return create_one(first); + } + return create_two(first, second); + } + Slice first_; Slice second_; - int size_; + int size_ = 1; }; struct EmptyRemoteFileLocation { @@ -459,6 +461,7 @@ class FullRemoteFileLocation { CHECK(!is_web()); return dc_id_; } + int64 get_access_hash() const { switch (location_type()) { case LocationType::Photo: @@ -473,6 +476,7 @@ class FullRemoteFileLocation { return 0; } } + int64 get_id() const { switch (location_type()) { case LocationType::Photo: @@ -486,18 +490,21 @@ class FullRemoteFileLocation { return 0; } } + bool delete_file_reference(Slice bad_file_reference) { auto res = FileReferenceView(file_reference_).delete_file_reference(bad_file_reference); if (res.second) { file_reference_ = res.first; + } else if (file_reference_ == bad_file_reference) { + file_reference_ = FileReferenceView::create_invalid(); } return res.second; } bool has_upload_file_reference() const { - return FileReferenceView(file_reference_).has_first(); + return FileReferenceView(file_reference_).has_upload(); } bool has_download_file_reference() const { - return FileReferenceView(file_reference_).has_second(); + return FileReferenceView(file_reference_).has_download(); } bool has_any_file_reference() const { return has_upload_file_reference() || has_download_file_reference(); @@ -506,11 +513,12 @@ class FullRemoteFileLocation { return file_reference_; } Slice get_upload_file_reference() const { - return FileReferenceView(file_reference_).first(); + return FileReferenceView(file_reference_).upload(); } Slice get_download_file_reference() const { - return FileReferenceView(file_reference_).second(); + return FileReferenceView(file_reference_).download(); } + string get_url() const { if (is_web()) { return web().url_; @@ -555,7 +563,7 @@ class FullRemoteFileLocation { case LocationType::Photo: return make_tl_object( photo().volume_id_, photo().local_id_, photo().secret_, - BufferSlice(FileReferenceView(file_reference_).second())); + BufferSlice(FileReferenceView(file_reference_).download())); case LocationType::Common: if (is_encrypted_secret()) { return make_tl_object(common().id_, common().access_hash_); @@ -585,7 +593,7 @@ class FullRemoteFileLocation { tl_object_ptr as_input_photo_impl(const char *file, int line) const { CHECK(is_photo()) << file << ' ' << line; return make_tl_object(photo().id_, photo().access_hash_, - BufferSlice(FileReferenceView(file_reference_).first())); + BufferSlice(FileReferenceView(file_reference_).upload())); } tl_object_ptr as_input_encrypted_file() const { @@ -609,7 +617,7 @@ class FullRemoteFileLocation { , variant_(PhotoRemoteFileLocation{id, access_hash, volume_id, secret, local_id}) { CHECK(is_photo()); FileReferenceView view(file_reference_); - if (!view.has_first() || !view.has_second()) { + if (!(view.has_upload() && view.has_download())) { LOG(ERROR) << "Tried to register file with invalid file reference"; file_reference_.clear(); } @@ -621,7 +629,7 @@ class FullRemoteFileLocation { , variant_(CommonRemoteFileLocation{id, access_hash}) { CHECK(is_common()); FileReferenceView view(file_reference_); - if (!view.has_first() || !view.has_second()) { + if (!(view.has_upload() && view.has_download())) { LOG(ERROR) << "Tried to register file with invalid file reference"; file_reference_.clear(); } @@ -677,7 +685,7 @@ class FullRemoteFileLocation { } static const int32 KEY_MAGIC = 0x64374632; -}; // namespace td +}; inline StringBuilder &operator<<(StringBuilder &string_builder, const FullRemoteFileLocation &full_remote_file_location) { diff --git a/td/telegram/files/FileManager.cpp b/td/telegram/files/FileManager.cpp index 18ccf264..9be1cb89 100644 --- a/td/telegram/files/FileManager.cpp +++ b/td/telegram/files/FileManager.cpp @@ -162,7 +162,11 @@ void FileNode::set_remote_location(const RemoteFileLocation &remote, FileLocatio } bool FileNode::delete_file_reference(Slice file_reference) { - if (remote_.type() == RemoteFileLocation::Type::Full && remote_.full().delete_file_reference(file_reference)) { + if (remote_.type() != RemoteFileLocation::Type::Full) { + return false; + } + + if (remote_.full().delete_file_reference(file_reference)) { VLOG(file_references) << "Do delete file reference of main file " << main_file_id_; upload_was_update_file_reference_ = false; download_was_update_file_reference_ = false; @@ -1531,7 +1535,7 @@ void FileManager::flush_to_pmc(FileNodePtr node, bool new_remote, bool new_local data.url_ = node->url_; data.owner_dialog_id_ = node->owner_dialog_id_; data.file_source_ids_ = context_->get_some_file_sources(view.file_id()); - VLOG(file_references) << "Save " << data.file_source_ids_ << " to database for file " << view.file_id() << " from " + VLOG(file_references) << "Save file " << view.file_id() << " to database with " << data.file_source_ids_ << " from " << source; file_db_->set_file_data(node->pmc_id_, data, (create_flag || new_remote), (create_flag || new_local), @@ -1950,6 +1954,15 @@ void FileManager::delete_file_reference(FileId file_id, string file_reference) { return; } node->delete_file_reference(file_reference); + auto remote = get_remote(file_id.get_remote()); + if (remote != nullptr) { + VLOG(file_references) << "Do delete file reference of remote file " << file_id; + if (remote->delete_file_reference(file_reference)) { + node->upload_was_update_file_reference_ = false; + node->download_was_update_file_reference_ = false; + node->on_pmc_changed(); + } + } try_flush_node_pmc(node, "delete_file_reference"); }