Remove RTL Override symbols from filenames.

This commit is contained in:
John Preston 2017-11-05 15:00:48 +04:00
parent cb5c59c86c
commit aec496d520
12 changed files with 154 additions and 68 deletions

View File

@ -1616,7 +1616,7 @@ namespace {
versionChanged = convert->setRemoteVersion(version);
convert->setRemoteLocation(dc, access);
convert->date = date;
convert->mime = mime;
convert->setMimeString(mime);
if (!thumb->isNull() && (convert->thumb->isNull() || convert->thumb->width() < thumb->width() || convert->thumb->height() < thumb->height() || versionChanged)) {
updateImage(convert->thumb, thumb);
}
@ -1648,7 +1648,7 @@ namespace {
} else {
result = DocumentData::create(document, dc, access, version, attributes);
result->date = date;
result->mime = mime;
result->setMimeString(mime);
result->thumb = thumb;
result->size = size;
result->recountIsImage();
@ -1666,7 +1666,7 @@ namespace {
result->setRemoteLocation(dc, access);
}
result->date = date;
result->mime = mime;
result->setMimeString(mime);
if (!thumb->isNull() && (result->thumb->isNull() || result->thumb->width() < thumb->width() || result->thumb->height() < thumb->height() || versionChanged)) {
result->thumb = thumb;
}

View File

@ -199,10 +199,18 @@ void SendFilesBox::prepareDocumentLayout() {
}
}
auto nameString = DocumentData::composeNameString(filename, songTitle, songPerformer);
_nameText.setText(st::semiboldTextStyle, nameString, _textNameOptions);
auto nameString = DocumentData::ComposeNameString(
filename,
songTitle,
songPerformer);
_nameText.setText(
st::semiboldTextStyle,
nameString,
_textNameOptions);
_statusText = formatSizeText(fileinfo.size());
_statusWidth = qMax(_nameText.maxWidth(), st::normalFont->width(_statusText));
_statusWidth = qMax(
_nameText.maxWidth(),
st::normalFont->width(_statusText));
}
}
@ -504,13 +512,17 @@ EditCaptionBox::EditCaptionBox(QWidget*, HistoryMedia *media, FullMsgId msgId) :
}
if (doc) {
if (doc->voice()) {
_name.setText(st::semiboldTextStyle, lang(lng_media_audio), _textNameOptions);
} else {
_name.setText(st::semiboldTextStyle, doc->composeNameString(), _textNameOptions);
}
auto nameString = doc->voice()
? lang(lng_media_audio)
: doc->composeNameString();
_name.setText(
st::semiboldTextStyle,
nameString,
_textNameOptions);
_status = formatSizeText(doc->size);
_statusw = qMax(_name.maxWidth(), st::normalFont->width(_status));
_statusw = qMax(
_name.maxWidth(),
st::normalFont->width(_status));
_isImage = doc->isImage();
_isAudio = (doc->voice() || doc->song());
}

View File

