File indexing completed on 2024-04-14 15:05:25
0001 /*************************************************************************** 0002 Private classes for the SMB client 0003 ------------------- 0004 begin : So Oct 21 2018 0005 copyright : (C) 2018-2019 by Alexander Reinholdt 0006 email : alexander.reinholdt@kdemail.net 0007 ***************************************************************************/ 0008 0009 /*************************************************************************** 0010 * This program is free software; you can redistribute it and/or modify * 0011 * it under the terms of the GNU General Public License as published by * 0012 * the Free Software Foundation; either version 2 of the License, or * 0013 * (at your option) any later version. * 0014 * * 0015 * This program is distributed in the hope that it will be useful, but * 0016 * WITHOUT ANY WARRANTY; without even the implied warranty of * 0017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 0018 * General Public License for more details. * 0019 * * 0020 * You should have received a copy of the GNU General Public License * 0021 * along with this program; if not, write to the * 0022 * Free Software Foundation, Inc., 51 Franklin Street, Suite 500, Boston,* 0023 * MA 02110-1335, USA * 0024 ***************************************************************************/ 0025 0026 #ifdef HAVE_CONFIG_H 0027 #include <config.h> 0028 #endif 0029 0030 // application specific includes 0031 #include "smb4kclient_p.h" 0032 #include "smb4ksettings.h" 0033 #include "smb4kwalletmanager.h" 0034 #include "smb4kcustomoptions.h" 0035 #include "smb4kcustomoptionsmanager.h" 0036 #include "smb4knotification.h" 0037 0038 // System includes 0039 #include <errno.h> 0040 // #include <sys/types.h> 0041 #include <sys/stat.h> 0042 // #include <unistd.h> 0043 0044 // Qt includes 0045 #include <QTimer> 0046 #include <QDebug> 0047 #include <QHostInfo> 0048 #include <QNetworkInterface> 0049 #include <QAbstractSocket> 0050 #include <QVBoxLayout> 0051 #include <QDialogButtonBox> 0052 #include <QListWidget> 0053 #include <QWindow> 0054 #include <QPushButton> 0055 #include <QLabel> 0056 #include <QToolBar> 0057 #include <QGroupBox> 0058 #include <QDir> 0059 #include <QSpinBox> 0060 #include <QPrinter> 0061 #include <QTemporaryDir> 0062 #include <QTextDocument> 0063 0064 // KDE includes 0065 #include <KI18n/KLocalizedString> 0066 #include <KConfigGui/KWindowConfig> 0067 #include <KIconThemes/KIconLoader> 0068 #include <KIOWidgets/KUrlComboBox> 0069 #include <KIO/Global> 0070 #include <KWidgetsAddons/KDualAction> 0071 #include <KIOWidgets/KUrlRequester> 0072 #include <KIOCore/KFileItem> 0073 0074 #define SMBC_DEBUG 0 0075 0076 using namespace Smb4KGlobal; 0077 0078 0079 // 0080 // Authentication function for libsmbclient 0081 // 0082 static void get_auth_data_with_context_fn(SMBCCTX *context, 0083 const char *server, 0084 const char *share, 0085 char *workgroup, 0086 int maxLenWorkgroup, 0087 char *username, 0088 int maxLenUsername, 0089 char *password, 0090 int maxLenPassword) 0091 { 0092 if (context != nullptr) 0093 { 0094 Smb4KClientJob *job = static_cast<Smb4KClientJob *>(smbc_getOptionUserData(context)); 0095 0096 if (job) 0097 { 0098 job->get_auth_data_fn(server, share, workgroup, maxLenWorkgroup, username, maxLenUsername, password, maxLenPassword); 0099 } 0100 } 0101 } 0102 0103 0104 // 0105 // Client job 0106 // 0107 Smb4KClientJob::Smb4KClientJob(QObject* parent) 0108 : KJob(parent), m_process(Smb4KGlobal::NoProcess) 0109 { 0110 } 0111 0112 0113 Smb4KClientJob::~Smb4KClientJob() 0114 { 0115 // 0116 // Clear the list of workgroups 0117 // 0118 while (!m_workgroups.isEmpty()) 0119 { 0120 m_workgroups.takeFirst().clear(); 0121 } 0122 0123 // 0124 // Clear the list of hosts 0125 // 0126 while (!m_hosts.isEmpty()) 0127 { 0128 m_hosts.takeFirst().clear(); 0129 } 0130 0131 // 0132 // Clear the list of shares 0133 // 0134 while (!m_shares.isEmpty()) 0135 { 0136 m_shares.takeFirst().clear(); 0137 } 0138 0139 // 0140 // Clear the list of files and directories 0141 // 0142 while (!m_files.isEmpty()) 0143 { 0144 m_files.takeFirst().clear(); 0145 } 0146 } 0147 0148 0149 void Smb4KClientJob::start() 0150 { 0151 QTimer::singleShot(50, this, SLOT(slotStartJob())); 0152 } 0153 0154 0155 void Smb4KClientJob::setNetworkItem(NetworkItemPtr item) 0156 { 0157 m_item = item; 0158 } 0159 0160 0161 NetworkItemPtr Smb4KClientJob::networkItem() const 0162 { 0163 return m_item; 0164 } 0165 0166 0167 void Smb4KClientJob::setProcess(Smb4KGlobal::Process process) 0168 { 0169 m_process = process; 0170 } 0171 0172 0173 Smb4KGlobal::Process Smb4KClientJob::process() const 0174 { 0175 return m_process; 0176 } 0177 0178 0179 void Smb4KClientJob::setPrintFileItem(const KFileItem& item) 0180 { 0181 m_fileItem = item; 0182 } 0183 0184 0185 KFileItem Smb4KClientJob::printFileItem() const 0186 { 0187 return m_fileItem; 0188 } 0189 0190 0191 void Smb4KClientJob::setPrintCopies(int copies) 0192 { 0193 m_copies = copies; 0194 } 0195 0196 0197 int Smb4KClientJob::printCopies() const 0198 { 0199 return m_copies; 0200 } 0201 0202 0203 void Smb4KClientJob::get_auth_data_fn(const char* server, const char* /*share*/, char* workgroup, int /*maxLenWorkgroup*/, char* username, int maxLenUsername, char* password, int maxLenPassword) 0204 { 0205 // 0206 // Authentication 0207 // 0208 switch (m_item->type()) 0209 { 0210 case Network: 0211 { 0212 // 0213 // No authentication needed 0214 // 0215 break; 0216 } 0217 case Workgroup: 0218 { 0219 // 0220 // Only request authentication data, if the master browsers require 0221 // authentication data. 0222 // 0223 if (Smb4KSettings::masterBrowsersRequireAuth()) 0224 { 0225 if (QString::fromUtf8(server).toUpper() != QString::fromUtf8(workgroup).toUpper()) 0226 { 0227 // 0228 // This is the master browser. Create a host object for it. 0229 // 0230 HostPtr h = HostPtr(new Smb4KHost()); 0231 h->setWorkgroupName(QString::fromUtf8(workgroup)); 0232 h->setHostName(QString::fromUtf8(server)); 0233 0234 // 0235 // Get the authentication data 0236 // 0237 Smb4KWalletManager::self()->readAuthInfo(h); 0238 0239 // 0240 // Copy the authentication data 0241 // 0242 qstrncpy(username, h->login().toUtf8().data(), maxLenUsername); 0243 qstrncpy(password, h->password().toUtf8().data(), maxLenPassword); 0244 } 0245 } 0246 0247 break; 0248 } 0249 case Host: 0250 { 0251 // 0252 // The host object 0253 // 0254 HostPtr h = m_item.staticCast<Smb4KHost>(); 0255 0256 // 0257 // Get the authentication data 0258 // 0259 Smb4KWalletManager::self()->readAuthInfo(h); 0260 0261 // 0262 // Copy the authentication data 0263 // 0264 qstrncpy(username, h->login().toUtf8().data(), maxLenUsername); 0265 qstrncpy(password, h->password().toUtf8().data(), maxLenPassword); 0266 0267 break; 0268 } 0269 case Share: 0270 { 0271 // 0272 // The share object 0273 // 0274 SharePtr s = m_item.staticCast<Smb4KShare>(); 0275 0276 // 0277 // Get the authentication data 0278 // 0279 Smb4KWalletManager::self()->readAuthInfo(s); 0280 0281 // 0282 // Copy the authentication data 0283 // 0284 qstrncpy(username, s->login().toUtf8().data(), maxLenUsername); 0285 qstrncpy(password, s->password().toUtf8().data(), maxLenPassword); 0286 0287 break; 0288 } 0289 case Directory: 0290 { 0291 // 0292 // The file object 0293 // 0294 FilePtr f = m_item.staticCast<Smb4KFile>(); 0295 0296 // 0297 // Create a share object 0298 // 0299 SharePtr s = SharePtr(new Smb4KShare()); 0300 s->setWorkgroupName(f->workgroupName()); 0301 s->setHostName(f->hostName()); 0302 s->setShareName(f->shareName()); 0303 s->setLogin(f->login()); 0304 s->setPassword(f->password()); 0305 0306 // 0307 // Get the authentication data 0308 // 0309 Smb4KWalletManager::self()->readAuthInfo(s); 0310 0311 // 0312 // Copy the authentication data 0313 // 0314 qstrncpy(username, s->login().toUtf8().data(), maxLenUsername); 0315 qstrncpy(password, s->password().toUtf8().data(), maxLenPassword); 0316 0317 break; 0318 } 0319 default: 0320 { 0321 break; 0322 } 0323 } 0324 } 0325 0326 0327 QList<WorkgroupPtr> Smb4KClientJob::workgroups() 0328 { 0329 return m_workgroups; 0330 } 0331 0332 0333 QList<HostPtr> Smb4KClientJob::hosts() 0334 { 0335 return m_hosts; 0336 } 0337 0338 0339 QList<SharePtr> Smb4KClientJob::shares() 0340 { 0341 return m_shares; 0342 } 0343 0344 0345 QList<FilePtr> Smb4KClientJob::files() 0346 { 0347 return m_files; 0348 } 0349 0350 0351 QString Smb4KClientJob::workgroup() 0352 { 0353 QString workgroup; 0354 0355 switch (m_item->type()) 0356 { 0357 case Network: 0358 { 0359 break; 0360 } 0361 case Workgroup: 0362 { 0363 workgroup = m_item->url().host().toUpper(); 0364 break; 0365 } 0366 case Host: 0367 { 0368 workgroup = m_item.staticCast<Smb4KHost>()->workgroupName(); 0369 break; 0370 } 0371 case Share: 0372 { 0373 workgroup = m_item.staticCast<Smb4KShare>()->workgroupName(); 0374 break; 0375 } 0376 case Directory: 0377 case File: 0378 { 0379 workgroup = m_item.staticCast<Smb4KFile>()->workgroupName(); 0380 break; 0381 } 0382 default: 0383 { 0384 break; 0385 } 0386 } 0387 0388 return workgroup; 0389 } 0390 0391 0392 void Smb4KClientJob::doLookups() 0393 { 0394 // 0395 // Read the given URL 0396 // 0397 int dirfd; 0398 struct smbc_dirent *dirp = nullptr; 0399 0400 dirfd = smbc_opendir(m_item->url().toString().toUtf8().data()); 0401 0402 if (dirfd < 0) 0403 { 0404 int errorCode = errno; 0405 0406 switch (errorCode) 0407 { 0408 case ENOMEM: 0409 { 0410 setError(OutOfMemoryError); 0411 setErrorText(i18n("Out of memory")); 0412 break; 0413 } 0414 case EACCES: 0415 { 0416 setError(AccessDeniedError); 0417 setErrorText(i18n("Permission denied")); 0418 break; 0419 } 0420 case EINVAL: 0421 { 0422 setError(InvalidUrlError); 0423 setErrorText(i18n("An invalid URL was passed")); 0424 break; 0425 } 0426 case ENOENT: 0427 { 0428 if (!m_item->type() != Network) 0429 { 0430 setError(NonExistentUrlError); 0431 setErrorText(i18n("The URL does not exist")); 0432 } 0433 break; 0434 } 0435 case ENOTDIR: 0436 { 0437 setError(NoDirectoryError); 0438 setErrorText(i18n("Name is not a directory")); 0439 break; 0440 } 0441 case EPERM: 0442 { 0443 setError(NotPermittedError); 0444 // Is the error message correct? 0445 setErrorText(i18n("Operation not permitted")); 0446 break; 0447 } 0448 case ENODEV: 0449 { 0450 setError(NotFoundError); 0451 setErrorText(i18n("The workgroup or server could not be found")); 0452 break; 0453 } 0454 default: 0455 { 0456 setError(UnknownError); 0457 setErrorText(i18n("Unknown error")); 0458 } 0459 } 0460 0461 emitResult(); 0462 return; 0463 } 0464 else 0465 { 0466 // 0467 // Get the entries of the "directory" 0468 // 0469 while ((dirp = smbc_readdir(dirfd)) != nullptr) 0470 { 0471 switch (dirp->smbc_type) 0472 { 0473 case SMBC_WORKGROUP: 0474 { 0475 // 0476 // Create a workgroup pointer 0477 // 0478 WorkgroupPtr workgroup = WorkgroupPtr(new Smb4KWorkgroup()); 0479 0480 // 0481 // Set the workgroup name 0482 // 0483 QString workgroupName = QString::fromUtf8(dirp->name); 0484 workgroup->setWorkgroupName(workgroupName); 0485 0486 // 0487 // Set the master browser 0488 // 0489 QString masterBrowserName = QString::fromUtf8(dirp->comment); 0490 workgroup->setMasterBrowserName(masterBrowserName); 0491 0492 // 0493 // Lookup IP address 0494 // 0495 QHostAddress address = lookupIpAddress(masterBrowserName); 0496 0497 // 0498 // Process the IP address. 0499 // If the address is null, the server most likely went offline. So, skip the 0500 // workgroup and delete the pointer. 0501 // 0502 if (!address.isNull()) 0503 { 0504 workgroup->setMasterBrowserIpAddress(address); 0505 m_workgroups << workgroup; 0506 } 0507 else 0508 { 0509 workgroup.clear(); 0510 } 0511 0512 break; 0513 } 0514 case SMBC_SERVER: 0515 { 0516 // 0517 // Create a host pointer 0518 // 0519 HostPtr host = HostPtr(new Smb4KHost()); 0520 0521 // 0522 // Set the workgroup name 0523 // 0524 host->setWorkgroupName(m_item->url().host()); 0525 0526 // 0527 // Set the host name 0528 // 0529 QString hostName = QString::fromUtf8(dirp->name); 0530 host->setHostName(hostName); 0531 0532 // 0533 // Set the comment 0534 // 0535 QString comment = QString::fromUtf8(dirp->comment); 0536 host->setComment(comment); 0537 0538 // 0539 // Lookup IP address 0540 // 0541 QHostAddress address = lookupIpAddress(hostName); 0542 0543 // 0544 // Process the IP address. 0545 // If the address is null, the server most likely went offline. So, skip it 0546 // and delete the pointer. 0547 // 0548 if (!address.isNull()) 0549 { 0550 host->setIpAddress(address); 0551 m_hosts << host; 0552 } 0553 else 0554 { 0555 host.clear(); 0556 } 0557 0558 break; 0559 } 0560 case SMBC_FILE_SHARE: 0561 { 0562 // 0563 // Create a share pointer 0564 // 0565 SharePtr share = SharePtr(new Smb4KShare()); 0566 0567 // 0568 // Set the workgroup name 0569 // 0570 share->setWorkgroupName(m_item.staticCast<Smb4KHost>()->workgroupName()); 0571 0572 // 0573 // Set the host name 0574 // 0575 share->setHostName(m_item->url().host()); 0576 0577 // 0578 // Set the share name 0579 // 0580 share->setShareName(QString::fromUtf8(dirp->name)); 0581 0582 // 0583 // Set the comment 0584 // 0585 share->setComment(QString::fromUtf8(dirp->comment)); 0586 0587 // 0588 // Set share type 0589 // 0590 share->setShareType(FileShare); 0591 0592 // 0593 // Set the authentication data 0594 // 0595 share->setLogin(m_item->url().userName()); 0596 share->setPassword(m_item->url().password()); 0597 0598 // 0599 // Lookup IP address 0600 // 0601 QHostAddress address = lookupIpAddress(m_item->url().host()); 0602 0603 // 0604 // Process the IP address. 0605 // If the address is null, the server most likely went offline. So, skip it 0606 // and delete the pointer. 0607 // 0608 if (!address.isNull()) 0609 { 0610 share->setHostIpAddress(address); 0611 m_shares << share; 0612 } 0613 else 0614 { 0615 share.clear(); 0616 } 0617 0618 break; 0619 } 0620 case SMBC_PRINTER_SHARE: 0621 { 0622 // 0623 // Create a share pointer 0624 // 0625 SharePtr share = SharePtr(new Smb4KShare()); 0626 0627 // 0628 // Set the workgroup name 0629 // 0630 share->setWorkgroupName(m_item.staticCast<Smb4KHost>()->workgroupName()); 0631 0632 // 0633 // Set the host name 0634 // 0635 share->setHostName(m_item->url().host()); 0636 0637 // 0638 // Set the share name 0639 // 0640 share->setShareName(QString::fromUtf8(dirp->name)); 0641 0642 // 0643 // Set the comment 0644 // 0645 share->setComment(QString::fromUtf8(dirp->comment)); 0646 0647 // 0648 // Set share type 0649 // 0650 share->setShareType(PrinterShare); 0651 0652 // 0653 // Set the authentication data 0654 // 0655 share->setLogin(m_item->url().userName()); 0656 share->setPassword(m_item->url().password()); 0657 0658 // 0659 // Lookup IP address 0660 // 0661 QHostAddress address = lookupIpAddress(m_item->url().host()); 0662 0663 // 0664 // Process the IP address. 0665 // If the address is null, the server most likely went offline. So, skip it 0666 // and delete the pointer. 0667 // 0668 if (!address.isNull()) 0669 { 0670 share->setHostIpAddress(address); 0671 m_shares << share; 0672 } 0673 else 0674 { 0675 share.clear(); 0676 } 0677 0678 break; 0679 } 0680 case SMBC_IPC_SHARE: 0681 { 0682 // 0683 // Create a share pointer 0684 // 0685 SharePtr share = SharePtr(new Smb4KShare()); 0686 0687 // 0688 // Set the workgroup name 0689 // 0690 share->setWorkgroupName(m_item.staticCast<Smb4KHost>()->workgroupName()); 0691 0692 // 0693 // Set the host name 0694 // 0695 share->setHostName(m_item->url().host()); 0696 0697 // 0698 // Set the share name 0699 // 0700 share->setShareName(QString::fromUtf8(dirp->name)); 0701 0702 // 0703 // Set the comment 0704 // 0705 share->setComment(QString::fromUtf8(dirp->comment)); 0706 0707 // 0708 // Set share type 0709 // 0710 share->setShareType(IpcShare); 0711 0712 // 0713 // Set the authentication data 0714 // 0715 share->setLogin(m_item->url().userName()); 0716 share->setPassword(m_item->url().password()); 0717 0718 // 0719 // Lookup IP address 0720 // 0721 QHostAddress address = lookupIpAddress(m_item->url().host()); 0722 0723 // 0724 // Process the IP address. 0725 // If the address is null, the server most likely went offline. So, skip it 0726 // and delete the pointer. 0727 // 0728 if (!address.isNull()) 0729 { 0730 share->setHostIpAddress(address); 0731 m_shares << share; 0732 } 0733 else 0734 { 0735 share.clear(); 0736 } 0737 0738 break; 0739 } 0740 case SMBC_DIR: 0741 { 0742 // 0743 // Do not process '.' and '..' directories 0744 // 0745 QString name = QString::fromUtf8(dirp->name); 0746 0747 if (name != "." && name != "..") 0748 { 0749 // 0750 // Create the URL for the discovered item 0751 // 0752 QUrl u = m_item->url(); 0753 u.setPath(m_item->url().path()+QDir::separator()+QString::fromUtf8(dirp->name)); 0754 0755 // 0756 // We do not stat directories. Directly create the directory object 0757 // 0758 FilePtr dir = FilePtr(new Smb4KFile(u, Directory)); 0759 0760 // 0761 // Set the workgroup name 0762 // 0763 dir->setWorkgroupName(m_item.staticCast<Smb4KShare>()->workgroupName()); 0764 0765 // 0766 // Set the authentication data 0767 // 0768 dir->setLogin(m_item->url().userName()); 0769 dir->setPassword(m_item->url().password()); 0770 0771 // 0772 // Lookup IP address 0773 // 0774 QHostAddress address = lookupIpAddress(m_item->url().host()); 0775 0776 // 0777 // Process the IP address. 0778 // If the address is null, the server most likely went offline. So, skip it 0779 // and delete the pointer. 0780 // 0781 if (!address.isNull()) 0782 { 0783 dir->setHostIpAddress(address); 0784 m_files << dir; 0785 } 0786 else 0787 { 0788 dir.clear(); 0789 } 0790 } 0791 0792 break; 0793 } 0794 case SMBC_FILE: 0795 { 0796 // 0797 // Create the URL for the discovered item 0798 // 0799 QUrl u = m_item->url(); 0800 u.setPath(m_item->url().path()+QDir::separator()+QString::fromUtf8(dirp->name)); 0801 0802 // 0803 // Create the directory object 0804 // 0805 FilePtr dir = FilePtr(new Smb4KFile(u, File)); 0806 0807 // 0808 // Set the workgroup name 0809 // 0810 dir->setWorkgroupName(m_item.staticCast<Smb4KShare>()->workgroupName()); 0811 0812 // 0813 // Stat the file 0814 // 0815 // FIXME 0816 0817 // 0818 // Set the authentication data 0819 // 0820 dir->setLogin(m_item->url().userName()); 0821 dir->setPassword(m_item->url().password()); 0822 0823 // 0824 // Lookup IP address 0825 // 0826 QHostAddress address = lookupIpAddress(m_item->url().host()); 0827 0828 // 0829 // Process the IP address. 0830 // If the address is null, the server most likely went offline. So, skip it 0831 // and delete the pointer. 0832 // 0833 if (!address.isNull()) 0834 { 0835 dir->setHostIpAddress(address); 0836 m_files << dir; 0837 } 0838 else 0839 { 0840 dir.clear(); 0841 } 0842 0843 break; 0844 } 0845 case SMBC_LINK: 0846 { 0847 qDebug() << "Processing links is not implemented."; 0848 qDebug() << dirp->name; 0849 qDebug() << dirp->comment; 0850 break; 0851 } 0852 default: 0853 { 0854 qDebug() << "Need to process network item " << dirp->name; 0855 break; 0856 } 0857 } 0858 } 0859 0860 smbc_closedir(dirfd); 0861 } 0862 } 0863 0864 0865 void Smb4KClientJob::doPrinting() 0866 { 0867 // 0868 // The URL that is to be printed 0869 // 0870 QUrl fileUrl; 0871 0872 // 0873 // Set the temporary directory 0874 // 0875 QTemporaryDir tempDir; 0876 0877 // 0878 // Check if we can directly print the file 0879 // 0880 if (m_fileItem.mimetype() == "application/postscript" || 0881 m_fileItem.mimetype() == "application/pdf" || 0882 m_fileItem.mimetype().startsWith(QLatin1String("image"))) 0883 { 0884 // 0885 // Set the URL to the incoming file 0886 // 0887 fileUrl = m_fileItem.url(); 0888 } 0889 else if (m_fileItem.mimetype() == "application/x-shellscript" || 0890 m_fileItem.mimetype().startsWith(QLatin1String("text")) || 0891 m_fileItem.mimetype().startsWith(QLatin1String("message"))) 0892 { 0893 // 0894 // Set a printer object 0895 // 0896 QPrinter printer(QPrinter::HighResolution); 0897 printer.setCreator("Smb4K"); 0898 printer.setOutputFormat(QPrinter::PdfFormat); 0899 printer.setOutputFileName(QString("%1/smb4k_print.pdf").arg(tempDir.path())); 0900 0901 // 0902 // Open the file that is to be printed and read it 0903 // 0904 QStringList contents; 0905 0906 QFile file(m_fileItem.url().path()); 0907 0908 if (file.open(QFile::ReadOnly|QFile::Text)) 0909 { 0910 QTextStream ts(&file); 0911 0912 while (!ts.atEnd()) 0913 { 0914 contents << ts.readLine(); 0915 } 0916 } 0917 else 0918 { 0919 return; 0920 } 0921 0922 // 0923 // Convert the file to PDF 0924 // 0925 QTextDocument doc; 0926 0927 if (m_fileItem.mimetype().endsWith(QLatin1String("html"))) 0928 { 0929 doc.setHtml(contents.join(" ")); 0930 } 0931 else 0932 { 0933 doc.setPlainText(contents.join("\n")); 0934 } 0935 0936 doc.print(&printer); 0937 0938 // 0939 // Set the URL to the converted file 0940 // 0941 fileUrl.setUrl(printer.outputFileName()); 0942 fileUrl.setScheme("file"); 0943 } 0944 else 0945 { 0946 Smb4KNotification::mimetypeNotSupported(m_fileItem.mimetype()); 0947 return; 0948 } 0949 0950 // 0951 // Get the open function for the printer 0952 // 0953 smbc_open_print_job_fn openPrinter = smbc_getFunctionOpenPrintJob(m_context); 0954 0955 if (!openPrinter) 0956 { 0957 setError(OpenPrintJobError); 0958 setErrorText(i18n("The print job could not be set up (step 1)")); 0959 0960 emitResult(); 0961 return; 0962 } 0963 0964 // 0965 // Open the printer for printing 0966 // 0967 SMBCFILE *printer = openPrinter(m_context, m_item->url().toString().toUtf8().data()); 0968 0969 if (!printer) 0970 { 0971 int errorCode = errno; 0972 0973 if (errorCode == EACCES) 0974 { 0975 setError(AccessDeniedError); 0976 setErrorText(i18n("Permission denied")); 0977 } 0978 else 0979 { 0980 setError(OpenPrintJobError); 0981 setErrorText(i18n("The print job could not be set up (step 2)")); 0982 } 0983 0984 emitResult(); 0985 return; 0986 } 0987 0988 // 0989 // Open the file 0990 // 0991 QFile file(fileUrl.path()); 0992 0993 if (!file.open(QFile::ReadOnly)) 0994 { 0995 setError(FileAccessError); 0996 setErrorText(i18n("The file %1 could not be read", fileUrl.path())); 0997 0998 emitResult(); 0999 return; 1000 } 1001 1002 // 1003 // Write X copies of the file to the printer 1004 // 1005 char buffer[4096]; 1006 qint64 bytes = 0; 1007 int copy = 0; 1008 1009 while (copy < m_copies) 1010 { 1011 while ((bytes = file.read(buffer, sizeof(buffer))) > 0) 1012 { 1013 smbc_write_fn writeFile = smbc_getFunctionWrite(m_context); 1014 1015 if (writeFile(m_context, printer, buffer, bytes) < 0) 1016 { 1017 setError(PrintFileError); 1018 setErrorText(i18n("The file %1 could not be printed to %2", fileUrl.path(), m_item.staticCast<Smb4KShare>()->displayString())); 1019 1020 smbc_close_fn closePrinter = smbc_getFunctionClose(m_context); 1021 closePrinter(m_context, printer); 1022 } 1023 } 1024 1025 copy++; 1026 } 1027 1028 // 1029 // Close the printer 1030 // 1031 smbc_close_fn closePrinter = smbc_getFunctionClose(m_context); 1032 closePrinter(m_context, printer); 1033 } 1034 1035 1036 QHostAddress Smb4KClientJob::lookupIpAddress(const QString& name) 1037 { 1038 // 1039 // The IP address object 1040 // 1041 QHostAddress ipAddress; 1042 1043 // If the IP address is not to be determined for the local machine, we can use QHostInfo to 1044 // determine it. Otherwise we need to use QNetworkInterface for it. 1045 if (name.toUpper() == QHostInfo::localHostName().toUpper() || 1046 name.toUpper() == globalSambaOptions()["netbios name"].toUpper() || 1047 name.toUpper() == Smb4KSettings::netBIOSName().toUpper()) 1048 { 1049 // FIXME: Do we need to honor 'interfaces' here? 1050 QList<QHostAddress> addresses = QNetworkInterface::allAddresses(); 1051 1052 // Get the IP address for the host. For the time being, prefer the 1053 // IPv4 address over the IPv6 address. 1054 for (const QHostAddress &addr : addresses) 1055 { 1056 // We only use global addresses. 1057 #if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0) 1058 if (addr.isGlobal()) 1059 #else 1060 if (!addr.isLoopback() && !addr.isMulticast()) 1061 #endif 1062 { 1063 if (addr.protocol() == QAbstractSocket::IPv4Protocol) 1064 { 1065 ipAddress = addr; 1066 break; 1067 } 1068 else if (addr.protocol() == QAbstractSocket::IPv6Protocol) 1069 { 1070 // FIXME: Use the right address here. 1071 ipAddress = addr; 1072 } 1073 } 1074 } 1075 } 1076 else 1077 { 1078 // Get the IP address 1079 QHostInfo hostInfo = QHostInfo::fromName(name); 1080 1081 if (hostInfo.error() == QHostInfo::NoError) 1082 { 1083 // Get the IP address for the host. For the time being, prefer the 1084 // IPv4 address over the IPv6 address. 1085 for (const QHostAddress &addr : hostInfo.addresses()) 1086 { 1087 // We only use global addresses. 1088 #if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0) 1089 if (addr.isGlobal()) 1090 #else 1091 if (!addr.isLoopback() && !addr.isMulticast()) 1092 #endif 1093 { 1094 if (addr.protocol() == QAbstractSocket::IPv4Protocol) 1095 { 1096 ipAddress = addr; 1097 break; 1098 } 1099 else if (addr.protocol() == QAbstractSocket::IPv6Protocol) 1100 { 1101 // FIXME: Use the right address here. 1102 ipAddress = addr; 1103 } 1104 } 1105 } 1106 } 1107 } 1108 1109 return ipAddress; 1110 } 1111 1112 1113 void Smb4KClientJob::slotStartJob() 1114 { 1115 // 1116 // Allocate new context 1117 // 1118 m_context = smbc_new_context(); 1119 1120 if (!m_context) 1121 { 1122 int errorCode = errno; 1123 1124 switch (errorCode) 1125 { 1126 case ENOMEM: 1127 { 1128 setError(OutOfMemoryError); 1129 setErrorText(i18n("Out of memory")); 1130 break; 1131 } 1132 default: 1133 { 1134 setError(UnknownError); 1135 setErrorText(i18n("Unknown error")); 1136 break; 1137 } 1138 } 1139 1140 emitResult(); 1141 return; 1142 } 1143 1144 // 1145 // Get the custom options 1146 // 1147 OptionsPtr options = Smb4KCustomOptionsManager::self()->findOptions(m_item); 1148 1149 // 1150 // Set debug level 1151 // 1152 smbc_setDebug(m_context, SMBC_DEBUG); 1153 1154 // 1155 // Set the NetBIOS name and the workgroup to make connections 1156 // 1157 switch (m_item->type()) 1158 { 1159 case Network: 1160 { 1161 // 1162 // We do not know about the servers and the domains/workgroups 1163 // present. So, do not set anything and use the default. 1164 // 1165 break; 1166 } 1167 case Workgroup: 1168 { 1169 // 1170 // Set the NetBIOS name of the master browser and the workgroup to be queried 1171 // 1172 WorkgroupPtr workgroup = m_item.staticCast<Smb4KWorkgroup>(); 1173 smbc_setNetbiosName(m_context, workgroup->masterBrowserName().toUtf8().data()); 1174 smbc_setWorkgroup(m_context, workgroup->workgroupName().toUtf8().data()); 1175 break; 1176 } 1177 case Host: 1178 { 1179 // 1180 // Set both the NetBIOS name of the server and the workgroup to be queried 1181 // 1182 HostPtr host = m_item.staticCast<Smb4KHost>(); 1183 smbc_setNetbiosName(m_context, host->hostName().toUtf8().data()); 1184 smbc_setWorkgroup(m_context, host->workgroupName().toUtf8().data()); 1185 break; 1186 } 1187 case Share: 1188 { 1189 // 1190 // Set both the NetBIOS name of the server and the workgroup to be queried 1191 // 1192 SharePtr share = m_item.staticCast<Smb4KShare>(); 1193 smbc_setNetbiosName(m_context, share->hostName().toUtf8().data()); 1194 smbc_setWorkgroup(m_context, share->workgroupName().toUtf8().data()); 1195 break; 1196 } 1197 case Directory: 1198 { 1199 // 1200 // Set both the NetBIOS name of the server and the workgroup to be queried 1201 // 1202 FilePtr file = m_item.staticCast<Smb4KFile>(); 1203 smbc_setNetbiosName(m_context, file->hostName().toUtf8().data()); 1204 smbc_setWorkgroup(m_context, file->workgroupName().toUtf8().data()); 1205 break; 1206 } 1207 default: 1208 { 1209 break; 1210 } 1211 } 1212 1213 // 1214 // Set the user for making the connection 1215 // 1216 if (!m_item->url().userName().isEmpty()) 1217 { 1218 smbc_setUser(m_context, m_item->url().userName().toUtf8().data()); 1219 } 1220 1221 // 1222 // Set the port 1223 // 1224 if (options) 1225 { 1226 if (options->useSmbPort()) 1227 { 1228 smbc_setPort(m_context, options->smbPort()); 1229 } 1230 else 1231 { 1232 smbc_setPort(m_context, 0 /* use the default */); 1233 } 1234 } 1235 else 1236 { 1237 if (Smb4KSettings::useRemoteSmbPort()) 1238 { 1239 smbc_setPort(m_context, Smb4KSettings::remoteSmbPort()); 1240 } 1241 else 1242 { 1243 smbc_setPort(m_context, 0 /* use the default */); 1244 } 1245 } 1246 1247 // 1248 // Set the user data (this class) 1249 // 1250 smbc_setOptionUserData(m_context, this); 1251 1252 // 1253 // Set number of master browsers to be used 1254 // 1255 if (Smb4KSettings::largeNetworkNeighborhood()) 1256 { 1257 smbc_setOptionBrowseMaxLmbCount(m_context, 3); 1258 } 1259 else 1260 { 1261 smbc_setOptionBrowseMaxLmbCount(m_context, 0 /* all master browsers */); 1262 } 1263 1264 // 1265 // Set the encryption level 1266 // 1267 if (Smb4KSettings::useEncryptionLevel()) 1268 { 1269 switch (Smb4KSettings::encryptionLevel()) 1270 { 1271 case Smb4KSettings::EnumEncryptionLevel::None: 1272 { 1273 smbc_setOptionSmbEncryptionLevel(m_context, SMBC_ENCRYPTLEVEL_NONE); 1274 break; 1275 } 1276 case Smb4KSettings::EnumEncryptionLevel::Request: 1277 { 1278 smbc_setOptionSmbEncryptionLevel(m_context, SMBC_ENCRYPTLEVEL_REQUEST); 1279 break; 1280 } 1281 case Smb4KSettings::EnumEncryptionLevel::Require: 1282 { 1283 smbc_setOptionSmbEncryptionLevel(m_context, SMBC_ENCRYPTLEVEL_REQUIRE); 1284 break; 1285 } 1286 default: 1287 { 1288 break; 1289 } 1290 } 1291 } 1292 1293 // 1294 // Set the usage of anonymous login 1295 // 1296 smbc_setOptionNoAutoAnonymousLogin(m_context, false); 1297 1298 // 1299 // Set the usage of the winbind ccache 1300 // 1301 smbc_setOptionUseCCache(m_context, Smb4KSettings::useWinbindCCache()); 1302 1303 // 1304 // Set usage of Kerberos 1305 // 1306 if (options) 1307 { 1308 smbc_setOptionUseKerberos(m_context, options->useKerberos()); 1309 } 1310 else 1311 { 1312 smbc_setOptionUseKerberos(m_context, Smb4KSettings::useKerberos()); 1313 } 1314 1315 smbc_setOptionFallbackAfterKerberos(m_context, 1); 1316 1317 // 1318 // Set the channel for debug output 1319 // 1320 smbc_setOptionDebugToStderr(m_context, 1); 1321 1322 // 1323 // Set auth callback function 1324 // 1325 smbc_setFunctionAuthDataWithContext(m_context, get_auth_data_with_context_fn); 1326 1327 // 1328 // Initialize context with the previously defined options 1329 // 1330 if (!smbc_init_context(m_context)) 1331 { 1332 int errorCode = errno; 1333 1334 switch (errorCode) 1335 { 1336 case ENOMEM: 1337 { 1338 setError(OutOfMemoryError); 1339 setErrorText(i18n("Out of memory")); 1340 break; 1341 } 1342 case EBADF: 1343 { 1344 setError(NullContextError); 1345 setErrorText(i18n("NULL context given")); 1346 break; 1347 } 1348 case ENOENT: 1349 { 1350 setError(SmbConfError); 1351 setErrorText(i18n("The smb.conf file would not load")); 1352 break; 1353 } 1354 default: 1355 { 1356 setError(UnknownError); 1357 setErrorText(i18n("Unknown error")); 1358 } 1359 } 1360 1361 smbc_free_context(m_context, 0); 1362 1363 emitResult(); 1364 return; 1365 } 1366 1367 // 1368 // Set the new context 1369 // 1370 (void)smbc_set_context(m_context); 1371 1372 // 1373 // Process the given URL according to the passed process 1374 // 1375 switch (m_process) 1376 { 1377 case LookupDomains: 1378 case LookupDomainMembers: 1379 case LookupShares: 1380 case LookupFiles: 1381 { 1382 doLookups(); 1383 break; 1384 } 1385 case PrintFile: 1386 { 1387 doPrinting(); 1388 break; 1389 } 1390 default: 1391 { 1392 break; 1393 } 1394 } 1395 1396 // 1397 // Free the context 1398 // 1399 smbc_free_context(m_context, 0); 1400 1401 // 1402 // Emit the result 1403 // 1404 emitResult(); 1405 } 1406 1407 1408 1409 Smb4KPreviewDialog::Smb4KPreviewDialog(const SharePtr& share, QWidget* parent) 1410 : QDialog(parent), m_share(share) 1411 { 1412 // 1413 // Dialog title 1414 // 1415 setWindowTitle(i18n("Preview of %1", share->displayString())); 1416 1417 // 1418 // Attributes 1419 // 1420 setAttribute(Qt::WA_DeleteOnClose, true); 1421 1422 // 1423 // Layout 1424 // 1425 QVBoxLayout *layout = new QVBoxLayout(this); 1426 setLayout(layout); 1427 1428 // 1429 // The list widget 1430 // 1431 QListWidget *listWidget = new QListWidget(this); 1432 listWidget->setSelectionMode(QAbstractItemView::SingleSelection); 1433 connect(listWidget, SIGNAL(itemActivated(QListWidgetItem*)), SLOT(slotItemActivated(QListWidgetItem*))); 1434 1435 layout->addWidget(listWidget, 0); 1436 1437 // 1438 // Toolbar 1439 // Use QToolBar here with the settings suggested by the note provided in the 'Detailed Description' 1440 // section of KToolBar (https://api.kde.org/frameworks/kxmlgui/html/classKToolBar.html) 1441 // 1442 QToolBar *toolBar = new QToolBar(this); 1443 toolBar->setToolButtonStyle(Qt::ToolButtonFollowStyle); 1444 toolBar->setProperty("otherToolbar", true); 1445 1446 // 1447 // Reload / cancel action 1448 // 1449 KDualAction *reloadAction = new KDualAction(toolBar); 1450 reloadAction->setObjectName("reload_action"); 1451 reloadAction->setInactiveText(i18n("Reload")); 1452 reloadAction->setInactiveIcon(KDE::icon("view-refresh")); 1453 reloadAction->setActiveText(i18n("Abort")); 1454 reloadAction->setActiveIcon(KDE::icon("process-stop")); 1455 reloadAction->setActive(false); 1456 reloadAction->setAutoToggle(false); 1457 1458 connect(reloadAction, SIGNAL(toggled(bool)), this, SLOT(slotReloadActionTriggered())); 1459 1460 toolBar->addAction(reloadAction); 1461 1462 // 1463 // Up action 1464 // 1465 QAction *upAction =toolBar->addAction(KDE::icon("go-up"), i18n("Up"), this, SLOT(slotUpActionTriggered())); 1466 upAction->setObjectName("up_action"); 1467 upAction->setEnabled(false); 1468 1469 toolBar->addSeparator(); 1470 1471 // 1472 // URL combo box 1473 // 1474 KUrlComboBox *urlCombo = new KUrlComboBox(KUrlComboBox::Directories, toolBar); 1475 urlCombo->setEditable(false); 1476 toolBar->addWidget(urlCombo); 1477 connect(urlCombo, SIGNAL(urlActivated(QUrl)), this, SLOT(slotUrlActivated(QUrl))); 1478 1479 layout->addWidget(toolBar, 0); 1480 1481 // 1482 // Dialog button box 1483 // 1484 QDialogButtonBox *buttonBox = new QDialogButtonBox(this); 1485 buttonBox->setOrientation(Qt::Horizontal); 1486 QPushButton *closeButton = buttonBox->addButton(QDialogButtonBox::Close); 1487 connect(closeButton, SIGNAL(clicked()), this, SLOT(slotClosingDialog())); 1488 1489 layout->addWidget(buttonBox, 0); 1490 1491 // 1492 // Set the minimum width 1493 // 1494 setMinimumWidth(sizeHint().width() > 350 ? sizeHint().width() : 350); 1495 1496 // 1497 // Set the dialog size 1498 // 1499 create(); 1500 1501 KConfigGroup group(Smb4KSettings::self()->config(), "PreviewDialog"); 1502 QSize dialogSize; 1503 1504 if (group.exists()) 1505 { 1506 KWindowConfig::restoreWindowSize(windowHandle(), group); 1507 dialogSize = windowHandle()->size(); 1508 } 1509 else 1510 { 1511 dialogSize = sizeHint(); 1512 } 1513 1514 resize(dialogSize); // workaround for QTBUG-40584 1515 1516 // 1517 // Start the preview 1518 // 1519 m_currentItem = m_share; 1520 QTimer::singleShot(0, this, SLOT(slotInitializePreview())); 1521 } 1522 1523 1524 Smb4KPreviewDialog::~Smb4KPreviewDialog() 1525 { 1526 // 1527 // Clear the share 1528 // 1529 m_share.clear(); 1530 1531 // 1532 // Clear the current item 1533 // 1534 m_currentItem.clear(); 1535 1536 // 1537 // Clear the listing 1538 // 1539 while (!m_listing.isEmpty()) 1540 { 1541 m_listing.takeFirst().clear(); 1542 } 1543 } 1544 1545 1546 SharePtr Smb4KPreviewDialog::share() const 1547 { 1548 return m_share; 1549 } 1550 1551 1552 void Smb4KPreviewDialog::slotClosingDialog() 1553 { 1554 // 1555 // Save the dialog size 1556 // 1557 KConfigGroup group(Smb4KSettings::self()->config(), "PreviewDialog"); 1558 KWindowConfig::saveWindowSize(windowHandle(), group); 1559 1560 // 1561 // Emit the aboutToClose() signal 1562 // 1563 emit aboutToClose(this); 1564 1565 // 1566 // Close the dialog 1567 // 1568 accept(); 1569 } 1570 1571 1572 void Smb4KPreviewDialog::slotReloadActionTriggered() 1573 { 1574 KDualAction *reloadAction = findChild<KDualAction *>(); 1575 1576 if (reloadAction->isActive()) 1577 { 1578 emit requestAbort(); 1579 } 1580 else 1581 { 1582 emit requestPreview(m_currentItem); 1583 } 1584 } 1585 1586 1587 void Smb4KPreviewDialog::slotUpActionTriggered() 1588 { 1589 // 1590 // Get the new URL 1591 // 1592 QUrl u = KIO::upUrl(m_currentItem->url()); 1593 1594 // 1595 // Create a new network item object, if necessary and set the new current 1596 // item. Also, disable the "Up" action, if necessary. 1597 // 1598 if (m_share->url().matches(u, QUrl::StripTrailingSlash)) 1599 { 1600 findChild<QAction *>("up_action")->setEnabled(false); 1601 m_currentItem = m_share; 1602 } 1603 else if (m_share->url().path().length() < u.path().length()) 1604 { 1605 FilePtr file = FilePtr(new Smb4KFile(u, Directory)); 1606 file->setWorkgroupName(m_share->workgroupName()); 1607 m_currentItem = file; 1608 } 1609 else 1610 { 1611 return; 1612 } 1613 1614 // 1615 // Emit the requestPreview() signal 1616 // 1617 emit requestPreview(m_currentItem); 1618 } 1619 1620 1621 void Smb4KPreviewDialog::slotUrlActivated(const QUrl &url) 1622 { 1623 // 1624 // Get the full authentication information. This is needed, since the combo 1625 // box only returns sanitized URLs, i.e. without password, etc. 1626 // 1627 QUrl u = url; 1628 u.setUserName(m_share->login()); 1629 u.setPassword(m_share->password()); 1630 1631 // 1632 // Create a new network item object, if necessary and set the new current 1633 // item. 1634 // 1635 if (m_share->url().matches(u, QUrl::StripTrailingSlash)) 1636 { 1637 m_currentItem = m_share; 1638 } 1639 else 1640 { 1641 FilePtr file = FilePtr(new Smb4KFile(u, Directory)); 1642 file->setWorkgroupName(m_share->workgroupName()); 1643 m_currentItem = file; 1644 } 1645 1646 // 1647 // Emit the requestPreview() signal 1648 // 1649 emit requestPreview(m_currentItem); 1650 } 1651 1652 1653 void Smb4KPreviewDialog::slotItemActivated(QListWidgetItem *item) 1654 { 1655 // 1656 // Only process the item if it represents a directory 1657 // 1658 if (item && item->type() == Directory) 1659 { 1660 // 1661 // Find the file item, make it the current one and emit the requestPreview() 1662 // signal. 1663 // 1664 for (const FilePtr &f : m_listing) 1665 { 1666 if (item->data(Qt::UserRole).toUrl().matches(f->url(), QUrl::None)) 1667 { 1668 m_currentItem = f; 1669 emit requestPreview(m_currentItem); 1670 break; 1671 } 1672 } 1673 } 1674 } 1675 1676 1677 void Smb4KPreviewDialog::slotInitializePreview() 1678 { 1679 emit requestPreview(m_currentItem); 1680 } 1681 1682 1683 void Smb4KPreviewDialog::slotPreviewResults(const QList<FilePtr> &list) 1684 { 1685 // 1686 // Only process data the belongs to this dialog 1687 // 1688 if (m_share->workgroupName() == list.first()->workgroupName() && m_share->hostName() == list.first()->hostName() && 1689 list.first()->url().path().startsWith(m_share->url().path())) 1690 { 1691 // 1692 // Clear the internal listing 1693 // 1694 while (!m_listing.isEmpty()) 1695 { 1696 m_listing.takeFirst().clear(); 1697 } 1698 1699 // 1700 // Copy the list into the private variable 1701 // 1702 m_listing = list; 1703 1704 // 1705 // Get the list widget 1706 // 1707 QListWidget *listWidget = findChild<QListWidget *>(); 1708 1709 // 1710 // Clear the list widget 1711 // 1712 listWidget->clear(); 1713 1714 // 1715 // Insert the new listing 1716 // 1717 if (listWidget) 1718 { 1719 for (const FilePtr &f : list) 1720 { 1721 QListWidgetItem *item = new QListWidgetItem(f->icon(), f->name(), listWidget, f->isDirectory() ? Directory : File); 1722 item->setData(Qt::UserRole, f->url()); 1723 } 1724 } 1725 1726 // 1727 // Sort the list widget 1728 // 1729 listWidget->sortItems(); 1730 1731 // 1732 // Add the URL to the combo box and show it. Omit duplicates. 1733 // 1734 KUrlComboBox *urlCombo = findChild<KUrlComboBox *>(); 1735 QStringList urls = urlCombo->urls(); 1736 urls << m_currentItem->url().toString(); 1737 urlCombo->setUrls(urls); 1738 urlCombo->setUrl(m_currentItem->url()); 1739 1740 // 1741 // Enable / disable the "Up" action 1742 // 1743 findChild<QAction *>("up_action")->setEnabled(!m_share->url().matches(m_currentItem->url(), QUrl::StripTrailingSlash)); 1744 } 1745 } 1746 1747 1748 void Smb4KPreviewDialog::slotAboutToStart(const NetworkItemPtr &item, int type) 1749 { 1750 if (type == LookupFiles) 1751 { 1752 switch (item->type()) 1753 { 1754 case Share: 1755 { 1756 SharePtr s = item.staticCast<Smb4KShare>(); 1757 1758 if (m_share->workgroupName() == s->workgroupName() && m_share->hostName() == s->hostName() && s->url().path().startsWith(m_share->url().path())) 1759 { 1760 KDualAction *reloadAction = findChild<KDualAction *>(); 1761 reloadAction->setActive(true); 1762 } 1763 1764 break; 1765 } 1766 case Directory: 1767 { 1768 FilePtr f = item.staticCast<Smb4KFile>(); 1769 1770 if (m_share->workgroupName() == f->workgroupName() && m_share->hostName() == f->hostName() && f->url().path().startsWith(m_share->url().path())) 1771 { 1772 KDualAction *reloadAction = findChild<KDualAction *>(); 1773 reloadAction->setActive(true); 1774 } 1775 1776 break; 1777 } 1778 default: 1779 { 1780 break; 1781 } 1782 } 1783 } 1784 } 1785 1786 1787 void Smb4KPreviewDialog::slotFinished(const NetworkItemPtr &item, int type) 1788 { 1789 if (type == LookupFiles) 1790 { 1791 switch (item->type()) 1792 { 1793 case Share: 1794 { 1795 SharePtr s = item.staticCast<Smb4KShare>(); 1796 1797 if (m_share->workgroupName() == s->workgroupName() && m_share->hostName() == s->hostName() && s->url().path().startsWith(m_share->url().path())) 1798 { 1799 KDualAction *reloadAction = findChild<KDualAction *>(); 1800 reloadAction->setActive(false); 1801 } 1802 1803 break; 1804 } 1805 case Directory: 1806 { 1807 FilePtr f = item.staticCast<Smb4KFile>(); 1808 1809 if (m_share->workgroupName() == f->workgroupName() && m_share->hostName() == f->hostName() && f->url().path().startsWith(m_share->url().path())) 1810 { 1811 KDualAction *reloadAction = findChild<KDualAction *>(); 1812 reloadAction->setActive(false); 1813 } 1814 1815 break; 1816 } 1817 default: 1818 { 1819 break; 1820 } 1821 } 1822 } 1823 } 1824 1825 1826 Smb4KPrintDialog::Smb4KPrintDialog(const SharePtr& share, QWidget* parent) 1827 : QDialog(parent), m_share(share) 1828 { 1829 // 1830 // Dialog title 1831 // 1832 setWindowTitle(i18n("Print File")); 1833 1834 // 1835 // Attributes 1836 // 1837 setAttribute(Qt::WA_DeleteOnClose, true); 1838 1839 // 1840 // Layout 1841 // 1842 QVBoxLayout *layout = new QVBoxLayout(this); 1843 setLayout(layout); 1844 1845 // 1846 // Information group box 1847 // 1848 QGroupBox *informationBox = new QGroupBox(i18n("Information"), this); 1849 QGridLayout *informationBoxLayout = new QGridLayout(informationBox); 1850 1851 // Printer name 1852 QLabel *printerNameLabel = new QLabel(i18n("Printer:"), informationBox); 1853 QLabel *printerName = new QLabel(share->displayString(), informationBox); 1854 1855 informationBoxLayout->addWidget(printerNameLabel, 0, 0, 0); 1856 informationBoxLayout->addWidget(printerName, 0, 1, 0); 1857 1858 // IP address 1859 QLabel *ipAddressLabel = new QLabel(i18n("IP Address:"), informationBox); 1860 QLabel *ipAddress = new QLabel(share->hostIpAddress(), informationBox); 1861 1862 informationBoxLayout->addWidget(ipAddressLabel, 1, 0, 0); 1863 informationBoxLayout->addWidget(ipAddress, 1, 1, 0); 1864 1865 // Workgroup 1866 QLabel *workgroupNameLabel = new QLabel(i18n("Domain:"), informationBox); 1867 QLabel *workgroupName = new QLabel(share->workgroupName(), informationBox); 1868 1869 informationBoxLayout->addWidget(workgroupNameLabel, 2, 0, 0); 1870 informationBoxLayout->addWidget(workgroupName, 2, 1, 0); 1871 1872 layout->addWidget(informationBox); 1873 1874 // 1875 // File and settings group box 1876 // 1877 QGroupBox *fileBox = new QGroupBox(i18n("File and Settings"), this); 1878 QGridLayout *fileBoxLayout = new QGridLayout(fileBox); 1879 1880 // File 1881 QLabel *fileLabel = new QLabel(i18n("File:"), fileBox); 1882 KUrlRequester *file = new KUrlRequester(fileBox); 1883 file->setMode(KFile::File|KFile::LocalOnly|KFile::ExistingOnly); 1884 file->setUrl(QUrl::fromLocalFile(QDir::homePath())); 1885 file->setWhatsThis(i18n("This is the file you want to print on the remote printer. " 1886 "Currently only a few mimetypes are supported such as PDF, Postscript, plain text, and " 1887 "images. If the file's mimetype is not supported, you need to convert it.")); 1888 connect(file, SIGNAL(textChanged(QString)), this, SLOT(slotUrlChanged())); 1889 1890 fileBoxLayout->addWidget(fileLabel, 0, 0, 0); 1891 fileBoxLayout->addWidget(file, 0, 1, 0); 1892 1893 // Copies 1894 QLabel *copiesLabel = new QLabel(i18n("Copies:"), fileBox); 1895 QSpinBox *copies = new QSpinBox(fileBox); 1896 copies->setValue(1); 1897 copies->setMinimum(1); 1898 copies->setWhatsThis(i18n("This is the number of copies you want to print.")); 1899 1900 fileBoxLayout->addWidget(copiesLabel, 1, 0, 0); 1901 fileBoxLayout->addWidget(copies, 1, 1, 0); 1902 1903 layout->addWidget(fileBox); 1904 1905 // 1906 // Buttons 1907 // 1908 QDialogButtonBox *buttonBox = new QDialogButtonBox(this); 1909 QPushButton *printButton = buttonBox->addButton(i18n("Print"), QDialogButtonBox::ActionRole); 1910 printButton->setObjectName("print_button"); 1911 printButton->setShortcut(Qt::CTRL|Qt::Key_P); 1912 connect(printButton, SIGNAL(clicked(bool)), this, SLOT(slotPrintButtonClicked())); 1913 1914 QPushButton *cancelButton = buttonBox->addButton(QDialogButtonBox::Cancel); 1915 cancelButton->setObjectName("cancel_button"); 1916 cancelButton->setShortcut(Qt::Key_Escape); 1917 cancelButton->setDefault(true); 1918 connect(cancelButton, SIGNAL(clicked(bool)), this, SLOT(slotCancelButtonClicked())); 1919 1920 layout->addWidget(buttonBox); 1921 1922 // 1923 // Set the minimum width 1924 // 1925 setMinimumWidth(sizeHint().width() > 350 ? sizeHint().width() : 350); 1926 1927 // 1928 // Set the dialog size 1929 // 1930 create(); 1931 1932 KConfigGroup group(Smb4KSettings::self()->config(), "PrintDialog"); 1933 QSize dialogSize; 1934 1935 if (group.exists()) 1936 { 1937 KWindowConfig::restoreWindowSize(windowHandle(), group); 1938 dialogSize = windowHandle()->size(); 1939 } 1940 else 1941 { 1942 dialogSize = sizeHint(); 1943 } 1944 1945 resize(dialogSize); // workaround for QTBUG-40584 1946 1947 // 1948 // Set the buttons 1949 // 1950 slotUrlChanged(); 1951 } 1952 1953 1954 Smb4KPrintDialog::~Smb4KPrintDialog() 1955 { 1956 } 1957 1958 1959 SharePtr Smb4KPrintDialog::share() const 1960 { 1961 return m_share; 1962 } 1963 1964 1965 KFileItem Smb4KPrintDialog::fileItem() const 1966 { 1967 return m_fileItem; 1968 } 1969 1970 1971 void Smb4KPrintDialog::slotUrlChanged() 1972 { 1973 // 1974 // Take the focus from the URL requester and give it to the dialog's 1975 // button box 1976 // 1977 QDialogButtonBox *buttonBox = findChild<QDialogButtonBox *>(); 1978 buttonBox->setFocus(); 1979 1980 // 1981 // Get the URL from the URL requester 1982 // 1983 KUrlRequester *file = findChild<KUrlRequester *>(); 1984 KFileItem fileItem = KFileItem(file->url()); 1985 1986 // 1987 // Apply the settings to the buttons of the dialog's button box 1988 // 1989 QPushButton *printButton = findChild<QPushButton *>("print_button"); 1990 printButton->setEnabled(fileItem.url().isValid() && fileItem.isFile()); 1991 printButton->setDefault(fileItem.url().isValid() && fileItem.isFile()); 1992 1993 QPushButton *cancelButton = findChild<QPushButton *>("cancel_button"); 1994 cancelButton->setDefault(!fileItem.url().isValid() || !fileItem.isFile()); 1995 } 1996 1997 1998 void Smb4KPrintDialog::slotPrintButtonClicked() 1999 { 2000 // 2001 // Get the file item that is to be printed 2002 // 2003 KUrlRequester *file = findChild<KUrlRequester *>(); 2004 m_fileItem = KFileItem(file->url()); 2005 2006 if (m_fileItem.url().isValid()) 2007 { 2008 // 2009 // Check if the mime type is supported or if the file can be 2010 // converted into a supported mimetype 2011 // 2012 if (m_fileItem.mimetype() != "application/postscript" && 2013 m_fileItem.mimetype() != "application/pdf" && 2014 m_fileItem.mimetype() != "application/x-shellscript" && 2015 !m_fileItem.mimetype().startsWith(QLatin1String("text")) && 2016 !m_fileItem.mimetype().startsWith(QLatin1String("message")) && 2017 !m_fileItem.mimetype().startsWith(QLatin1String("image"))) 2018 { 2019 Smb4KNotification::mimetypeNotSupported(m_fileItem.mimetype()); 2020 return; 2021 } 2022 2023 // 2024 // Save the window size 2025 // 2026 KConfigGroup group(Smb4KSettings::self()->config(), "PrintDialog"); 2027 KWindowConfig::saveWindowSize(windowHandle(), group); 2028 2029 // 2030 // Emit the printFile() signal 2031 // 2032 QSpinBox *copies = findChild<QSpinBox *>(); 2033 emit printFile(m_share, m_fileItem, copies->value()); 2034 2035 // 2036 // Emit the aboutToClose() signal 2037 // 2038 emit aboutToClose(this); 2039 2040 // 2041 // Close the print dialog 2042 // 2043 accept(); 2044 } 2045 } 2046 2047 2048 void Smb4KPrintDialog::slotCancelButtonClicked() 2049 { 2050 // 2051 // Abort the printing 2052 // 2053 Smb4KClient::self()->abort(); 2054 2055 // 2056 // Emit the aboutToClose() signal 2057 // 2058 emit aboutToClose(this); 2059 2060 // 2061 // Reject the dialog 2062 // 2063 reject(); 2064 } 2065 2066 2067