mirror of https://github.com/procxx/kepka.git
version 0.6.9 - some network and protocol improvements, checkboxes in photos overview, other fixes
This commit is contained in:
parent
c89f13bb53
commit
868b9843b0
|
@ -1,5 +1,5 @@
|
||||||
AppVersionStr=0.6.8
|
AppVersionStr=0.6.9
|
||||||
AppVersion=6008
|
AppVersion=6009
|
||||||
|
|
||||||
if [ ! -f "./../Linux/Release/deploy/$AppVersionStr/tlinuxupd$AppVersion" ]; then
|
if [ ! -f "./../Linux/Release/deploy/$AppVersionStr/tlinuxupd$AppVersion" ]; then
|
||||||
echo "tlinuxupd$AppVersion not found!";
|
echo "tlinuxupd$AppVersion not found!";
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
AppVersionStr=0.6.8
|
AppVersionStr=0.6.9
|
||||||
AppVersion=6008
|
AppVersion=6009
|
||||||
|
|
||||||
if [ ! -f "./../Linux/Release/deploy/$AppVersionStr/tlinux32upd$AppVersion" ]; then
|
if [ ! -f "./../Linux/Release/deploy/$AppVersionStr/tlinux32upd$AppVersion" ]; then
|
||||||
echo "tlinux32upd$AppVersion not found!"
|
echo "tlinux32upd$AppVersion not found!"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
AppVersionStr=0.6.8
|
AppVersionStr=0.6.9
|
||||||
AppVersion=6008
|
AppVersion=6009
|
||||||
|
|
||||||
if [ ! -f "./../Mac/Release/deploy/$AppVersionStr/tmacupd$AppVersion" ]; then
|
if [ ! -f "./../Mac/Release/deploy/$AppVersionStr/tmacupd$AppVersion" ]; then
|
||||||
echo "tmacupd$AppVersion not found!"
|
echo "tmacupd$AppVersion not found!"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
AppVersionStr=0.6.8
|
AppVersionStr=0.6.9
|
||||||
AppVersion=6008
|
AppVersion=6009
|
||||||
|
|
||||||
if [ ! -f "./../Win32/Deploy/deploy/$AppVersionStr/tupdate$AppVersion" ]; then
|
if [ ! -f "./../Win32/Deploy/deploy/$AppVersionStr/tupdate$AppVersion" ]; then
|
||||||
echo "tupdate$AppVersion not found!"
|
echo "tupdate$AppVersion not found!"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
AppVersionStr=0.6.8
|
AppVersionStr=0.6.9
|
||||||
AppVersion=6008
|
AppVersion=6009
|
||||||
|
|
||||||
if [ -d "./../Linux/Release/deploy/$AppVersionStr" ]; then
|
if [ -d "./../Linux/Release/deploy/$AppVersionStr" ]; then
|
||||||
echo "Deploy folder for version $AppVersionStr already exists!"
|
echo "Deploy folder for version $AppVersionStr already exists!"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
AppVersionStr=0.6.8
|
AppVersionStr=0.6.9
|
||||||
AppVersion=6008
|
AppVersion=6009
|
||||||
|
|
||||||
if [ -d "./../Linux/Release/deploy/$AppVersionStr" ]; then
|
if [ -d "./../Linux/Release/deploy/$AppVersionStr" ]; then
|
||||||
echo "Deploy folder for version $AppVersionStr already exists!"
|
echo "Deploy folder for version $AppVersionStr already exists!"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
AppVersionStr=0.6.8
|
AppVersionStr=0.6.9
|
||||||
AppVersion=6008
|
AppVersion=6009
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "Preparing version $AppVersionStr.."
|
echo "Preparing version $AppVersionStr.."
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
@echo OFF
|
@echo OFF
|
||||||
|
|
||||||
set "AppVersionStr=0.6.8"
|
set "AppVersionStr=0.6.9"
|
||||||
echo.
|
echo.
|
||||||
echo Preparing version %AppVersionStr%..
|
echo Preparing version %AppVersionStr%..
|
||||||
echo.
|
echo.
|
||||||
|
|
|
@ -61,7 +61,10 @@ lng_connecting: "Connecting..";
|
||||||
lng_reconnecting: "Reconnect in %1 s..";
|
lng_reconnecting: "Reconnect in %1 s..";
|
||||||
lng_reconnecting_try_now: "Try now";
|
lng_reconnecting_try_now: "Try now";
|
||||||
|
|
||||||
lng_status_offline: "offline";
|
lng_status_offline: "last seen a long time ago";
|
||||||
|
lng_status_recently: "last seen recently";
|
||||||
|
lng_status_last_week: "last seen within a week";
|
||||||
|
lng_status_last_month: "last seen within a month";
|
||||||
lng_status_invisible: "invisible";
|
lng_status_invisible: "invisible";
|
||||||
lng_status_lastseen: "last seen {when}";
|
lng_status_lastseen: "last seen {when}";
|
||||||
lng_status_lastseen_now: "just now";
|
lng_status_lastseen_now: "just now";
|
||||||
|
|
|
@ -1572,6 +1572,9 @@ medviewPhotoSpritePos: point(14px, 14px);
|
||||||
|
|
||||||
overviewPhotoSkip: 10px;
|
overviewPhotoSkip: 10px;
|
||||||
overviewPhotoMinSize: 100px;
|
overviewPhotoMinSize: 100px;
|
||||||
|
overviewPhotoCheck: sprite(245px, 308px, 32px, 32px);
|
||||||
|
overviewPhotoChecked: sprite(278px, 308px, 32px, 32px);
|
||||||
|
overviewPhotoSelectOverlay: #0a7bb03f;
|
||||||
|
|
||||||
// Mac specific
|
// Mac specific
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
|
|
||||||
#define MyAppShortName "Telegram"
|
#define MyAppShortName "Telegram"
|
||||||
#define MyAppName "Telegram Desktop"
|
#define MyAppName "Telegram Desktop"
|
||||||
#define MyAppVersion "0.6.8"
|
#define MyAppVersion "0.6.9"
|
||||||
#define MyAppVersionZero "0.6.8"
|
#define MyAppVersionZero "0.6.9"
|
||||||
#define MyAppFullVersion "0.6.8.0"
|
#define MyAppFullVersion "0.6.9.0"
|
||||||
#define MyAppPublisher "Telegram Messenger LLP"
|
#define MyAppPublisher "Telegram Messenger LLP"
|
||||||
#define MyAppURL "https://tdesktop.com"
|
#define MyAppURL "https://tdesktop.com"
|
||||||
#define MyAppExeName "Telegram.exe"
|
#define MyAppExeName "Telegram.exe"
|
||||||
|
|
|
@ -183,8 +183,15 @@ namespace App {
|
||||||
}
|
}
|
||||||
|
|
||||||
QString onlineText(int32 online, int32 now, bool precise) {
|
QString onlineText(int32 online, int32 now, bool precise) {
|
||||||
if (!online) return lang(lng_status_offline);
|
if (online <= 0) {
|
||||||
if (online < 0) return lang(lng_status_invisible);
|
switch (online) {
|
||||||
|
case 0: return lang(lng_status_offline);
|
||||||
|
case -2: return lang(lng_status_recently);
|
||||||
|
case -3: return lang(lng_status_last_week);
|
||||||
|
case -4: return lang(lng_status_last_month);
|
||||||
|
}
|
||||||
|
return lang(lng_status_invisible);
|
||||||
|
}
|
||||||
if (online > now) {
|
if (online > now) {
|
||||||
return lang(lng_status_online);
|
return lang(lng_status_online);
|
||||||
}
|
}
|
||||||
|
@ -329,6 +336,10 @@ namespace App {
|
||||||
|
|
||||||
data->loaded = true;
|
data->loaded = true;
|
||||||
if (status) switch (status->type()) {
|
if (status) switch (status->type()) {
|
||||||
|
case mtpc_userStatusEmpty: data->onlineTill = 0; break;
|
||||||
|
case mtpc_userStatusRecently: data->onlineTill = -2; break;
|
||||||
|
case mtpc_userStatusLastWeek: data->onlineTill = -3; break;
|
||||||
|
case mtpc_userStatusLastMonth: data->onlineTill = -4; break;
|
||||||
case mtpc_userStatusOffline: data->onlineTill = status->c_userStatusOffline().vwas_online.v; break;
|
case mtpc_userStatusOffline: data->onlineTill = status->c_userStatusOffline().vwas_online.v; break;
|
||||||
case mtpc_userStatusOnline: data->onlineTill = status->c_userStatusOnline().vexpires.v; break;
|
case mtpc_userStatusOnline: data->onlineTill = status->c_userStatusOnline().vexpires.v; break;
|
||||||
}
|
}
|
||||||
|
@ -408,7 +419,7 @@ namespace App {
|
||||||
if (!data) continue;
|
if (!data) continue;
|
||||||
|
|
||||||
data->loaded = true;
|
data->loaded = true;
|
||||||
data->updateName(title.trimmed(), QString());
|
data->updateName(title.trimmed(), QString(), QString());
|
||||||
|
|
||||||
if (App::main()) App::main()->peerUpdated(data);
|
if (App::main()) App::main()->peerUpdated(data);
|
||||||
}
|
}
|
||||||
|
|
|
@ -633,7 +633,6 @@ void Application::startApp() {
|
||||||
|
|
||||||
readSupportTemplates();
|
readSupportTemplates();
|
||||||
|
|
||||||
MTP::setLayer(mtpLayerMax);
|
|
||||||
MTP::start();
|
MTP::start();
|
||||||
|
|
||||||
MTP::setStateChangedHandler(mtpStateChanged);
|
MTP::setStateChangedHandler(mtpStateChanged);
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 56 KiB |
Binary file not shown.
Before Width: | Height: | Size: 96 KiB After Width: | Height: | Size: 97 KiB |
|
@ -281,7 +281,7 @@ bool AddContactBox::onSaveFail(const RPCError &error) {
|
||||||
QString err(error.type());
|
QString err(error.type());
|
||||||
QString firstName = _firstInput.text().trimmed(), lastName = _lastInput.text().trimmed();
|
QString firstName = _firstInput.text().trimmed(), lastName = _lastInput.text().trimmed();
|
||||||
if (err == "CHAT_TITLE_NOT_MODIFIED") {
|
if (err == "CHAT_TITLE_NOT_MODIFIED") {
|
||||||
_peer->updateName(firstName, QString());
|
_peer->updateName(firstName, QString(), QString());
|
||||||
emit closed();
|
emit closed();
|
||||||
return true;
|
return true;
|
||||||
} else if (err == "NO_CHAT_TITLE") {
|
} else if (err == "NO_CHAT_TITLE") {
|
||||||
|
|
|
@ -231,6 +231,7 @@ void AddParticipantInner::mousePressEvent(QMouseEvent *e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddParticipantInner::chooseParticipant() {
|
void AddParticipantInner::chooseParticipant() {
|
||||||
|
_time = unixtime();
|
||||||
int32 rh = st::profileListPhotoSize + st::profileListPadding.height() * 2, from;
|
int32 rh = st::profileListPhotoSize + st::profileListPadding.height() * 2, from;
|
||||||
if (_filter.isEmpty()) {
|
if (_filter.isEmpty()) {
|
||||||
if (!_sel || contactData(_sel)->inchat) return;
|
if (!_sel || contactData(_sel)->inchat) return;
|
||||||
|
@ -293,6 +294,7 @@ void AddParticipantInner::updateSel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddParticipantInner::updateFilter(QString filter) {
|
void AddParticipantInner::updateFilter(QString filter) {
|
||||||
|
_time = unixtime();
|
||||||
QStringList f;
|
QStringList f;
|
||||||
if (!filter.isEmpty()) {
|
if (!filter.isEmpty()) {
|
||||||
QStringList filterList = filter.split(cWordSplit(), QString::SkipEmptyParts);
|
QStringList filterList = filter.split(cWordSplit(), QString::SkipEmptyParts);
|
||||||
|
@ -405,6 +407,7 @@ AddParticipantInner::~AddParticipantInner() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddParticipantInner::selectSkip(int32 dir) {
|
void AddParticipantInner::selectSkip(int32 dir) {
|
||||||
|
_time = unixtime();
|
||||||
_mouseSel = false;
|
_mouseSel = false;
|
||||||
int32 rh = st::profileListPhotoSize + st::profileListPadding.height() * 2, origDir = dir;
|
int32 rh = st::profileListPhotoSize + st::profileListPadding.height() * 2, origDir = dir;
|
||||||
if (_filter.isEmpty()) {
|
if (_filter.isEmpty()) {
|
||||||
|
|
|
@ -17,8 +17,8 @@ Copyright (c) 2014 John Preston, https://tdesktop.com
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
static const int32 AppVersion = 6008;
|
static const int32 AppVersion = 6009;
|
||||||
static const wchar_t *AppVersionStr = L"0.6.8";
|
static const wchar_t *AppVersionStr = L"0.6.9";
|
||||||
|
|
||||||
static const wchar_t *AppNameOld = L"Telegram Win (Unofficial)";
|
static const wchar_t *AppNameOld = L"Telegram Win (Unofficial)";
|
||||||
static const wchar_t *AppName = L"Telegram Desktop";
|
static const wchar_t *AppName = L"Telegram Desktop";
|
||||||
|
|
|
@ -3975,7 +3975,7 @@ QString textAccentFold(const QString &text) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (ch->isHighSurrogate() && ch + 1 < e && (ch + 1)->isLowSurrogate()) {
|
if (ch->isHighSurrogate() && ch + 1 < e && (ch + 1)->isLowSurrogate()) {
|
||||||
QChar noAccent = QChar::surrogateToUcs4(*ch, *(ch + 1));
|
QChar noAccent = chNoAccent(QChar::surrogateToUcs4(*ch, *(ch + 1)));
|
||||||
if (noAccent.unicode() > 0) {
|
if (noAccent.unicode() > 0) {
|
||||||
copying = true;
|
copying = true;
|
||||||
result[i] = noAccent;
|
result[i] = noAccent;
|
||||||
|
|
|
@ -296,12 +296,13 @@ const ChatData *PeerData::asChat() const {
|
||||||
return chat ? static_cast<const ChatData *>(this) : App::chat(id | 0x100000000L);
|
return chat ? static_cast<const ChatData *>(this) : App::chat(id | 0x100000000L);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeerData::updateName(const QString &newName, const QString &newNameOrPhone) {
|
void PeerData::updateName(const QString &newName, const QString &newNameOrPhone, const QString &newUsername) {
|
||||||
if (name == newName && nameOrPhone == newNameOrPhone) return;
|
if (name == newName && nameOrPhone == newNameOrPhone && (chat || asUser()->username == newUsername)) return;
|
||||||
|
|
||||||
++nameVersion;
|
++nameVersion;
|
||||||
name = newName;
|
name = newName;
|
||||||
nameOrPhone = newNameOrPhone;
|
nameOrPhone = newNameOrPhone;
|
||||||
|
if (!chat) asUser()->username = newUsername;
|
||||||
Names oldNames = names;
|
Names oldNames = names;
|
||||||
NameFirstChars oldChars = chars;
|
NameFirstChars oldChars = chars;
|
||||||
fillNames();
|
fillNames();
|
||||||
|
@ -352,24 +353,23 @@ void PeerData::fillNames() {
|
||||||
|
|
||||||
|
|
||||||
void UserData::setName(const QString &first, const QString &last, const QString &phoneName, const QString &usern) {
|
void UserData::setName(const QString &first, const QString &last, const QString &phoneName, const QString &usern) {
|
||||||
bool updName = !first.isEmpty() || !last.isEmpty();
|
bool updName = !first.isEmpty() || !last.isEmpty(), updUsername = (username != usern);
|
||||||
|
|
||||||
if (username != usern) {
|
|
||||||
username = usern;
|
|
||||||
if (App::main()) {
|
|
||||||
App::main()->peerUsernameChanged(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (updName && first.trimmed().isEmpty()) {
|
if (updName && first.trimmed().isEmpty()) {
|
||||||
firstName = last;
|
firstName = last;
|
||||||
lastName = QString();
|
lastName = QString();
|
||||||
updateName(firstName, phoneName);
|
updateName(firstName, phoneName, usern);
|
||||||
} else {
|
} else {
|
||||||
if (updName) {
|
if (updName) {
|
||||||
firstName = first;
|
firstName = first;
|
||||||
lastName = last;
|
lastName = last;
|
||||||
}
|
}
|
||||||
updateName(firstName + ' ' + lastName, phoneName);
|
updateName(firstName + ' ' + lastName, phoneName, usern);
|
||||||
|
}
|
||||||
|
if (updUsername) {
|
||||||
|
if (App::main()) {
|
||||||
|
App::main()->peerUsernameChanged(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1168,7 +1168,7 @@ HistoryItem *History::createItem(HistoryBlock *block, const MTPmessage &msg, boo
|
||||||
case mtpc_messageActionChatEditTitle: {
|
case mtpc_messageActionChatEditTitle: {
|
||||||
const MTPDmessageActionChatEditTitle &d(action.c_messageActionChatEditTitle());
|
const MTPDmessageActionChatEditTitle &d(action.c_messageActionChatEditTitle());
|
||||||
ChatData *chat = peer->asChat();
|
ChatData *chat = peer->asChat();
|
||||||
if (chat) chat->updateName(qs(d.vtitle), QString());
|
if (chat) chat->updateName(qs(d.vtitle), QString(), QString());
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3074,7 +3074,7 @@ void ImageLinkManager::init() {
|
||||||
App::setProxySettings(*manager);
|
App::setProxySettings(*manager);
|
||||||
|
|
||||||
connect(manager, SIGNAL(authenticationRequired(QNetworkReply*, QAuthenticator*)), this, SLOT(onFailed(QNetworkReply*)));
|
connect(manager, SIGNAL(authenticationRequired(QNetworkReply*, QAuthenticator*)), this, SLOT(onFailed(QNetworkReply*)));
|
||||||
connect(manager, SIGNAL(sslErrors(QNetworkReply*, const QList<QSslError>&errors)), this, SLOT(onFailed(QNetworkReply*)));
|
connect(manager, SIGNAL(sslErrors(QNetworkReply*, const QList<QSslError>&)), this, SLOT(onFailed(QNetworkReply*)));
|
||||||
connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(onFinished(QNetworkReply*)));
|
connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(onFinished(QNetworkReply*)));
|
||||||
|
|
||||||
if (black) delete black;
|
if (black) delete black;
|
||||||
|
|
|
@ -82,7 +82,7 @@ struct PeerData {
|
||||||
ChatData *asChat();
|
ChatData *asChat();
|
||||||
const ChatData *asChat() const;
|
const ChatData *asChat() const;
|
||||||
|
|
||||||
void updateName(const QString &newName, const QString &newNameOrPhone);
|
void updateName(const QString &newName, const QString &newNameOrPhone, const QString &newUsername);
|
||||||
|
|
||||||
void fillNames();
|
void fillNames();
|
||||||
|
|
||||||
|
|
|
@ -1548,7 +1548,7 @@ HistoryWidget::HistoryWidget(QWidget *parent) : QWidget(parent)
|
||||||
connect(&_attachDocument, SIGNAL(clicked()), this, SLOT(onDocumentSelect()));
|
connect(&_attachDocument, SIGNAL(clicked()), this, SLOT(onDocumentSelect()));
|
||||||
connect(&_attachPhoto, SIGNAL(clicked()), this, SLOT(onPhotoSelect()));
|
connect(&_attachPhoto, SIGNAL(clicked()), this, SLOT(onPhotoSelect()));
|
||||||
connect(&_field, SIGNAL(submitted(bool)), this, SLOT(onSend(bool)));
|
connect(&_field, SIGNAL(submitted(bool)), this, SLOT(onSend(bool)));
|
||||||
connect(&_field, SIGNAL(cancelled()), this, SIGNAL(cancelled()));
|
connect(&_field, SIGNAL(cancelled()), this, SLOT(onCancel()));
|
||||||
connect(&_field, SIGNAL(tabbed()), this, SLOT(onFieldTabbed()));
|
connect(&_field, SIGNAL(tabbed()), this, SLOT(onFieldTabbed()));
|
||||||
connect(&_field, SIGNAL(resized()), this, SLOT(onFieldResize()));
|
connect(&_field, SIGNAL(resized()), this, SLOT(onFieldResize()));
|
||||||
connect(&_field, SIGNAL(focused()), this, SLOT(onFieldFocused()));
|
connect(&_field, SIGNAL(focused()), this, SLOT(onFieldFocused()));
|
||||||
|
@ -3161,6 +3161,11 @@ void HistoryWidget::setFieldText(const QString &text) {
|
||||||
noTypingUpdate = false;
|
noTypingUpdate = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HistoryWidget::onCancel() {
|
||||||
|
showPeer(0);
|
||||||
|
emit cancelled();
|
||||||
|
}
|
||||||
|
|
||||||
void HistoryWidget::peerUpdated(PeerData *data) {
|
void HistoryWidget::peerUpdated(PeerData *data) {
|
||||||
if (data && data == histPeer) {
|
if (data && data == histPeer) {
|
||||||
updateListSize();
|
updateListSize();
|
||||||
|
|
|
@ -343,6 +343,8 @@ signals:
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
|
void onCancel();
|
||||||
|
|
||||||
void peerUpdated(PeerData *data);
|
void peerUpdated(PeerData *data);
|
||||||
|
|
||||||
void cancelTyping();
|
void cancelTyping();
|
||||||
|
|
|
@ -2252,6 +2252,9 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
|
||||||
if (user) {
|
if (user) {
|
||||||
switch (d.vstatus.type()) {
|
switch (d.vstatus.type()) {
|
||||||
case mtpc_userStatusEmpty: user->onlineTill = 0; break;
|
case mtpc_userStatusEmpty: user->onlineTill = 0; break;
|
||||||
|
case mtpc_userStatusRecently: user->onlineTill = -2; break;
|
||||||
|
case mtpc_userStatusLastWeek: user->onlineTill = -3; break;
|
||||||
|
case mtpc_userStatusLastMonth: user->onlineTill = -4; break;
|
||||||
case mtpc_userStatusOffline: user->onlineTill = d.vstatus.c_userStatusOffline().vwas_online.v; break;
|
case mtpc_userStatusOffline: user->onlineTill = d.vstatus.c_userStatusOffline().vwas_online.v; break;
|
||||||
case mtpc_userStatusOnline: user->onlineTill = d.vstatus.c_userStatusOnline().vexpires.v; break;
|
case mtpc_userStatusOnline: user->onlineTill = d.vstatus.c_userStatusOnline().vexpires.v; break;
|
||||||
}
|
}
|
||||||
|
@ -2263,8 +2266,12 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
|
||||||
case mtpc_updateUserName: {
|
case mtpc_updateUserName: {
|
||||||
const MTPDupdateUserName &d(update.c_updateUserName());
|
const MTPDupdateUserName &d(update.c_updateUserName());
|
||||||
UserData *user = App::userLoaded(d.vuser_id.v);
|
UserData *user = App::userLoaded(d.vuser_id.v);
|
||||||
if (user && user->contact <= 0) {
|
if (user) {
|
||||||
|
if (user->contact <= 0) {
|
||||||
user->setName(textOneLine(qs(d.vfirst_name)), textOneLine(qs(d.vlast_name)), user->nameOrPhone, textOneLine(qs(d.vusername)));
|
user->setName(textOneLine(qs(d.vfirst_name)), textOneLine(qs(d.vlast_name)), user->nameOrPhone, textOneLine(qs(d.vusername)));
|
||||||
|
} else {
|
||||||
|
user->setName(textOneLine(user->firstName), textOneLine(user->lastName), user->nameOrPhone, textOneLine(qs(d.vusername)));
|
||||||
|
}
|
||||||
if (App::main()) App::main()->peerUpdated(user);
|
if (App::main()) App::main()->peerUpdated(user);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
|
@ -177,11 +177,11 @@ with open('scheme.tl') as f:
|
||||||
funcsText += '\tMTP' + name + '(' + ', '.join(prmsStr) + ') : ' + ', '.join(prmsInit) + ' {\n\t}\n';
|
funcsText += '\tMTP' + name + '(' + ', '.join(prmsStr) + ') : ' + ', '.join(prmsInit) + ' {\n\t}\n';
|
||||||
funcsText += '\n';
|
funcsText += '\n';
|
||||||
|
|
||||||
funcsText += '\tuint32 size() const {\n'; # count size
|
funcsText += '\tuint32 innerLength() const {\n'; # count size
|
||||||
size = [];
|
size = [];
|
||||||
for k in prmsList:
|
for k in prmsList:
|
||||||
v = prms[k];
|
v = prms[k];
|
||||||
size.append('v' + k + '.size()');
|
size.append('v' + k + '.innerLength()');
|
||||||
if (not len(size)):
|
if (not len(size)):
|
||||||
size.append('0');
|
size.append('0');
|
||||||
funcsText += '\t\treturn ' + ' + '.join(size) + ';\n';
|
funcsText += '\t\treturn ' + ' + '.join(size) + ';\n';
|
||||||
|
@ -402,7 +402,7 @@ for restype in typesList:
|
||||||
writeText += '\t\t';
|
writeText += '\t\t';
|
||||||
readText += '\tv.v' + paramName + '.read(from, end);\n';
|
readText += '\tv.v' + paramName + '.read(from, end);\n';
|
||||||
writeText += '\tv.v' + paramName + '.write(to);\n';
|
writeText += '\tv.v' + paramName + '.write(to);\n';
|
||||||
sizeList.append('v.v' + paramName + '.size()');
|
sizeList.append('v.v' + paramName + '.innerLength()');
|
||||||
|
|
||||||
forwards += 'class MTPD' + name + ';\n'; # data class forward declaration
|
forwards += 'class MTPD' + name + ';\n'; # data class forward declaration
|
||||||
|
|
||||||
|
@ -505,8 +505,8 @@ for restype in typesList:
|
||||||
if (withData):
|
if (withData):
|
||||||
typesText += getters;
|
typesText += getters;
|
||||||
|
|
||||||
typesText += '\n\tuint32 size() const;\n'; # size method
|
typesText += '\n\tuint32 innerLength() const;\n'; # size method
|
||||||
inlineMethods += '\ninline uint32 MTP' + restype + '::size() const {\n';
|
inlineMethods += '\ninline uint32 MTP' + restype + '::innerLength() const {\n';
|
||||||
if (withType and sizeCases):
|
if (withType and sizeCases):
|
||||||
inlineMethods += '\tswitch (_type) {\n';
|
inlineMethods += '\tswitch (_type) {\n';
|
||||||
inlineMethods += sizeCases;
|
inlineMethods += sizeCases;
|
||||||
|
|
|
@ -350,10 +350,6 @@ namespace _mtp_internal {
|
||||||
requestsByDC.remove(requestId);
|
requestsByDC.remove(requestId);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 getLayer() {
|
|
||||||
return layer;
|
|
||||||
}
|
|
||||||
|
|
||||||
mtpRequestId storeRequest(mtpRequest &request, const RPCResponseHandler &parser) {
|
mtpRequestId storeRequest(mtpRequest &request, const RPCResponseHandler &parser) {
|
||||||
mtpRequestId res = reqid();
|
mtpRequestId res = reqid();
|
||||||
request->requestId = res;
|
request->requestId = res;
|
||||||
|
@ -379,20 +375,25 @@ namespace _mtp_internal {
|
||||||
return req;
|
return req;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wrapInvokeAfter(mtpRequest &to, const mtpRequest &from, const mtpRequestMap &haveSent) {
|
void wrapInvokeAfter(mtpRequest &to, const mtpRequest &from, const mtpRequestMap &haveSent, int32 skipBeforeRequest) {
|
||||||
mtpMsgId afterId(*(mtpMsgId*)(from->after->data() + 4));
|
mtpMsgId afterId(*(mtpMsgId*)(from->after->data() + 4));
|
||||||
mtpRequestMap::const_iterator i = afterId ? haveSent.constFind(afterId) : haveSent.cend();
|
mtpRequestMap::const_iterator i = afterId ? haveSent.constFind(afterId) : haveSent.cend();
|
||||||
int32 size = to->size(), len = (*from)[7] >> 2, headlen = 4, fulllen = headlen + len;
|
int32 size = to->size(), lenInInts = (from.innerLength() >> 2), headlen = 4, fulllen = headlen + lenInInts;
|
||||||
if (i == haveSent.constEnd()) { // no invoke after or such msg was not sent or was completed recently
|
if (i == haveSent.constEnd()) { // no invoke after or such msg was not sent or was completed recently
|
||||||
to->resize(size + fulllen);
|
to->resize(size + fulllen + skipBeforeRequest);
|
||||||
memcpy(to->data() + size, from->constData() + 4, fulllen * sizeof(mtpPrime));
|
if (skipBeforeRequest) {
|
||||||
|
memcpy(to->data() + size, from->constData() + 4, headlen * sizeof(mtpPrime));
|
||||||
|
memcpy(to->data() + size + headlen + skipBeforeRequest, from->constData() + 4 + headlen, lenInInts * sizeof(mtpPrime));
|
||||||
} else {
|
} else {
|
||||||
to->resize(size + fulllen + 3);
|
memcpy(to->data() + size, from->constData() + 4, fulllen * sizeof(mtpPrime));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
to->resize(size + fulllen + skipBeforeRequest + 3);
|
||||||
memcpy(to->data() + size, from->constData() + 4, headlen * sizeof(mtpPrime));
|
memcpy(to->data() + size, from->constData() + 4, headlen * sizeof(mtpPrime));
|
||||||
(*to)[size + 3] += 3 * sizeof(mtpPrime);
|
(*to)[size + 3] += 3 * sizeof(mtpPrime);
|
||||||
*((mtpTypeId*)&((*to)[size + headlen])) = mtpc_invokeAfterMsg;
|
*((mtpTypeId*)&((*to)[size + headlen + skipBeforeRequest])) = mtpc_invokeAfterMsg;
|
||||||
memcpy(to->data() + size + headlen + 1, &afterId, 2 * sizeof(mtpPrime));
|
memcpy(to->data() + size + headlen + skipBeforeRequest + 1, &afterId, 2 * sizeof(mtpPrime));
|
||||||
memcpy(to->data() + size + headlen + 3, from->constData() + 4 + headlen, len * sizeof(mtpPrime));
|
memcpy(to->data() + size + headlen + skipBeforeRequest + 3, from->constData() + 4 + headlen, lenInInts * sizeof(mtpPrime));
|
||||||
if (size + 3 != 7) (*to)[7] += 3 * sizeof(mtpPrime);
|
if (size + 3 != 7) (*to)[7] += 3 * sizeof(mtpPrime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -624,15 +625,6 @@ namespace MTP {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setLayer(uint32 l) {
|
|
||||||
if (l > mtpLayerMax) {
|
|
||||||
l = mtpLayerMax;
|
|
||||||
} else if (!l) {
|
|
||||||
l = 1;
|
|
||||||
}
|
|
||||||
layer = l - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setdc(int32 dc, bool fromZeroOnly) {
|
void setdc(int32 dc, bool fromZeroOnly) {
|
||||||
if (!started) return;
|
if (!started) return;
|
||||||
|
|
||||||
|
|
|
@ -26,13 +26,11 @@ namespace _mtp_internal {
|
||||||
void registerRequest(mtpRequestId requestId, int32 dc);
|
void registerRequest(mtpRequestId requestId, int32 dc);
|
||||||
void unregisterRequest(mtpRequestId requestId);
|
void unregisterRequest(mtpRequestId requestId);
|
||||||
|
|
||||||
uint32 getLayer();
|
|
||||||
|
|
||||||
static const uint32 dcShift = 10000;
|
static const uint32 dcShift = 10000;
|
||||||
|
|
||||||
mtpRequestId storeRequest(mtpRequest &request, const RPCResponseHandler &parser);
|
mtpRequestId storeRequest(mtpRequest &request, const RPCResponseHandler &parser);
|
||||||
mtpRequest getRequest(mtpRequestId req);
|
mtpRequest getRequest(mtpRequestId req);
|
||||||
void wrapInvokeAfter(mtpRequest &to, const mtpRequest &from, const mtpRequestMap &haveSent);
|
void wrapInvokeAfter(mtpRequest &to, const mtpRequest &from, const mtpRequestMap &haveSent, int32 skipBeforeRequest = 0);
|
||||||
void clearCallbacks(mtpRequestId requestId, int32 errorCode = RPCError::NoError); // 0 - do not toggle onError callback
|
void clearCallbacks(mtpRequestId requestId, int32 errorCode = RPCError::NoError); // 0 - do not toggle onError callback
|
||||||
void clearCallbacksDelayed(const RPCCallbackClears &requestIds);
|
void clearCallbacksDelayed(const RPCCallbackClears &requestIds);
|
||||||
void performDelayedClear();
|
void performDelayedClear();
|
||||||
|
@ -86,8 +84,6 @@ namespace MTP {
|
||||||
void restart();
|
void restart();
|
||||||
void restart(int32 dcMask);
|
void restart(int32 dcMask);
|
||||||
|
|
||||||
void setLayer(uint32 layer);
|
|
||||||
|
|
||||||
void setdc(int32 dc, bool fromZeroOnly = false);
|
void setdc(int32 dc, bool fromZeroOnly = false);
|
||||||
int32 maindc();
|
int32 maindc();
|
||||||
int32 dcstate(int32 dc = 0);
|
int32 dcstate(int32 dc = 0);
|
||||||
|
@ -98,7 +94,7 @@ namespace MTP {
|
||||||
MTProtoSessionPtr session = _mtp_internal::getSession(dc);
|
MTProtoSessionPtr session = _mtp_internal::getSession(dc);
|
||||||
if (!session) return 0;
|
if (!session) return 0;
|
||||||
|
|
||||||
return session->send(request, callbacks, msCanWait, _mtp_internal::getLayer(), !dc, after);
|
return session->send(request, callbacks, msCanWait, true, !dc, after);
|
||||||
}
|
}
|
||||||
template <typename TRequest>
|
template <typename TRequest>
|
||||||
inline mtpRequestId send(const TRequest &request, RPCDoneHandlerPtr onDone, RPCFailHandlerPtr onFail = RPCFailHandlerPtr(), int32 dc = 0, uint64 msCanWait = 0, mtpRequestId after = 0) {
|
inline mtpRequestId send(const TRequest &request, RPCDoneHandlerPtr onDone, RPCFailHandlerPtr onFail = RPCFailHandlerPtr(), int32 dc = 0, uint64 msCanWait = 0, mtpRequestId after = 0) {
|
||||||
|
|
|
@ -473,7 +473,7 @@ namespace {
|
||||||
mtpBuffer _preparePQFake(const MTPint128 &nonce) {
|
mtpBuffer _preparePQFake(const MTPint128 &nonce) {
|
||||||
MTPReq_pq req_pq(nonce);
|
MTPReq_pq req_pq(nonce);
|
||||||
mtpBuffer buffer;
|
mtpBuffer buffer;
|
||||||
uint32 requestSize = req_pq.size() >> 2;
|
uint32 requestSize = req_pq.innerLength() >> 2;
|
||||||
|
|
||||||
buffer.resize(0);
|
buffer.resize(0);
|
||||||
buffer.reserve(8 + requestSize);
|
buffer.reserve(8 + requestSize);
|
||||||
|
@ -604,7 +604,7 @@ void MTPabstractTcpConnection::socketRead() {
|
||||||
}
|
}
|
||||||
|
|
||||||
MTPautoConnection::MTPautoConnection(QThread *thread) : status(WaitingBoth),
|
MTPautoConnection::MTPautoConnection(QThread *thread) : status(WaitingBoth),
|
||||||
tcpNonce(MTP::nonce<MTPint128>()), httpNonce(MTP::nonce<MTPint128>()) {
|
tcpNonce(MTP::nonce<MTPint128>()), httpNonce(MTP::nonce<MTPint128>()), _tcpTimeout(1) {
|
||||||
moveToThread(thread);
|
moveToThread(thread);
|
||||||
|
|
||||||
manager.moveToThread(thread);
|
manager.moveToThread(thread);
|
||||||
|
@ -613,6 +613,9 @@ tcpNonce(MTP::nonce<MTPint128>()), httpNonce(MTP::nonce<MTPint128>()) {
|
||||||
httpStartTimer.moveToThread(thread);
|
httpStartTimer.moveToThread(thread);
|
||||||
httpStartTimer.setSingleShot(true);
|
httpStartTimer.setSingleShot(true);
|
||||||
connect(&httpStartTimer, SIGNAL(timeout()), this, SLOT(onHttpStart()));
|
connect(&httpStartTimer, SIGNAL(timeout()), this, SLOT(onHttpStart()));
|
||||||
|
tcpTimeoutTimer.moveToThread(thread);
|
||||||
|
tcpTimeoutTimer.setSingleShot(true);
|
||||||
|
connect(&tcpTimeoutTimer, SIGNAL(timeout()), this, SLOT(onTcpTimeoutTimer()));
|
||||||
|
|
||||||
sock.moveToThread(thread);
|
sock.moveToThread(thread);
|
||||||
sock.setProxy(QNetworkProxy(QNetworkProxy::NoProxy));
|
sock.setProxy(QNetworkProxy(QNetworkProxy::NoProxy));
|
||||||
|
@ -627,7 +630,7 @@ void MTPautoConnection::onHttpStart() {
|
||||||
if (status == HttpReady) {
|
if (status == HttpReady) {
|
||||||
DEBUG_LOG(("Connection Info: Http-transport chosen by timer"));
|
DEBUG_LOG(("Connection Info: Http-transport chosen by timer"));
|
||||||
status = UsingHttp;
|
status = UsingHttp;
|
||||||
sock.disconnect();
|
sock.disconnectFromHost();
|
||||||
emit connected();
|
emit connected();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -638,13 +641,37 @@ void MTPautoConnection::onSocketConnected() {
|
||||||
|
|
||||||
DEBUG_LOG(("Connection Info: sending fake req_pq through tcp transport"));
|
DEBUG_LOG(("Connection Info: sending fake req_pq through tcp transport"));
|
||||||
|
|
||||||
|
if (_tcpTimeout < 0) _tcpTimeout = -_tcpTimeout;
|
||||||
|
tcpTimeoutTimer.start(_tcpTimeout * 1000);
|
||||||
|
|
||||||
tcpSend(buffer);
|
tcpSend(buffer);
|
||||||
} else if (status == WaitingHttp || status == UsingHttp) {
|
} else if (status == WaitingHttp || status == UsingHttp) {
|
||||||
sock.disconnect();
|
sock.disconnectFromHost();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MTPautoConnection::onTcpTimeoutTimer() {
|
||||||
|
if (status == HttpReady || status == WaitingBoth || status == WaitingTcp) {
|
||||||
|
if (_tcpTimeout < 64) _tcpTimeout *= 2;
|
||||||
|
_tcpTimeout = -_tcpTimeout;
|
||||||
|
|
||||||
|
QAbstractSocket::SocketState state = sock.state();
|
||||||
|
if (state == QAbstractSocket::ConnectedState || state == QAbstractSocket::ConnectingState || state == QAbstractSocket::HostLookupState) {
|
||||||
|
sock.disconnectFromHost();
|
||||||
|
} else if (state != QAbstractSocket::ClosingState) {
|
||||||
|
sock.connectToHost(QHostAddress(_addr), _port);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MTPautoConnection::onSocketDisconnected() {
|
void MTPautoConnection::onSocketDisconnected() {
|
||||||
|
if (_tcpTimeout < 0) {
|
||||||
|
_tcpTimeout = -_tcpTimeout;
|
||||||
|
if (status == HttpReady || status == WaitingBoth || status == WaitingTcp) {
|
||||||
|
sock.connectToHost(QHostAddress(_addr), _port);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (status == WaitingBoth) {
|
if (status == WaitingBoth) {
|
||||||
status = WaitingHttp;
|
status = WaitingHttp;
|
||||||
} else if (status == WaitingTcp || status == UsingTcp) {
|
} else if (status == WaitingTcp || status == UsingTcp) {
|
||||||
|
@ -725,14 +752,17 @@ void MTPautoConnection::connectToServer(const QString &addr, int32 port) {
|
||||||
address = QUrl(qsl("http://%1:%2/api").arg(addr).arg(80));//not port - always 80 port for http transport
|
address = QUrl(qsl("http://%1:%2/api").arg(addr).arg(80));//not port - always 80 port for http transport
|
||||||
connect(&manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(requestFinished(QNetworkReply*)));
|
connect(&manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(requestFinished(QNetworkReply*)));
|
||||||
|
|
||||||
|
_addr = addr;
|
||||||
|
_port = port;
|
||||||
|
|
||||||
|
connect(&sock, SIGNAL(readyRead()), this, SLOT(socketRead()));
|
||||||
|
sock.connectToHost(QHostAddress(_addr), _port);
|
||||||
|
|
||||||
mtpBuffer buffer(_preparePQFake(httpNonce));
|
mtpBuffer buffer(_preparePQFake(httpNonce));
|
||||||
|
|
||||||
DEBUG_LOG(("Connection Info: sending fake req_pq through http transport"));
|
DEBUG_LOG(("Connection Info: sending fake req_pq through http transport"));
|
||||||
|
|
||||||
httpSend(buffer);
|
httpSend(buffer);
|
||||||
|
|
||||||
sock.connectToHost(QHostAddress(addr), port);
|
|
||||||
connect(&sock, SIGNAL(readyRead()), this, SLOT(socketRead()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MTPautoConnection::isConnected() {
|
bool MTPautoConnection::isConnected() {
|
||||||
|
@ -766,7 +796,7 @@ void MTPautoConnection::requestFinished(QNetworkReply *reply) {
|
||||||
} else {
|
} else {
|
||||||
DEBUG_LOG(("Connection Info: Http-transport chosen by pq-response, awaited"));
|
DEBUG_LOG(("Connection Info: Http-transport chosen by pq-response, awaited"));
|
||||||
status = UsingHttp;
|
status = UsingHttp;
|
||||||
sock.disconnect();
|
sock.disconnectFromHost();
|
||||||
emit connected();
|
emit connected();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -786,7 +816,7 @@ void MTPautoConnection::requestFinished(QNetworkReply *reply) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mayBeBadKey = _handleHttpError(reply);
|
bool mayBeBadKey = _handleHttpError(reply) && _sentEncrypted;
|
||||||
if (status == WaitingBoth) {
|
if (status == WaitingBoth) {
|
||||||
status = WaitingTcp;
|
status = WaitingTcp;
|
||||||
} else if (status == WaitingHttp || status == UsingHttp) {
|
} else if (status == WaitingHttp || status == UsingHttp) {
|
||||||
|
@ -802,14 +832,15 @@ void MTPautoConnection::socketPacket(mtpPrime *packet, uint32 size) {
|
||||||
if (data.size() == 1) {
|
if (data.size() == 1) {
|
||||||
if (status == WaitingBoth) {
|
if (status == WaitingBoth) {
|
||||||
status = WaitingHttp;
|
status = WaitingHttp;
|
||||||
sock.disconnect();
|
sock.disconnectFromHost();
|
||||||
} else if (status == HttpReady) {
|
} else if (status == HttpReady) {
|
||||||
DEBUG_LOG(("Connection Info: Http-transport chosen by bad tcp response, ready"));
|
DEBUG_LOG(("Connection Info: Http-transport chosen by bad tcp response, ready"));
|
||||||
status = UsingHttp;
|
status = UsingHttp;
|
||||||
sock.disconnect();
|
sock.disconnectFromHost();
|
||||||
emit connected();
|
emit connected();
|
||||||
} else if (status == WaitingTcp || status == UsingTcp) {
|
} else if (status == WaitingTcp || status == UsingTcp) {
|
||||||
emit error(data[0] == -404);
|
bool mayBeBadKey = (data[0] == -404) && _sentEncrypted;
|
||||||
|
emit error(mayBeBadKey);
|
||||||
} else {
|
} else {
|
||||||
LOG(("Strange Tcp Error; status %1").arg(status));
|
LOG(("Strange Tcp Error; status %1").arg(status));
|
||||||
}
|
}
|
||||||
|
@ -817,6 +848,7 @@ void MTPautoConnection::socketPacket(mtpPrime *packet, uint32 size) {
|
||||||
receivedQueue.push_back(data);
|
receivedQueue.push_back(data);
|
||||||
emit receivedData();
|
emit receivedData();
|
||||||
} else if (status == WaitingBoth || status == WaitingTcp || status == HttpReady) {
|
} else if (status == WaitingBoth || status == WaitingTcp || status == HttpReady) {
|
||||||
|
tcpTimeoutTimer.stop();
|
||||||
try {
|
try {
|
||||||
MTPResPQ res_pq = _readPQFakeReply(data);
|
MTPResPQ res_pq = _readPQFakeReply(data);
|
||||||
const MTPDresPQ &res_pq_data(res_pq.c_resPQ());
|
const MTPDresPQ &res_pq_data(res_pq.c_resPQ());
|
||||||
|
@ -828,11 +860,11 @@ void MTPautoConnection::socketPacket(mtpPrime *packet, uint32 size) {
|
||||||
} catch (Exception &e) {
|
} catch (Exception &e) {
|
||||||
if (status == WaitingBoth) {
|
if (status == WaitingBoth) {
|
||||||
status = WaitingHttp;
|
status = WaitingHttp;
|
||||||
sock.disconnect();
|
sock.disconnectFromHost();
|
||||||
} else if (status == HttpReady) {
|
} else if (status == HttpReady) {
|
||||||
DEBUG_LOG(("Connection Info: Http-transport chosen by bad tcp response, awaited"));
|
DEBUG_LOG(("Connection Info: Http-transport chosen by bad tcp response, awaited"));
|
||||||
status = UsingHttp;
|
status = UsingHttp;
|
||||||
sock.disconnect();
|
sock.disconnectFromHost();
|
||||||
emit connected();
|
emit connected();
|
||||||
} else {
|
} else {
|
||||||
emit error();
|
emit error();
|
||||||
|
@ -907,14 +939,15 @@ void MTPtcpConnection::disconnectFromServer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MTPtcpConnection::connectToServer(const QString &addr, int32 port) {
|
void MTPtcpConnection::connectToServer(const QString &addr, int32 port) {
|
||||||
sock.connectToHost(QHostAddress(addr), port);
|
|
||||||
connect(&sock, SIGNAL(readyRead()), this, SLOT(socketRead()));
|
connect(&sock, SIGNAL(readyRead()), this, SLOT(socketRead()));
|
||||||
|
sock.connectToHost(QHostAddress(addr), port);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MTPtcpConnection::socketPacket(mtpPrime *packet, uint32 size) {
|
void MTPtcpConnection::socketPacket(mtpPrime *packet, uint32 size) {
|
||||||
mtpBuffer data = _handleTcpResponse(packet, size);
|
mtpBuffer data = _handleTcpResponse(packet, size);
|
||||||
if (data.size() == 1) {
|
if (data.size() == 1) {
|
||||||
emit error(data[0] == -404);
|
bool mayBeBadKey = (data[0] == -404) && _sentEncrypted;
|
||||||
|
emit error(mayBeBadKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
receivedQueue.push_back(data);
|
receivedQueue.push_back(data);
|
||||||
|
@ -1002,7 +1035,7 @@ void MTPhttpConnection::requestFinished(QNetworkReply *reply) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mayBeBadKey = _handleHttpError(reply);
|
bool mayBeBadKey = _handleHttpError(reply) && _sentEncrypted;
|
||||||
|
|
||||||
emit error(mayBeBadKey);
|
emit error(mayBeBadKey);
|
||||||
}
|
}
|
||||||
|
@ -1362,6 +1395,7 @@ void MTProtoConnectionPrivate::tryToSend() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool needsLayer = !sessionData->layerWasInited();
|
||||||
bool prependOnly = false;
|
bool prependOnly = false;
|
||||||
mtpRequest pingRequest;
|
mtpRequest pingRequest;
|
||||||
if (toSendPingId) {
|
if (toSendPingId) {
|
||||||
|
@ -1370,7 +1404,7 @@ void MTProtoConnectionPrivate::tryToSend() {
|
||||||
prependOnly = (getState() != MTProtoConnection::Connected);
|
prependOnly = (getState() != MTProtoConnection::Connected);
|
||||||
DEBUG_LOG(("MTP Info: sending ping, ping_id: %1, prepend_only: %2").arg(ping.vping_id.v).arg(prependOnly ? "[TRUE]" : "[FALSE]"));
|
DEBUG_LOG(("MTP Info: sending ping, ping_id: %1, prepend_only: %2").arg(ping.vping_id.v).arg(prependOnly ? "[TRUE]" : "[FALSE]"));
|
||||||
|
|
||||||
uint32 pingSize = ping.size() >> 2; // copy from MTProtoSession::send
|
uint32 pingSize = ping.innerLength() >> 2; // copy from MTProtoSession::send
|
||||||
pingRequest = mtpRequestData::prepare(pingSize);
|
pingRequest = mtpRequestData::prepare(pingSize);
|
||||||
ping.write(*pingRequest);
|
ping.write(*pingRequest);
|
||||||
|
|
||||||
|
@ -1391,7 +1425,7 @@ void MTProtoConnectionPrivate::tryToSend() {
|
||||||
if (!prependOnly && !ackRequestData.isEmpty()) {
|
if (!prependOnly && !ackRequestData.isEmpty()) {
|
||||||
MTPMsgsAck ack(MTP_msgs_ack(MTP_vector<MTPlong>(ackRequestData)));
|
MTPMsgsAck ack(MTP_msgs_ack(MTP_vector<MTPlong>(ackRequestData)));
|
||||||
|
|
||||||
ackRequest = mtpRequestData::prepare(ack.size() >> 2);
|
ackRequest = mtpRequestData::prepare(ack.innerLength() >> 2);
|
||||||
ack.write(*ackRequest);
|
ack.write(*ackRequest);
|
||||||
|
|
||||||
ackRequest->msDate = getms(true); // > 0 - can send without container
|
ackRequest->msDate = getms(true); // > 0 - can send without container
|
||||||
|
@ -1402,7 +1436,7 @@ void MTProtoConnectionPrivate::tryToSend() {
|
||||||
if (!prependOnly && !resendRequestData.isEmpty()) {
|
if (!prependOnly && !resendRequestData.isEmpty()) {
|
||||||
MTPMsgResendReq resend(MTP_msg_resend_req(MTP_vector<MTPlong>(resendRequestData)));
|
MTPMsgResendReq resend(MTP_msg_resend_req(MTP_vector<MTPlong>(resendRequestData)));
|
||||||
|
|
||||||
resendRequest = mtpRequestData::prepare(resend.size() >> 2);
|
resendRequest = mtpRequestData::prepare(resend.innerLength() >> 2);
|
||||||
resend.write(*resendRequest);
|
resend.write(*resendRequest);
|
||||||
|
|
||||||
resendRequest->msDate = getms(true); // > 0 - can send without container
|
resendRequest->msDate = getms(true); // > 0 - can send without container
|
||||||
|
@ -1426,7 +1460,7 @@ void MTProtoConnectionPrivate::tryToSend() {
|
||||||
if (!stateReq.isEmpty()) {
|
if (!stateReq.isEmpty()) {
|
||||||
MTPMsgsStateReq req(MTP_msgs_state_req(MTP_vector<MTPlong>(stateReq)));
|
MTPMsgsStateReq req(MTP_msgs_state_req(MTP_vector<MTPlong>(stateReq)));
|
||||||
|
|
||||||
stateRequest = mtpRequestData::prepare(req.size() >> 2);
|
stateRequest = mtpRequestData::prepare(req.innerLength() >> 2);
|
||||||
req.write(*stateRequest);
|
req.write(*stateRequest);
|
||||||
|
|
||||||
stateRequest->msDate = getms(true); // > 0 - can send without container
|
stateRequest->msDate = getms(true); // > 0 - can send without container
|
||||||
|
@ -1434,6 +1468,14 @@ void MTProtoConnectionPrivate::tryToSend() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MTPInitConnection<mtpRequest> initWrapperImpl, *initWrapper = &initWrapperImpl;
|
||||||
|
int32 initSize = 0, initSizeInInts = 0;
|
||||||
|
if (needsLayer) {
|
||||||
|
initWrapperImpl = MTPInitConnection<mtpRequest>(MTP_int(ApiId), MTP_string(cApiDeviceModel()), MTP_string(cApiSystemVersion()), MTP_string(cApiAppVersion()), MTP_string(ApiLang), mtpRequest());
|
||||||
|
initSizeInInts = (initWrapper->innerLength() >> 2) + 2;
|
||||||
|
initSize = initSizeInInts * sizeof(mtpPrime);
|
||||||
|
}
|
||||||
|
|
||||||
bool needAnyResponse = false;
|
bool needAnyResponse = false;
|
||||||
mtpRequest toSendRequest;
|
mtpRequest toSendRequest;
|
||||||
{
|
{
|
||||||
|
@ -1473,14 +1515,27 @@ void MTProtoConnectionPrivate::tryToSend() {
|
||||||
QWriteLocker locker2(sessionData->haveSentMutex());
|
QWriteLocker locker2(sessionData->haveSentMutex());
|
||||||
mtpRequestMap &haveSent(sessionData->haveSentMap());
|
mtpRequestMap &haveSent(sessionData->haveSentMap());
|
||||||
haveSent.insert(msgId, toSendRequest);
|
haveSent.insert(msgId, toSendRequest);
|
||||||
|
|
||||||
|
if (needsLayer && !toSendRequest->needsLayer) needsLayer = false;
|
||||||
if (toSendRequest->after) {
|
if (toSendRequest->after) {
|
||||||
int32 toSendSize = toSendRequest->at(7) >> 2;
|
int32 toSendSize = toSendRequest.innerLength() >> 2;
|
||||||
mtpRequest wrappedRequest(mtpRequestData::prepare(toSendSize, toSendSize + 3)); // cons + msg_id
|
mtpRequest wrappedRequest(mtpRequestData::prepare(toSendSize, toSendSize + 3)); // cons + msg_id
|
||||||
wrappedRequest->resize(4);
|
wrappedRequest->resize(4);
|
||||||
memcpy(wrappedRequest->data(), toSendRequest->constData(), 4 * sizeof(mtpPrime));
|
memcpy(wrappedRequest->data(), toSendRequest->constData(), 4 * sizeof(mtpPrime));
|
||||||
_mtp_internal::wrapInvokeAfter(wrappedRequest, toSendRequest, haveSent);
|
_mtp_internal::wrapInvokeAfter(wrappedRequest, toSendRequest, haveSent);
|
||||||
toSendRequest = wrappedRequest;
|
toSendRequest = wrappedRequest;
|
||||||
}
|
}
|
||||||
|
if (needsLayer) {
|
||||||
|
int32 noWrapSize = (toSendRequest.innerLength() >> 2), toSendSize = noWrapSize + initSizeInInts;
|
||||||
|
mtpRequest wrappedRequest(mtpRequestData::prepare(toSendSize));
|
||||||
|
memcpy(wrappedRequest->data(), toSendRequest->constData(), 7 * sizeof(mtpPrime)); // all except length
|
||||||
|
wrappedRequest->push_back(mtpc_invokeWithLayer);
|
||||||
|
wrappedRequest->push_back(mtpCurrentLayer);
|
||||||
|
initWrapper->write(*wrappedRequest);
|
||||||
|
wrappedRequest->resize(wrappedRequest->size() + noWrapSize);
|
||||||
|
memcpy(wrappedRequest->data() + wrappedRequest->size() - noWrapSize, toSendRequest->constData() + 8, noWrapSize * sizeof(mtpPrime));
|
||||||
|
toSendRequest = wrappedRequest;
|
||||||
|
}
|
||||||
|
|
||||||
needAnyResponse = true;
|
needAnyResponse = true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1489,6 +1544,7 @@ void MTProtoConnectionPrivate::tryToSend() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else { // send in container
|
} else { // send in container
|
||||||
|
bool willNeedInit = false;
|
||||||
uint32 containerSize = 1 + 1, idsWrapSize = (toSendCount << 1); // cons + vector size, idsWrapSize - size of "request-like" wrap for msgId vector
|
uint32 containerSize = 1 + 1, idsWrapSize = (toSendCount << 1); // cons + vector size, idsWrapSize - size of "request-like" wrap for msgId vector
|
||||||
if (pingRequest) containerSize += mtpRequestData::messageSize(pingRequest);
|
if (pingRequest) containerSize += mtpRequestData::messageSize(pingRequest);
|
||||||
if (ackRequest) containerSize += mtpRequestData::messageSize(ackRequest);
|
if (ackRequest) containerSize += mtpRequestData::messageSize(ackRequest);
|
||||||
|
@ -1496,6 +1552,17 @@ void MTProtoConnectionPrivate::tryToSend() {
|
||||||
if (stateRequest) containerSize += mtpRequestData::messageSize(stateRequest);
|
if (stateRequest) containerSize += mtpRequestData::messageSize(stateRequest);
|
||||||
for (mtpPreRequestMap::iterator i = toSend.begin(), e = toSend.end(); i != e; ++i) {
|
for (mtpPreRequestMap::iterator i = toSend.begin(), e = toSend.end(); i != e; ++i) {
|
||||||
containerSize += mtpRequestData::messageSize(i.value());
|
containerSize += mtpRequestData::messageSize(i.value());
|
||||||
|
if (needsLayer && i.value()->needsLayer) {
|
||||||
|
containerSize += initSizeInInts;
|
||||||
|
willNeedInit = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mtpBuffer initSerialized;
|
||||||
|
if (willNeedInit) {
|
||||||
|
initSerialized.reserve(initSizeInInts);
|
||||||
|
initSerialized.push_back(mtpc_invokeWithLayer);
|
||||||
|
initSerialized.push_back(mtpCurrentLayer);
|
||||||
|
initWrapper->write(initSerialized);
|
||||||
}
|
}
|
||||||
toSendRequest = mtpRequestData::prepare(containerSize, containerSize + 3 * toSend.size()); // prepare container + each in invoke after
|
toSendRequest = mtpRequestData::prepare(containerSize, containerSize + 3 * toSend.size()); // prepare container + each in invoke after
|
||||||
toSendRequest->push_back(mtpc_msg_container);
|
toSendRequest->push_back(mtpc_msg_container);
|
||||||
|
@ -1530,8 +1597,20 @@ void MTProtoConnectionPrivate::tryToSend() {
|
||||||
if (req->requestId) {
|
if (req->requestId) {
|
||||||
if (mtpRequestData::needAck(req)) {
|
if (mtpRequestData::needAck(req)) {
|
||||||
req->msDate = mtpRequestData::isStateRequest(req) ? 0 : getms(true);
|
req->msDate = mtpRequestData::isStateRequest(req) ? 0 : getms(true);
|
||||||
|
int32 reqNeedsLayer = (needsLayer && req->needsLayer) ? toSendRequest->size() : 0;
|
||||||
if (req->after) {
|
if (req->after) {
|
||||||
_mtp_internal::wrapInvokeAfter(toSendRequest, req, haveSent);
|
_mtp_internal::wrapInvokeAfter(toSendRequest, req, haveSent, reqNeedsLayer ? initSizeInInts : 0);
|
||||||
|
if (reqNeedsLayer) {
|
||||||
|
memcpy(toSendRequest->data() + reqNeedsLayer + 4, initSerialized.constData(), initSize);
|
||||||
|
*(toSendRequest->data() + reqNeedsLayer + 3) += initSize;
|
||||||
|
}
|
||||||
|
added = true;
|
||||||
|
} else if (reqNeedsLayer) {
|
||||||
|
toSendRequest->resize(reqNeedsLayer + initSizeInInts + mtpRequestData::messageSize(req));
|
||||||
|
memcpy(toSendRequest->data() + reqNeedsLayer, req->constData() + 4, 4 * sizeof(mtpPrime));
|
||||||
|
memcpy(toSendRequest->data() + reqNeedsLayer + 4, initSerialized.constData(), initSize);
|
||||||
|
memcpy(toSendRequest->data() + reqNeedsLayer + 4 + initSizeInInts, req->constData() + 8, req.innerLength());
|
||||||
|
*(toSendRequest->data() + reqNeedsLayer + 3) += initSize;
|
||||||
added = true;
|
added = true;
|
||||||
}
|
}
|
||||||
haveSent.insert(msgId, req);
|
haveSent.insert(msgId, req);
|
||||||
|
@ -2329,6 +2408,10 @@ int32 MTProtoConnectionPrivate::handleOneReceived(const mtpPrime *from, const mt
|
||||||
response.resize(end - from);
|
response.resize(end - from);
|
||||||
memcpy(response.data(), from, (end - from) * sizeof(mtpPrime));
|
memcpy(response.data(), from, (end - from) * sizeof(mtpPrime));
|
||||||
}
|
}
|
||||||
|
if (!sessionData->layerWasInited()) {
|
||||||
|
sessionData->setLayerWasInited(true);
|
||||||
|
sessionData->owner()->notifyLayerInited(true);
|
||||||
|
}
|
||||||
|
|
||||||
mtpRequestId requestId = wasSent(reqMsgId.v);
|
mtpRequestId requestId = wasSent(reqMsgId.v);
|
||||||
if (requestId && requestId != mtpRequestId(0xFFFFFFFF)) {
|
if (requestId && requestId != mtpRequestId(0xFFFFFFFF)) {
|
||||||
|
@ -2787,7 +2870,7 @@ void MTProtoConnectionPrivate::pqAnswered() {
|
||||||
|
|
||||||
string &dhEncString(req_DH_params.vencrypted_data._string().v);
|
string &dhEncString(req_DH_params.vencrypted_data._string().v);
|
||||||
|
|
||||||
uint32 p_q_inner_size = p_q_inner.size(), encSize = (p_q_inner_size >> 2) + 6;
|
uint32 p_q_inner_size = p_q_inner.innerLength(), encSize = (p_q_inner_size >> 2) + 6;
|
||||||
if (encSize >= 65) {
|
if (encSize >= 65) {
|
||||||
mtpBuffer tmp;
|
mtpBuffer tmp;
|
||||||
tmp.reserve(encSize);
|
tmp.reserve(encSize);
|
||||||
|
@ -2854,7 +2937,7 @@ void MTProtoConnectionPrivate::dhParamsAnswered() {
|
||||||
return restart();
|
return restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 nlen = authKeyData->new_nonce.size(), slen = authKeyData->server_nonce.size();
|
uint32 nlen = authKeyData->new_nonce.innerLength(), slen = authKeyData->server_nonce.innerLength();
|
||||||
uchar tmp_aes[1024], sha1ns[20], sha1sn[20], sha1nn[20];
|
uchar tmp_aes[1024], sha1ns[20], sha1sn[20], sha1nn[20];
|
||||||
memcpy(tmp_aes, &authKeyData->new_nonce, nlen);
|
memcpy(tmp_aes, &authKeyData->new_nonce, nlen);
|
||||||
memcpy(tmp_aes + nlen, &authKeyData->server_nonce, slen);
|
memcpy(tmp_aes + nlen, &authKeyData->server_nonce, slen);
|
||||||
|
@ -2979,7 +3062,7 @@ void MTProtoConnectionPrivate::dhClientParamsSend() {
|
||||||
|
|
||||||
string &sdhEncString(req_client_DH_params.vencrypted_data._string().v);
|
string &sdhEncString(req_client_DH_params.vencrypted_data._string().v);
|
||||||
|
|
||||||
uint32 client_dh_inner_size = client_dh_inner.size(), encSize = (client_dh_inner_size >> 2) + 5, encFullSize = encSize;
|
uint32 client_dh_inner_size = client_dh_inner.innerLength(), encSize = (client_dh_inner_size >> 2) + 5, encFullSize = encSize;
|
||||||
if (encSize & 0x03) {
|
if (encSize & 0x03) {
|
||||||
encFullSize += 4 - (encSize & 0x03);
|
encFullSize += 4 - (encSize & 0x03);
|
||||||
}
|
}
|
||||||
|
@ -3047,7 +3130,7 @@ void MTProtoConnectionPrivate::dhClientParamsAnswered() {
|
||||||
|
|
||||||
DEBUG_LOG(("AuthKey Info: auth key gen succeed, id: %1, server salt: %2, auth key: %3").arg(authKey->keyId()).arg(serverSalt).arg(mb(authKeyData->auth_key, 256).str()));
|
DEBUG_LOG(("AuthKey Info: auth key gen succeed, id: %1, server salt: %2, auth key: %3").arg(authKey->keyId()).arg(serverSalt).arg(mb(authKeyData->auth_key, 256).str()));
|
||||||
|
|
||||||
sessionData->owner()->keyCreated(authKey); // slot will call authKeyCreated()
|
sessionData->owner()->notifyKeyCreated(authKey); // slot will call authKeyCreated()
|
||||||
sessionData->clear();
|
sessionData->clear();
|
||||||
unlockKey();
|
unlockKey();
|
||||||
} return;
|
} return;
|
||||||
|
@ -3146,7 +3229,7 @@ void MTProtoConnectionPrivate::sendPing() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MTProtoConnectionPrivate::onError(bool mayBeBadKey) {
|
void MTProtoConnectionPrivate::onError(bool mayBeBadKey) {
|
||||||
MTP_LOG(dc, ("Restarting after error.."));
|
MTP_LOG(dc, ("Restarting after error, maybe bad key: %1..").arg(logBool(mayBeBadKey)));
|
||||||
return restart(mayBeBadKey);
|
return restart(mayBeBadKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3157,7 +3240,7 @@ template <typename TRequest>
|
||||||
void MTProtoConnectionPrivate::sendRequestNotSecure(const TRequest &request) {
|
void MTProtoConnectionPrivate::sendRequestNotSecure(const TRequest &request) {
|
||||||
try {
|
try {
|
||||||
mtpBuffer buffer;
|
mtpBuffer buffer;
|
||||||
uint32 requestSize = request.size() >> 2;
|
uint32 requestSize = request.innerLength() >> 2;
|
||||||
|
|
||||||
buffer.resize(0);
|
buffer.resize(0);
|
||||||
buffer.reserve(8 + requestSize);
|
buffer.reserve(8 + requestSize);
|
||||||
|
@ -3264,6 +3347,7 @@ bool MTProtoConnectionPrivate::sendRequest(mtpRequest &request, bool needAnyResp
|
||||||
|
|
||||||
DEBUG_LOG(("MTP Info: sending request, size: %1, num: %2, time: %3").arg(fullSize + 6).arg((*request)[4]).arg((*request)[5]));
|
DEBUG_LOG(("MTP Info: sending request, size: %1, num: %2, time: %3").arg(fullSize + 6).arg((*request)[4]).arg((*request)[5]));
|
||||||
|
|
||||||
|
conn->setSentEncrypted();
|
||||||
conn->sendData(result);
|
conn->sendData(result);
|
||||||
|
|
||||||
if (needAnyResponse) {
|
if (needAnyResponse) {
|
||||||
|
|
|
@ -106,6 +106,13 @@ class MTPabstractConnection : public QObject {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
MTPabstractConnection() : _sentEncrypted(false) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void setSentEncrypted() {
|
||||||
|
_sentEncrypted = true;
|
||||||
|
}
|
||||||
|
|
||||||
virtual void sendData(mtpBuffer &buffer) = 0; // has size + 3, buffer[0] = len, buffer[1] = packetnum, buffer[last] = crc32
|
virtual void sendData(mtpBuffer &buffer) = 0; // has size + 3, buffer[0] = len, buffer[1] = packetnum, buffer[last] = crc32
|
||||||
virtual void disconnectFromServer() = 0;
|
virtual void disconnectFromServer() = 0;
|
||||||
virtual void connectToServer(const QString &addr, int32 port) = 0;
|
virtual void connectToServer(const QString &addr, int32 port) = 0;
|
||||||
|
@ -135,6 +142,7 @@ signals:
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
BuffersQueue receivedQueue; // list of received packets, not processed yet
|
BuffersQueue receivedQueue; // list of received packets, not processed yet
|
||||||
|
bool _sentEncrypted;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -189,6 +197,8 @@ public slots:
|
||||||
void onSocketDisconnected();
|
void onSocketDisconnected();
|
||||||
void onHttpStart();
|
void onHttpStart();
|
||||||
|
|
||||||
|
void onTcpTimeoutTimer();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void socketPacket(mtpPrime *packet, uint32 packetSize);
|
void socketPacket(mtpPrime *packet, uint32 packetSize);
|
||||||
|
@ -215,6 +225,10 @@ private:
|
||||||
typedef QSet<QNetworkReply*> Requests;
|
typedef QSet<QNetworkReply*> Requests;
|
||||||
Requests requests;
|
Requests requests;
|
||||||
|
|
||||||
|
QString _addr;
|
||||||
|
int32 _port, _tcpTimeout;
|
||||||
|
QTimer tcpTimeoutTimer;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class MTPtcpConnection : public MTPabstractTcpConnection {
|
class MTPtcpConnection : public MTPabstractTcpConnection {
|
||||||
|
|
|
@ -172,12 +172,20 @@ void mtpTextSerializeCore(MTPStringLogger &to, const mtpPrime *&from, const mtpP
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
for (uint32 i = 1; i < mtpLayerMax; ++i) {
|
for (uint32 i = 1; i < mtpLayerMaxSingle; ++i) {
|
||||||
if (cons == mtpLayers[i]) {
|
if (cons == mtpLayers[i]) {
|
||||||
to.add("[LAYER").add(mtpWrapNumber(i + 1)).add("] "); mtpTextSerializeType(to, from, end, 0, level);
|
to.add("[LAYER").add(mtpWrapNumber(i + 1)).add("] "); mtpTextSerializeType(to, from, end, 0, level);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (cons == mtpc_invokeWithLayer) {
|
||||||
|
if (from >= end) {
|
||||||
|
throw Exception("from >= end in invokeWithLayer");
|
||||||
|
}
|
||||||
|
int32 layer = *(from++);
|
||||||
|
to.add("[LAYER").add(mtpWrapNumber(layer)).add("] "); mtpTextSerializeType(to, from, end, 0, level);
|
||||||
|
return;
|
||||||
|
}
|
||||||
throw Exception(QString("unknown cons 0x%1").arg(cons, 0, 16));
|
throw Exception(QString("unknown cons 0x%1").arg(cons, 0, 16));
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,7 @@ public:
|
||||||
explicit mtpRequest(mtpRequestData *ptr) : QSharedPointer<mtpRequestData>(ptr) {
|
explicit mtpRequest(mtpRequestData *ptr) : QSharedPointer<mtpRequestData>(ptr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 size() const;
|
uint32 innerLength() const;
|
||||||
void write(mtpBuffer &to) const;
|
void write(mtpBuffer &to) const;
|
||||||
|
|
||||||
typedef void ResponseType; // don't know real response type =(
|
typedef void ResponseType; // don't know real response type =(
|
||||||
|
@ -74,10 +74,12 @@ public:
|
||||||
// in toSend: = 0 - must send in container, > 0 - can send without container
|
// in toSend: = 0 - must send in container, > 0 - can send without container
|
||||||
// in haveSent: = 0 - container with msgIds, > 0 - when was sent
|
// in haveSent: = 0 - container with msgIds, > 0 - when was sent
|
||||||
uint64 msDate;
|
uint64 msDate;
|
||||||
|
|
||||||
mtpRequestId requestId;
|
mtpRequestId requestId;
|
||||||
mtpRequest after;
|
mtpRequest after;
|
||||||
|
bool needsLayer;
|
||||||
|
|
||||||
mtpRequestData(bool/* sure*/) : msDate(0), requestId(0) {
|
mtpRequestData(bool/* sure*/) : msDate(0), requestId(0), needsLayer(false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static mtpRequest prepare(uint32 requestSize, uint32 maxSize = 0) {
|
static mtpRequest prepare(uint32 requestSize, uint32 maxSize = 0) {
|
||||||
|
@ -92,7 +94,7 @@ public:
|
||||||
static void padding(mtpRequest &request) {
|
static void padding(mtpRequest &request) {
|
||||||
if (request->size() < 9) return;
|
if (request->size() < 9) return;
|
||||||
|
|
||||||
uint32 requestSize = ((*request)[7] >> 2), padding = _padding(requestSize), fullSize = 8 + requestSize + padding; // 2: salt, 2: session_id, 2: msg_id, 1: seq_no, 1: message_length
|
uint32 requestSize = (request.innerLength() >> 2), padding = _padding(requestSize), fullSize = 8 + requestSize + padding; // 2: salt, 2: session_id, 2: msg_id, 1: seq_no, 1: message_length
|
||||||
if (uint32(request->size()) != fullSize) {
|
if (uint32(request->size()) != fullSize) {
|
||||||
request->resize(fullSize);
|
request->resize(fullSize);
|
||||||
if (padding) {
|
if (padding) {
|
||||||
|
@ -103,7 +105,7 @@ public:
|
||||||
|
|
||||||
static uint32 messageSize(const mtpRequest &request) {
|
static uint32 messageSize(const mtpRequest &request) {
|
||||||
if (request->size() < 9) return 0;
|
if (request->size() < 9) return 0;
|
||||||
return 4 + ((*request)[7] >> 2); // 2: msg_id, 1: seq_no, q: message_length
|
return 4 + (request.innerLength() >> 2); // 2: msg_id, 1: seq_no, q: message_length
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isSentContainer(const mtpRequest &request); // "request-like" wrap for msgIds vector
|
static bool isSentContainer(const mtpRequest &request); // "request-like" wrap for msgIds vector
|
||||||
|
@ -119,7 +121,7 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline uint32 mtpRequest::size() const { // for template MTP requests and MTPBoxed instanciation
|
inline uint32 mtpRequest::innerLength() const { // for template MTP requests and MTPBoxed instanciation
|
||||||
mtpRequestData *value = data();
|
mtpRequestData *value = data();
|
||||||
if (!value || value->size() < 9) return 0;
|
if (!value || value->size() < 9) return 0;
|
||||||
return value->at(7);
|
return value->at(7);
|
||||||
|
@ -128,7 +130,7 @@ inline uint32 mtpRequest::size() const { // for template MTP requests and MTPBox
|
||||||
inline void mtpRequest::write(mtpBuffer &to) const {
|
inline void mtpRequest::write(mtpBuffer &to) const {
|
||||||
mtpRequestData *value = data();
|
mtpRequestData *value = data();
|
||||||
if (!value || value->size() < 9) return;
|
if (!value || value->size() < 9) return;
|
||||||
uint32 was = to.size(), s = size() / sizeof(mtpPrime);
|
uint32 was = to.size(), s = innerLength() / sizeof(mtpPrime);
|
||||||
to.resize(was + s);
|
to.resize(was + s);
|
||||||
memcpy(to.data() + was, value->constData() + 8, s * sizeof(mtpPrime));
|
memcpy(to.data() + was, value->constData() + 8, s * sizeof(mtpPrime));
|
||||||
}
|
}
|
||||||
|
@ -335,6 +337,8 @@ enum {
|
||||||
mtpc_invokeWithLayer17 = 0x50858a19,
|
mtpc_invokeWithLayer17 = 0x50858a19,
|
||||||
mtpc_invokeWithLayer18 = 0x1c900537,
|
mtpc_invokeWithLayer18 = 0x1c900537,
|
||||||
|
|
||||||
|
mtpc_invokeWithLayer = 0xda9b0d0d, // after 18 layer
|
||||||
|
|
||||||
// manually parsed
|
// manually parsed
|
||||||
mtpc_rpc_result = 0xf35c6d01,
|
mtpc_rpc_result = 0xf35c6d01,
|
||||||
mtpc_msg_container = 0x73f1f8dc,
|
mtpc_msg_container = 0x73f1f8dc,
|
||||||
|
@ -362,7 +366,8 @@ static const mtpTypeId mtpLayers[] = {
|
||||||
mtpc_invokeWithLayer16,
|
mtpc_invokeWithLayer16,
|
||||||
mtpc_invokeWithLayer17,
|
mtpc_invokeWithLayer17,
|
||||||
mtpc_invokeWithLayer18,
|
mtpc_invokeWithLayer18,
|
||||||
}, mtpLayerMax = sizeof(mtpLayers) / sizeof(mtpLayers[0]);
|
}, mtpLayerMaxSingle = sizeof(mtpLayers) / sizeof(mtpLayers[0]);
|
||||||
|
static const mtpPrime mtpCurrentLayer = 19;
|
||||||
|
|
||||||
template <typename bareT>
|
template <typename bareT>
|
||||||
class MTPBoxed : public bareT {
|
class MTPBoxed : public bareT {
|
||||||
|
@ -386,8 +391,8 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 size() const {
|
uint32 innerLength() const {
|
||||||
return sizeof(mtpTypeId) + bareT::size();
|
return sizeof(mtpTypeId) + bareT::innerLength();
|
||||||
}
|
}
|
||||||
void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) {
|
void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) {
|
||||||
if (from + 1 > end) throw mtpErrorInsufficient();
|
if (from + 1 > end) throw mtpErrorInsufficient();
|
||||||
|
@ -414,7 +419,7 @@ public:
|
||||||
read(from, end, cons);
|
read(from, end, cons);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 size() const {
|
uint32 innerLength() const {
|
||||||
return sizeof(int32);
|
return sizeof(int32);
|
||||||
}
|
}
|
||||||
mtpTypeId type() const {
|
mtpTypeId type() const {
|
||||||
|
@ -457,7 +462,7 @@ public:
|
||||||
read(from, end, cons);
|
read(from, end, cons);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 size() const {
|
uint32 innerLength() const {
|
||||||
return sizeof(uint64);
|
return sizeof(uint64);
|
||||||
}
|
}
|
||||||
mtpTypeId type() const {
|
mtpTypeId type() const {
|
||||||
|
@ -503,7 +508,7 @@ public:
|
||||||
read(from, end, cons);
|
read(from, end, cons);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 size() const {
|
uint32 innerLength() const {
|
||||||
return sizeof(uint64) + sizeof(uint64);
|
return sizeof(uint64) + sizeof(uint64);
|
||||||
}
|
}
|
||||||
mtpTypeId type() const {
|
mtpTypeId type() const {
|
||||||
|
@ -552,8 +557,8 @@ public:
|
||||||
read(from, end, cons);
|
read(from, end, cons);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 size() const {
|
uint32 innerLength() const {
|
||||||
return l.size() + h.size();
|
return l.innerLength() + h.innerLength();
|
||||||
}
|
}
|
||||||
mtpTypeId type() const {
|
mtpTypeId type() const {
|
||||||
return mtpc_int256;
|
return mtpc_int256;
|
||||||
|
@ -596,7 +601,7 @@ public:
|
||||||
read(from, end, cons);
|
read(from, end, cons);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 size() const {
|
uint32 innerLength() const {
|
||||||
return sizeof(float64);
|
return sizeof(float64);
|
||||||
}
|
}
|
||||||
mtpTypeId type() const {
|
mtpTypeId type() const {
|
||||||
|
@ -666,7 +671,7 @@ public:
|
||||||
return *(const MTPDstring*)data;
|
return *(const MTPDstring*)data;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 size() const {
|
uint32 innerLength() const {
|
||||||
uint32 l = c_string().v.length();
|
uint32 l = c_string().v.length();
|
||||||
if (l < 254) {
|
if (l < 254) {
|
||||||
l += 1;
|
l += 1;
|
||||||
|
@ -770,7 +775,7 @@ public:
|
||||||
read(from, end, cons);
|
read(from, end, cons);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 size() const {
|
uint32 innerLength() const {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
mtpTypeId type() const {
|
mtpTypeId type() const {
|
||||||
|
@ -858,10 +863,10 @@ public:
|
||||||
return *(const MTPDvector<T>*)data;
|
return *(const MTPDvector<T>*)data;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 size() const {
|
uint32 innerLength() const {
|
||||||
uint32 result(sizeof(uint32));
|
uint32 result(sizeof(uint32));
|
||||||
for (typename VType::const_iterator i = c_vector().v.cbegin(), e = c_vector().v.cend(); i != e; ++i) {
|
for (typename VType::const_iterator i = c_vector().v.cbegin(), e = c_vector().v.cend(); i != e; ++i) {
|
||||||
result += i->size();
|
result += i->innerLength();
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -961,8 +966,8 @@ public:
|
||||||
return *(const MTPDerror*)data;
|
return *(const MTPDerror*)data;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 size() const {
|
uint32 innerLength() const {
|
||||||
return c_error().vcode.size() + c_error().vtext.size();
|
return c_error().vcode.innerLength() + c_error().vtext.innerLength();
|
||||||
}
|
}
|
||||||
mtpTypeId type() const {
|
mtpTypeId type() const {
|
||||||
return mtpc_error;
|
return mtpc_error;
|
||||||
|
@ -999,7 +1004,7 @@ public:
|
||||||
read(from, end, cons);
|
read(from, end, cons);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 size() const {
|
uint32 innerLength() const {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
mtpTypeId type() const {
|
mtpTypeId type() const {
|
||||||
|
|
|
@ -350,7 +350,7 @@ void mtpSetDC(int32 dc) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MTProtoDC::MTProtoDC(int32 id, const mtpAuthKeyPtr &key) : _id(id), _key(key), _connectionInited(false), _connectionInitSent(false) {
|
MTProtoDC::MTProtoDC(int32 id, const mtpAuthKeyPtr &key) : _id(id), _key(key), _connectionInited(false) {
|
||||||
connect(this, SIGNAL(authKeyCreated()), this, SLOT(authKeyWrite()), Qt::QueuedConnection);
|
connect(this, SIGNAL(authKeyCreated()), this, SLOT(authKeyWrite()), Qt::QueuedConnection);
|
||||||
|
|
||||||
QMutexLocker lock(&_keysMapForWriteMutex);
|
QMutexLocker lock(&_keysMapForWriteMutex);
|
||||||
|
@ -371,6 +371,7 @@ void MTProtoDC::authKeyWrite() {
|
||||||
void MTProtoDC::setKey(const mtpAuthKeyPtr &key) {
|
void MTProtoDC::setKey(const mtpAuthKeyPtr &key) {
|
||||||
DEBUG_LOG(("AuthKey Info: MTProtoDC::setKey(%1), emitting authKeyCreated, dc %2").arg(key ? key->keyId() : 0).arg(_id));
|
DEBUG_LOG(("AuthKey Info: MTProtoDC::setKey(%1), emitting authKeyCreated, dc %2").arg(key ? key->keyId() : 0).arg(_id));
|
||||||
_key = key;
|
_key = key;
|
||||||
|
_connectionInited = false;
|
||||||
emit authKeyCreated();
|
emit authKeyCreated();
|
||||||
|
|
||||||
QMutexLocker lock(&_keysMapForWriteMutex);
|
QMutexLocker lock(&_keysMapForWriteMutex);
|
||||||
|
|
|
@ -29,13 +29,6 @@ public:
|
||||||
void setKey(const mtpAuthKeyPtr &key);
|
void setKey(const mtpAuthKeyPtr &key);
|
||||||
void destroyKey();
|
void destroyKey();
|
||||||
|
|
||||||
bool needConnectionInit() {
|
|
||||||
QMutexLocker lock(&initLock);
|
|
||||||
if (_connectionInited || _connectionInitSent) return false;
|
|
||||||
_connectionInitSent = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool connectionInited() const {
|
bool connectionInited() const {
|
||||||
QMutexLocker lock(&initLock);
|
QMutexLocker lock(&initLock);
|
||||||
bool res = _connectionInited;
|
bool res = _connectionInited;
|
||||||
|
@ -49,6 +42,7 @@ public:
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void authKeyCreated();
|
void authKeyCreated();
|
||||||
|
void layerWasInited(bool was);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
|
@ -61,7 +55,6 @@ private:
|
||||||
int32 _id;
|
int32 _id;
|
||||||
mtpAuthKeyPtr _key;
|
mtpAuthKeyPtr _key;
|
||||||
bool _connectionInited;
|
bool _connectionInited;
|
||||||
bool _connectionInitSent;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef QSharedPointer<MTProtoDC> MTProtoDCPtr;
|
typedef QSharedPointer<MTProtoDC> MTProtoDCPtr;
|
||||||
|
|
|
@ -174,8 +174,7 @@ bool mtpFileLoader::loadPart() {
|
||||||
App::app()->killDownloadSessionsStop(dc);
|
App::app()->killDownloadSessionsStop(dc);
|
||||||
}
|
}
|
||||||
|
|
||||||
MTPupload_GetFile request(MTPupload_getFile(loc, MTP_int(offset), MTP_int(limit)));
|
mtpRequestId reqId = MTP::send(MTPupload_GetFile(MTPupload_getFile(loc, MTP_int(offset), MTP_int(limit))), rpcDone(&mtpFileLoader::partLoaded, offset), rpcFail(&mtpFileLoader::partFailed), MTP::dld[dcIndex] + dc, 50);
|
||||||
mtpRequestId reqId = MTP::send(request, rpcDone(&mtpFileLoader::partLoaded, offset), rpcFail(&mtpFileLoader::partFailed), MTP::dld[dcIndex] + dc, 50);
|
|
||||||
|
|
||||||
++queue->queries;
|
++queue->queries;
|
||||||
dr.v[dcIndex] += limit;
|
dr.v[dcIndex] += limit;
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -113,8 +113,11 @@ void MTProtoSession::start(int32 dcenter, uint32 connects) {
|
||||||
|
|
||||||
ReadLockerAttempt lock(keyMutex());
|
ReadLockerAttempt lock(keyMutex());
|
||||||
data.setKey(lock ? dc->getKey() : mtpAuthKeyPtr(0));
|
data.setKey(lock ? dc->getKey() : mtpAuthKeyPtr(0));
|
||||||
|
if (lock && dc->connectionInited()) {
|
||||||
|
data.setLayerWasInited(true);
|
||||||
|
}
|
||||||
connect(dc.data(), SIGNAL(authKeyCreated()), this, SLOT(authKeyCreatedForDC()));
|
connect(dc.data(), SIGNAL(authKeyCreated()), this, SLOT(authKeyCreatedForDC()));
|
||||||
|
connect(dc.data(), SIGNAL(layerWasInited(bool)), this, SLOT(layerWasInitedForDC(bool)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -376,21 +379,9 @@ void MTProtoSession::sendPrepared(const mtpRequest &request, uint64 msCanWait, b
|
||||||
sendAnything(msCanWait);
|
sendAnything(msCanWait);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MTProtoSession::sendPreparedWithInit(const mtpRequest &request, uint64 msCanWait) { // returns true, if emit of needToSend() is needed
|
void MTProtoSession::sendPreparedWithInit(const mtpRequest &request, uint64 msCanWait) {
|
||||||
if (request->size() > 8 && request->at(8) == mtpc_initConnection) {
|
request->needsLayer = true;
|
||||||
sendPrepared(request, msCanWait, false);
|
sendPrepared(request, msCanWait, false);
|
||||||
return;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
MTPInitConnection<mtpRequest> requestWrap(MTPinitConnection<mtpRequest>(MTP_int(ApiId), MTP_string(cApiDeviceModel()), MTP_string(cApiSystemVersion()), MTP_string(cApiAppVersion()), MTP_string(ApiLang), request));
|
|
||||||
uint32 requestSize = requestWrap.size() >> 2;
|
|
||||||
mtpRequest reqSerialized(mtpRequestData::prepare(requestSize));
|
|
||||||
requestWrap.write(*reqSerialized);
|
|
||||||
request->resize(reqSerialized->size());
|
|
||||||
memcpy(request->data(), reqSerialized->constData(), reqSerialized->size());
|
|
||||||
}
|
|
||||||
request->msDate = getms(true); // > 0 - can send without container
|
|
||||||
sendPrepared(request, msCanWait);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QReadWriteLock *MTProtoSession::keyMutex() const {
|
QReadWriteLock *MTProtoSession::keyMutex() const {
|
||||||
|
@ -403,11 +394,22 @@ void MTProtoSession::authKeyCreatedForDC() {
|
||||||
emit authKeyCreated();
|
emit authKeyCreated();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MTProtoSession::keyCreated(const mtpAuthKeyPtr &key) {
|
void MTProtoSession::notifyKeyCreated(const mtpAuthKeyPtr &key) {
|
||||||
DEBUG_LOG(("AuthKey Info: MTProtoSession::keyCreated(), setting, dc %1").arg(dcId));
|
DEBUG_LOG(("AuthKey Info: MTProtoSession::keyCreated(), setting, dc %1").arg(dcId));
|
||||||
dc->setKey(key);
|
dc->setKey(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MTProtoSession::layerWasInitedForDC(bool wasInited) {
|
||||||
|
DEBUG_LOG(("MTP Info: MTProtoSession::layerWasInitedForDC slot, dc %1").arg(dcId));
|
||||||
|
data.setLayerWasInited(wasInited);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MTProtoSession::notifyLayerInited(bool wasInited) {
|
||||||
|
DEBUG_LOG(("MTP Info: emitting MTProtoDC::layerWasInited(%1), dc %2").arg(logBool(wasInited)).arg(dcId));
|
||||||
|
dc->setConnectionInited(wasInited);
|
||||||
|
emit dc->layerWasInited(wasInited);
|
||||||
|
}
|
||||||
|
|
||||||
void MTProtoSession::destroyKey() {
|
void MTProtoSession::destroyKey() {
|
||||||
if (!dc) return;
|
if (!dc) return;
|
||||||
|
|
||||||
|
|
|
@ -28,8 +28,8 @@ public:
|
||||||
|
|
||||||
MTPSessionData(MTProtoSession *creator)
|
MTPSessionData(MTProtoSession *creator)
|
||||||
: _session(0), _salt(0)
|
: _session(0), _salt(0)
|
||||||
, _messagesSent(0), fakeRequestId(-2000000000)
|
, _messagesSent(0), _fakeRequestId(-2000000000)
|
||||||
, _owner(creator), keyChecked(false) {
|
, _owner(creator), _keyChecked(false), _layerInited(false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSession(uint64 session) {
|
void setSession(uint64 session) {
|
||||||
|
@ -45,6 +45,14 @@ public:
|
||||||
QReadLocker locker(&lock);
|
QReadLocker locker(&lock);
|
||||||
return _session;
|
return _session;
|
||||||
}
|
}
|
||||||
|
bool layerWasInited() const {
|
||||||
|
QReadLocker locker(&lock);
|
||||||
|
return _layerInited;
|
||||||
|
}
|
||||||
|
void setLayerWasInited(bool was) {
|
||||||
|
QWriteLocker locker(&lock);
|
||||||
|
_layerInited = was;
|
||||||
|
}
|
||||||
|
|
||||||
void setSalt(uint64 salt) {
|
void setSalt(uint64 salt) {
|
||||||
QWriteLocker locker(&lock);
|
QWriteLocker locker(&lock);
|
||||||
|
@ -56,26 +64,31 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
const mtpAuthKeyPtr &getKey() const {
|
const mtpAuthKeyPtr &getKey() const {
|
||||||
return authKey;
|
return _authKey;
|
||||||
}
|
}
|
||||||
void setKey(const mtpAuthKeyPtr &key) {
|
void setKey(const mtpAuthKeyPtr &key) {
|
||||||
if (authKey != key) {
|
if (_authKey != key) {
|
||||||
uint64 session;
|
uint64 session;
|
||||||
memsetrnd(session);
|
memsetrnd(session);
|
||||||
authKey = key;
|
_authKey = key;
|
||||||
|
|
||||||
DEBUG_LOG(("MTP Info: new auth key set in SessionData, id %1, setting random server_session %2").arg(key ? key->keyId() : 0).arg(session));
|
DEBUG_LOG(("MTP Info: new auth key set in SessionData, id %1, setting random server_session %2").arg(key ? key->keyId() : 0).arg(session));
|
||||||
setSession(session);
|
QWriteLocker locker(&lock);
|
||||||
|
if (_session != session) {
|
||||||
|
_session = session;
|
||||||
|
_messagesSent = 0;
|
||||||
|
}
|
||||||
|
_layerInited = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isCheckedKey() const {
|
bool isCheckedKey() const {
|
||||||
QReadLocker locker(&lock);
|
QReadLocker locker(&lock);
|
||||||
return keyChecked;
|
return _keyChecked;
|
||||||
}
|
}
|
||||||
void setCheckedKey(bool checked) {
|
void setCheckedKey(bool checked) {
|
||||||
QWriteLocker locker(&lock);
|
QWriteLocker locker(&lock);
|
||||||
keyChecked = checked;
|
_keyChecked = checked;
|
||||||
}
|
}
|
||||||
|
|
||||||
QReadWriteLock *keyMutex() const;
|
QReadWriteLock *keyMutex() const;
|
||||||
|
@ -147,11 +160,11 @@ public:
|
||||||
|
|
||||||
mtpRequestId nextFakeRequestId() { // must be locked by haveReceivedMutex()
|
mtpRequestId nextFakeRequestId() { // must be locked by haveReceivedMutex()
|
||||||
if (haveReceived.isEmpty() || haveReceived.cbegin().key() > 0) {
|
if (haveReceived.isEmpty() || haveReceived.cbegin().key() > 0) {
|
||||||
fakeRequestId = -2000000000;
|
_fakeRequestId = -2000000000;
|
||||||
} else {
|
} else {
|
||||||
++fakeRequestId;
|
++_fakeRequestId;
|
||||||
}
|
}
|
||||||
return fakeRequestId;
|
return _fakeRequestId;
|
||||||
}
|
}
|
||||||
|
|
||||||
MTProtoSession *owner() {
|
MTProtoSession *owner() {
|
||||||
|
@ -174,12 +187,12 @@ private:
|
||||||
uint64 _session, _salt;
|
uint64 _session, _salt;
|
||||||
|
|
||||||
uint32 _messagesSent;
|
uint32 _messagesSent;
|
||||||
mtpRequestId fakeRequestId;
|
mtpRequestId _fakeRequestId;
|
||||||
|
|
||||||
MTProtoSession *_owner;
|
MTProtoSession *_owner;
|
||||||
|
|
||||||
mtpAuthKeyPtr authKey;
|
mtpAuthKeyPtr _authKey;
|
||||||
bool keyChecked;
|
bool _keyChecked, _layerInited;
|
||||||
|
|
||||||
mtpPreRequestMap toSend; // map of request_id -> request, that is waiting to be sent
|
mtpPreRequestMap toSend; // map of request_id -> request, that is waiting to be sent
|
||||||
mtpRequestMap haveSent; // map of msg_id -> request, that was sent, msDate = 0 for msgs_state_req (no resend / state req), msDate = 0, seqNo = 0 for containers
|
mtpRequestMap haveSent; // map of msg_id -> request, that was sent, msDate = 0 for msgs_state_req (no resend / state req), msDate = 0, seqNo = 0 for containers
|
||||||
|
@ -216,11 +229,12 @@ public:
|
||||||
~MTProtoSession();
|
~MTProtoSession();
|
||||||
|
|
||||||
QReadWriteLock *keyMutex() const;
|
QReadWriteLock *keyMutex() const;
|
||||||
void keyCreated(const mtpAuthKeyPtr &key);
|
void notifyKeyCreated(const mtpAuthKeyPtr &key);
|
||||||
void destroyKey();
|
void destroyKey();
|
||||||
|
void notifyLayerInited(bool wasInited);
|
||||||
|
|
||||||
template <typename TRequest>
|
template <typename TRequest>
|
||||||
mtpRequestId send(const TRequest &request, RPCResponseHandler callbacks = RPCResponseHandler(), uint64 msCanWait = 0, uint32 layer = 0, bool toMainDC = false, mtpRequestId after = 0); // send mtp request
|
mtpRequestId send(const TRequest &request, RPCResponseHandler callbacks = RPCResponseHandler(), uint64 msCanWait = 0, bool needsLayer = false, bool toMainDC = false, mtpRequestId after = 0); // send mtp request
|
||||||
void sendAnything(uint64 msCanWait);
|
void sendAnything(uint64 msCanWait);
|
||||||
|
|
||||||
void cancel(mtpRequestId requestId, mtpMsgId msgId);
|
void cancel(mtpRequestId requestId, mtpMsgId msgId);
|
||||||
|
@ -247,6 +261,7 @@ signals:
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
void authKeyCreatedForDC();
|
void authKeyCreatedForDC();
|
||||||
|
void layerWasInitedForDC(bool wasInited);
|
||||||
|
|
||||||
void tryToReceive();
|
void tryToReceive();
|
||||||
void checkRequestsByTimer();
|
void checkRequestsByTimer();
|
||||||
|
@ -255,9 +270,6 @@ public slots:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
template <typename TRequest>
|
|
||||||
mtpRequestId sendFirst(const MTPInitConnection<TRequest> &request, RPCResponseHandler callbacks = RPCResponseHandler(), uint64 msCanWait = 0, uint32 layer = 0, bool toMainDC = false, mtpRequestId after = 0); // send first mtp request
|
|
||||||
|
|
||||||
typedef QList<MTProtoConnection*> MTProtoConnections;
|
typedef QList<MTProtoConnection*> MTProtoConnections;
|
||||||
MTProtoConnections connections;
|
MTProtoConnections connections;
|
||||||
|
|
||||||
|
|
|
@ -18,22 +18,17 @@ Copyright (c) 2014 John Preston, https://tdesktop.com
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
template <typename TRequest>
|
template <typename TRequest>
|
||||||
mtpRequestId MTProtoSession::send(const TRequest &request, RPCResponseHandler callbacks, uint64 msCanWait, uint32 layer, bool toMainDC, mtpRequestId after) {
|
mtpRequestId MTProtoSession::send(const TRequest &request, RPCResponseHandler callbacks, uint64 msCanWait, bool needsLayer, bool toMainDC, mtpRequestId after) {
|
||||||
mtpRequestId requestId = 0;
|
mtpRequestId requestId = 0;
|
||||||
if (layer && dc->needConnectionInit()) {
|
|
||||||
MTPInitConnection<TRequest> requestWrap(MTPinitConnection<TRequest>(MTP_int(ApiId), MTP_string(cApiDeviceModel()), MTP_string(cApiSystemVersion()), MTP_string(cApiAppVersion()), MTP_string(ApiLang), request));
|
|
||||||
return sendFirst(requestWrap, callbacks, msCanWait, layer, toMainDC, after);
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
uint32 requestSize = request.size() >> 2;
|
uint32 requestSize = request.innerLength() >> 2;
|
||||||
if (dc->connectionInited()) layer = 0;
|
mtpRequest reqSerialized(mtpRequestData::prepare(requestSize));
|
||||||
mtpRequest reqSerialized(mtpRequestData::prepare(requestSize + (layer ? 1 : 0)));
|
|
||||||
if (layer) reqSerialized->push_back(mtpLayers[layer]);
|
|
||||||
request.write(*reqSerialized);
|
request.write(*reqSerialized);
|
||||||
|
|
||||||
DEBUG_LOG(("MTP Info: adding request to toSendMap, msCanWait %1").arg(msCanWait));
|
DEBUG_LOG(("MTP Info: adding request to toSendMap, msCanWait %1").arg(msCanWait));
|
||||||
|
|
||||||
reqSerialized->msDate = getms(true); // > 0 - can send without container
|
reqSerialized->msDate = getms(true); // > 0 - can send without container
|
||||||
|
reqSerialized->needsLayer = needsLayer;
|
||||||
if (after) reqSerialized->after = _mtp_internal::getRequest(after);
|
if (after) reqSerialized->after = _mtp_internal::getRequest(after);
|
||||||
requestId = _mtp_internal::storeRequest(reqSerialized, callbacks);
|
requestId = _mtp_internal::storeRequest(reqSerialized, callbacks);
|
||||||
|
|
||||||
|
@ -45,44 +40,3 @@ mtpRequestId MTProtoSession::send(const TRequest &request, RPCResponseHandler ca
|
||||||
if (requestId) _mtp_internal::registerRequest(requestId, toMainDC ? -getDC() : getDC());
|
if (requestId) _mtp_internal::registerRequest(requestId, toMainDC ? -getDC() : getDC());
|
||||||
return requestId;
|
return requestId;
|
||||||
}
|
}
|
||||||
|
|
||||||
class RPCWrappedDcDoneHandler : public RPCAbstractDoneHandler {
|
|
||||||
public:
|
|
||||||
RPCWrappedDcDoneHandler(const MTProtoDCPtr &dc, const RPCDoneHandlerPtr &ondone) : _dc(dc), _ondone(ondone) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) const {
|
|
||||||
_dc->setConnectionInited();
|
|
||||||
if (_ondone) (*_ondone)(requestId, from, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
MTProtoDCPtr _dc;
|
|
||||||
RPCDoneHandlerPtr _ondone;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename TRequest>
|
|
||||||
mtpRequestId MTProtoSession::sendFirst(const MTPInitConnection<TRequest> &request, RPCResponseHandler callbacks, uint64 msCanWait, uint32 layer, bool toMainDC, mtpRequestId after) {
|
|
||||||
mtpRequestId requestId = 0;
|
|
||||||
try {
|
|
||||||
uint32 requestSize = request.size() >> 2;
|
|
||||||
mtpRequest reqSerialized(mtpRequestData::prepare(requestSize + (layer ? 1 : 0)));
|
|
||||||
if (layer) reqSerialized->push_back(mtpLayers[layer]);
|
|
||||||
request.write(*reqSerialized);
|
|
||||||
|
|
||||||
DEBUG_LOG(("MTP Info: adding wrapped to init connection request to toSendMap, msCanWait %1").arg(msCanWait));
|
|
||||||
callbacks.onDone = RPCDoneHandlerPtr(new RPCWrappedDcDoneHandler(dc, callbacks.onDone));
|
|
||||||
reqSerialized->msDate = getms(true); // > 0 - can send without container
|
|
||||||
if (after) reqSerialized->after = _mtp_internal::getRequest(after);
|
|
||||||
requestId = _mtp_internal::storeRequest(reqSerialized, callbacks);
|
|
||||||
|
|
||||||
sendPrepared(reqSerialized, msCanWait);
|
|
||||||
} catch (Exception &e) {
|
|
||||||
requestId = 0;
|
|
||||||
_mtp_internal::rpcErrorOccured(requestId, callbacks, rpcClientError("NO_REQUEST_ID", QString("sendFirst() failed to queue request, exception: %1").arg(e.what())));
|
|
||||||
}
|
|
||||||
if (requestId) {
|
|
||||||
_mtp_internal::registerRequest(requestId, toMainDC ? -getDC() : getDC());
|
|
||||||
}
|
|
||||||
return requestId;
|
|
||||||
}
|
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
/////////////////// Layer cons
|
/////////////////// Layer cons
|
||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
//invokeAfterMsg#cb9f372d msg_id:long query:!X = X;
|
//invokeAfterMsg#cb9f372d msg_id:long query:!X = X;
|
||||||
//invokeAfterMsgs#3dc4b4f0 msg_ids:Vector<long> query:!X = X;
|
//invokeAfterMsgs#3dc4b4f0 msg_ids:Vector<long> query:!X = X;
|
||||||
//invokeWithLayer1#53835315 query:!X = X;
|
//invokeWithLayer1#53835315 query:!X = X;
|
||||||
|
@ -34,6 +33,7 @@
|
||||||
//invokeWithLayer16#cf5f0987 query:!X = X;
|
//invokeWithLayer16#cf5f0987 query:!X = X;
|
||||||
//invokeWithLayer17#50858a19 query:!X = X;
|
//invokeWithLayer17#50858a19 query:!X = X;
|
||||||
//invokeWithLayer18#1c900537 query:!X = X;
|
//invokeWithLayer18#1c900537 query:!X = X;
|
||||||
|
//invokeWithLayer#da9b0d0d layer:int query:!X = X; // after 18 layer
|
||||||
|
|
||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
/// Authorization key creation
|
/// Authorization key creation
|
||||||
|
@ -287,7 +287,7 @@ contactBlocked#561bc879 user_id:int date:int = ContactBlocked;
|
||||||
|
|
||||||
contactSuggested#3de191a1 user_id:int mutual_contacts:int = ContactSuggested;
|
contactSuggested#3de191a1 user_id:int mutual_contacts:int = ContactSuggested;
|
||||||
|
|
||||||
contactStatus#aa77b873 user_id:int expires:int = ContactStatus;
|
contactStatus#d3680c61 user_id:int status:UserStatus = ContactStatus;
|
||||||
|
|
||||||
chatLocated#3631cf4c chat_id:int distance:int = ChatLocated;
|
chatLocated#3631cf4c chat_id:int distance:int = ChatLocated;
|
||||||
|
|
||||||
|
@ -510,6 +510,34 @@ contacts.found#566000e results:Vector<ContactFound> users:Vector<User> = contact
|
||||||
|
|
||||||
updateServiceNotification#382dd3e4 type:string message:string media:MessageMedia popup:Bool = Update;
|
updateServiceNotification#382dd3e4 type:string message:string media:MessageMedia popup:Bool = Update;
|
||||||
|
|
||||||
|
userStatusRecently#e26f42f1 = UserStatus;
|
||||||
|
userStatusLastWeek#7bf09fc = UserStatus;
|
||||||
|
userStatusLastMonth#77ebc742 = UserStatus;
|
||||||
|
|
||||||
|
updatePrivacy#ee3b272a key:PrivacyKey rules:Vector<PrivacyRule> = Update;
|
||||||
|
|
||||||
|
inputPrivacyKeyStatusTimestamp#4f96cb18 = InputPrivacyKey;
|
||||||
|
|
||||||
|
privacyKeyStatusTimestamp#bc2eab30 = PrivacyKey;
|
||||||
|
|
||||||
|
inputPrivacyValueAllowContacts#d09e07b = InputPrivacyRule;
|
||||||
|
inputPrivacyValueAllowAll#184b35ce = InputPrivacyRule;
|
||||||
|
inputPrivacyValueAllowUsers#131cc67f users:Vector<InputUser> = InputPrivacyRule;
|
||||||
|
inputPrivacyValueDisallowContacts#ba52007 = InputPrivacyRule;
|
||||||
|
inputPrivacyValueDisallowAll#d66b66c9 = InputPrivacyRule;
|
||||||
|
inputPrivacyValueDisallowUsers#90110467 users:Vector<InputUser> = InputPrivacyRule;
|
||||||
|
|
||||||
|
privacyValueAllowContacts#fffe1bac = PrivacyRule;
|
||||||
|
privacyValueAllowAll#65427b82 = PrivacyRule;
|
||||||
|
privacyValueAllowUsers#4d5bbe0c users:Vector<int> = PrivacyRule;
|
||||||
|
privacyValueDisallowContacts#f888fa1a = PrivacyRule;
|
||||||
|
privacyValueDisallowAll#8b73e763 = PrivacyRule;
|
||||||
|
privacyValueDisallowUsers#c7f49b7 users:Vector<int> = PrivacyRule;
|
||||||
|
|
||||||
|
account.privacyRules#554abb6f rules:Vector<PrivacyRule> users:Vector<User> = account.PrivacyRules;
|
||||||
|
|
||||||
|
accountDaysTTL#b8d0afdf days:int = AccountDaysTTL;
|
||||||
|
|
||||||
---functions---
|
---functions---
|
||||||
|
|
||||||
invokeAfterMsg#cb9f372d msg_id:long query:!X = X;
|
invokeAfterMsg#cb9f372d msg_id:long query:!X = X;
|
||||||
|
@ -631,3 +659,9 @@ account.checkUsername#2714d86c username:string = Bool;
|
||||||
account.updateUsername#3e0bdd7c username:string = User;
|
account.updateUsername#3e0bdd7c username:string = User;
|
||||||
|
|
||||||
contacts.search#11f812d8 q:string limit:int = contacts.Found;
|
contacts.search#11f812d8 q:string limit:int = contacts.Found;
|
||||||
|
|
||||||
|
account.getPrivacy#dadbc950 key:InputPrivacyKey = account.PrivacyRules;
|
||||||
|
account.setPrivacy#c9f81ce8 key:InputPrivacyKey rules:Vector<InputPrivacyRule> = account.PrivacyRules;
|
||||||
|
account.deleteAccount#418d4e0b reason:string = Bool;
|
||||||
|
account.getAccountTTL#8fc711d = AccountDaysTTL;
|
||||||
|
account.setAccountTTL#2442485e ttl:AccountDaysTTL = Bool;
|
||||||
|
|
|
@ -40,6 +40,7 @@ OverviewInner::OverviewInner(OverviewWidget *overview, ScrollArea *scroll, const
|
||||||
, _hist(App::history(peer->id))
|
, _hist(App::history(peer->id))
|
||||||
, _photosInRow(1)
|
, _photosInRow(1)
|
||||||
, _photosToAdd(0)
|
, _photosToAdd(0)
|
||||||
|
, _selMode(false)
|
||||||
, _width(0)
|
, _width(0)
|
||||||
, _height(0)
|
, _height(0)
|
||||||
, _minHeight(0)
|
, _minHeight(0)
|
||||||
|
@ -425,7 +426,7 @@ void OverviewInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton bu
|
||||||
dragActionUpdate(screenPos);
|
dragActionUpdate(screenPos);
|
||||||
|
|
||||||
if (textlnkOver()) {
|
if (textlnkOver()) {
|
||||||
if (textlnkDown() == textlnkOver() && _dragAction != Dragging) {
|
if (textlnkDown() == textlnkOver() && _dragAction != Dragging && !_selMode) {
|
||||||
needClick = textlnkDown();
|
needClick = textlnkDown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -662,7 +663,10 @@ void OverviewInner::paintEvent(QPaintEvent *e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sel == FullItemSel) {
|
if (sel == FullItemSel) {
|
||||||
p.fillRect(QRect(pos.x(), pos.y(), _vsize, _vsize), st::msgInSelectOverlay->b);
|
p.fillRect(QRect(pos.x(), pos.y(), _vsize, _vsize), st::overviewPhotoSelectOverlay->b);
|
||||||
|
p.drawPixmap(QPoint(pos.x() + _vsize - st::overviewPhotoChecked.pxWidth(), pos.y() + _vsize - st::overviewPhotoChecked.pxHeight()), App::sprite(), st::overviewPhotoChecked);
|
||||||
|
} else if (_selMode/* || (selfrom < count && selfrom <= selto && 0 <= selto)*/) {
|
||||||
|
p.drawPixmap(QPoint(pos.x() + _vsize - st::overviewPhotoChecked.pxWidth(), pos.y() + _vsize - st::overviewPhotoChecked.pxHeight()), App::sprite(), st::overviewPhotoCheck);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
|
@ -1136,6 +1140,10 @@ void OverviewInner::switchType(MediaOverviewType type) {
|
||||||
if (App::wnd()) App::wnd()->update();
|
if (App::wnd()) App::wnd()->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OverviewInner::setSelectMode(bool enabled) {
|
||||||
|
_selMode = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
void OverviewInner::openContextUrl() {
|
void OverviewInner::openContextUrl() {
|
||||||
HistoryItem *was = App::hoveredLinkItem();
|
HistoryItem *was = App::hoveredLinkItem();
|
||||||
App::hoveredLinkItem(App::contextItem());
|
App::hoveredLinkItem(App::contextItem());
|
||||||
|
@ -1620,6 +1628,8 @@ MediaOverviewType OverviewWidget::type() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void OverviewWidget::switchType(MediaOverviewType type) {
|
void OverviewWidget::switchType(MediaOverviewType type) {
|
||||||
|
_selCount = 0;
|
||||||
|
_inner.setSelectMode(false);
|
||||||
_inner.switchType(type);
|
_inner.switchType(type);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case OverviewPhotos: _header = lang(lng_profile_photos_header); break;
|
case OverviewPhotos: _header = lang(lng_profile_photos_header); break;
|
||||||
|
@ -1628,7 +1638,6 @@ void OverviewWidget::switchType(MediaOverviewType type) {
|
||||||
case OverviewAudios: _header = lang(lng_profile_audios_header); break;
|
case OverviewAudios: _header = lang(lng_profile_audios_header); break;
|
||||||
}
|
}
|
||||||
noSelectingScroll();
|
noSelectingScroll();
|
||||||
_selCount = 0;
|
|
||||||
App::main()->topBar()->showSelected(0);
|
App::main()->topBar()->showSelected(0);
|
||||||
updateTopBarSelection();
|
updateTopBarSelection();
|
||||||
_scroll.scrollToY(_scroll.scrollTopMax());
|
_scroll.scrollToY(_scroll.scrollTopMax());
|
||||||
|
@ -1639,6 +1648,7 @@ void OverviewWidget::updateTopBarSelection() {
|
||||||
int32 selectedForForward, selectedForDelete;
|
int32 selectedForForward, selectedForDelete;
|
||||||
_inner.getSelectionState(selectedForForward, selectedForDelete);
|
_inner.getSelectionState(selectedForForward, selectedForDelete);
|
||||||
_selCount = selectedForDelete ? selectedForDelete : selectedForForward;
|
_selCount = selectedForDelete ? selectedForDelete : selectedForForward;
|
||||||
|
_inner.setSelectMode(_selCount > 0);
|
||||||
if (App::main()) {
|
if (App::main()) {
|
||||||
App::main()->topBar()->showSelected(_selCount > 0 ? _selCount : 0);
|
App::main()->topBar()->showSelected(_selCount > 0 ? _selCount : 0);
|
||||||
App::main()->topBar()->update();
|
App::main()->topBar()->update();
|
||||||
|
|
|
@ -55,6 +55,8 @@ public:
|
||||||
MediaOverviewType type() const;
|
MediaOverviewType type() const;
|
||||||
void switchType(MediaOverviewType type);
|
void switchType(MediaOverviewType type);
|
||||||
|
|
||||||
|
void setSelectMode(bool enabled);
|
||||||
|
|
||||||
void mediaOverviewUpdated();
|
void mediaOverviewUpdated();
|
||||||
void changingMsgId(HistoryItem *row, MsgId newId);
|
void changingMsgId(HistoryItem *row, MsgId newId);
|
||||||
void msgUpdated(const HistoryItem *msg);
|
void msgUpdated(const HistoryItem *msg);
|
||||||
|
@ -124,6 +126,7 @@ private:
|
||||||
} CachedSize;
|
} CachedSize;
|
||||||
typedef QMap<PhotoData*, CachedSize> CachedSizes;
|
typedef QMap<PhotoData*, CachedSize> CachedSizes;
|
||||||
CachedSizes _cached;
|
CachedSizes _cached;
|
||||||
|
bool _selMode;
|
||||||
|
|
||||||
// other
|
// other
|
||||||
typedef struct _CachedItem {
|
typedef struct _CachedItem {
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>0.6.8</string>
|
<string>0.6.9</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>NOTE</key>
|
<key>NOTE</key>
|
||||||
|
|
Binary file not shown.
|
@ -1521,7 +1521,7 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
CURRENT_PROJECT_VERSION = 0.6.8;
|
CURRENT_PROJECT_VERSION = 0.6.9;
|
||||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||||
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
||||||
GCC_OPTIMIZATION_LEVEL = 0;
|
GCC_OPTIMIZATION_LEVEL = 0;
|
||||||
|
@ -1539,7 +1539,7 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
COPY_PHASE_STRIP = YES;
|
COPY_PHASE_STRIP = YES;
|
||||||
CURRENT_PROJECT_VERSION = 0.6.8;
|
CURRENT_PROJECT_VERSION = 0.6.9;
|
||||||
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
|
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
|
||||||
GCC_OPTIMIZATION_LEVEL = fast;
|
GCC_OPTIMIZATION_LEVEL = fast;
|
||||||
GCC_PREFIX_HEADER = ./SourceFiles/stdafx.h;
|
GCC_PREFIX_HEADER = ./SourceFiles/stdafx.h;
|
||||||
|
@ -1565,10 +1565,10 @@
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
CODE_SIGN_IDENTITY = "";
|
CODE_SIGN_IDENTITY = "";
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
CURRENT_PROJECT_VERSION = 0.6.8;
|
CURRENT_PROJECT_VERSION = 0.6.9;
|
||||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||||
DYLIB_COMPATIBILITY_VERSION = 0.6;
|
DYLIB_COMPATIBILITY_VERSION = 0.6;
|
||||||
DYLIB_CURRENT_VERSION = 0.6.8;
|
DYLIB_CURRENT_VERSION = 0.6.9;
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
FRAMEWORK_SEARCH_PATHS = "";
|
FRAMEWORK_SEARCH_PATHS = "";
|
||||||
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
||||||
|
@ -1708,10 +1708,10 @@
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
CODE_SIGN_IDENTITY = "";
|
CODE_SIGN_IDENTITY = "";
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
CURRENT_PROJECT_VERSION = 0.6.8;
|
CURRENT_PROJECT_VERSION = 0.6.9;
|
||||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||||
DYLIB_COMPATIBILITY_VERSION = 0.6;
|
DYLIB_COMPATIBILITY_VERSION = 0.6;
|
||||||
DYLIB_CURRENT_VERSION = 0.6.8;
|
DYLIB_CURRENT_VERSION = 0.6.9;
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
FRAMEWORK_SEARCH_PATHS = "";
|
FRAMEWORK_SEARCH_PATHS = "";
|
||||||
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
||||||
|
|
|
@ -0,0 +1,137 @@
|
||||||
|
/*************************************************
|
||||||
|
* Perl-Compatible Regular Expressions *
|
||||||
|
*************************************************/
|
||||||
|
|
||||||
|
/* PCRE is a library of functions to support regular expressions whose syntax
|
||||||
|
and semantics are as close as possible to those of the Perl 5 language.
|
||||||
|
|
||||||
|
Written by Philip Hazel
|
||||||
|
Copyright (c) 1997-2013 University of Cambridge
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of the University of Cambridge nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* This module contains an internal function for validating UTF-16 character
|
||||||
|
strings. */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef PCRE_HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Generate code with 16 bit character support. */
|
||||||
|
#define COMPILE_PCRE16
|
||||||
|
|
||||||
|
#include "pcre_internal.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************
|
||||||
|
* Validate a UTF-16 string *
|
||||||
|
*************************************************/
|
||||||
|
|
||||||
|
/* This function is called (optionally) at the start of compile or match, to
|
||||||
|
check that a supposed UTF-16 string is actually valid. The early check means
|
||||||
|
that subsequent code can assume it is dealing with a valid string. The check
|
||||||
|
can be turned off for maximum performance, but the consequences of supplying an
|
||||||
|
invalid string are then undefined.
|
||||||
|
|
||||||
|
From release 8.21 more information about the details of the error are passed
|
||||||
|
back in the returned value:
|
||||||
|
|
||||||
|
PCRE_UTF16_ERR0 No error
|
||||||
|
PCRE_UTF16_ERR1 Missing low surrogate at the end of the string
|
||||||
|
PCRE_UTF16_ERR2 Invalid low surrogate
|
||||||
|
PCRE_UTF16_ERR3 Isolated low surrogate
|
||||||
|
PCRE_UTF16_ERR4 Unused (was non-character)
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
string points to the string
|
||||||
|
length length of string, or -1 if the string is zero-terminated
|
||||||
|
errp pointer to an error position offset variable
|
||||||
|
|
||||||
|
Returns: = 0 if the string is a valid UTF-16 string
|
||||||
|
> 0 otherwise, setting the offset of the bad character
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
PRIV(valid_utf)(PCRE_PUCHAR string, int length, int *erroroffset)
|
||||||
|
{
|
||||||
|
#ifdef SUPPORT_UTF
|
||||||
|
register PCRE_PUCHAR p;
|
||||||
|
register pcre_uint32 c;
|
||||||
|
|
||||||
|
if (length < 0)
|
||||||
|
{
|
||||||
|
for (p = string; *p != 0; p++);
|
||||||
|
length = p - string;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (p = string; length-- > 0; p++)
|
||||||
|
{
|
||||||
|
c = *p;
|
||||||
|
|
||||||
|
if ((c & 0xf800) != 0xd800)
|
||||||
|
{
|
||||||
|
/* Normal UTF-16 code point. Neither high nor low surrogate. */
|
||||||
|
}
|
||||||
|
else if ((c & 0xfc00) == 0xd800)
|
||||||
|
{
|
||||||
|
/* High surrogate. Must be a followed by a low surrogate. */
|
||||||
|
if (length == 0)
|
||||||
|
{
|
||||||
|
*erroroffset = p - string;
|
||||||
|
return PCRE_UTF16_ERR1;
|
||||||
|
}
|
||||||
|
p++;
|
||||||
|
length--;
|
||||||
|
if ((*p & 0xfc00) != 0xdc00)
|
||||||
|
{
|
||||||
|
*erroroffset = p - string;
|
||||||
|
return PCRE_UTF16_ERR2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Isolated low surrogate. Always an error. */
|
||||||
|
*erroroffset = p - string;
|
||||||
|
return PCRE_UTF16_ERR3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* SUPPORT_UTF */
|
||||||
|
(void)(string); /* Keep picky compilers happy */
|
||||||
|
(void)(length);
|
||||||
|
(void)(erroroffset);
|
||||||
|
#endif /* SUPPORT_UTF */
|
||||||
|
|
||||||
|
return PCRE_UTF16_ERR0; /* This indicates success */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* End of pcre16_valid_utf16.c */
|
Loading…
Reference in New Issue