mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Added support for quoted-printable encoding to contact media.
This commit is contained in:
parent
10f7b985c7
commit
82428aef28
3 changed files with 89 additions and 47 deletions
|
@ -1219,6 +1219,92 @@ std::unique_ptr<HistoryView::Media> MediaFile::createView(
|
||||||
_document);
|
_document);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SharedContact::VcardItems SharedContact::ParseVcard(const QString &data) {
|
||||||
|
const auto decode = [&](const QByteArray &input) -> QString {
|
||||||
|
auto output = QByteArray();
|
||||||
|
for (auto i = 0; i < input.size(); ++i) {
|
||||||
|
if ((input.at(i) == '=') && ((i + 2) < input.size())) {
|
||||||
|
const auto value = input.mid((++i)++, 2);
|
||||||
|
auto converted = false;
|
||||||
|
const auto character = char(value.toUInt(&converted, 16));
|
||||||
|
if (converted) {
|
||||||
|
output.append(character);
|
||||||
|
} else {
|
||||||
|
output.append('=');
|
||||||
|
output.append(value);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
output.append(input.at(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return QString::fromUtf8(output);
|
||||||
|
};
|
||||||
|
|
||||||
|
using Type = SharedContact::VcardItemType;
|
||||||
|
auto items = SharedContact::VcardItems();
|
||||||
|
for (const auto &item : data.split('\n')) {
|
||||||
|
const auto parts = item.split(':');
|
||||||
|
if (parts.size() == 2) {
|
||||||
|
const auto &type = parts.front();
|
||||||
|
const auto attributes = type.split(';', Qt::SkipEmptyParts);
|
||||||
|
|
||||||
|
const auto c = Qt::CaseInsensitive;
|
||||||
|
auto isQuotedPrintable = false;
|
||||||
|
for (const auto &attribute : attributes) {
|
||||||
|
const auto parts = attribute.split('=', Qt::SkipEmptyParts);
|
||||||
|
if (parts.size() == 2) {
|
||||||
|
if (parts.front().startsWith("ENCODING", c)) {
|
||||||
|
isQuotedPrintable = parts[1].startsWith(
|
||||||
|
"QUOTED-PRINTABLE",
|
||||||
|
c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto &value = isQuotedPrintable
|
||||||
|
? decode(parts[1].toUtf8())
|
||||||
|
: parts[1];
|
||||||
|
|
||||||
|
if (type.startsWith("TEL")) {
|
||||||
|
const auto telType = type.contains("PREF")
|
||||||
|
? Type::PhoneMain
|
||||||
|
: type.contains("HOME")
|
||||||
|
? Type::PhoneHome
|
||||||
|
: type.contains("WORK")
|
||||||
|
? Type::PhoneWork
|
||||||
|
: (type.contains("CELL")
|
||||||
|
|| type.contains("MOBILE"))
|
||||||
|
? Type::PhoneMobile
|
||||||
|
: type.contains("OTHER")
|
||||||
|
? Type::PhoneOther
|
||||||
|
: Type::Phone;
|
||||||
|
items[telType] = value;
|
||||||
|
} else if (type.startsWith("EMAIL")) {
|
||||||
|
items[Type::Email] = value;
|
||||||
|
} else if (type.startsWith("URL")) {
|
||||||
|
items[Type::Url] = value;
|
||||||
|
} else if (type.startsWith("NOTE")) {
|
||||||
|
items[Type::Note] = value;
|
||||||
|
} else if (type.startsWith("ORG")) {
|
||||||
|
items[Type::Organization] = base::duplicate(value)
|
||||||
|
.replace(';', ' ')
|
||||||
|
.trimmed();
|
||||||
|
} else if (type.startsWith("ADR")) {
|
||||||
|
items[Type::Address] = value;
|
||||||
|
} else if (type.startsWith("BDAY")) {
|
||||||
|
items[Type::Birthday] = value;
|
||||||
|
} else if (type.startsWith("N")) {
|
||||||
|
items[Type::Name] = base::duplicate(value)
|
||||||
|
.replace(';', ' ')
|
||||||
|
.trimmed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
MediaContact::MediaContact(
|
MediaContact::MediaContact(
|
||||||
not_null<HistoryItem*> parent,
|
not_null<HistoryItem*> parent,
|
||||||
UserId userId,
|
UserId userId,
|
||||||
|
|
|
@ -70,6 +70,8 @@ struct SharedContact final {
|
||||||
};
|
};
|
||||||
|
|
||||||
using VcardItems = base::flat_map<VcardItemType, QString>;
|
using VcardItems = base::flat_map<VcardItemType, QString>;
|
||||||
|
static VcardItems ParseVcard(const QString &);
|
||||||
|
|
||||||
VcardItems vcardItems;
|
VcardItems vcardItems;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -211,59 +211,13 @@ std::unique_ptr<Data::Media> HistoryItem::CreateMedia(
|
||||||
const MTPMessageMedia &media) {
|
const MTPMessageMedia &media) {
|
||||||
using Result = std::unique_ptr<Data::Media>;
|
using Result = std::unique_ptr<Data::Media>;
|
||||||
return media.match([&](const MTPDmessageMediaContact &media) -> Result {
|
return media.match([&](const MTPDmessageMediaContact &media) -> Result {
|
||||||
|
|
||||||
const auto vcardItems = [&] {
|
|
||||||
using Type = Data::SharedContact::VcardItemType;
|
|
||||||
auto items = Data::SharedContact::VcardItems();
|
|
||||||
for (const auto &item : qs(media.vvcard()).split('\n')) {
|
|
||||||
const auto parts = item.split(':');
|
|
||||||
if (parts.size() == 2) {
|
|
||||||
const auto &type = parts.front();
|
|
||||||
const auto &value = parts[1];
|
|
||||||
|
|
||||||
if (type.startsWith("TEL")) {
|
|
||||||
const auto telType = type.contains("PREF")
|
|
||||||
? Type::PhoneMain
|
|
||||||
: type.contains("HOME")
|
|
||||||
? Type::PhoneHome
|
|
||||||
: type.contains("WORK")
|
|
||||||
? Type::PhoneWork
|
|
||||||
: (type.contains("CELL")
|
|
||||||
|| type.contains("MOBILE"))
|
|
||||||
? Type::PhoneMobile
|
|
||||||
: type.contains("OTHER")
|
|
||||||
? Type::PhoneOther
|
|
||||||
: Type::Phone;
|
|
||||||
items[telType] = value;
|
|
||||||
} else if (type.startsWith("EMAIL")) {
|
|
||||||
items[Type::Email] = value;
|
|
||||||
} else if (type.startsWith("URL")) {
|
|
||||||
items[Type::Url] = value;
|
|
||||||
} else if (type.startsWith("NOTE")) {
|
|
||||||
items[Type::Note] = value;
|
|
||||||
} else if (type.startsWith("ORG")) {
|
|
||||||
items[Type::Organization] = value;
|
|
||||||
items[Type::Organization].replace(';', ' ');
|
|
||||||
} else if (type.startsWith("ADR")) {
|
|
||||||
items[Type::Address] = value;
|
|
||||||
} else if (type.startsWith("BDAY")) {
|
|
||||||
items[Type::Birthday] = value;
|
|
||||||
} else if (type.startsWith("N")) {
|
|
||||||
items[Type::Name] = value;
|
|
||||||
items[Type::Name].replace(';', ' ');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return items;
|
|
||||||
}();
|
|
||||||
|
|
||||||
return std::make_unique<Data::MediaContact>(
|
return std::make_unique<Data::MediaContact>(
|
||||||
item,
|
item,
|
||||||
media.vuser_id().v,
|
media.vuser_id().v,
|
||||||
qs(media.vfirst_name()),
|
qs(media.vfirst_name()),
|
||||||
qs(media.vlast_name()),
|
qs(media.vlast_name()),
|
||||||
qs(media.vphone_number()),
|
qs(media.vphone_number()),
|
||||||
vcardItems);
|
Data::SharedContact::ParseVcard(qs(media.vvcard())));
|
||||||
}, [&](const MTPDmessageMediaGeo &media) -> Result {
|
}, [&](const MTPDmessageMediaGeo &media) -> Result {
|
||||||
return media.vgeo().match([&](const MTPDgeoPoint &point) -> Result {
|
return media.vgeo().match([&](const MTPDgeoPoint &point) -> Result {
|
||||||
return std::make_unique<Data::MediaLocation>(
|
return std::make_unique<Data::MediaLocation>(
|
||||||
|
|
Loading…
Add table
Reference in a new issue