File indexing completed on 2024-07-14 04:54:32

0001 /*
0002     The configuration page for the mount options
0003 
0004     SPDX-FileCopyrightText: 2015-2023 Alexander Reinholdt <alexander.reinholdt@kdemail.net>
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 // application specific includes
0009 #include "smb4kconfigpagemounting.h"
0010 #include "core/smb4kglobal.h"
0011 
0012 #if defined(Q_OS_LINUX)
0013 #include "core/smb4kmountsettings_linux.h"
0014 #elif defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD)
0015 #include "core/smb4kmountsettings_bsd.h"
0016 #endif
0017 
0018 // Qt includes
0019 #include <QGroupBox>
0020 #include <QInputDialog>
0021 #include <QLabel>
0022 #include <QMenu>
0023 #include <QSpinBox>
0024 #include <QToolButton>
0025 #include <QVBoxLayout>
0026 
0027 // KDE includes
0028 #include <KComboBox>
0029 #include <KIconLoader>
0030 #include <KLocalizedString>
0031 #include <KMessageBox>
0032 
0033 using namespace Smb4KGlobal;
0034 
0035 Smb4KConfigPageMounting::Smb4KConfigPageMounting(QWidget *parent)
0036     : QTabWidget(parent)
0037 {
0038     setupWidget();
0039 }
0040 
0041 Smb4KConfigPageMounting::~Smb4KConfigPageMounting()
0042 {
0043 }
0044 
0045 bool Smb4KConfigPageMounting::checkSettings()
0046 {
0047     if (!m_mountPrefix->url().isValid()) {
0048         m_mountPrefix->setFocus();
0049         return false;
0050     }
0051 
0052     if (m_useFileMode->isChecked() && m_fileMode->text().trimmed().isEmpty()) {
0053         m_fileMode->setFocus();
0054         return false;
0055     }
0056 
0057     if (m_useDirectoryMode->isChecked() && m_directoryMode->text().trimmed().isEmpty()) {
0058         m_directoryMode->setFocus();
0059         return false;
0060     }
0061 
0062     return true;
0063 }
0064 
0065 #if defined(Q_OS_LINUX)
0066 //
0067 // Linux
0068 //
0069 void Smb4KConfigPageMounting::setupWidget()
0070 {
0071     //
0072     // Basic Settings tab
0073     //
0074     QWidget *basicTab = new QWidget(this);
0075     QVBoxLayout *basicTabLayout = new QVBoxLayout(basicTab);
0076 
0077     //
0078     // Directories
0079     //
0080     QGroupBox *directoryBox = new QGroupBox(i18n("Directories"), basicTab);
0081     QGridLayout *directoryBoxLayout = new QGridLayout(directoryBox);
0082 
0083     QLabel *mountPrefixLabel = new QLabel(Smb4KMountSettings::self()->mountPrefixItem()->label(), directoryBox);
0084     m_mountPrefix = new KUrlRequester(directoryBox);
0085     m_mountPrefix->setMode(KFile::Directory | KFile::LocalOnly);
0086     m_mountPrefix->setObjectName(QStringLiteral("kcfg_MountPrefix"));
0087 
0088     mountPrefixLabel->setBuddy(m_mountPrefix);
0089 
0090     QCheckBox *lowercaseSubdirs = new QCheckBox(Smb4KMountSettings::self()->forceLowerCaseSubdirsItem()->label(), directoryBox);
0091     lowercaseSubdirs->setObjectName(QStringLiteral("kcfg_ForceLowerCaseSubdirs"));
0092 
0093     directoryBoxLayout->addWidget(mountPrefixLabel, 0, 0);
0094     directoryBoxLayout->addWidget(m_mountPrefix, 0, 1);
0095     directoryBoxLayout->addWidget(lowercaseSubdirs, 1, 0, 1, 2);
0096 
0097     basicTabLayout->addWidget(directoryBox, 0);
0098 
0099     //
0100     // Behavior
0101     //
0102     QGroupBox *behaviorBox = new QGroupBox(i18n("Behavior"), this);
0103     QVBoxLayout *behaviorBoxLayout = new QVBoxLayout(behaviorBox);
0104 
0105     QCheckBox *remountShares = new QCheckBox(Smb4KMountSettings::self()->remountSharesItem()->label(), behaviorBox);
0106     remountShares->setObjectName(QStringLiteral("kcfg_RemountShares"));
0107 
0108     m_remountSettingsWidget = new QWidget(behaviorBox);
0109     m_remountSettingsWidget->setEnabled(false);
0110     QGridLayout *remountSettingsWidgetLayout = new QGridLayout(m_remountSettingsWidget);
0111     remountSettingsWidgetLayout->setContentsMargins(0, 0, 0, 0);
0112 
0113     QLabel *remountAttemptsLabel = new QLabel(Smb4KMountSettings::self()->remountAttemptsItem()->label(), m_remountSettingsWidget);
0114     remountAttemptsLabel->setObjectName(QStringLiteral("RemountAttemptsLabel"));
0115     remountAttemptsLabel->setIndent(25);
0116 
0117     QSpinBox *remountAttempts = new QSpinBox(m_remountSettingsWidget);
0118     remountAttempts->setObjectName(QStringLiteral("kcfg_RemountAttempts"));
0119     remountAttemptsLabel->setBuddy(remountAttempts);
0120 
0121     QLabel *remountIntervalLabel = new QLabel(Smb4KMountSettings::self()->remountIntervalItem()->label(), m_remountSettingsWidget);
0122     remountIntervalLabel->setObjectName(QStringLiteral("RemountIntervalLabel"));
0123     remountIntervalLabel->setIndent(25);
0124 
0125     QSpinBox *remountInterval = new QSpinBox(m_remountSettingsWidget);
0126     remountInterval->setObjectName(QStringLiteral("kcfg_RemountInterval"));
0127     remountInterval->setSuffix(i18n(" min"));
0128     remountIntervalLabel->setBuddy(remountInterval);
0129 
0130     remountSettingsWidgetLayout->addWidget(remountAttemptsLabel, 0, 0);
0131     remountSettingsWidgetLayout->addWidget(remountAttempts, 0, 1);
0132     remountSettingsWidgetLayout->addWidget(remountIntervalLabel, 1, 0);
0133     remountSettingsWidgetLayout->addWidget(remountInterval, 1, 1);
0134 
0135     QCheckBox *unmountAllShares = new QCheckBox(Smb4KMountSettings::self()->unmountSharesOnExitItem()->label(), behaviorBox);
0136     unmountAllShares->setObjectName(QStringLiteral("kcfg_UnmountSharesOnExit"));
0137 
0138     QCheckBox *unmountForeignShares = new QCheckBox(Smb4KMountSettings::self()->unmountForeignSharesItem()->label(), behaviorBox);
0139     unmountForeignShares->setObjectName(QStringLiteral("kcfg_UnmountForeignShares"));
0140 
0141     QCheckBox *unmountInaccessibleShares = new QCheckBox(Smb4KMountSettings::self()->forceUnmountInaccessibleItem()->label(), behaviorBox);
0142     unmountInaccessibleShares->setObjectName(QStringLiteral("kcfg_ForceUnmountInaccessible"));
0143 
0144     QCheckBox *detectAllShares = new QCheckBox(Smb4KMountSettings::self()->detectAllSharesItem()->label(), behaviorBox);
0145     detectAllShares->setObjectName(QStringLiteral("kcfg_DetectAllShares"));
0146 
0147     behaviorBoxLayout->addWidget(remountShares);
0148     behaviorBoxLayout->addWidget(m_remountSettingsWidget);
0149     behaviorBoxLayout->addWidget(unmountAllShares);
0150     behaviorBoxLayout->addWidget(unmountInaccessibleShares);
0151     behaviorBoxLayout->addWidget(unmountForeignShares);
0152     behaviorBoxLayout->addWidget(detectAllShares);
0153 
0154     basicTabLayout->addWidget(behaviorBox, 0);
0155     basicTabLayout->addStretch(100);
0156 
0157     addTab(basicTab, i18n("Basic Settings"));
0158 
0159     //
0160     // Common Mount Settings tab
0161     //
0162     QWidget *commonTab = new QWidget(this);
0163     QVBoxLayout *commonTabLayout = new QVBoxLayout(commonTab);
0164 
0165     //
0166     // Common options group box
0167     //
0168     QGroupBox *commonOptions = new QGroupBox(i18n("Common Options"), commonTab);
0169     QGridLayout *commonOptionsLayout = new QGridLayout(commonOptions);
0170 
0171     // Write access
0172     QCheckBox *useWriteAccess = new QCheckBox(Smb4KMountSettings::self()->useWriteAccessItem()->label(), commonOptions);
0173     useWriteAccess->setObjectName(QStringLiteral("kcfg_UseWriteAccess"));
0174 
0175     KComboBox *writeAccess = new KComboBox(commonOptions);
0176     writeAccess->setObjectName(QStringLiteral("kcfg_WriteAccess"));
0177 
0178     QList<KCoreConfigSkeleton::ItemEnum::Choice> writeAccessChoices = Smb4KMountSettings::self()->writeAccessItem()->choices();
0179 
0180     for (const KCoreConfigSkeleton::ItemEnum::Choice &wa : qAsConst(writeAccessChoices)) {
0181         writeAccess->addItem(wa.label);
0182     }
0183 
0184     commonOptionsLayout->addWidget(useWriteAccess, 0, 0);
0185     commonOptionsLayout->addWidget(writeAccess, 0, 1);
0186 
0187     // Character set
0188     QCheckBox *useCharacterSet = new QCheckBox(Smb4KMountSettings::self()->useClientCharsetItem()->label(), commonOptions);
0189     useCharacterSet->setObjectName(QStringLiteral("kcfg_UseClientCharset"));
0190 
0191     KComboBox *characterSet = new KComboBox(commonOptions);
0192     characterSet->setObjectName(QStringLiteral("kcfg_ClientCharset"));
0193 
0194     QList<KCoreConfigSkeleton::ItemEnum::Choice> charsetChoices = Smb4KMountSettings::self()->clientCharsetItem()->choices();
0195 
0196     for (const KCoreConfigSkeleton::ItemEnum::Choice &c : qAsConst(charsetChoices)) {
0197         characterSet->addItem(c.label);
0198     }
0199 
0200     commonOptionsLayout->addWidget(useCharacterSet, 1, 0);
0201     commonOptionsLayout->addWidget(characterSet, 1, 1);
0202 
0203     // Remote filesystem port
0204     QCheckBox *useFilesystemPort = new QCheckBox(Smb4KMountSettings::self()->useRemoteFileSystemPortItem()->label(), commonOptions);
0205     useFilesystemPort->setObjectName(QStringLiteral("kcfg_UseRemoteFileSystemPort"));
0206 
0207     QSpinBox *filesystemPort = new QSpinBox(commonOptions);
0208     filesystemPort->setObjectName(QStringLiteral("kcfg_RemoteFileSystemPort"));
0209 
0210     commonOptionsLayout->addWidget(useFilesystemPort, 2, 0);
0211     commonOptionsLayout->addWidget(filesystemPort, 2, 1);
0212 
0213     commonTabLayout->addWidget(commonOptions, 0);
0214 
0215     //
0216     // CIFS Unix Extensions Support group box
0217     //
0218     QGroupBox *cifsExtensionSupportBox = new QGroupBox(i18n("CIFS Unix Extensions Support"), commonTab);
0219     QVBoxLayout *cifsExtensionSupportLayout = new QVBoxLayout(cifsExtensionSupportBox);
0220 
0221     // CIFS Unix extensions support
0222     QCheckBox *cifsExtensionsSupport = new QCheckBox(Smb4KMountSettings::self()->cifsUnixExtensionsSupportItem()->label(), cifsExtensionSupportBox);
0223     cifsExtensionsSupport->setObjectName(QStringLiteral("kcfg_CifsUnixExtensionsSupport"));
0224 
0225     cifsExtensionSupportLayout->addWidget(cifsExtensionsSupport);
0226 
0227     m_singleCifsExtensionsSettingsWidget = new QWidget(cifsExtensionSupportBox);
0228     m_singleCifsExtensionsSettingsWidget->setEnabled(false);
0229     QGridLayout *singleCifsSettingsWidgetLayout = new QGridLayout(m_singleCifsExtensionsSettingsWidget);
0230     singleCifsSettingsWidgetLayout->setContentsMargins(0, 0, 0, 0);
0231 
0232     // User information
0233     QCheckBox *useUserId = new QCheckBox(Smb4KMountSettings::self()->useUserIdItem()->label(), m_singleCifsExtensionsSettingsWidget);
0234     useUserId->setObjectName(QStringLiteral("kcfg_UseUserId"));
0235 
0236     QWidget *userIdInputWidget = new QWidget(m_singleCifsExtensionsSettingsWidget);
0237     userIdInputWidget->setObjectName(QStringLiteral("UserIdInputWidget"));
0238 
0239     QGridLayout *userIdInputWidgetLayout = new QGridLayout(userIdInputWidget);
0240     userIdInputWidgetLayout->setContentsMargins(0, 0, 0, 0);
0241 
0242     m_userId = new KLineEdit(userIdInputWidget);
0243     m_userId->setObjectName(QStringLiteral("kcfg_UserId"));
0244     m_userId->setAlignment(Qt::AlignRight);
0245     m_userId->setReadOnly(true);
0246 
0247     QToolButton *userChooser = new QToolButton(userIdInputWidget);
0248     userChooser->setIcon(KDE::icon(QStringLiteral("edit-find-user")));
0249     userChooser->setToolTip(i18n("Choose a different user"));
0250     userChooser->setPopupMode(QToolButton::InstantPopup);
0251 
0252     QMenu *userMenu = new QMenu(userChooser);
0253     userChooser->setMenu(userMenu);
0254 
0255     QList<KUser> allUsers = KUser::allUsers();
0256 
0257     for (const KUser &u : qAsConst(allUsers)) {
0258         QAction *userAction = userMenu->addAction(u.loginName() + QStringLiteral(" (") + u.userId().toString() + QStringLiteral(")"));
0259         userAction->setData(u.userId().nativeId());
0260     }
0261 
0262     userIdInputWidgetLayout->addWidget(m_userId, 0, 0);
0263     userIdInputWidgetLayout->addWidget(userChooser, 0, 1, Qt::AlignCenter);
0264 
0265     singleCifsSettingsWidgetLayout->addWidget(useUserId, 0, 0);
0266     singleCifsSettingsWidgetLayout->addWidget(userIdInputWidget, 0, 1);
0267 
0268     // Group information
0269     QCheckBox *useGroupId = new QCheckBox(Smb4KMountSettings::self()->useGroupIdItem()->label(), m_singleCifsExtensionsSettingsWidget);
0270     useGroupId->setObjectName(QStringLiteral("kcfg_UseGroupId"));
0271 
0272     QWidget *groupIdInputWidget = new QWidget(m_singleCifsExtensionsSettingsWidget);
0273     groupIdInputWidget->setObjectName(QStringLiteral("GroupIdInputWidget"));
0274 
0275     QGridLayout *groupIdInputWidgetLayout = new QGridLayout(groupIdInputWidget);
0276     groupIdInputWidgetLayout->setContentsMargins(0, 0, 0, 0);
0277 
0278     m_groupId = new KLineEdit(groupIdInputWidget);
0279     m_groupId->setObjectName(QStringLiteral("kcfg_GroupId"));
0280     m_groupId->setAlignment(Qt::AlignRight);
0281     m_groupId->setReadOnly(true);
0282 
0283     QToolButton *groupChooser = new QToolButton(groupIdInputWidget);
0284     groupChooser->setIcon(KDE::icon(QStringLiteral("edit-find-user")));
0285     groupChooser->setToolTip(i18n("Choose a different group"));
0286     groupChooser->setPopupMode(QToolButton::InstantPopup);
0287 
0288     QMenu *groupMenu = new QMenu(groupChooser);
0289     groupChooser->setMenu(groupMenu);
0290 
0291     QList<KUserGroup> groupList = KUserGroup::allGroups();
0292 
0293     for (const KUserGroup &g : qAsConst(groupList)) {
0294         QAction *groupAction = groupMenu->addAction(g.name() + QStringLiteral(" (") + g.groupId().toString() + QStringLiteral(")"));
0295         groupAction->setData(g.groupId().nativeId());
0296     }
0297 
0298     groupIdInputWidgetLayout->addWidget(m_groupId, 0, 0);
0299     groupIdInputWidgetLayout->addWidget(groupChooser, 0, 1, Qt::AlignCenter);
0300 
0301     singleCifsSettingsWidgetLayout->addWidget(useGroupId, 1, 0);
0302     singleCifsSettingsWidgetLayout->addWidget(groupIdInputWidget, 1, 1);
0303 
0304     // File mask
0305     m_useFileMode = new QCheckBox(Smb4KMountSettings::self()->useFileModeItem()->label(), m_singleCifsExtensionsSettingsWidget);
0306     m_useFileMode->setObjectName(QStringLiteral("kcfg_UseFileMode"));
0307 
0308     m_fileMode = new KLineEdit(m_singleCifsExtensionsSettingsWidget);
0309     m_fileMode->setObjectName(QStringLiteral("kcfg_FileMode"));
0310     m_fileMode->setClearButtonEnabled(true);
0311     m_fileMode->setAlignment(Qt::AlignRight);
0312 
0313     singleCifsSettingsWidgetLayout->addWidget(m_useFileMode, 2, 0);
0314     singleCifsSettingsWidgetLayout->addWidget(m_fileMode, 2, 1);
0315 
0316     // Directory mask
0317     m_useDirectoryMode = new QCheckBox(Smb4KMountSettings::self()->useDirectoryModeItem()->label(), m_singleCifsExtensionsSettingsWidget);
0318     m_useDirectoryMode->setObjectName(QStringLiteral("kcfg_UseDirectoryMode"));
0319 
0320     m_directoryMode = new KLineEdit(m_singleCifsExtensionsSettingsWidget);
0321     m_directoryMode->setObjectName(QStringLiteral("kcfg_DirectoryMode"));
0322     m_directoryMode->setClearButtonEnabled(true);
0323     m_directoryMode->setAlignment(Qt::AlignRight);
0324 
0325     singleCifsSettingsWidgetLayout->addWidget(m_useDirectoryMode, 3, 0);
0326     singleCifsSettingsWidgetLayout->addWidget(m_directoryMode, 3, 1);
0327 
0328     cifsExtensionSupportLayout->addWidget(m_singleCifsExtensionsSettingsWidget);
0329 
0330     commonTabLayout->addWidget(cifsExtensionSupportBox, 1);
0331     commonTabLayout->addStretch(100);
0332 
0333     addTab(commonTab, i18n("Common Mount Settings"));
0334 
0335     //
0336     // Advanced Mount Settings tab
0337     //
0338     QWidget *advancedTab = new QWidget(this);
0339     QVBoxLayout *advancedTabLayout = new QVBoxLayout(advancedTab);
0340 
0341     QGroupBox *advancedOptions = new QGroupBox(i18n("Advanced Options"), advancedTab);
0342     QGridLayout *advancedOptionsLayout = new QGridLayout(advancedOptions);
0343 
0344     // Force Uid
0345     QCheckBox *forceUid = new QCheckBox(Smb4KMountSettings::self()->forceUIDItem()->label(), advancedOptions);
0346     forceUid->setObjectName(QStringLiteral("kcfg_ForceUID"));
0347 
0348     advancedOptionsLayout->addWidget(forceUid, 0, 0);
0349 
0350     // Force Gid
0351     QCheckBox *forceGid = new QCheckBox(Smb4KMountSettings::self()->forceGIDItem()->label(), advancedOptions);
0352     forceGid->setObjectName(QStringLiteral("kcfg_ForceGID"));
0353 
0354     advancedOptionsLayout->addWidget(forceGid, 0, 1);
0355 
0356     // Permission checks
0357     QCheckBox *permissionChecks = new QCheckBox(Smb4KMountSettings::self()->permissionChecksItem()->label(), advancedOptions);
0358     permissionChecks->setObjectName(QStringLiteral("kcfg_PermissionChecks"));
0359 
0360     advancedOptionsLayout->addWidget(permissionChecks, 1, 0);
0361 
0362     // Client controls Ids
0363     QCheckBox *clientControlsIds = new QCheckBox(Smb4KMountSettings::self()->clientControlsIDsItem()->label(), advancedOptions);
0364     clientControlsIds->setObjectName(QStringLiteral("kcfg_ClientControlsIDs"));
0365 
0366     advancedOptionsLayout->addWidget(clientControlsIds, 1, 1);
0367 
0368     // Use server inode numbers
0369     QCheckBox *useServerInodes = new QCheckBox(Smb4KMountSettings::self()->serverInodeNumbersItem()->label(), advancedOptions);
0370     useServerInodes->setObjectName(QStringLiteral("kcfg_ServerInodeNumbers"));
0371 
0372     advancedOptionsLayout->addWidget(useServerInodes, 2, 0);
0373 
0374     // Translate reserved characters
0375     QCheckBox *translateReservedCharacters = new QCheckBox(Smb4KMountSettings::self()->translateReservedCharsItem()->label(), advancedOptions);
0376     translateReservedCharacters->setObjectName(QStringLiteral("kcfg_TranslateReservedChars"));
0377 
0378     advancedOptionsLayout->addWidget(translateReservedCharacters, 2, 1);
0379 
0380     // No locking
0381     QCheckBox *no_locking = new QCheckBox(Smb4KMountSettings::self()->noLockingItem()->label(), advancedOptions);
0382     no_locking->setObjectName(QStringLiteral("kcfg_NoLocking"));
0383 
0384     advancedOptionsLayout->addWidget(no_locking, 3, 0);
0385 
0386     // Extra widget for the rest of the options
0387     QWidget *advancedOptionsExtraWidget = new QWidget(advancedOptions);
0388     QGridLayout *advancedOptionsExtraWidgetLayout = new QGridLayout(advancedOptionsExtraWidget);
0389     advancedOptionsExtraWidgetLayout->setContentsMargins(0, 0, 0, 0);
0390 
0391     // SMB protocol version
0392     QCheckBox *useSmbProtocol = new QCheckBox(Smb4KMountSettings::self()->useSmbProtocolVersionItem()->label(), advancedOptionsExtraWidget);
0393     useSmbProtocol->setObjectName(QStringLiteral("kcfg_UseSmbProtocolVersion"));
0394 
0395     KComboBox *smbProtocol = new KComboBox(advancedOptionsExtraWidget);
0396     smbProtocol->setObjectName(QStringLiteral("kcfg_SmbProtocolVersion"));
0397 
0398     QList<KCoreConfigSkeleton::ItemEnum::Choice> smbProtocolChoices = Smb4KMountSettings::self()->smbProtocolVersionItem()->choices();
0399 
0400     for (const KCoreConfigSkeleton::ItemEnum::Choice &c : qAsConst(smbProtocolChoices)) {
0401         smbProtocol->addItem(c.label);
0402     }
0403 
0404     advancedOptionsExtraWidgetLayout->addWidget(useSmbProtocol, 0, 0);
0405     advancedOptionsExtraWidgetLayout->addWidget(smbProtocol, 0, 1);
0406 
0407     // Cache mode
0408     QCheckBox *useCacheMode = new QCheckBox(Smb4KMountSettings::self()->useCacheModeItem()->label(), advancedOptionsExtraWidget);
0409     useCacheMode->setObjectName(QStringLiteral("kcfg_UseCacheMode"));
0410 
0411     KComboBox *cacheMode = new KComboBox(advancedOptionsExtraWidget);
0412     cacheMode->setObjectName(QStringLiteral("kcfg_CacheMode"));
0413 
0414     QList<KCoreConfigSkeleton::ItemEnum::Choice> cacheModeChoices = Smb4KMountSettings::self()->cacheModeItem()->choices();
0415 
0416     for (const KCoreConfigSkeleton::ItemEnum::Choice &c : qAsConst(cacheModeChoices)) {
0417         cacheMode->addItem(c.label);
0418     }
0419 
0420     advancedOptionsExtraWidgetLayout->addWidget(useCacheMode, 1, 0);
0421     advancedOptionsExtraWidgetLayout->addWidget(cacheMode, 1, 1);
0422 
0423     // Security mode
0424     QCheckBox *useSecurityMode = new QCheckBox(Smb4KMountSettings::self()->useSecurityModeItem()->label(), advancedOptionsExtraWidget);
0425     useSecurityMode->setObjectName(QStringLiteral("kcfg_UseSecurityMode"));
0426 
0427     KComboBox *securityMode = new KComboBox(advancedOptionsExtraWidget);
0428     securityMode->setObjectName(QStringLiteral("kcfg_SecurityMode"));
0429 
0430     QList<KConfigSkeleton::ItemEnum::Choice> securityModeChoices = Smb4KMountSettings::self()->securityModeItem()->choices();
0431 
0432     for (const KConfigSkeleton::ItemEnum::Choice &c : qAsConst(securityModeChoices)) {
0433         securityMode->addItem(c.label);
0434     }
0435 
0436     advancedOptionsExtraWidgetLayout->addWidget(useSecurityMode, 2, 0);
0437     advancedOptionsExtraWidgetLayout->addWidget(securityMode, 2, 1);
0438 
0439     // Additional options
0440     QCheckBox *useAdditionalCifsOptions = new QCheckBox(Smb4KMountSettings::self()->useCustomCifsOptionsItem()->label(), advancedOptionsExtraWidget);
0441     useAdditionalCifsOptions->setObjectName(QStringLiteral("kcfg_UseCustomCifsOptions"));
0442 
0443     QWidget *additionalOptionsWidget = new QWidget(advancedOptionsExtraWidget);
0444     QHBoxLayout *additionalOptionsWidgetLayout = new QHBoxLayout(additionalOptionsWidget);
0445     additionalOptionsWidgetLayout->setContentsMargins(0, 0, 0, 0);
0446 
0447     m_additionalCifsOptions = new KLineEdit(additionalOptionsWidget);
0448     m_additionalCifsOptions->setObjectName(QStringLiteral("kcfg_CustomCIFSOptions"));
0449     m_additionalCifsOptions->setReadOnly(true);
0450     m_additionalCifsOptions->setClearButtonEnabled(true);
0451 
0452     QToolButton *additionalOptionsEdit = new QToolButton(advancedOptionsExtraWidget);
0453     additionalOptionsEdit->setIcon(KDE::icon(QStringLiteral("document-edit")));
0454     additionalOptionsEdit->setToolTip(i18n("Edit the additional CIFS options."));
0455 
0456     additionalOptionsWidgetLayout->addWidget(m_additionalCifsOptions, 0);
0457     additionalOptionsWidgetLayout->addWidget(additionalOptionsEdit, 0);
0458 
0459     advancedOptionsExtraWidgetLayout->addWidget(useAdditionalCifsOptions, 3, 0);
0460     advancedOptionsExtraWidgetLayout->addWidget(additionalOptionsWidget, 3, 1);
0461 
0462     advancedOptionsLayout->addWidget(advancedOptionsExtraWidget, 4, 0, 1, 2);
0463 
0464     advancedTabLayout->addWidget(advancedOptions, 0);
0465     advancedTabLayout->addStretch(100);
0466 
0467     addTab(advancedTab, i18n("Advanced Mount Settings"));
0468 
0469     connect(userMenu, &QMenu::triggered, this, &Smb4KConfigPageMounting::slotNewUserTriggered);
0470     connect(groupMenu, &QMenu::triggered, this, &Smb4KConfigPageMounting::slotNewGroupTriggered);
0471     connect(cifsExtensionsSupport, &QCheckBox::toggled, this, &Smb4KConfigPageMounting::slotCIFSUnixExtensionsSupport);
0472     connect(additionalOptionsEdit, &QToolButton::clicked, this, &Smb4KConfigPageMounting::slotAdditionalCIFSOptions);
0473     connect(remountShares, &QCheckBox::toggled, this, &Smb4KConfigPageMounting::slotRemountSharesToggled);
0474 }
0475 #elif defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD)
0476 //
0477 // FreeBSD and NetBSD
0478 //
0479 void Smb4KConfigPageMounting::setupWidget()
0480 {
0481     //
0482     // Basic Settings tab
0483     //
0484     QWidget *basicTab = new QWidget(this);
0485     QVBoxLayout *basicTabLayout = new QVBoxLayout(basicTab);
0486 
0487     //
0488     // Directories
0489     //
0490     QGroupBox *directoryBox = new QGroupBox(i18n("Directories"), basicTab);
0491     QGridLayout *directoryBoxLayout = new QGridLayout(directoryBox);
0492 
0493     QLabel *mountPrefixLabel = new QLabel(Smb4KMountSettings::self()->mountPrefixItem()->label(), directoryBox);
0494     m_mountPrefix = new KUrlRequester(directoryBox);
0495     m_mountPrefix->setMode(KFile::Directory | KFile::LocalOnly);
0496     m_mountPrefix->setObjectName(QStringLiteral("kcfg_MountPrefix"));
0497 
0498     mountPrefixLabel->setBuddy(m_mountPrefix);
0499 
0500     QCheckBox *lowercaseSubdirs = new QCheckBox(Smb4KMountSettings::self()->forceLowerCaseSubdirsItem()->label(), directoryBox);
0501     lowercaseSubdirs->setObjectName(QStringLiteral("kcfg_ForceLowerCaseSubdirs"));
0502 
0503     directoryBoxLayout->addWidget(mountPrefixLabel, 0, 0);
0504     directoryBoxLayout->addWidget(m_mountPrefix, 0, 1);
0505     directoryBoxLayout->addWidget(lowercaseSubdirs, 1, 0, 1, 2);
0506 
0507     basicTabLayout->addWidget(directoryBox, 0);
0508 
0509     //
0510     // Behavior
0511     //
0512     QGroupBox *behaviorBox = new QGroupBox(i18n("Behavior"), this);
0513     QVBoxLayout *behaviorBoxLayout = new QVBoxLayout(behaviorBox);
0514 
0515     QCheckBox *remountShares = new QCheckBox(Smb4KMountSettings::self()->remountSharesItem()->label(), behaviorBox);
0516     remountShares->setObjectName(QStringLiteral("kcfg_RemountShares"));
0517 
0518     m_remountSettingsWidget = new QWidget(behaviorBox);
0519     m_remountSettingsWidget->setEnabled(false);
0520     QGridLayout *remountSettingsWidgetLayout = new QGridLayout(m_remountSettingsWidget);
0521     remountSettingsWidgetLayout->setContentsMargins(0, 0, 0, 0);
0522 
0523     QLabel *remountAttemptsLabel = new QLabel(Smb4KMountSettings::self()->remountAttemptsItem()->label(), m_remountSettingsWidget);
0524     remountAttemptsLabel->setObjectName(QStringLiteral("RemountAttemptsLabel"));
0525     remountAttemptsLabel->setIndent(25);
0526 
0527     QSpinBox *remountAttempts = new QSpinBox(m_remountSettingsWidget);
0528     remountAttempts->setObjectName(QStringLiteral("kcfg_RemountAttempts"));
0529     remountAttemptsLabel->setBuddy(remountAttempts);
0530 
0531     QLabel *remountIntervalLabel = new QLabel(Smb4KMountSettings::self()->remountIntervalItem()->label(), m_remountSettingsWidget);
0532     remountIntervalLabel->setObjectName(QStringLiteral("RemountIntervalLabel"));
0533     remountIntervalLabel->setIndent(25);
0534 
0535     QSpinBox *remountInterval = new QSpinBox(m_remountSettingsWidget);
0536     remountInterval->setObjectName(QStringLiteral("kcfg_RemountInterval"));
0537     remountInterval->setSuffix(i18n(" min"));
0538     remountIntervalLabel->setBuddy(remountInterval);
0539 
0540     remountSettingsWidgetLayout->addWidget(remountAttemptsLabel, 0, 0);
0541     remountSettingsWidgetLayout->addWidget(remountAttempts, 0, 1);
0542     remountSettingsWidgetLayout->addWidget(remountIntervalLabel, 1, 0);
0543     remountSettingsWidgetLayout->addWidget(remountInterval, 1, 1);
0544 
0545     QCheckBox *unmountAllShares = new QCheckBox(Smb4KMountSettings::self()->unmountSharesOnExitItem()->label(), behaviorBox);
0546     unmountAllShares->setObjectName(QStringLiteral("kcfg_UnmountSharesOnExit"));
0547 
0548     QCheckBox *unmountForeignShares = new QCheckBox(Smb4KMountSettings::self()->unmountForeignSharesItem()->label(), behaviorBox);
0549     unmountForeignShares->setObjectName(QStringLiteral("kcfg_UnmountForeignShares"));
0550 
0551     QCheckBox *detectAllShares = new QCheckBox(Smb4KMountSettings::self()->detectAllSharesItem()->label(), behaviorBox);
0552     detectAllShares->setObjectName(QStringLiteral("kcfg_DetectAllShares"));
0553 
0554     behaviorBoxLayout->addWidget(remountShares);
0555     behaviorBoxLayout->addWidget(m_remountSettingsWidget);
0556     behaviorBoxLayout->addWidget(unmountAllShares);
0557     behaviorBoxLayout->addWidget(unmountForeignShares);
0558     behaviorBoxLayout->addWidget(detectAllShares);
0559 
0560     basicTabLayout->addWidget(behaviorBox, 0);
0561     basicTabLayout->addStretch(100);
0562 
0563     addTab(basicTab, i18n("Basic Settings"));
0564 
0565     //
0566     // Mount Settings tab
0567     //
0568     QWidget *mountTab = new QWidget(this);
0569     QVBoxLayout *mountTabLayout = new QVBoxLayout(mountTab);
0570 
0571     //
0572     // Common Options
0573     //
0574     QGroupBox *commonOptionsBox = new QGroupBox(i18n("Common Options"), mountTab);
0575     QGridLayout *commonOptionsBoxLayout = new QGridLayout(commonOptionsBox);
0576 
0577     // User information
0578     QCheckBox *useUserId = new QCheckBox(Smb4KMountSettings::self()->useUserIdItem()->label(), commonOptionsBox);
0579     useUserId->setObjectName(QStringLiteral("kcfg_UseUserId"));
0580 
0581     QWidget *userIdInputWidget = new QWidget(commonOptionsBox);
0582     userIdInputWidget->setObjectName(QStringLiteral("UserIdInputWidget"));
0583 
0584     QGridLayout *userLayout = new QGridLayout(userIdInputWidget);
0585     userLayout->setContentsMargins(0, 0, 0, 0);
0586 
0587     m_userId = new KLineEdit(userIdInputWidget);
0588     m_userId->setObjectName(QStringLiteral("kcfg_UserId"));
0589     m_userId->setAlignment(Qt::AlignRight);
0590     m_userId->setReadOnly(true);
0591 
0592     QToolButton *userChooser = new QToolButton(userIdInputWidget);
0593     userChooser->setIcon(KDE::icon(QStringLiteral("edit-find-user")));
0594     userChooser->setToolTip(i18n("Choose a different user"));
0595     userChooser->setPopupMode(QToolButton::InstantPopup);
0596 
0597     QMenu *userMenu = new QMenu(userChooser);
0598     userChooser->setMenu(userMenu);
0599 
0600     QList<KUser> allUsers = KUser::allUsers();
0601 
0602     for (const KUser &u : allUsers) {
0603         QAction *userAction = userMenu->addAction(u.loginName() + QStringLiteral(" (") + u.userId().toString() + QStringLiteral(")"));
0604         userAction->setData(u.userId().nativeId());
0605     }
0606 
0607     userLayout->addWidget(m_userId, 0, 0);
0608     userLayout->addWidget(userChooser, 0, 1, Qt::AlignCenter);
0609 
0610     commonOptionsBoxLayout->addWidget(useUserId, 0, 0);
0611     commonOptionsBoxLayout->addWidget(userIdInputWidget, 0, 1);
0612 
0613     // Group information
0614     QCheckBox *useGroupId = new QCheckBox(Smb4KMountSettings::self()->useGroupIdItem()->label(), commonOptionsBox);
0615     useGroupId->setObjectName(QStringLiteral("kcfg_UseGroupId"));
0616 
0617     QWidget *groupIdInputWidget = new QWidget(commonOptionsBox);
0618     groupIdInputWidget->setObjectName(QStringLiteral("GroupIdInputWidget"));
0619 
0620     QGridLayout *groupLayout = new QGridLayout(groupIdInputWidget);
0621     groupLayout->setContentsMargins(0, 0, 0, 0);
0622 
0623     m_groupId = new KLineEdit(groupIdInputWidget);
0624     m_groupId->setObjectName(QStringLiteral("kcfg_GroupId"));
0625     m_groupId->setAlignment(Qt::AlignRight);
0626     m_groupId->setReadOnly(true);
0627 
0628     QToolButton *groupChooser = new QToolButton(groupIdInputWidget);
0629     groupChooser->setIcon(KDE::icon(QStringLiteral("edit-find-user")));
0630     groupChooser->setToolTip(i18n("Choose a different group"));
0631     groupChooser->setPopupMode(QToolButton::InstantPopup);
0632 
0633     QMenu *groupMenu = new QMenu(groupChooser);
0634     groupChooser->setMenu(groupMenu);
0635 
0636     QList<KUserGroup> groupList = KUserGroup::allGroups();
0637 
0638     for (const KUserGroup &g : groupList) {
0639         QAction *groupAction = groupMenu->addAction(g.name() + QStringLiteral(" (") + g.groupId().toString() + QStringLiteral(")"));
0640         groupAction->setData(g.groupId().nativeId());
0641     }
0642 
0643     groupLayout->addWidget(m_groupId, 0, 0);
0644     groupLayout->addWidget(groupChooser, 0, 1, Qt::AlignCenter);
0645 
0646     commonOptionsBoxLayout->addWidget(useGroupId, 1, 0);
0647     commonOptionsBoxLayout->addWidget(groupIdInputWidget, 1, 1);
0648 
0649     // File mask
0650     m_useFileMode = new QCheckBox(Smb4KMountSettings::self()->useFileModeItem()->label(), commonOptionsBox);
0651     m_useFileMode->setObjectName(QStringLiteral("kcfg_UseFileMode"));
0652 
0653     m_fileMode = new KLineEdit(commonOptionsBox);
0654     m_fileMode->setObjectName(QStringLiteral("kcfg_FileMode"));
0655     m_fileMode->setClearButtonEnabled(true);
0656     m_fileMode->setAlignment(Qt::AlignRight);
0657 
0658     commonOptionsBoxLayout->addWidget(m_useFileMode, 2, 0);
0659     commonOptionsBoxLayout->addWidget(m_fileMode, 2, 1);
0660 
0661     // Directory mask
0662     m_useDirectoryMode = new QCheckBox(Smb4KMountSettings::self()->useDirectoryModeItem()->label(), commonOptionsBox);
0663     m_useDirectoryMode->setObjectName(QStringLiteral("kcfg_UseDirectoryMode"));
0664 
0665     m_directoryMode = new KLineEdit(commonOptionsBox);
0666     m_directoryMode->setObjectName(QStringLiteral("kcfg_DirectoryMode"));
0667     m_directoryMode->setClearButtonEnabled(true);
0668     m_directoryMode->setAlignment(Qt::AlignRight);
0669 
0670     commonOptionsBoxLayout->addWidget(m_useDirectoryMode, 3, 0);
0671     commonOptionsBoxLayout->addWidget(m_directoryMode, 3, 1);
0672 
0673     //
0674     // Character sets
0675     //
0676     QGroupBox *characterSetsBox = new QGroupBox(i18n("Character Sets"), mountTab);
0677     QVBoxLayout *characterSetsBoxLayout = new QVBoxLayout(characterSetsBox);
0678 
0679     // Client character set
0680     QCheckBox *useCharacterSets = new QCheckBox(Smb4KMountSettings::self()->useCharacterSetsItem()->label(), characterSetsBox);
0681     useCharacterSets->setObjectName(QStringLiteral("kcfg_UseCharacterSets"));
0682 
0683     m_characterSetSettingsWidget = new QWidget(characterSetsBox);
0684     m_characterSetSettingsWidget->setEnabled(false);
0685     QGridLayout *characterSetSettingsWidgetLayout = new QGridLayout(m_characterSetSettingsWidget);
0686     characterSetSettingsWidgetLayout->setContentsMargins(0, 0, 0, 0);
0687 
0688     QLabel *clientCharacterSetLabel = new QLabel(Smb4KMountSettings::self()->clientCharsetItem()->label(), m_characterSetSettingsWidget);
0689     clientCharacterSetLabel->setIndent(25);
0690 
0691     KComboBox *clientCharacterSet = new KComboBox(m_characterSetSettingsWidget);
0692     clientCharacterSet->setObjectName(QStringLiteral("kcfg_ClientCharset"));
0693 
0694     QList<KCoreConfigSkeleton::ItemEnum::Choice> charsetChoices = Smb4KMountSettings::self()->clientCharsetItem()->choices();
0695 
0696     for (const KCoreConfigSkeleton::ItemEnum::Choice &c : charsetChoices) {
0697         clientCharacterSet->addItem(c.label);
0698     }
0699 
0700     clientCharacterSetLabel->setBuddy(clientCharacterSet);
0701 
0702     // Server character set
0703     QLabel *serverCharacterSetLabel = new QLabel(Smb4KMountSettings::self()->serverCodepageItem()->label(), m_characterSetSettingsWidget);
0704     serverCharacterSetLabel->setIndent(25);
0705     serverCharacterSetLabel->setObjectName(QStringLiteral("ServerCodepageLabel"));
0706 
0707     KComboBox *serverCharacterSet = new KComboBox(m_characterSetSettingsWidget);
0708     serverCharacterSet->setObjectName(QStringLiteral("kcfg_ServerCodepage"));
0709 
0710     QList<KCoreConfigSkeleton::ItemEnum::Choice> codepageChoices = Smb4KMountSettings::self()->serverCodepageItem()->choices();
0711 
0712     for (const KCoreConfigSkeleton::ItemEnum::Choice &c : codepageChoices) {
0713         serverCharacterSet->addItem(c.label);
0714     }
0715 
0716     serverCharacterSetLabel->setBuddy(serverCharacterSet);
0717 
0718     characterSetSettingsWidgetLayout->addWidget(clientCharacterSetLabel, 0, 0);
0719     characterSetSettingsWidgetLayout->addWidget(clientCharacterSet, 0, 1);
0720     characterSetSettingsWidgetLayout->addWidget(serverCharacterSetLabel, 1, 0);
0721     characterSetSettingsWidgetLayout->addWidget(serverCharacterSet, 1, 1);
0722 
0723     characterSetsBoxLayout->addWidget(useCharacterSets);
0724     characterSetsBoxLayout->addWidget(m_characterSetSettingsWidget);
0725 
0726     mountTabLayout->addWidget(commonOptionsBox, 0);
0727     mountTabLayout->addWidget(characterSetsBox, 0);
0728     mountTabLayout->addStretch(100);
0729 
0730     addTab(mountTab, i18n("Mount Settings"));
0731 
0732     connect(userMenu, &QMenu::triggered, this, &Smb4KConfigPageMounting::slotNewUserTriggered);
0733     connect(groupMenu, &QMenu::triggered, this, &Smb4KConfigPageMounting::slotNewGroupTriggered);
0734     connect(useCharacterSets, &QCheckBox::toggled, this, &Smb4KConfigPageMounting::slotCharacterSets);
0735     connect(remountShares, &QCheckBox::toggled, this, &Smb4KConfigPageMounting::slotRemountSharesToggled);
0736 }
0737 #else
0738 //
0739 // Dummy
0740 //
0741 void Smb4KConfigPageMounting::setupWidget()
0742 {
0743 }
0744 #endif
0745 
0746 void Smb4KConfigPageMounting::slotNewUserTriggered(QAction *action)
0747 {
0748     m_userId->setText(action->data().toString());
0749 }
0750 
0751 void Smb4KConfigPageMounting::slotNewGroupTriggered(QAction *action)
0752 {
0753     m_groupId->setText(action->data().toString());
0754 }
0755 
0756 #if defined(Q_OS_LINUX)
0757 void Smb4KConfigPageMounting::slotCIFSUnixExtensionsSupport(bool checked)
0758 {
0759     m_singleCifsExtensionsSettingsWidget->setEnabled(!checked);
0760 }
0761 
0762 void Smb4KConfigPageMounting::slotAdditionalCIFSOptions()
0763 {
0764     QString options = m_additionalCifsOptions->originalText();
0765 
0766     bool ok = false;
0767     options = QInputDialog::getText(this,
0768                                     i18n("Additional CIFS Options"),
0769                                     i18n("<qt>Enter the desired options as a comma separated list:</qt>"),
0770                                     QLineEdit::Normal,
0771                                     options,
0772                                     &ok);
0773 
0774     if (ok) {
0775         if (!options.trimmed().isEmpty()) {
0776             // SECURITY: Only pass those arguments to mount.cifs that do not pose
0777             // a potential security risk and that have not already been defined.
0778             //
0779             // This is, among others, the proper fix to the security issue reported
0780             // by Heiner Markert (aka CVE-2014-2581).
0781             QStringList allowedArgs = allowedMountArguments();
0782             QStringList deniedArgs;
0783             QStringList list = options.split(QStringLiteral(","), Qt::SkipEmptyParts);
0784             QMutableStringListIterator it(list);
0785 
0786             while (it.hasNext()) {
0787                 QString arg = it.next().section(QStringLiteral("="), 0, 0);
0788 
0789                 if (!allowedArgs.contains(arg)) {
0790                     deniedArgs << arg;
0791                     it.remove();
0792                 }
0793             }
0794 
0795             if (!deniedArgs.isEmpty()) {
0796                 QString msg =
0797                     i18np("The following entry is going to be removed from the additional options:<br>%2.<br>Please read the handbook for details.",
0798                           "The following %1 entries are going to be removed from the additional options:<br>%2.<br>Please read the handbook for details.",
0799                           deniedArgs.size(),
0800                           deniedArgs.join(QStringLiteral(", ")));
0801                 KMessageBox::information(this, msg);
0802             }
0803 
0804             m_additionalCifsOptions->setText(list.join(QStringLiteral(",")).trimmed());
0805         } else {
0806             m_additionalCifsOptions->clear();
0807         }
0808     }
0809 }
0810 #endif
0811 
0812 #if defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD)
0813 void Smb4KConfigPageMounting::slotCharacterSets(bool on)
0814 {
0815     m_characterSetSettingsWidget->setEnabled(on);
0816 }
0817 #endif
0818 
0819 void Smb4KConfigPageMounting::slotRemountSharesToggled(bool on)
0820 {
0821     m_remountSettingsWidget->setEnabled(on);
0822 }