Skip to content

Commit

Permalink
Apply file type/size restrictions in export.
Browse files Browse the repository at this point in the history
  • Loading branch information
john-preston committed Jun 17, 2018
1 parent df91b2b commit 8d52ca6
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 41 deletions.
1 change: 1 addition & 0 deletions Telegram/SourceFiles/export/data/export_data_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ void ParseAttributes(
}, [&](const MTPDdocumentAttributeAnimated &data) {
result.isAnimated = true;
}, [&](const MTPDdocumentAttributeSticker &data) {
result.isSticker = true;
result.stickerEmoji = ParseString(data.valt);
}, [&](const MTPDdocumentAttributeVideo &data) {
if (data.is_round_message()) {
Expand Down
8 changes: 8 additions & 0 deletions Telegram/SourceFiles/export/data/export_data_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,20 @@ struct FileLocation {
};

struct File {
enum class SkipReason {
None,
Unavailable,
FileType,
FileSize,
};
FileLocation location;
int size = 0;
QByteArray content;

QString suggestedPath;

QString relativePath;
SkipReason skipReason = SkipReason::None;
};

struct Image {
Expand Down Expand Up @@ -89,6 +96,7 @@ struct Document {
Utf8String songTitle;
int duration = 0;

bool isSticker = false;
bool isAnimated = false;
bool isVideoMessage = false;
bool isVoiceMessage = false;
Expand Down
121 changes: 89 additions & 32 deletions Telegram/SourceFiles/export/export_api_wrap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,8 @@ constexpr auto kChatsSliceLimit = 100;
constexpr auto kMessagesSliceLimit = 100;
constexpr auto kFileMaxSize = 1500 * 1024 * 1024;

bool WillLoadFile(const Data::File &file) {
return file.relativePath.isEmpty()
&& (!file.content.isEmpty() || file.location.dcId != 0);
bool FileIsAvailable(const Data::File &file) {
return file.relativePath.isEmpty() && (file.location.dcId != 0);
}

} // namespace
Expand Down Expand Up @@ -258,17 +257,16 @@ void ApiWrap::loadNextUserpic() {
Expects(_userpicsProcess != nullptr);
Expects(_userpicsProcess->slice.has_value());

const auto &list = _userpicsProcess->slice->list;
auto &list = _userpicsProcess->slice->list;
while (true) {
const auto index = ++_userpicsProcess->fileIndex;
if (index >= list.size()) {
break;
}
const auto &file = list[index].image.file;
if (WillLoadFile(file)) {
loadFile(
file,
[=](const QString &path) { loadUserpicDone(path); });
const auto ready = processFileLoad(
list[index].image.file,
[=](const QString &path) { loadUserpicDone(path); });
if (!ready) {
return;
}
}
Expand Down Expand Up @@ -510,17 +508,16 @@ void ApiWrap::loadNextMessageFile() {
Expects(_dialogsProcess->single->slice.has_value());

const auto process = _dialogsProcess->single.get();
const auto &list = process->slice->list;
auto &list = process->slice->list;
while (true) {
const auto index = ++process->fileIndex;
if (index >= list.size()) {
break;
}
const auto &file = list[index].file();
if (WillLoadFile(file)) {
loadFile(
file,
[=](const QString &path) { loadMessageFileDone(path); });
const auto ready = processFileLoad(
list[index].file(),
[=](const QString &path) { loadMessageFileDone(path); });
if (!ready) {
return;
}
}
Expand Down Expand Up @@ -569,32 +566,92 @@ void ApiWrap::finishDialogs() {
base::take(_dialogsProcess)->finish();
}

void ApiWrap::loadFile(const Data::File &file, FnMut<void(QString)> done) {
Expects(_fileProcess == nullptr);
bool ApiWrap::processFileLoad(
Data::File &file,
FnMut<void(QString)> done,
Data::Message *message) {
using SkipReason = Data::File::SkipReason;

if (!file.relativePath.isEmpty()) {
return true;
} else if (writePreloadedFile(file)) {
return true;
} else if (!FileIsAvailable(file)) {
file.skipReason = SkipReason::Unavailable;
return true;
}

using Type = MediaSettings::Type;
const auto type = message ? message->media.content.match(
[&](const Data::Document &data) {
if (data.isSticker) {
return Type::Sticker;
} else if (data.isVideoMessage) {
return Type::VideoMessage;
} else if (data.isVoiceMessage) {
return Type::VoiceMessage;
} else if (data.isAnimated) {
return Type::GIF;
} else if (data.isVideoFile) {
return Type::Video;
} else {
return Type::File;
}
}, [](const auto &data) {
return Type::Photo;
}) : Type::Photo;

if ((_settings->media.types & type) != type) {
file.skipReason = SkipReason::FileType;
return true;
} else if (file.size >= _settings->media.sizeLimit) {
file.skipReason = SkipReason::FileSize;
return true;
}
loadFile(file, std::move(done));
return false;
}

bool ApiWrap::writePreloadedFile(Data::File &file) {
Expects(_settings != nullptr);
Expects(WillLoadFile(file));

using namespace Output;
const auto relativePath = File::PrepareRelativePath(
_settings->path,
file.suggestedPath);
_fileProcess = std::make_unique<FileProcess>(
_settings->path + relativePath);
_fileProcess->relativePath = relativePath;
_fileProcess->location = file.location;
_fileProcess->size = file.size;
_fileProcess->done = std::move(done);

if (!file.content.isEmpty()) {
const auto process = prepareFileProcess(file);
auto &output = _fileProcess->file;
if (output.writeBlock(file.content) == File::Result::Success) {
_fileProcess->done(relativePath);
} else {
error(QString("Could not open '%1'.").arg(relativePath));
file.relativePath = process->relativePath;
return true;
}
} else {
loadFilePart();
error(QString("Could not write '%1'.").arg(process->relativePath));
}
return false;
}

void ApiWrap::loadFile(const Data::File &file, FnMut<void(QString)> done) {
Expects(_fileProcess == nullptr);
Expects(FileIsAvailable(file));

_fileProcess = prepareFileProcess(file);
_fileProcess->done = std::move(done);

loadFilePart();
}

auto ApiWrap::prepareFileProcess(const Data::File &file) const
-> std::unique_ptr<FileProcess> {
Expects(_settings != nullptr);

const auto relativePath = Output::File::PrepareRelativePath(
_settings->path,
file.suggestedPath);
auto result = std::make_unique<FileProcess>(
_settings->path + relativePath);
result->relativePath = relativePath;
result->location = file.location;
result->size = file.size;
return result;
}

void ApiWrap::loadFilePart() {
Expand Down
20 changes: 13 additions & 7 deletions Telegram/SourceFiles/export/export_api_wrap.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ struct SessionsList;
struct DialogsInfo;
struct DialogInfo;
struct MessagesSlice;
struct Message;
} // namespace Data

struct Settings;
Expand Down Expand Up @@ -56,6 +57,10 @@ class ApiWrap {
~ApiWrap();

private:
struct UserpicsProcess;
struct FileProcess;
struct DialogsProcess;

void startMainSession(FnMut<void()> done);

void handleUserpicsSlice(const MTPphotos_Photos &result);
Expand All @@ -64,8 +69,6 @@ class ApiWrap {
void loadUserpicDone(const QString &relativePath);
void finishUserpics();

void requestSavedContacts();

void requestDialogsSlice();
void appendDialogsSlice(Data::DialogsInfo &&info);
void finishDialogsList();
Expand All @@ -75,10 +78,18 @@ class ApiWrap {
void requestMessagesSlice();
void loadMessagesFiles(Data::MessagesSlice &&slice);
void loadNextMessageFile();

void loadMessageFileDone(const QString &relativePath);
void finishMessages();
void finishDialogs();

bool processFileLoad(
Data::File &file,
FnMut<void(QString)> done,
Data::Message *message = nullptr);
std::unique_ptr<FileProcess> prepareFileProcess(
const Data::File &file) const;
bool writePreloadedFile(Data::File &file);
void loadFile(const Data::File &file, FnMut<void(QString)> done);
void loadFilePart();
void filePartDone(int offset, const MTPupload_File &result);
Expand All @@ -99,13 +110,8 @@ class ApiWrap {
std::unique_ptr<Settings> _settings;
MTPInputUser _user = MTP_inputUserSelf();

struct UserpicsProcess;
std::unique_ptr<UserpicsProcess> _userpicsProcess;

struct FileProcess;
std::unique_ptr<FileProcess> _fileProcess;

struct DialogsProcess;
std::unique_ptr<DialogsProcess> _dialogsProcess;

rpl::event_stream<RPCError> _errors;
Expand Down
14 changes: 12 additions & 2 deletions Telegram/SourceFiles/export/output/export_output_text.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,13 @@ QByteArray SerializeMessage(
const auto pushAction = [&](const QByteArray &action) {
push("Action", action);
};
const auto pushTTL = [&](
const QByteArray &label = "Self destruct period") {
if (const auto ttl = message.media.ttl) {
push(label, NumberToString(ttl) + " sec.");
}
};

message.action.content.match([&](const ActionChatCreate &data) {
pushActor();
pushAction("Create group");
Expand Down Expand Up @@ -299,11 +306,12 @@ QByteArray SerializeMessage(
}

message.media.content.match([&](const Photo &photo) {
pushTTL();
}, [&](const Document &data) {
const auto pushPath = [&](const QByteArray &label) {
push(label, FormatFilePath(data.file));
};
if (!data.stickerEmoji.isEmpty()) {
if (data.isSticker) {
pushPath("Sticker");
push("Emoji", data.stickerEmoji);
} else if (data.isVideoMessage) {
Expand All @@ -321,7 +329,7 @@ QByteArray SerializeMessage(
} else {
pushPath("File");
}
if (data.stickerEmoji.isEmpty()) {
if (!data.isSticker) {
push("Mime type", data.mime);
}
if (data.duration) {
Expand All @@ -331,6 +339,7 @@ QByteArray SerializeMessage(
push("Width", NumberToString(data.width));
push("Height", NumberToString(data.height));
}
pushTTL();
}, [&](const ContactInfo &data) {
push("Contact information", SerializeKeyValue({
{ "First name", data.firstName },
Expand All @@ -342,6 +351,7 @@ QByteArray SerializeMessage(
{ "Latitude", NumberToString(data.latitude) },
{ "Longitude", NumberToString(data.longitude) },
}) : QByteArray("(empty value)"));
pushTTL("Live location period");
}, [&](const Venue &data) {
push("Place name", data.title);
push("Address", data.address);
Expand Down

0 comments on commit 8d52ca6

Please sign in to comment.