void ImapAccess::doConnect() { if (m_netWatcher) { // We're temporarily "disabling" this connection. Otherwise this "offline preference" // would get saved into the config file, which would be bad. disconnect(m_netWatcher, &Mailbox::NetworkWatcher::desiredNetworkPolicyChanged, this, &ImapAccess::desiredNetworkPolicyChanged); } if (m_imapModel) { // Disconnect from network, nuke the models Q_ASSERT(m_netWatcher); m_netWatcher->setNetworkOffline(); delete m_threadingMsgListModel; m_threadingMsgListModel = 0; delete m_msgQNAM; m_msgQNAM = 0; delete m_oneMessageModel; m_oneMessageModel = 0; delete m_visibleTasksModel; m_visibleTasksModel = 0; delete m_msgListModel; m_msgListModel = 0; delete m_mailboxSubtreeModel; m_mailboxSubtreeModel = 0; delete m_mailboxModel; m_mailboxModel = 0; delete m_netWatcher; m_netWatcher = 0; delete m_imapModel; m_imapModel = 0; } Q_ASSERT(!m_imapModel); Imap::Mailbox::SocketFactoryPtr factory; Imap::Mailbox::TaskFactoryPtr taskFactory(new Imap::Mailbox::TaskFactory()); Streams::ProxySettings proxySettings = m_settings->value(Common::SettingsNames::imapUseSystemProxy, true).toBool() ? Streams::ProxySettings::RespectSystemProxy : Streams::ProxySettings::DirectConnect; switch (m_connectionMethod) { case Common::ConnectionMethod::Invalid: factory.reset(new Streams::FakeSocketFactory(Imap::CONN_STATE_LOGOUT)); break; case Common::ConnectionMethod::NetCleartext: case Common::ConnectionMethod::NetStartTls: factory.reset(new Streams::TlsAbleSocketFactory(server(), port())); factory->setStartTlsRequired(m_connectionMethod == Common::ConnectionMethod::NetStartTls); factory->setProxySettings(proxySettings, QStringLiteral("imap")); break; case Common::ConnectionMethod::NetDedicatedTls: factory.reset(new Streams::SslSocketFactory(server(), port())); factory->setProxySettings(proxySettings, QStringLiteral("imap")); break; case Common::ConnectionMethod::Process: QStringList args = m_settings->value(Common::SettingsNames::imapProcessKey).toString().split(QLatin1Char(' ')); if (args.isEmpty()) { // it's going to fail anyway args << QLatin1String(""); } QString appName = args.takeFirst(); factory.reset(new Streams::ProcessSocketFactory(appName, args)); break; } bool shouldUsePersistentCache = m_settings->value(Common::SettingsNames::cacheOfflineKey).toString() != Common::SettingsNames::cacheOfflineNone; if (shouldUsePersistentCache && !QDir().mkpath(m_cacheDir)) { onCacheError(tr("Failed to create directory %1").arg(m_cacheDir)); shouldUsePersistentCache = false; } if (shouldUsePersistentCache) { QFile::Permissions expectedPerms = QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner; if (QFileInfo(m_cacheDir).permissions() != expectedPerms) { if (!QFile::setPermissions(m_cacheDir, expectedPerms)) { #ifndef Q_OS_WIN32 onCacheError(tr("Failed to set safe permissions on cache directory %1").arg(m_cacheDir)); shouldUsePersistentCache = false; #endif } } } std::shared_ptr<Imap::Mailbox::AbstractCache> cache; if (!shouldUsePersistentCache) { cache.reset(new Imap::Mailbox::MemoryCache()); } else { cache.reset(new Imap::Mailbox::CombinedCache(QStringLiteral("trojita-imap-cache"), m_cacheDir)); cache->setErrorHandler([this](const QString &e) { this->onCacheError(e); }); if (! static_cast<Imap::Mailbox::CombinedCache *>(cache.get())->open()) { // Error message was already shown by the cacheError() slot cache.reset(new Imap::Mailbox::MemoryCache()); } else { if (m_settings->value(Common::SettingsNames::cacheOfflineKey).toString() == Common::SettingsNames::cacheOfflineAll) { cache->setRenewalThreshold(0); } else { const int defaultCacheLifetime = 30; bool ok; int num = m_settings->value(Common::SettingsNames::cacheOfflineNumberDaysKey, defaultCacheLifetime).toInt(&ok); if (!ok) num = defaultCacheLifetime; cache->setRenewalThreshold(num); } } } m_imapModel = new Imap::Mailbox::Model(this, cache, std::move(factory), std::move(taskFactory)); m_imapModel->setObjectName(QStringLiteral("imapModel-%1").arg(m_accountName)); m_imapModel->setCapabilitiesBlacklist(m_settings->value(Common::SettingsNames::imapBlacklistedCapabilities).toStringList()); m_imapModel->setProperty("trojita-imap-id-no-versions", !m_settings->value(Common::SettingsNames::interopRevealVersions, true).toBool()); m_imapModel->setProperty("trojita-imap-idle-renewal", m_settings->value(Common::SettingsNames::imapIdleRenewal).toUInt() * 60 * 1000); m_imapModel->setNumberRefreshInterval(numberRefreshInterval()); connect(m_imapModel, &Mailbox::Model::alertReceived, this, &ImapAccess::alertReceived); connect(m_imapModel, &Mailbox::Model::imapError, this, &ImapAccess::imapError); connect(m_imapModel, &Mailbox::Model::networkError, this, &ImapAccess::networkError); //connect(m_imapModel, &Mailbox::Model::logged, this, &ImapAccess::slotLogged); connect(m_imapModel, &Mailbox::Model::needsSslDecision, this, &ImapAccess::slotSslErrors); connect(m_imapModel, &Mailbox::Model::requireStartTlsInFuture, this, &ImapAccess::onRequireStartTlsInFuture); if (m_settings->value(Common::SettingsNames::imapNeedsNetwork, true).toBool()) { m_netWatcher = new Imap::Mailbox::SystemNetworkWatcher(this, m_imapModel); } else { m_netWatcher = new Imap::Mailbox::DummyNetworkWatcher(this, m_imapModel); } connect(m_netWatcher, &Mailbox::NetworkWatcher::desiredNetworkPolicyChanged, this, &ImapAccess::desiredNetworkPolicyChanged); switch (preferredNetworkPolicy()) { case Imap::Mailbox::NETWORK_OFFLINE: QMetaObject::invokeMethod(m_netWatcher, "setNetworkOffline", Qt::QueuedConnection); break; case Imap::Mailbox::NETWORK_EXPENSIVE: QMetaObject::invokeMethod(m_netWatcher, "setNetworkExpensive", Qt::QueuedConnection); break; case Imap::Mailbox::NETWORK_ONLINE: QMetaObject::invokeMethod(m_netWatcher, "setNetworkOnline", Qt::QueuedConnection); break; } m_imapModel->setImapUser(username()); if (!m_password.isNull()) { // Really; the idea is to wait before it has been set for the first time m_imapModel->setImapPassword(password()); } m_mailboxModel = new Imap::Mailbox::MailboxModel(this, m_imapModel); m_mailboxModel->setObjectName(QStringLiteral("mailboxModel-%1").arg(m_accountName)); m_mailboxSubtreeModel = new Imap::Mailbox::SubtreeModelOfMailboxModel(this); m_mailboxSubtreeModel->setObjectName(QStringLiteral("mailboxSubtreeModel-%1").arg(m_accountName)); m_mailboxSubtreeModel->setSourceModel(m_mailboxModel); m_mailboxSubtreeModel->setOriginalRoot(); m_msgListModel = new Imap::Mailbox::MsgListModel(this, m_imapModel); m_msgListModel->setObjectName(QStringLiteral("msgListModel-%1").arg(m_accountName)); m_visibleTasksModel = new Imap::Mailbox::VisibleTasksModel(this, m_imapModel->taskModel()); m_visibleTasksModel->setObjectName(QStringLiteral("visibleTasksModel-%1").arg(m_accountName)); m_oneMessageModel = new Imap::Mailbox::OneMessageModel(m_imapModel); m_oneMessageModel->setObjectName(QStringLiteral("oneMessageModel-%1").arg(m_accountName)); m_msgQNAM = new Imap::Network::MsgPartNetAccessManager(this); m_msgQNAM->setObjectName(QStringLiteral("m_msgQNAM-%1").arg(m_accountName)); m_threadingMsgListModel = new Imap::Mailbox::ThreadingMsgListModel(this); m_threadingMsgListModel->setObjectName(QStringLiteral("threadingMsgListModel-%1").arg(m_accountName)); m_threadingMsgListModel->setSourceModel(m_msgListModel); emit modelsChanged(); }
void ImapAccess::doConnect() { Q_ASSERT(!m_imapModel); Imap::Mailbox::SocketFactoryPtr factory; Imap::Mailbox::TaskFactoryPtr taskFactory(new Imap::Mailbox::TaskFactory()); Streams::ProxySettings proxySettings = m_settings->value(Common::SettingsNames::imapUseSystemProxy, true).toBool() ? Streams::ProxySettings::RespectSystemProxy : Streams::ProxySettings::DirectConnect; switch (m_connectionMethod) { case Common::ConnectionMethod::Invalid: factory.reset(new Streams::FakeSocketFactory(Imap::CONN_STATE_LOGOUT)); break; case Common::ConnectionMethod::NetCleartext: case Common::ConnectionMethod::NetStartTls: factory.reset(new Streams::TlsAbleSocketFactory(server(), port())); factory->setStartTlsRequired(m_connectionMethod == Common::ConnectionMethod::NetStartTls); factory->setProxySettings(proxySettings, QLatin1String("imap")); break; case Common::ConnectionMethod::NetDedicatedTls: factory.reset(new Streams::SslSocketFactory(server(), port())); factory->setProxySettings(proxySettings, QLatin1String("imap")); break; case Common::ConnectionMethod::Process: QStringList args = m_settings->value(Common::SettingsNames::imapProcessKey).toString().split(QLatin1Char(' ')); if (args.isEmpty()) { // it's going to fail anyway args << QLatin1String(""); } QString appName = args.takeFirst(); factory.reset(new Streams::ProcessSocketFactory(appName, args)); break; } bool shouldUsePersistentCache = m_settings->value(Common::SettingsNames::cacheOfflineKey).toString() != Common::SettingsNames::cacheOfflineNone; if (shouldUsePersistentCache && !QDir().mkpath(m_cacheDir)) { onCacheError(tr("Failed to create directory %1").arg(m_cacheDir)); shouldUsePersistentCache = false; } if (shouldUsePersistentCache) { QFile::Permissions expectedPerms = QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner; if (QFileInfo(m_cacheDir).permissions() != expectedPerms) { if (!QFile::setPermissions(m_cacheDir, expectedPerms)) { #ifndef Q_OS_WIN32 onCacheError(tr("Failed to set safe permissions on cache directory %1").arg(m_cacheDir)); shouldUsePersistentCache = false; #endif } } } Imap::Mailbox::AbstractCache *cache = 0; if (!shouldUsePersistentCache) { cache = new Imap::Mailbox::MemoryCache(this); } else { cache = new Imap::Mailbox::CombinedCache(this, QLatin1String("trojita-imap-cache"), m_cacheDir); connect(cache, SIGNAL(error(QString)), this, SLOT(onCacheError(QString))); if (! static_cast<Imap::Mailbox::CombinedCache *>(cache)->open()) { // Error message was already shown by the cacheError() slot cache->deleteLater(); cache = new Imap::Mailbox::MemoryCache(this); } else { if (m_settings->value(Common::SettingsNames::cacheOfflineKey).toString() == Common::SettingsNames::cacheOfflineAll) { cache->setRenewalThreshold(0); } else { const int defaultCacheLifetime = 30; bool ok; int num = m_settings->value(Common::SettingsNames::cacheOfflineNumberDaysKey, defaultCacheLifetime).toInt(&ok); if (!ok) num = defaultCacheLifetime; cache->setRenewalThreshold(num); } } } m_imapModel = new Imap::Mailbox::Model(this, cache, std::move(factory), std::move(taskFactory)); m_imapModel->setObjectName(QString::fromUtf8("imapModel-%1").arg(m_accountName)); m_imapModel->setCapabilitiesBlacklist(m_settings->value(Common::SettingsNames::imapBlacklistedCapabilities).toStringList()); m_imapModel->setProperty("trojita-imap-enable-id", m_settings->value(Common::SettingsNames::imapEnableId, true).toBool()); connect(m_imapModel, SIGNAL(alertReceived(QString)), this, SLOT(alertReceived(QString))); connect(m_imapModel, SIGNAL(imapError(QString)), this, SLOT(imapError(QString))); connect(m_imapModel, SIGNAL(networkError(QString)), this, SLOT(networkError(QString))); //connect(m_imapModel, SIGNAL(logged(uint,Common::LogMessage)), this, SLOT(slotLogged(uint,Common::LogMessage))); connect(m_imapModel, SIGNAL(needsSslDecision(QList<QSslCertificate>,QList<QSslError>)), this, SLOT(slotSslErrors(QList<QSslCertificate>,QList<QSslError>))); if (m_settings->value(Common::SettingsNames::imapNeedsNetwork, true).toBool()) { m_netWatcher = new Imap::Mailbox::SystemNetworkWatcher(this, m_imapModel); } else { m_netWatcher = new Imap::Mailbox::DummyNetworkWatcher(this, m_imapModel); } QMetaObject::invokeMethod(m_netWatcher, m_settings->value(Common::SettingsNames::imapStartOffline).toBool() ? "setNetworkOffline" : "setNetworkOnline", Qt::QueuedConnection); m_imapModel->setImapUser(username()); if (!m_password.isNull()) { // Really; the idea is to wait before it has been set for the first time m_imapModel->setImapPassword(password()); } m_mailboxModel = new Imap::Mailbox::MailboxModel(this, m_imapModel); m_mailboxModel->setObjectName(QString::fromUtf8("mailboxModel-%1").arg(m_accountName)); m_mailboxSubtreeModel = new Imap::Mailbox::SubtreeModelOfMailboxModel(this); m_mailboxSubtreeModel->setObjectName(QString::fromUtf8("mailboxSubtreeModel-%1").arg(m_accountName)); m_mailboxSubtreeModel->setSourceModel(m_mailboxModel); m_mailboxSubtreeModel->setOriginalRoot(); m_msgListModel = new Imap::Mailbox::MsgListModel(this, m_imapModel); m_msgListModel->setObjectName(QString::fromUtf8("msgListModel-%1").arg(m_accountName)); m_visibleTasksModel = new Imap::Mailbox::VisibleTasksModel(this, m_imapModel->taskModel()); m_visibleTasksModel->setObjectName(QString::fromUtf8("visibleTasksModel-%1").arg(m_accountName)); m_oneMessageModel = new Imap::Mailbox::OneMessageModel(m_imapModel); m_oneMessageModel->setObjectName(QString::fromUtf8("oneMessageModel-%1").arg(m_accountName)); m_msgQNAM = new Imap::Network::MsgPartNetAccessManager(this); m_msgQNAM->setObjectName(QString::fromUtf8("m_msgQNAM-%1").arg(m_accountName)); m_threadingMsgListModel = new Imap::Mailbox::ThreadingMsgListModel(this); m_threadingMsgListModel->setObjectName(QString::fromUtf8("threadingMsgListModel-%1").arg(m_accountName)); m_threadingMsgListModel->setSourceModel(m_msgListModel); emit modelsChanged(); }