@ -159,18 +159,18 @@ QString documentSaveFilename(const DocumentData *data, bool forceSavingAs = fals
}
QString name, filter, caption, prefix;
MimeType mimeType = mimeTypeForName(data->mime);
MimeType mimeType = mimeTypeForName(data->mimeString());
QStringList p = mimeType.globPatterns();
QString pattern = p.isEmpty() ? QString() : p.front();
if (data->voice()) {
bool mp3 = (data->mime == qstr("audio/mp3"));
auto mp3 = data->hasMimeType(qstr("audio/mp3"));
name = already.isEmpty() ? (mp3 ? qsl(".mp3") : qsl(".ogg")) : already;
filter = mp3 ? qsl("MP3 Audio (*.mp3);;") : qsl("OGG Opus Audio (*.ogg);;");
filter += FileDialog::AllFilesFilter();
caption = lang(lng_save_audio);
prefix = qsl("audio");
} else if (data->isVideo()) {
name = already.isEmpty() ? data->name : already;
name = already.isEmpty() ? data->filename() : already;
if (name.isEmpty()) {
name = pattern.isEmpty() ? qsl(".mov") : pattern.replace('*', QString());
}
@ -182,7 +182,7 @@ QString documentSaveFilename(const DocumentData *data, bool forceSavingAs = fals
caption = lang(lng_save_video);
prefix = qsl("video");
} else {
name = already.isEmpty() ? data->name : already;
name = already.isEmpty() ? data->filename() : already;
if (name.isEmpty()) {
name = pattern.isEmpty() ? qsl(".unknown") : pattern.replace('*', QString());
}
@ -444,7 +444,17 @@ void DocumentData::setattributes(const QVector<MTPDocumentAttribute> &attributes
song()->performer = qs(d.vperformer);
}
} break;
case mtpc_documentAttributeFilename: name = qs(attributes[i].c_documentAttributeFilename().vfile_name); break;
case mtpc_documentAttributeFilename: {
auto &attribute = attributes[i];
auto remoteFileName = qs(
attribute.c_documentAttributeFilename().vfile_name);
// We don't want RTL Override characters in filenames,
// because they introduce a security issue, when a filename
// "Fil[RTLO]gepj.exe" looks like "Filexe.jpeg" being ".exe"
auto rtlOverride = QChar(0x202E);
_filename = std::move(remoteFileName).replace(rtlOverride, "");
} break;
}
}
if (type == StickerDocument) {
@ -868,7 +878,7 @@ void DocumentData::recountIsImage() {
if (isAnimation() || isVideo()) {
return;
}
_duration = fileIsImage(name, mime) ? 1 : -1; // hack
_duration = fileIsImage(filename(), mimeString()) ? 1 : -1; // hack
}
bool DocumentData::setRemoteVersion(int32 version) {
@ -928,7 +938,10 @@ DocumentData::~DocumentData() {
}
}
QString DocumentData::composeNameString(const QString &filename, const QString &songTitle, const QString &songPerformer) {
QString DocumentData::ComposeNameString(
const QString &filename,
const QString &songTitle,
const QString &songPerformer) {
if (songTitle.isEmpty() && songPerformer.isEmpty()) {
return filename.isEmpty() ? qsl("Unknown File") : filename;
}

View File

@ -184,24 +184,26 @@ public:
bool isAnimation() const {
return (type == AnimatedDocument)
|| isRoundVideo()
|| !mime.compare(qstr("image/gif"), Qt::CaseInsensitive);
|| hasMimeType(qstr("image/gif"));
}
bool isGifv() const {
return (type == AnimatedDocument)
&& !mime.compare(qstr("video/mp4"), Qt::CaseInsensitive);
&& hasMimeType(qstr("video/mp4"));
}
bool isTheme() const {
return
name.endsWith(
_filename.endsWith(
qstr(".tdesktop-theme"),
Qt::CaseInsensitive)
|| name.endsWith(
|| _filename.endsWith(
qstr(".tdesktop-palette"),
Qt::CaseInsensitive);
}
bool tryPlaySong() const {
return (song() != nullptr)
|| mime.startsWith(qstr("audio/"), Qt::CaseInsensitive);
|| _mimeString.startsWith(
qstr("audio/"),
Qt::CaseInsensitive);
}
bool isMusic() const {
if (auto s = song()) {
@ -247,14 +249,25 @@ public:
// to (this) received from the server "same" document.
void collectLocalData(DocumentData *local);
QString filename() const {
return _filename;
}
QString mimeString() const {
return _mimeString;
}
bool hasMimeType(QLatin1String mime) const {
return !_mimeString.compare(mime, Qt::CaseInsensitive);
}
void setMimeString(const QString &mime) {
_mimeString = mime;
}
~DocumentData();
DocumentId id = 0;
DocumentType type = FileDocument;
QSize dimensions;
int32 date = 0;
QString name;
QString mime;
ImagePtr thumb, replyPreview;
int32 size = 0;
@ -267,18 +280,18 @@ public:
return ::mediaKey(locationType(), _dc, id, _version);
}
static QString composeNameString(
static QString ComposeNameString(
const QString &filename,
const QString &songTitle,
const QString &songPerformer);
QString composeNameString() const {
if (auto songData = song()) {
return composeNameString(
name,
return ComposeNameString(
_filename,
songData->title,
songData->performer);
}
return composeNameString(name, QString(), QString());
return ComposeNameString(_filename, QString(), QString());
}
private:
@ -305,6 +318,8 @@ private:
uint64 _access = 0;
int32 _version = 0;
QString _url;
QString _filename;
QString _mimeString;
FileLocation _location;
QByteArray _data;

View File

@ -1107,7 +1107,7 @@ void HistoryDocument::createComponents(bool caption) {
} else {
mask |= HistoryDocumentNamed::Bit();
if (!_data->song()
&& !documentIsExecutableName(_data->name)
&& !documentIsExecutableName(_data->filename())
&& !_data->thumb->isNull()
&& _data->thumb->width()
&& _data->thumb->height()) {
@ -1128,8 +1128,8 @@ void HistoryDocument::createComponents(bool caption) {
}
void HistoryDocument::fillNamedFromData(HistoryDocumentNamed *named) {
auto name = named->_name = _data->composeNameString();
named->_namew = st::semiboldFont->width(name);
auto nameString = named->_name = _data->composeNameString();
named->_namew = st::semiboldFont->width(nameString);
}
void HistoryDocument::initDimensions() {

View File

@ -99,7 +99,9 @@ ApiWrap::RequestMessageDataCallback replyEditMessageDataCallback() {
}
MTPVector<MTPDocumentAttribute> composeDocumentAttributes(DocumentData *document) {
QVector<MTPDocumentAttribute> attributes(1, MTP_documentAttributeFilename(MTP_string(document->name)));
auto filenameAttribute = MTP_documentAttributeFilename(
MTP_string(document->filename()));
auto attributes = QVector<MTPDocumentAttribute>(1, filenameAttribute);
if (document->dimensions.width() > 0 && document->dimensions.height() > 0) {
int32 duration = document->duration();
if (duration >= 0) {
@ -4428,7 +4430,15 @@ void HistoryWidget::onDocumentUploaded(const FullMsgId &newId, bool silent, cons
sendFlags |= MTPmessages_SendMedia::Flag::f_silent;
}
auto caption = item->getMedia() ? item->getMedia()->getCaption() : TextWithEntities();
auto media = MTP_inputMediaUploadedDocument(MTP_flags(0), file, MTPInputFile(), MTP_string(document->mime), composeDocumentAttributes(document), MTP_string(caption.text), MTPVector<MTPInputDocument>(), MTP_int(0));
auto media = MTP_inputMediaUploadedDocument(
MTP_flags(0),
file,
MTPInputFile(),
MTP_string(document->mimeString()),
composeDocumentAttributes(document),
MTP_string(caption.text),
MTPVector<MTPInputDocument>(),
MTP_int(0));
hist->sendRequestId = MTP::send(MTPmessages_SendMedia(MTP_flags(sendFlags), item->history()->peer->input, MTP_int(replyTo), media, MTP_long(randomId), MTPnullMarkup), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), App::main()->rpcFail(&MainWidget::sendMessageFail), 0, 0, hist->sendRequestId);
}
}
@ -4453,7 +4463,7 @@ void HistoryWidget::onThumbDocumentUploaded(const FullMsgId &newId, bool silent,
sendFlags |= MTPmessages_SendMedia::Flag::f_silent;
}
auto caption = media ? media->getCaption() : TextWithEntities();
auto media = MTP_inputMediaUploadedDocument(MTP_flags(MTPDinputMediaUploadedDocument::Flag::f_thumb), file, thumb, MTP_string(document->mime), composeDocumentAttributes(document), MTP_string(caption.text), MTPVector<MTPInputDocument>(), MTP_int(0));
auto media = MTP_inputMediaUploadedDocument(MTP_flags(MTPDinputMediaUploadedDocument::Flag::f_thumb), file, thumb, MTP_string(document->mimeString()), composeDocumentAttributes(document), MTP_string(caption.text), MTPVector<MTPInputDocument>(), MTP_int(0));
hist->sendRequestId = MTP::send(MTPmessages_SendMedia(MTP_flags(sendFlags), item->history()->peer->input, MTP_int(replyTo), media, MTP_long(randomId), MTPnullMarkup), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), App::main()->rpcFail(&MainWidget::sendMessageFail), 0, 0, hist->sendRequestId);
}
}
@ -5888,18 +5898,18 @@ void HistoryWidget::updatePreview() {
if (_previewData->title.isEmpty()) {
if (_previewData->description.text.isEmpty()) {
title = _previewData->author;
desc = ((_previewData->document && !_previewData->document->name.isEmpty()) ? _previewData->document->name : _previewData->url);
desc = ((_previewData->document && !_previewData->document->filename().isEmpty()) ? _previewData->document->filename() : _previewData->url);
} else {
title = _previewData->description.text;
desc = _previewData->author.isEmpty() ? ((_previewData->document && !_previewData->document->name.isEmpty()) ? _previewData->document->name : _previewData->url) : _previewData->author;
desc = _previewData->author.isEmpty() ? ((_previewData->document && !_previewData->document->filename().isEmpty()) ? _previewData->document->filename() : _previewData->url) : _previewData->author;
}
} else {
title = _previewData->title;
desc = _previewData->description.text.isEmpty() ? (_previewData->author.isEmpty() ? ((_previewData->document && !_previewData->document->name.isEmpty()) ? _previewData->document->name : _previewData->url) : _previewData->author) : _previewData->description.text;
desc = _previewData->description.text.isEmpty() ? (_previewData->author.isEmpty() ? ((_previewData->document && !_previewData->document->filename().isEmpty()) ? _previewData->document->filename() : _previewData->url) : _previewData->author) : _previewData->description.text;
}
} else {
title = _previewData->siteName;
desc = _previewData->title.isEmpty() ? (_previewData->description.text.isEmpty() ? (_previewData->author.isEmpty() ? ((_previewData->document && !_previewData->document->name.isEmpty()) ? _previewData->document->name : _previewData->url) : _previewData->author) : _previewData->description.text) : _previewData->title;
desc = _previewData->title.isEmpty() ? (_previewData->description.text.isEmpty() ? (_previewData->author.isEmpty() ? ((_previewData->document && !_previewData->document->filename().isEmpty()) ? _previewData->document->filename() : _previewData->url) : _previewData->author) : _previewData->description.text) : _previewData->title;
}
if (title.isEmpty()) {
if (_previewData->document) {

View File

@ -152,28 +152,33 @@ QString formatPlayedText(qint64 played, qint64 duration) {
}
int32 documentColorIndex(DocumentData *document, QString &ext) {
int32 colorIndex = 0;
auto colorIndex = 0;
QString name = document ? (document->name.isEmpty() ? (document->sticker() ? lang(lng_in_dlg_sticker) : qsl("Unknown File")) : document->name) : lang(lng_message_empty);
auto name = document
? (document->filename().isEmpty()
? (document->sticker()
? lang(lng_in_dlg_sticker)
: qsl("Unknown File"))
: document->filename())
: lang(lng_message_empty);
name = name.toLower();
int32 lastDot = name.lastIndexOf('.');
QString mime = document ? document->mime.toLower() : QString();
auto lastDot = name.lastIndexOf('.');
auto mime = document
? document->mimeString().toLower()
: QString();
if (name.endsWith(qstr(".doc")) ||
name.endsWith(qstr(".txt")) ||
name.endsWith(qstr(".psd")) ||
mime.startsWith(qstr("text/"))
) {
mime.startsWith(qstr("text/"))) {
colorIndex = 0;
} else if (
name.endsWith(qstr(".xls")) ||
name.endsWith(qstr(".csv"))
) {
name.endsWith(qstr(".csv"))) {
colorIndex = 1;
} else if (
name.endsWith(qstr(".pdf")) ||
name.endsWith(qstr(".ppt")) ||
name.endsWith(qstr(".key"))
) {
name.endsWith(qstr(".key"))) {
colorIndex = 2;
} else if (
name.endsWith(qstr(".zip")) ||
@ -181,15 +186,22 @@ int32 documentColorIndex(DocumentData *document, QString &ext) {
name.endsWith(qstr(".ai")) ||
name.endsWith(qstr(".mp3")) ||
name.endsWith(qstr(".mov")) ||
name.endsWith(qstr(".avi"))
) {
name.endsWith(qstr(".avi"))) {
colorIndex = 3;
} else {
QChar ch = (lastDot >= 0 && lastDot + 1 < name.size()) ? name.at(lastDot + 1) : (name.isEmpty() ? (mime.isEmpty() ? '0' : mime.at(0)) : name.at(0));
auto ch = (lastDot >= 0 && lastDot + 1 < name.size())
? name.at(lastDot + 1)
: (name.isEmpty()
? (mime.isEmpty() ? '0' : mime.at(0))
: name.at(0));
colorIndex = (ch.unicode() % 4);
}
ext = document ? ((lastDot < 0 || lastDot + 2 > name.size()) ? name : name.mid(lastDot + 1)) : QString();
ext = document
? ((lastDot < 0 || lastDot + 2 > name.size())
? name
: name.mid(lastDot + 1))
: QString();
return colorIndex;
}

View File

@ -322,9 +322,15 @@ void CoverWidget::handleSongChange() {
TextWithEntities textWithEntities;
if (song->performer.isEmpty()) {
textWithEntities.text = song->title.isEmpty() ? (current.audio()->name.isEmpty() ? qsl("Unknown Track") : current.audio()->name) : song->title;
textWithEntities.text = song->title.isEmpty()
? (current.audio()->filename().isEmpty()
? qsl("Unknown Track")
: current.audio()->filename())
: song->title;
} else {
auto title = song->title.isEmpty() ? qsl("Unknown Track") : TextUtilities::Clean(song->title);
auto title = song->title.isEmpty()
? qsl("Unknown Track")
: TextUtilities::Clean(song->title);
textWithEntities.text = song->performer + QString::fromUtf8(" \xe2\x80\x93 ") + title;
textWithEntities.entities.append({ EntityInTextBold, 0, song->performer.size(), QString() });
}

View File

@ -499,10 +499,17 @@ void Widget::handleSongChange() {
} else {
auto song = current.audio()->song();
if (!song || song->performer.isEmpty()) {
textWithEntities.text = (!song || song->title.isEmpty()) ? (current.audio()->name.isEmpty() ? qsl("Unknown Track") : current.audio()->name) : song->title;
textWithEntities.text = (!song || song->title.isEmpty())
? (current.audio()->filename().isEmpty()
? qsl("Unknown Track")
: current.audio()->filename())
: song->title;
} else {
auto title = song->title.isEmpty() ? qsl("Unknown Track") : TextUtilities::Clean(song->title);
textWithEntities.text = song->performer + QString::fromUtf8(" \xe2\x80\x93 ") + title;
auto title = song->title.isEmpty()
? qsl("Unknown Track")
: TextUtilities::Clean(song->title);
auto dash = QString::fromUtf8(" \xe2\x80\x93 ");
textWithEntities.text = song->performer + dash + title;
textWithEntities.entities.append({ EntityInTextBold, 0, song->performer.size(), QString() });
}
}

View File

@ -738,7 +738,7 @@ void MediaView::onSaveAs() {
QFileInfo alreadyInfo(location.name());
QDir alreadyDir(alreadyInfo.dir());
QString name = alreadyInfo.fileName(), filter;
MimeType mimeType = mimeTypeForName(_doc->mime);
MimeType mimeType = mimeTypeForName(_doc->mimeString());
QStringList p = mimeType.globPatterns();
QString pattern = p.isEmpty() ? QString() : p.front();
if (name.isEmpty()) {
@ -873,7 +873,10 @@ void MediaView::onDownload() {
const FileLocation &location(_doc->location(true));
if (location.accessEnable()) {
if (!QDir().exists(path)) QDir().mkpath(path);
toName = filedialogNextFilename(_doc->name, location.name(), path);
toName = filedialogNextFilename(
_doc->filename(),
location.name(),
path);
if (!toName.isEmpty() && toName != location.name()) {
QFile(toName).remove();
if (!QFile(location.name()).copy(toName)) {
@ -1398,7 +1401,13 @@ void MediaView::displayDocument(DocumentData *doc, HistoryItem *item) { // empty
int32 maxw = st::mediaviewFileSize.width() - st::mediaviewFileIconSize - st::mediaviewFilePadding * 3;
if (_doc) {
_docName = (_doc->type == StickerDocument) ? lang(lng_in_dlg_sticker) : (_doc->type == AnimatedDocument ? qsl("GIF") : (_doc->name.isEmpty() ? lang(lng_mediaview_doc_image) : _doc->name));
_docName = (_doc->type == StickerDocument)
? lang(lng_in_dlg_sticker)
: (_doc->type == AnimatedDocument
? qsl("GIF")
: (_doc->filename().isEmpty()
? lang(lng_mediaview_doc_image)
: _doc->filename()));
} else {
_docName = lang(lng_message_empty);
}
@ -2826,13 +2835,13 @@ void MediaView::updateHeader() {
auto count = _fullCount ? *_fullCount : -1;
if (index >= 0 && index < count && count > 1) {
if (_doc) {
_headerText = lng_mediaview_file_n_of_count(lt_file, _doc->name.isEmpty() ? lang(lng_mediaview_doc_image) : _doc->name, lt_n, QString::number(index + 1), lt_count, QString::number(count));
_headerText = lng_mediaview_file_n_of_count(lt_file, _doc->filename().isEmpty() ? lang(lng_mediaview_doc_image) : _doc->filename(), lt_n, QString::number(index + 1), lt_count, QString::number(count));
} else {
_headerText = lng_mediaview_n_of_count(lt_n, QString::number(index + 1), lt_count, QString::number(count));
}
} else {
if (_doc) {
_headerText = _doc->name.isEmpty() ? lang(lng_mediaview_doc_image) : _doc->name;
_headerText = _doc->filename().isEmpty() ? lang(lng_mediaview_doc_image) : _doc->filename();
} else if (_msgid) {
_headerText = lang(lng_mediaview_single_photo);
} else if (_user) {

View File

@ -52,7 +52,9 @@ TextWithEntities ComposeNameWithEntities(DocumentData *document) {
TextWithEntities result;
auto song = document->song();
if (!song || (song->title.isEmpty() && song->performer.isEmpty())) {
result.text = document->name.isEmpty() ? qsl("Unknown File") : document->name;
result.text = document->filename().isEmpty()
? qsl("Unknown File")
: document->filename();
result.entities.push_back({ EntityInTextBold, 0, result.text.size() });
} else if (song->performer.isEmpty()) {
result.text = song->title;
@ -1037,7 +1039,7 @@ bool Document::withThumb() const {
&& !_data->thumb->isNull()
&& _data->thumb->width()
&& _data->thumb->height()
&& !documentIsExecutableName(_data->name);
&& !documentIsExecutableName(_data->filename());
}
bool Document::updateStatusText() {

View File

@ -37,7 +37,7 @@ namespace Serialize {
void Document::writeToStream(QDataStream &stream, DocumentData *document) {
stream << quint64(document->id) << quint64(document->_access) << qint32(document->date);
stream << qint32(document->_version);
stream << document->name << document->mime << qint32(document->_dc) << qint32(document->size);
stream << document->filename() << document->mimeString() << qint32(document->_dc) << qint32(document->size);
stream << qint32(document->dimensions.width()) << qint32(document->dimensions.height());
stream << qint32(document->type);
if (auto sticker = document->sticker()) {
@ -148,7 +148,7 @@ int Document::sizeInStream(DocumentData *document) {
// id + access + date + version
result += sizeof(quint64) + sizeof(quint64) + sizeof(qint32) + sizeof(qint32);
// + namelen + name + mimelen + mime + dc + size
result += stringSize(document->name) + stringSize(document->mime) + sizeof(qint32) + sizeof(qint32);
result += stringSize(document->filename()) + stringSize(document->mimeString()) + sizeof(qint32) + sizeof(qint32);
// + width + height
result += sizeof(qint32) + sizeof(qint32);
// + type