storage_settings_scheme.cpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #include "storage/details/storage_settings_scheme.h"
  8. #include "storage/details/storage_file_utilities.h"
  9. #include "storage/cache/storage_cache_database.h"
  10. #include "storage/serialize_common.h"
  11. #include "storage/storage_media_prepare.h"
  12. #include "core/application.h"
  13. #include "core/core_settings.h"
  14. #include "mtproto/mtproto_config.h"
  15. #include "ui/widgets/fields/input_field.h"
  16. #include "ui/chat/attach/attach_send_files_way.h"
  17. #include "ui/power_saving.h"
  18. #include "window/themes/window_theme.h"
  19. #include "core/update_checker.h"
  20. #include "platform/platform_specific.h"
  21. #include "boxes/send_files_box.h"
  22. namespace Storage {
  23. namespace details {
  24. namespace {
  25. using Cache::Database;
  26. [[nodiscard]] bool NoTimeLimit(qint32 storedLimitValue) {
  27. // This is a workaround for a bug in storing the cache time limit.
  28. // See https://github.com/telegramdesktop/tdesktop/issues/5611
  29. return !storedLimitValue
  30. || (storedLimitValue == qint32(std::numeric_limits<int32>::max()))
  31. || (storedLimitValue == qint32(std::numeric_limits<int64>::max()));
  32. }
  33. } // namespace
  34. bool ReadSetting(
  35. quint32 blockId,
  36. QDataStream &stream,
  37. int version,
  38. ReadSettingsContext &context) {
  39. switch (blockId) {
  40. case dbiDcOptionOldOld: {
  41. quint32 dcId, port;
  42. QString host, ip;
  43. stream >> dcId >> host >> ip >> port;
  44. if (!CheckStreamStatus(stream)) return false;
  45. context.fallbackConfigLegacyDcOptions.constructAddOne(
  46. dcId,
  47. 0,
  48. ip.toStdString(),
  49. port,
  50. {});
  51. context.legacyRead = true;
  52. } break;
  53. case dbiDcOptionOld: {
  54. quint32 dcIdWithShift, port;
  55. qint32 flags;
  56. QString ip;
  57. stream >> dcIdWithShift >> flags >> ip >> port;
  58. if (!CheckStreamStatus(stream)) return false;
  59. context.fallbackConfigLegacyDcOptions.constructAddOne(
  60. dcIdWithShift,
  61. MTPDdcOption::Flags::from_raw(flags),
  62. ip.toStdString(),
  63. port,
  64. {});
  65. context.legacyRead = true;
  66. } break;
  67. case dbiDcOptionsOld: {
  68. auto serialized = QByteArray();
  69. stream >> serialized;
  70. if (!CheckStreamStatus(stream)) return false;
  71. context.fallbackConfigLegacyDcOptions.constructFromSerialized(
  72. serialized);
  73. context.legacyRead = true;
  74. } break;
  75. case dbiApplicationSettings: {
  76. auto serialized = QByteArray();
  77. stream >> serialized;
  78. if (!CheckStreamStatus(stream)) return false;
  79. Core::App().settings().addFromSerialized(serialized);
  80. } break;
  81. case dbiChatSizeMaxOld: {
  82. qint32 maxSize;
  83. stream >> maxSize;
  84. if (!CheckStreamStatus(stream)) return false;
  85. context.fallbackConfigLegacyChatSizeMax = maxSize;
  86. context.legacyRead = true;
  87. } break;
  88. case dbiSavedGifsLimitOld: {
  89. qint32 limit;
  90. stream >> limit;
  91. if (!CheckStreamStatus(stream)) return false;
  92. context.fallbackConfigLegacySavedGifsLimit = limit;
  93. context.legacyRead = true;
  94. } break;
  95. case dbiStickersRecentLimitOld: {
  96. qint32 limit;
  97. stream >> limit;
  98. if (!CheckStreamStatus(stream)) return false;
  99. context.fallbackConfigLegacyStickersRecentLimit = limit;
  100. context.legacyRead = true;
  101. } break;
  102. case dbiStickersFavedLimitOld: {
  103. qint32 limit;
  104. stream >> limit;
  105. if (!CheckStreamStatus(stream)) return false;
  106. context.fallbackConfigLegacyStickersFavedLimit = limit;
  107. context.legacyRead = true;
  108. } break;
  109. case dbiMegagroupSizeMaxOld: {
  110. qint32 maxSize;
  111. stream >> maxSize;
  112. if (!CheckStreamStatus(stream)) return false;
  113. context.fallbackConfigLegacyMegagroupSizeMax = maxSize;
  114. context.legacyRead = true;
  115. } break;
  116. case dbiUser: {
  117. quint32 dcId;
  118. qint32 userId;
  119. stream >> userId >> dcId;
  120. if (!CheckStreamStatus(stream)) return false;
  121. DEBUG_LOG(("MTP Info: user found, dc %1, uid %2").arg(dcId).arg(userId));
  122. context.mtpLegacyMainDcId = dcId;
  123. context.mtpLegacyUserId = userId;
  124. } break;
  125. case dbiKey: {
  126. qint32 dcId;
  127. stream >> dcId;
  128. auto key = Serialize::read<MTP::AuthKey::Data>(stream);
  129. if (!CheckStreamStatus(stream)) return false;
  130. context.mtpLegacyKeys.push_back(std::make_shared<MTP::AuthKey>(
  131. MTP::AuthKey::Type::ReadFromFile,
  132. dcId,
  133. key));
  134. } break;
  135. case dbiMtpAuthorization: {
  136. auto serialized = QByteArray();
  137. stream >> serialized;
  138. if (!CheckStreamStatus(stream)) return false;
  139. context.mtpAuthorization = serialized;
  140. } break;
  141. case dbiAutoStart: {
  142. qint32 v;
  143. stream >> v;
  144. if (!CheckStreamStatus(stream)) return false;
  145. cSetAutoStart(v == 1);
  146. } break;
  147. case dbiStartMinimized: {
  148. qint32 v;
  149. stream >> v;
  150. if (!CheckStreamStatus(stream)) return false;
  151. cSetStartMinimized(v == 1);
  152. } break;
  153. case dbiSendToMenu: {
  154. qint32 v;
  155. stream >> v;
  156. if (!CheckStreamStatus(stream)) return false;
  157. cSetSendToMenu(v == 1);
  158. } break;
  159. case dbiUseExternalVideoPlayerOld: {
  160. qint32 v;
  161. stream >> v;
  162. if (!CheckStreamStatus(stream)) return false;
  163. } break;
  164. case dbiCacheSettingsOld: {
  165. qint64 size;
  166. qint32 time;
  167. stream >> size >> time;
  168. if (!CheckStreamStatus(stream)
  169. || size <= Database::Settings().maxDataSize
  170. || (!NoTimeLimit(time) && time < 0)) {
  171. return false;
  172. }
  173. context.cacheTotalSizeLimit = size;
  174. context.cacheTotalTimeLimit = NoTimeLimit(time) ? 0 : time;
  175. context.cacheBigFileTotalSizeLimit = size;
  176. context.cacheBigFileTotalTimeLimit = NoTimeLimit(time) ? 0 : time;
  177. context.legacyRead = true;
  178. } break;
  179. case dbiCacheSettings: {
  180. qint64 size, sizeBig;
  181. qint32 time, timeBig;
  182. stream >> size >> time >> sizeBig >> timeBig;
  183. if (!CheckStreamStatus(stream)
  184. || size <= Database::Settings().maxDataSize
  185. || sizeBig <= Database::Settings().maxDataSize
  186. || (!NoTimeLimit(time) && time < 0)
  187. || (!NoTimeLimit(timeBig) && timeBig < 0)) {
  188. return false;
  189. }
  190. context.cacheTotalSizeLimit = size;
  191. context.cacheTotalTimeLimit = NoTimeLimit(time) ? 0 : time;
  192. context.cacheBigFileTotalSizeLimit = sizeBig;
  193. context.cacheBigFileTotalTimeLimit = NoTimeLimit(timeBig) ? 0 : timeBig;
  194. } break;
  195. case dbiPowerSaving: {
  196. qint32 settings;
  197. stream >> settings;
  198. if (!CheckStreamStatus(stream)) {
  199. return false;
  200. }
  201. PowerSaving::Set(PowerSaving::Flags::from_raw(settings));
  202. } break;
  203. case dbiSoundFlashBounceNotifyOld: {
  204. qint32 v;
  205. stream >> v;
  206. if (!CheckStreamStatus(stream)) return false;
  207. Core::App().settings().setSoundNotify((v & 0x01) == 0x01);
  208. Core::App().settings().setFlashBounceNotify((v & 0x02) == 0x00);
  209. context.legacyRead = true;
  210. } break;
  211. case dbiAutoDownloadOld: {
  212. qint32 photo, audio, gif;
  213. stream >> photo >> audio >> gif;
  214. if (!CheckStreamStatus(stream)) return false;
  215. using namespace Data::AutoDownload;
  216. auto &settings = context.sessionSettings().autoDownload();
  217. const auto disabled = [](qint32 value, qint32 mask) {
  218. return (value & mask) != 0;
  219. };
  220. const auto set = [&](Type type, qint32 value) {
  221. constexpr auto kNoPrivate = qint32(0x01);
  222. constexpr auto kNoGroups = qint32(0x02);
  223. if (disabled(value, kNoPrivate)) {
  224. settings.setBytesLimit(Source::User, type, 0);
  225. }
  226. if (disabled(value, kNoGroups)) {
  227. settings.setBytesLimit(Source::Group, type, 0);
  228. settings.setBytesLimit(Source::Channel, type, 0);
  229. }
  230. };
  231. set(Type::Photo, photo);
  232. set(Type::VoiceMessage, audio);
  233. set(Type::AutoPlayGIF, gif);
  234. set(Type::AutoPlayVideoMessage, gif);
  235. context.legacyRead = true;
  236. } break;
  237. case dbiAutoPlayOld: {
  238. qint32 gif;
  239. stream >> gif;
  240. if (!CheckStreamStatus(stream)) return false;
  241. if (!gif) {
  242. using namespace Data::AutoDownload;
  243. auto &settings = context.sessionSettings().autoDownload();
  244. const auto types = {
  245. Type::AutoPlayGIF,
  246. Type::AutoPlayVideo,
  247. Type::AutoPlayVideoMessage,
  248. };
  249. const auto sources = {
  250. Source::User,
  251. Source::Group,
  252. Source::Channel
  253. };
  254. for (const auto source : sources) {
  255. for (const auto type : types) {
  256. settings.setBytesLimit(source, type, 0);
  257. }
  258. }
  259. }
  260. context.legacyRead = true;
  261. } break;
  262. case dbiDialogsModeOld: {
  263. qint32 enabled, modeInt;
  264. stream >> enabled >> modeInt;
  265. if (!CheckStreamStatus(stream)) return false;
  266. context.legacyRead = true;
  267. } break;
  268. case dbiDialogsFiltersOld: {
  269. qint32 enabled;
  270. stream >> enabled;
  271. if (!CheckStreamStatus(stream)) return false;
  272. context.sessionSettings().setDialogsFiltersEnabled(enabled == 1);
  273. context.legacyRead = true;
  274. } break;
  275. case dbiModerateModeOld: {
  276. qint32 enabled;
  277. stream >> enabled;
  278. if (!CheckStreamStatus(stream)) return false;
  279. Core::App().settings().setModerateModeEnabled(enabled == 1);
  280. context.legacyRead = true;
  281. } break;
  282. case dbiIncludeMutedOld: {
  283. qint32 v;
  284. stream >> v;
  285. if (!CheckStreamStatus(stream)) return false;
  286. Core::App().settings().setIncludeMutedCounter(v == 1);
  287. context.legacyRead = true;
  288. } break;
  289. case dbiShowingSavedGifsOld: {
  290. qint32 v;
  291. stream >> v;
  292. if (!CheckStreamStatus(stream)) return false;
  293. context.legacyRead = true;
  294. } break;
  295. case dbiDesktopNotifyOld: {
  296. qint32 v;
  297. stream >> v;
  298. if (!CheckStreamStatus(stream)) return false;
  299. Core::App().settings().setDesktopNotify(v == 1);
  300. context.legacyRead = true;
  301. } break;
  302. case dbiWindowsNotificationsOld: {
  303. qint32 v;
  304. stream >> v;
  305. if (!CheckStreamStatus(stream)) return false;
  306. context.legacyRead = true;
  307. } break;
  308. case dbiNativeNotificationsOld: {
  309. qint32 v;
  310. stream >> v;
  311. if (!CheckStreamStatus(stream)) return false;
  312. Core::App().settings().setNativeNotifications(v == 1);
  313. context.legacyRead = true;
  314. } break;
  315. case dbiNotificationsCountOld: {
  316. qint32 v;
  317. stream >> v;
  318. if (!CheckStreamStatus(stream)) return false;
  319. Core::App().settings().setNotificationsCount((v > 0 ? v : 3));
  320. context.legacyRead = true;
  321. } break;
  322. case dbiNotificationsCornerOld: {
  323. qint32 v;
  324. stream >> v;
  325. if (!CheckStreamStatus(stream)) return false;
  326. Core::App().settings().setNotificationsCorner(static_cast<Core::Settings::ScreenCorner>((v >= 0 && v < 4) ? v : 2));
  327. context.legacyRead = true;
  328. } break;
  329. case dbiDialogsWidthRatioOld: {
  330. qint32 v;
  331. stream >> v;
  332. if (!CheckStreamStatus(stream)) return false;
  333. Core::App().settings().updateDialogsWidthRatio(v / 1000000., false);
  334. context.legacyRead = true;
  335. } break;
  336. case dbiLastSeenWarningSeenOld: {
  337. qint32 v;
  338. stream >> v;
  339. if (!CheckStreamStatus(stream)) return false;
  340. Core::App().settings().setLastSeenWarningSeen(v == 1);
  341. context.legacyRead = true;
  342. } break;
  343. case dbiSessionSettings: {
  344. QByteArray v;
  345. stream >> v;
  346. if (!CheckStreamStatus(stream)) return false;
  347. context.sessionSettings().addFromSerialized(v);
  348. } break;
  349. case dbiWorkModeOld: {
  350. qint32 v;
  351. stream >> v;
  352. if (!CheckStreamStatus(stream)) return false;
  353. const auto newMode = [v] {
  354. using WorkMode = Core::Settings::WorkMode;
  355. switch (static_cast<WorkMode>(v)) {
  356. case WorkMode::TrayOnly: return WorkMode::TrayOnly;
  357. case WorkMode::WindowOnly: return WorkMode::WindowOnly;
  358. };
  359. return WorkMode::WindowAndTray;
  360. }();
  361. Core::App().settings().setWorkMode(newMode);
  362. context.legacyRead = true;
  363. } break;
  364. case dbiTxtDomainStringOldOld: {
  365. QString v;
  366. stream >> v;
  367. if (!CheckStreamStatus(stream)) return false;
  368. context.legacyRead = true;
  369. } break;
  370. case dbiTxtDomainStringOld: {
  371. QString v;
  372. stream >> v;
  373. if (!CheckStreamStatus(stream)) return false;
  374. context.fallbackConfigLegacyTxtDomainString = v;
  375. context.legacyRead = true;
  376. } break;
  377. case dbiConnectionTypeOldOld: {
  378. qint32 v;
  379. stream >> v;
  380. if (!CheckStreamStatus(stream)) return false;
  381. // const auto dbictAuto = 0;
  382. // const auto dbictHttpAuto = 1; // not used
  383. const auto dbictHttpProxy = 2;
  384. const auto dbictTcpProxy = 3;
  385. // const auto dbictProxiesListOld = 4;
  386. // const auto dbictProxiesList = 5;
  387. MTP::ProxyData proxy;
  388. switch (v) {
  389. case dbictHttpProxy:
  390. case dbictTcpProxy: {
  391. qint32 port;
  392. stream >> proxy.host >> port >> proxy.user >> proxy.password;
  393. if (!CheckStreamStatus(stream)) return false;
  394. proxy.port = uint32(port);
  395. proxy.type = (v == dbictTcpProxy)
  396. ? MTP::ProxyData::Type::Socks5
  397. : MTP::ProxyData::Type::Http;
  398. } break;
  399. };
  400. auto &proxySettings = Core::App().settings().proxy();
  401. proxySettings.setSelected(proxy ? proxy : MTP::ProxyData());
  402. proxySettings.setSettings(proxy
  403. ? MTP::ProxyData::Settings::Enabled
  404. : MTP::ProxyData::Settings::System);
  405. proxySettings.list() = proxy
  406. ? std::vector<MTP::ProxyData>{ 1, proxy }
  407. : std::vector<MTP::ProxyData>{};
  408. Core::App().refreshGlobalProxy();
  409. context.legacyRead = true;
  410. } break;
  411. case dbiConnectionTypeOld: {
  412. qint32 connectionType;
  413. stream >> connectionType;
  414. if (!CheckStreamStatus(stream)) {
  415. return false;
  416. }
  417. auto &proxySettings = Core::App().settings().proxy();
  418. const auto legacyProxyTypeShift = 1024;
  419. // const auto dbictAuto = 0;
  420. // const auto dbictHttpAuto = 1; // not used
  421. const auto dbictHttpProxy = 2;
  422. const auto dbictTcpProxy = 3;
  423. const auto dbictProxiesListOld = 4;
  424. const auto dbictProxiesList = 5;
  425. const auto readProxy = [&] {
  426. using Type = MTP::ProxyData::Type;
  427. qint32 proxyType, port;
  428. MTP::ProxyData proxy;
  429. stream
  430. >> proxyType
  431. >> proxy.host
  432. >> port
  433. >> proxy.user
  434. >> proxy.password;
  435. proxy.port = port;
  436. proxy.type = (proxyType == dbictTcpProxy)
  437. ? Type::Socks5
  438. : (proxyType == dbictHttpProxy)
  439. ? Type::Http
  440. : (proxyType == legacyProxyTypeShift + int(Type::Socks5))
  441. ? Type::Socks5
  442. : (proxyType == legacyProxyTypeShift + int(Type::Http))
  443. ? Type::Http
  444. : (proxyType == legacyProxyTypeShift + int(Type::Mtproto))
  445. ? Type::Mtproto
  446. : Type::None;
  447. return proxy;
  448. };
  449. if (connectionType == dbictProxiesListOld
  450. || connectionType == dbictProxiesList) {
  451. qint32 count = 0, index = 0;
  452. stream >> count >> index;
  453. qint32 settings = 0, calls = 0;
  454. if (connectionType == dbictProxiesList) {
  455. stream >> settings >> calls;
  456. } else if (std::abs(index) > count) {
  457. calls = 1;
  458. index -= (index > 0 ? count : -count);
  459. }
  460. auto list = std::vector<MTP::ProxyData>();
  461. for (auto i = 0; i < count; ++i) {
  462. const auto proxy = readProxy();
  463. if (proxy) {
  464. list.push_back(proxy);
  465. } else if (index < -int64(list.size())) {
  466. ++index;
  467. } else if (index > list.size()) {
  468. --index;
  469. }
  470. }
  471. if (!CheckStreamStatus(stream)) {
  472. return false;
  473. }
  474. proxySettings.list() = list;
  475. if (connectionType == dbictProxiesListOld) {
  476. settings = static_cast<qint32>(
  477. (index > 0 && index <= list.size()
  478. ? MTP::ProxyData::Settings::Enabled
  479. : MTP::ProxyData::Settings::System));
  480. index = std::abs(index);
  481. }
  482. proxySettings.setSelected((index > 0 && index <= list.size())
  483. ? list[index - 1]
  484. : MTP::ProxyData());
  485. const auto unchecked = static_cast<MTP::ProxyData::Settings>(settings);
  486. switch (unchecked) {
  487. case MTP::ProxyData::Settings::Enabled:
  488. proxySettings.setSettings(proxySettings.selected()
  489. ? MTP::ProxyData::Settings::Enabled
  490. : MTP::ProxyData::Settings::System);
  491. break;
  492. case MTP::ProxyData::Settings::Disabled:
  493. case MTP::ProxyData::Settings::System:
  494. proxySettings.setSettings(unchecked);
  495. break;
  496. default:
  497. proxySettings.setSettings(MTP::ProxyData::Settings::System);
  498. break;
  499. }
  500. proxySettings.setUseProxyForCalls(calls == 1);
  501. } else {
  502. const auto proxy = readProxy();
  503. if (!CheckStreamStatus(stream)) {
  504. return false;
  505. }
  506. if (proxy) {
  507. proxySettings.list() = { 1, proxy };
  508. proxySettings.setSelected(proxy);
  509. proxySettings.setSettings((connectionType == dbictTcpProxy
  510. || connectionType == dbictHttpProxy)
  511. ? MTP::ProxyData::Settings::Enabled
  512. : MTP::ProxyData::Settings::System);
  513. } else {
  514. proxySettings.list() = {};
  515. proxySettings.setSelected(MTP::ProxyData());
  516. proxySettings.setSettings(MTP::ProxyData::Settings::System);
  517. }
  518. }
  519. Core::App().refreshGlobalProxy();
  520. context.legacyRead = true;
  521. } break;
  522. case dbiThemeKeyOld: {
  523. quint64 key = 0;
  524. stream >> key;
  525. if (!CheckStreamStatus(stream)) return false;
  526. DEBUG_LOG(("Theme: read key legacy: %1").arg(key));
  527. context.themeKeyLegacy = key;
  528. context.legacyRead = true;
  529. } break;
  530. case dbiThemeKey: {
  531. quint64 keyDay = 0, keyNight = 0;
  532. quint32 nightMode = 0;
  533. stream >> keyDay >> keyNight >> nightMode;
  534. if (!CheckStreamStatus(stream)) return false;
  535. DEBUG_LOG(("Theme: read keys (night: %1) day_key: %2, night_key: %3, "
  536. ).arg(Logs::b(nightMode == 1)
  537. ).arg(keyDay
  538. ).arg(keyNight));
  539. context.themeKeyDay = keyDay;
  540. context.themeKeyNight = keyNight;
  541. Window::Theme::SetNightModeValue(nightMode == 1);
  542. } break;
  543. case dbiBackgroundKey: {
  544. quint64 keyDay = 0, keyNight = 0;
  545. stream >> keyDay >> keyNight;
  546. if (!CheckStreamStatus(stream)) return false;
  547. context.backgroundKeyDay = keyDay;
  548. context.backgroundKeyNight = keyNight;
  549. context.backgroundKeysRead = true;
  550. } break;
  551. case dbiLangPackKey: {
  552. quint64 langPackKey = 0;
  553. stream >> langPackKey;
  554. if (!CheckStreamStatus(stream)) return false;
  555. context.langPackKey = langPackKey;
  556. } break;
  557. case dbiLanguagesKey: {
  558. quint64 languagesKey = 0;
  559. stream >> languagesKey;
  560. if (!CheckStreamStatus(stream)) return false;
  561. context.languagesKey = languagesKey;
  562. } break;
  563. case dbiTryIPv6Old: {
  564. qint32 v;
  565. stream >> v;
  566. if (!CheckStreamStatus(stream)) return false;
  567. Core::App().settings().proxy().setTryIPv6(v == 1);
  568. context.legacyRead = true;
  569. } break;
  570. case dbiSeenTrayTooltip: {
  571. qint32 v;
  572. stream >> v;
  573. if (!CheckStreamStatus(stream)) return false;
  574. cSetSeenTrayTooltip(v == 1);
  575. } break;
  576. case dbiAutoUpdate: {
  577. qint32 v;
  578. stream >> v;
  579. if (!CheckStreamStatus(stream)) return false;
  580. cSetAutoUpdate(v == 1);
  581. if (!Core::UpdaterDisabled() && !cAutoUpdate()) {
  582. Core::UpdateChecker().stop();
  583. }
  584. } break;
  585. case dbiLastUpdateCheck: {
  586. qint32 v;
  587. stream >> v;
  588. if (!CheckStreamStatus(stream)) return false;
  589. cSetLastUpdateCheck(v);
  590. } break;
  591. case dbiScaleOld: {
  592. qint32 v;
  593. stream >> v;
  594. if (!CheckStreamStatus(stream)) return false;
  595. SetScaleChecked([&] {
  596. constexpr auto kAuto = 0;
  597. constexpr auto kOne = 1;
  598. constexpr auto kOneAndQuarter = 2;
  599. constexpr auto kOneAndHalf = 3;
  600. constexpr auto kTwo = 4;
  601. switch (v) {
  602. case kAuto: return style::kScaleAuto;
  603. case kOne: return 100;
  604. case kOneAndQuarter: return 125;
  605. case kOneAndHalf: return 150;
  606. case kTwo: return 200;
  607. }
  608. return cConfigScale();
  609. }());
  610. context.legacyRead = true;
  611. } break;
  612. case dbiScalePercent: {
  613. qint32 v;
  614. stream >> v;
  615. if (!CheckStreamStatus(stream)) return false;
  616. // If cConfigScale() has value then it was set via command line.
  617. if (cConfigScale() == style::kScaleAuto) {
  618. SetScaleChecked(v);
  619. }
  620. } break;
  621. case dbiLangOld: { // deprecated
  622. qint32 v;
  623. stream >> v;
  624. if (!CheckStreamStatus(stream)) return false;
  625. context.legacyRead = true;
  626. } break;
  627. case dbiLangFileOld: { // deprecated
  628. QString v;
  629. stream >> v;
  630. if (!CheckStreamStatus(stream)) return false;
  631. context.legacyRead = true;
  632. } break;
  633. case dbiWindowPositionOld: {
  634. auto position = Core::WindowPosition();
  635. if (!CheckStreamStatus(stream)) {
  636. return false;
  637. }
  638. stream >> position.x >> position.y >> position.w >> position.h;
  639. stream >> position.moncrc >> position.maximized;
  640. if (!CheckStreamStatus(stream)) return false;
  641. DEBUG_LOG(("Window Pos: Read from legacy storage %1, %2, %3, %4 (scale %5%, maximized %6)")
  642. .arg(position.x)
  643. .arg(position.y)
  644. .arg(position.w)
  645. .arg(position.h)
  646. .arg(position.scale)
  647. .arg(Logs::b(position.maximized)));
  648. Core::App().settings().setWindowPosition(position);
  649. context.legacyRead = true;
  650. } break;
  651. case dbiLoggedPhoneNumberOld: { // deprecated
  652. QString v;
  653. stream >> v;
  654. if (!CheckStreamStatus(stream)) return false;
  655. context.legacyRead = true;
  656. } break;
  657. case dbiMutePeerOld: { // deprecated
  658. quint64 peerId;
  659. stream >> peerId;
  660. if (!CheckStreamStatus(stream)) return false;
  661. context.legacyRead = true;
  662. } break;
  663. case dbiMutedPeersOld: { // deprecated
  664. quint32 count;
  665. stream >> count;
  666. if (!CheckStreamStatus(stream)) return false;
  667. for (uint32 i = 0; i < count; ++i) {
  668. quint64 peerId;
  669. stream >> peerId;
  670. }
  671. if (!CheckStreamStatus(stream)) return false;
  672. context.legacyRead = true;
  673. } break;
  674. case dbiSendKeyOld: {
  675. qint32 v;
  676. stream >> v;
  677. if (!CheckStreamStatus(stream)) return false;
  678. using SendSettings = Ui::InputSubmitSettings;
  679. const auto unchecked = static_cast<SendSettings>(v);
  680. if (unchecked != SendSettings::Enter
  681. && unchecked != SendSettings::CtrlEnter) {
  682. return false;
  683. }
  684. Core::App().settings().setSendSubmitWay(unchecked);
  685. context.legacyRead = true;
  686. } break;
  687. case dbiCatsAndDogsOld: { // deprecated
  688. qint32 v;
  689. stream >> v;
  690. if (!CheckStreamStatus(stream)) return false;
  691. context.legacyRead = true;
  692. } break;
  693. case dbiTileBackgroundOld: {
  694. qint32 v;
  695. stream >> v;
  696. if (!CheckStreamStatus(stream)) return false;
  697. bool tile = (version < 8005 && !context.legacyHasCustomDayBackground)
  698. ? false
  699. : (v == 1);
  700. if (Window::Theme::IsNightMode()) {
  701. context.tileDay = tile;
  702. } else {
  703. context.tileNight = tile;
  704. }
  705. context.tileRead = true;
  706. context.legacyRead = true;
  707. } break;
  708. case dbiTileBackground: {
  709. qint32 tileDay, tileNight;
  710. stream >> tileDay >> tileNight;
  711. if (!CheckStreamStatus(stream)) return false;
  712. context.tileDay = tileDay;
  713. context.tileNight = tileNight;
  714. context.tileRead = true;
  715. } break;
  716. case dbiAdaptiveForWideOld: {
  717. qint32 v;
  718. stream >> v;
  719. if (!CheckStreamStatus(stream)) return false;
  720. Core::App().settings().setAdaptiveForWide(v == 1);
  721. context.legacyRead = true;
  722. } break;
  723. case dbiAutoLockOld: {
  724. qint32 v;
  725. stream >> v;
  726. if (!CheckStreamStatus(stream)) return false;
  727. Core::App().settings().setAutoLock(v);
  728. context.legacyRead = true;
  729. } break;
  730. case dbiReplaceEmojiOld: {
  731. qint32 v;
  732. stream >> v;
  733. if (!CheckStreamStatus(stream)) return false;
  734. Core::App().settings().setReplaceEmoji(v == 1);
  735. context.legacyRead = true;
  736. } break;
  737. case dbiSuggestEmojiOld: {
  738. qint32 v;
  739. stream >> v;
  740. if (!CheckStreamStatus(stream)) return false;
  741. Core::App().settings().setSuggestEmoji(v == 1);
  742. context.legacyRead = true;
  743. } break;
  744. case dbiSuggestStickersByEmojiOld: {
  745. qint32 v;
  746. stream >> v;
  747. if (!CheckStreamStatus(stream)) return false;
  748. Core::App().settings().setSuggestStickersByEmoji(v == 1);
  749. context.legacyRead = true;
  750. } break;
  751. case dbiDefaultAttach: {
  752. qint32 v;
  753. stream >> v;
  754. if (!CheckStreamStatus(stream)) return false;
  755. } break;
  756. case dbiNotifyViewOld: {
  757. qint32 v;
  758. stream >> v;
  759. if (!CheckStreamStatus(stream)) return false;
  760. const auto newView = [&] {
  761. using Notify = Core::Settings::NotifyView;
  762. switch (static_cast<Notify>(v)) {
  763. case Notify::ShowNothing: return Notify::ShowNothing;
  764. case Notify::ShowName: return Notify::ShowName;
  765. }
  766. return Notify::ShowPreview;
  767. }();
  768. Core::App().settings().setNotifyView(newView);
  769. context.legacyRead = true;
  770. } break;
  771. case dbiAskDownloadPathOld: {
  772. qint32 v;
  773. stream >> v;
  774. if (!CheckStreamStatus(stream)) return false;
  775. Core::App().settings().setAskDownloadPath(v == 1);
  776. context.legacyRead = true;
  777. } break;
  778. case dbiDownloadPathOldOld: {
  779. QString v;
  780. stream >> v;
  781. if (!CheckStreamStatus(stream)) return false;
  782. #ifndef OS_WIN_STORE
  783. if (!v.isEmpty() && v != FileDialog::Tmp() && !v.endsWith('/')) {
  784. v += '/';
  785. }
  786. Core::App().settings().setDownloadPathBookmark(QByteArray());
  787. Core::App().settings().setDownloadPath(v);
  788. #endif // OS_WIN_STORE
  789. context.legacyRead = true;
  790. } break;
  791. case dbiDownloadPathOld: {
  792. QString v;
  793. QByteArray bookmark;
  794. stream >> v >> bookmark;
  795. if (!CheckStreamStatus(stream)) return false;
  796. #ifndef OS_WIN_STORE
  797. if (!v.isEmpty() && v != FileDialog::Tmp() && !v.endsWith('/')) {
  798. v += '/';
  799. }
  800. Core::App().settings().setDownloadPathBookmark(bookmark);
  801. Core::App().settings().setDownloadPath(v);
  802. psDownloadPathEnableAccess();
  803. #endif // OS_WIN_STORE
  804. context.legacyRead = true;
  805. } break;
  806. case dbiCompressPastedImageOld: {
  807. qint32 v;
  808. stream >> v;
  809. if (!CheckStreamStatus(stream)) return false;
  810. auto way = Ui::SendFilesWay();
  811. way.setGroupFiles(v == 1);
  812. way.setSendImagesAsPhotos(v == 1);
  813. Core::App().settings().setSendFilesWay(way);
  814. context.legacyRead = true;
  815. } break;
  816. case dbiEmojiTabOld: { // deprecated
  817. qint32 v;
  818. stream >> v;
  819. if (!CheckStreamStatus(stream)) return false;
  820. context.legacyRead = true;
  821. } break;
  822. case dbiRecentEmojiOldOldOld: {
  823. auto v = QVector<QPair<uint32, ushort>>();
  824. stream >> v;
  825. if (!CheckStreamStatus(stream)) return false;
  826. if (!v.isEmpty()) {
  827. auto p = QVector<QPair<QString, ushort>>();
  828. p.reserve(v.size());
  829. for (auto &item : v) {
  830. auto oldKey = uint64(item.first);
  831. switch (oldKey) {
  832. case 0xD83CDDEFLLU: oldKey = 0xD83CDDEFD83CDDF5LLU; break;
  833. case 0xD83CDDF0LLU: oldKey = 0xD83CDDF0D83CDDF7LLU; break;
  834. case 0xD83CDDE9LLU: oldKey = 0xD83CDDE9D83CDDEALLU; break;
  835. case 0xD83CDDE8LLU: oldKey = 0xD83CDDE8D83CDDF3LLU; break;
  836. case 0xD83CDDFALLU: oldKey = 0xD83CDDFAD83CDDF8LLU; break;
  837. case 0xD83CDDEBLLU: oldKey = 0xD83CDDEBD83CDDF7LLU; break;
  838. case 0xD83CDDEALLU: oldKey = 0xD83CDDEAD83CDDF8LLU; break;
  839. case 0xD83CDDEELLU: oldKey = 0xD83CDDEED83CDDF9LLU; break;
  840. case 0xD83CDDF7LLU: oldKey = 0xD83CDDF7D83CDDFALLU; break;
  841. case 0xD83CDDECLLU: oldKey = 0xD83CDDECD83CDDE7LLU; break;
  842. }
  843. auto id = Ui::Emoji::IdFromOldKey(oldKey);
  844. if (!id.isEmpty()) {
  845. p.push_back(qMakePair(id, item.second));
  846. }
  847. }
  848. Core::App().settings().setLegacyRecentEmojiPreload(std::move(p));
  849. }
  850. context.legacyRead = true;
  851. } break;
  852. case dbiRecentEmojiOldOld: {
  853. auto v = QVector<QPair<uint64, ushort>>();
  854. stream >> v;
  855. if (!CheckStreamStatus(stream)) return false;
  856. if (!v.isEmpty()) {
  857. auto p = QVector<QPair<QString, ushort>>();
  858. p.reserve(v.size());
  859. for (auto &item : v) {
  860. auto id = Ui::Emoji::IdFromOldKey(item.first);
  861. if (!id.isEmpty()) {
  862. p.push_back(qMakePair(id, item.second));
  863. }
  864. }
  865. Core::App().settings().setLegacyRecentEmojiPreload(std::move(p));
  866. }
  867. context.legacyRead = true;
  868. } break;
  869. case dbiRecentEmojiOld: {
  870. auto v = QVector<QPair<QString, ushort>>();
  871. stream >> v;
  872. if (!CheckStreamStatus(stream)) return false;
  873. Core::App().settings().setLegacyRecentEmojiPreload(std::move(v));
  874. context.legacyRead = true;
  875. } break;
  876. case dbiRecentStickers: {
  877. RecentStickerPreload v;
  878. stream >> v;
  879. if (!CheckStreamStatus(stream)) return false;
  880. cSetRecentStickersPreload(v);
  881. } break;
  882. case dbiEmojiVariantsOldOld: {
  883. auto v = QMap<uint32, uint64>();
  884. stream >> v;
  885. if (!CheckStreamStatus(stream)) return false;
  886. auto variants = QMap<QString, int>();
  887. for (auto i = v.cbegin(), e = v.cend(); i != e; ++i) {
  888. auto id = Ui::Emoji::IdFromOldKey(static_cast<uint64>(i.key()));
  889. if (!id.isEmpty()) {
  890. auto index = Ui::Emoji::ColorIndexFromOldKey(i.value());
  891. variants.insert(id, index);
  892. }
  893. }
  894. Core::App().settings().setLegacyEmojiVariants(std::move(variants));
  895. context.legacyRead = true;
  896. } break;
  897. case dbiEmojiVariantsOld: {
  898. auto v = QMap<QString, int>();
  899. stream >> v;
  900. if (!CheckStreamStatus(stream)) return false;
  901. Core::App().settings().setLegacyEmojiVariants(std::move(v));
  902. context.legacyRead = true;
  903. } break;
  904. case dbiHiddenPinnedMessagesOld: {
  905. auto v = QMap<uint64, int32>();
  906. stream >> v;
  907. if (!CheckStreamStatus(stream)) return false;
  908. for (auto i = v.begin(), e = v.end(); i != e; ++i) {
  909. context.sessionSettings().setHiddenPinnedMessageId(
  910. DeserializePeerId(i.key()),
  911. MsgId(0), // topicRootId
  912. MsgId(i.value()));
  913. }
  914. context.legacyRead = true;
  915. } break;
  916. case dbiDialogLastPath: {
  917. QString path;
  918. stream >> path;
  919. if (!CheckStreamStatus(stream)) return false;
  920. cSetDialogLastPath(path);
  921. } break;
  922. case dbiSongVolumeOld: {
  923. qint32 v;
  924. stream >> v;
  925. if (!CheckStreamStatus(stream)) return false;
  926. Core::App().settings().setSongVolume(std::clamp(v / 1e6, 0., 1.));
  927. context.legacyRead = true;
  928. } break;
  929. case dbiVideoVolumeOld: {
  930. qint32 v;
  931. stream >> v;
  932. if (!CheckStreamStatus(stream)) return false;
  933. Core::App().settings().setVideoVolume(std::clamp(v / 1e6, 0., 1.));
  934. context.legacyRead = true;
  935. } break;
  936. case dbiPlaybackSpeedOld: {
  937. qint32 v;
  938. stream >> v;
  939. if (!CheckStreamStatus(stream)) return false;
  940. if (v == 2) {
  941. Core::App().settings().setVoicePlaybackSpeed(2.);
  942. }
  943. context.legacyRead = true;
  944. } break;
  945. case dbiCallSettingsOld: {
  946. QByteArray callSettings;
  947. stream >> callSettings;
  948. if (!CheckStreamStatus(stream)) return false;
  949. QDataStream settingsStream(&callSettings, QIODevice::ReadOnly);
  950. settingsStream.setVersion(QDataStream::Qt_5_1);
  951. QString outputDeviceID;
  952. QString inputDeviceID;
  953. qint32 outputVolume;
  954. qint32 inputVolume;
  955. qint32 duckingEnabled;
  956. settingsStream >> outputDeviceID;
  957. settingsStream >> outputVolume;
  958. settingsStream >> inputDeviceID;
  959. settingsStream >> inputVolume;
  960. settingsStream >> duckingEnabled;
  961. if (CheckStreamStatus(settingsStream)) {
  962. auto &app = Core::App().settings();
  963. app.setCallPlaybackDeviceId(outputDeviceID);
  964. app.setCallCaptureDeviceId(inputDeviceID);
  965. app.setCallOutputVolume(outputVolume);
  966. app.setCallInputVolume(inputVolume);
  967. app.setCallAudioDuckingEnabled(duckingEnabled);
  968. }
  969. context.legacyRead = true;
  970. } break;
  971. case dbiFallbackProductionConfig: {
  972. QByteArray config;
  973. stream >> config;
  974. if (!CheckStreamStatus(stream)) return false;
  975. context.fallbackConfig = config;
  976. } break;
  977. default:
  978. LOG(("App Error: unknown blockId in _readSetting: %1").arg(blockId));
  979. return false;
  980. }
  981. return true;
  982. }
  983. void ApplyReadFallbackConfig(ReadSettingsContext &context) {
  984. if (context.fallbackConfig.isEmpty()) {
  985. auto &config = Core::App().fallbackProductionConfig();
  986. config.dcOptions().addFromOther(
  987. std::move(context.fallbackConfigLegacyDcOptions));
  988. if (context.fallbackConfigLegacyChatSizeMax > 0) {
  989. config.setChatSizeMax(context.fallbackConfigLegacyChatSizeMax);
  990. }
  991. if (context.fallbackConfigLegacyStickersRecentLimit > 0) {
  992. config.setStickersRecentLimit(
  993. context.fallbackConfigLegacyStickersRecentLimit);
  994. }
  995. if (context.fallbackConfigLegacyMegagroupSizeMax > 0) {
  996. config.setMegagroupSizeMax(
  997. context.fallbackConfigLegacyMegagroupSizeMax);
  998. }
  999. if (!context.fallbackConfigLegacyTxtDomainString.isEmpty()) {
  1000. config.setTxtDomainString(
  1001. context.fallbackConfigLegacyTxtDomainString);
  1002. }
  1003. } else {
  1004. Core::App().constructFallbackProductionConfig(context.fallbackConfig);
  1005. }
  1006. }
  1007. } // namespace details
  1008. } // namespace Storage