diff --git a/smb/discovery.h b/smb/discovery.h --- a/smb/discovery.h +++ b/smb/discovery.h @@ -21,8 +21,8 @@ #ifndef DISCOVERY_H #define DISCOVERY_H -#include #include +#include class Discovery { @@ -50,4 +50,3 @@ }; #endif // DISCOVERY_H - diff --git a/smb/dnssddiscoverer.h b/smb/dnssddiscoverer.h --- a/smb/dnssddiscoverer.h +++ b/smb/dnssddiscoverer.h @@ -23,8 +23,8 @@ #include -#include #include +#include #include "discovery.h" @@ -55,7 +55,7 @@ void stop() override; void maybeFinish(); - KDNSSD::ServiceBrowser m_browser { QStringLiteral("_smb._tcp") }; + KDNSSD::ServiceBrowser m_browser {QStringLiteral("_smb._tcp")}; QList m_services; int m_resolvedCount = 0; bool m_disconnected = false; diff --git a/smb/dnssddiscoverer.cpp b/smb/dnssddiscoverer.cpp --- a/smb/dnssddiscoverer.cpp +++ b/smb/dnssddiscoverer.cpp @@ -78,8 +78,7 @@ } } - connect(service.data(), &KDNSSD::RemoteService::resolved, - this, [=] { + connect(service.data(), &KDNSSD::RemoteService::resolved, this, [=] { ++m_resolvedCount; emit newDiscovery(Discovery::Ptr(new DNSSDDiscovery(service))); maybeFinish(); diff --git a/smb/kio_smb.h b/smb/kio_smb.h --- a/smb/kio_smb.h +++ b/smb/kio_smb.h @@ -32,7 +32,6 @@ // ///////////////////////////////////////////////////////////////////////////// - #ifndef KIO_SMB_H_INCLUDED #define KIO_SMB_H_INCLUDED @@ -49,108 +48,104 @@ //----------------------------- // Standard C library includes //----------------------------- +#include +#include +#include +#include +#include #include -#include #include #include -#include -#include -#include -#include -#include +#include #include //----------------------------- // Qt includes //----------------------------- +#include #include #include -#include //------------------------------- // Samba client library includes //------------------------------- -extern "C" -{ +extern "C" { #include } //--------------------------- // kio_smb internal includes //--------------------------- #include "kio_smb_internal.h" -#define MAX_XFER_BUF_SIZE 65534 +#define MAX_XFER_BUF_SIZE 65534 using namespace KIO; -//=========================================================================== - - class SMBSlave : public QObject, public KIO::SlaveBase { Q_OBJECT private: - class SMBError { + class SMBError + { public: int kioErrorId; QString errorString; }; //--------------------------------------------------------------------- // please make sure your private data does not duplicate existing data //--------------------------------------------------------------------- - bool m_initialized_smbc; + bool m_initialized_smbc; /** * From Controlcenter */ - QString m_default_user; - QString m_default_workgroup = QStringLiteral("WORKGROUP"); // overwritten with value from smbc - QString m_default_password; - QString m_default_encoding; + QString m_default_user; + QString m_default_workgroup = QStringLiteral("WORKGROUP"); // overwritten with value from smbc + QString m_default_password; + QString m_default_encoding; /** * we store the current url, it's needed for * callback authorization method */ - SMBUrl m_current_url; + SMBUrl m_current_url; /** * From Controlcenter, show SHARE$ or not */ -// bool m_showHiddenShares; //currently unused, Alex + // bool m_showHiddenShares; //currently unused, Alex /** * libsmbclient need global variables to store in, * else it crashes on exit next method after use cache_stat, * looks like gcc (C/C++) failure */ - struct stat st{}; + struct stat st { + }; protected: //--------------------------------------------- // Authentication functions (kio_smb_auth.cpp) //--------------------------------------------- // (please prefix functions with auth) - /** * Description : Initializes the libsmbclient * Return : true on success false with errno set on error */ bool auth_initialize_smbc(); int checkPassword(SMBUrl &url); - //--------------------------------------------- // Cache functions (kio_smb_auth.cpp) //--------------------------------------------- - //Stat methods + // Stat methods //----------------------------------------- // Browsing functions (kio_smb_browse.cpp) @@ -163,7 +158,7 @@ * Parameter : SMBUrl the url to stat * Return : cache_stat() return code */ - int browse_stat_path(const SMBUrl& url, UDSEntry& udsentry); + int browse_stat_path(const SMBUrl &url, UDSEntry &udsentry); /** * Description : call smbc_stat and return stats of the url @@ -174,20 +169,18 @@ * method segfault on returning try to change the stat* * variable */ - int cache_stat( const SMBUrl& url, struct stat* st ); + int cache_stat(const SMBUrl &url, struct stat *st); //--------------------------------------------- // Configuration functions (kio_smb_config.cpp) //--------------------------------------------- // (please prefix functions with config) - //--------------------------------------- // Directory functions (kio_smb_dir.cpp) //--------------------------------------- // (please prefix functions with dir) - //-------------------------------------- // File IO functions (kio_smb_file.cpp) //-------------------------------------- @@ -197,7 +190,6 @@ // Misc functions (this file) //---------------------------- - /** * Description : correct a given URL * valid URL's are @@ -214,75 +206,70 @@ * Parameter : QUrl the url to check * Return : new QUrl if it is corrected. else the same QUrl */ - QUrl checkURL(const QUrl& kurl) const; + QUrl checkURL(const QUrl &kurl) const; - void reportError(const SMBUrl& url, const int errNum); - void reportWarning(const SMBUrl& url, const int errNum); + void reportError(const SMBUrl &url, const int errNum); + void reportWarning(const SMBUrl &url, const int errNum); public: - //----------------------------------------------------------------------- // smbclient authentication callback (note that this is called by the // global ::auth_smbc_get_data() call. - void auth_smbc_get_data(const char *server,const char *share, - char *workgroup, int wgmaxlen, - char *username, int unmaxlen, - char *password, int pwmaxlen); - + void auth_smbc_get_data(const char *server, const char *share, char *workgroup, int wgmaxlen, char *username, int unmaxlen, char *password, int pwmaxlen); //----------------------------------------------------------------------- // Overwritten functions from the base class that define the operation of // this slave. (See the base class headerfile slavebase.h for more // details) //----------------------------------------------------------------------- // Functions overwritten in kio_smb.cpp - SMBSlave(const QByteArray& pool, const QByteArray& app); + SMBSlave(const QByteArray &pool, const QByteArray &app); ~SMBSlave() override; // Functions overwritten in kio_smb_browse.cpp - void listDir( const QUrl& url ) override; - void stat( const QUrl& url ) override; + void listDir(const QUrl &url) override; + void stat(const QUrl &url) override; // Functions overwritten in kio_smb_config.cpp void reparseConfiguration() override; // Functions overwritten in kio_smb_dir.cpp - void copy( const QUrl& src, const QUrl &dst, int permissions, KIO::JobFlags flags ) override; - void del( const QUrl& kurl, bool isfile) override; - void mkdir( const QUrl& kurl, int permissions ) override; - void rename( const QUrl& src, const QUrl& dest, KIO::JobFlags flags ) override; + void copy(const QUrl &src, const QUrl &dst, int permissions, KIO::JobFlags flags) override; + void del(const QUrl &kurl, bool isfile) override; + void mkdir(const QUrl &kurl, int permissions) override; + void rename(const QUrl &src, const QUrl &dest, KIO::JobFlags flags) override; // Functions overwritten in kio_smb_file.cpp - void get( const QUrl& kurl ) override; - void put( const QUrl& kurl, int permissions, KIO::JobFlags flags ) override; - void open( const QUrl& kurl, QIODevice::OpenMode mode ) override; - void read( KIO::filesize_t bytesRequested ) override; - void write( const QByteArray &fileData ) override; - void seek( KIO::filesize_t offset ) override; - void truncate( KIO::filesize_t length ); + void get(const QUrl &kurl) override; + void put(const QUrl &kurl, int permissions, KIO::JobFlags flags) override; + void open(const QUrl &kurl, QIODevice::OpenMode mode) override; + void read(KIO::filesize_t bytesRequested) override; + void write(const QByteArray &fileData) override; + void seek(KIO::filesize_t offset) override; + void truncate(KIO::filesize_t length); void close() override; // Functions not implemented (yet) - //virtual void setHost(const QString& host, int port, const QString& user, const QString& pass); - //virtual void openConnection(); - //virtual void closeConnection(); - //virtual void slave_status(); - void special( const QByteArray & ) override; + // virtual void setHost(const QString& host, int port, const QString& user, const QString& pass); + // virtual void openConnection(); + // virtual void closeConnection(); + // virtual void slave_status(); + void special(const QByteArray &) override; protected: void virtual_hook(int id, void *data) override; private: - SMBError errnumToKioError(const SMBUrl& url, const int errNum); - void smbCopy(const QUrl& src, const QUrl &dst, int permissions, KIO::JobFlags flags); - void smbCopyGet(const QUrl& ksrc, const QUrl& kdst, int permissions, KIO::JobFlags flags); - void smbCopyPut(const QUrl& ksrc, const QUrl& kdst, int permissions, KIO::JobFlags flags); + SMBError errnumToKioError(const SMBUrl &url, const int errNum); + void smbCopy(const QUrl &src, const QUrl &dst, int permissions, KIO::JobFlags flags); + void smbCopyGet(const QUrl &ksrc, const QUrl &kdst, int permissions, KIO::JobFlags flags); + void smbCopyPut(const QUrl &ksrc, const QUrl &kdst, int permissions, KIO::JobFlags flags); bool workaroundEEXIST(const int errNum) const; void fileSystemFreeSpace(const QUrl &url); - /** + /** * Used in open(), read(), write(), and close() * FIXME Placing these in the private section above causes m_openUrl = kurl * to fail in SMBSlave::open. Need to find out why this is. @@ -297,26 +284,14 @@ //========================================================================== // the global libsmbclient authentication callback function -extern "C" -{ - -void auth_smbc_get_data(SMBCCTX * context, - const char *server,const char *share, - char *workgroup, int wgmaxlen, - char *username, int unmaxlen, - char *password, int pwmaxlen); - +extern "C" { +void auth_smbc_get_data(SMBCCTX *context, const char *server, const char *share, char *workgroup, int wgmaxlen, char *username, int unmaxlen, char *password, int pwmaxlen); } - //=========================================================================== // Main slave entrypoint (see kio_smb.cpp) -extern "C" -{ - -int kdemain( int argc, char **argv ); - +extern "C" { +int kdemain(int argc, char **argv); } - -#endif //#endif KIO_SMB_H_INCLUDED +#endif //#endif KIO_SMB_H_INCLUDED diff --git a/smb/kio_smb.cpp b/smb/kio_smb.cpp --- a/smb/kio_smb.cpp +++ b/smb/kio_smb.cpp @@ -51,8 +51,8 @@ * * Upstream bug report: https://bugzilla.samba.org/show_bug.cgi?id=13050 */ - static const QVersionNumber firstBrokenVer{4, 7, 0}; - static const QVersionNumber lastBrokenVer{4, 7, 6}; + static const QVersionNumber firstBrokenVer {4, 7, 0}; + static const QVersionNumber lastBrokenVer {4, 7, 6}; const QVersionNumber currentVer = QVersionNumber::fromString(smbc_version()); qCDebug(KIO_SMB_LOG) << "Using libsmbclient library version" << currentVer; @@ -65,27 +65,25 @@ return false; } -//=========================================================================== -SMBSlave::SMBSlave(const QByteArray& pool, const QByteArray& app) - : SlaveBase( "smb", pool, app ), - m_openFd(-1), - m_enableEEXISTWorkaround(needsEEXISTWorkaround()) +SMBSlave::SMBSlave(const QByteArray &pool, const QByteArray &app) + : SlaveBase("smb", pool, app) + , m_openFd(-1) + , m_enableEEXISTWorkaround(needsEEXISTWorkaround()) { m_initialized_smbc = false; - //read in the default workgroup info... + // read in the default workgroup info... reparseConfiguration(); - //initialize the library... + // initialize the library... auth_initialize_smbc(); } - -//=========================================================================== SMBSlave::~SMBSlave() = default; -void SMBSlave::virtual_hook(int id, void *data) { - switch(id) { +void SMBSlave::virtual_hook(int id, void *data) +{ + switch (id) { case SlaveBase::GetFileSystemFreeSpace: { QUrl *url = static_cast(data); fileSystemFreeSpace(*url); @@ -100,17 +98,15 @@ } } -//=========================================================================== -int Q_DECL_EXPORT kdemain( int argc, char **argv ) +int Q_DECL_EXPORT kdemain(int argc, char **argv) { QCoreApplication app(argc, argv); - if( argc != 4 ) - { + if (argc != 4) { qCDebug(KIO_SMB_LOG) << "Usage: kio_smb protocol domain-socket1 domain-socket2"; return -1; } - SMBSlave slave( argv[2], argv[3] ); + SMBSlave slave(argv[2], argv[3]); slave.dispatchLoop(); diff --git a/smb/kio_smb_auth.cpp b/smb/kio_smb_auth.cpp --- a/smb/kio_smb_auth.cpp +++ b/smb/kio_smb_auth.cpp @@ -32,25 +32,22 @@ #include "kio_smb.h" #include "kio_smb_internal.h" +#include #include #include #include -#include -// call for libsmbclient -//========================================================================== void auth_smbc_get_data(SMBCCTX * context, const char *server,const char *share, char *workgroup, int wgmaxlen, char *username, int unmaxlen, char *password, int pwmaxlen) -//========================================================================== { if (context != nullptr) { #ifdef DEPRECATED_SMBC_INTERFACE - auto *theSlave = static_cast(smbc_getOptionUserData(context)); + auto *theSlave = static_cast(smbc_getOptionUserData(context)); #else - auto *theSlave = static_cast(smbc_option_get(context, "user_data")); + auto *theSlave = static_cast(smbc_option_get(context, "user_data")); #endif theSlave->auth_smbc_get_data(server, share, workgroup,wgmaxlen, @@ -60,17 +57,14 @@ } -//-------------------------------------------------------------------------- void SMBSlave::auth_smbc_get_data(const char *server,const char *share, char *workgroup, int wgmaxlen, char *username, int unmaxlen, char *password, int pwmaxlen) -//-------------------------------------------------------------------------- { - //check this to see if we "really" need to authenticate... + // check this to see if we "really" need to authenticate... SMBUrlType t = m_current_url.getType(); - if( t == SMBURLTYPE_ENTIRE_NETWORK ) - { + if (t == SMBURLTYPE_ENTIRE_NETWORK) { qCDebug(KIO_SMB_LOG) << "we don't really need to authenticate for this top level url, returning"; return; } @@ -98,16 +92,12 @@ qCDebug(KIO_SMB_LOG) << "libsmb-auth-callback URL:" << info.url; - if ( !checkCachedAuthentication( info ) ) - { - if ( m_default_user.isEmpty() ) - { + if (!checkCachedAuthentication(info)) { + if (m_default_user.isEmpty()) { // ok, we do not know the password. Let's try anonymous before we try for real info.username = "anonymous"; info.password.clear(); - } - else - { + } else { // user defined a default username/password in kcontrol; try this info.username = m_default_user; info.password = m_default_password; @@ -154,17 +144,15 @@ info.setExtraField("anonymous", true); // arbitrary default for dialog info.setExtraField("domain", m_default_workgroup); - if ( share.isEmpty() ) - info.prompt = i18n( - "Please enter authentication information for %1" , - url.host() ); + if (share.isEmpty()) + info.prompt = i18n("Please enter authentication information for %1", url.host()); else info.prompt = i18n( - "Please enter authentication information for:\n" - "Server = %1\n" - "Share = %2" , - url.host() , - share ); + "Please enter authentication information for:\n" + "Server = %1\n" + "Share = %2", + url.host(), + share); info.username = url.userName(); qCDebug(KIO_SMB_LOG) << "call openPasswordDialog for " << info.url; @@ -186,10 +174,6 @@ return passwordDialogErrorCode; } -//-------------------------------------------------------------------------- -// Initializes the smbclient library -// -// Returns: 0 on success -1 with errno set on error bool SMBSlave::auth_initialize_smbc() { if (m_initialized_smbc) { @@ -219,7 +203,7 @@ #else smb_context->debug = debug_level; smb_context->callbacks.auth_fn = NULL; - smbc_option_set(smb_context, "auth_function", (void*)::auth_smbc_get_data); + smbc_option_set(smb_context, "auth_function", (void *)::auth_smbc_get_data); smbc_option_set(smb_context, "user_data", this); #if defined(SMB_CTX_FLAG_USE_KERBEROS) && defined(SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS) diff --git a/smb/kio_smb_browse.cpp b/smb/kio_smb_browse.cpp --- a/smb/kio_smb_browse.cpp +++ b/smb/kio_smb_browse.cpp @@ -34,128 +34,124 @@ #include "kio_smb.h" #include "kio_smb_internal.h" -#include #include -#include +#include #include +#include #include #include -#include #include +#include -#include -#include "wsdiscoverer.h" #include "dnssddiscoverer.h" +#include "wsdiscoverer.h" +#include using namespace KIO; -int SMBSlave::cache_stat(const SMBUrl &url, struct stat* st ) +int SMBSlave::cache_stat(const SMBUrl &url, struct stat *st) { int cacheStatErr; - int result = smbc_stat( url.toSmbcUrl(), st); - if (result == 0){ + int result = smbc_stat(url.toSmbcUrl(), st); + if (result == 0) { cacheStatErr = 0; } else { cacheStatErr = errno; } qCDebug(KIO_SMB_LOG) << "size " << static_cast(st->st_size); return cacheStatErr; } -//--------------------------------------------------------------------------- -int SMBSlave::browse_stat_path(const SMBUrl &url, UDSEntry& udsentry) +int SMBSlave::browse_stat_path(const SMBUrl &url, UDSEntry &udsentry) { - int cacheStatErr = cache_stat(url, &st); - if(cacheStatErr == 0) - { - if(!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode)) - { - qCDebug(KIO_SMB_LOG) << "mode: "<< st.st_mode; - warning(i18n("%1:\n" - "Unknown file type, neither directory or file.", url.toDisplayString())); - return EINVAL; - } - - if (!S_ISDIR(st.st_mode)) { - // Awkwardly documented at - // https://www.samba.org/samba/docs/using_samba/ch08.html - // libsmb_stat.c assigns special meaning to +x permissions - // (obviously only on files, all dirs are +x so this hacky representation - // wouldn't work!): - // - S_IXUSR = DOS archive: This file has been touched since the last DOS backup was performed on it. - // - S_IXGRP = DOS system: This file has a specific purpose required by the operating system. - // - S_IXOTH = DOS hidden: This file has been marked to be invisible to the user, unless the operating system is explicitly set to show it. - // Only hiding has backing through KIO right now. - if (st.st_mode & S_IXOTH) { // DOS hidden - udsentry.fastInsert(KIO::UDSEntry::UDS_HIDDEN, true); - } - } - - // UID and GID **must** not be mapped. The values returned by libsmbclient are - // simply the getuid/getgid of the process. They mean absolutely nothing. - // Also see libsmb_stat.c. - // Related: https://bugs.kde.org/show_bug.cgi?id=212801 - - // POSIX Access mode must not be mapped either! - // It's meaningless for smb shares and downright disadvantagous. - // The mode attributes outside the ones used and document above are - // useless. The only one actively set is readonlyness. - // - // BUT the READONLY attribute does nothing on NT systems: - // https://support.microsoft.com/en-us/help/326549/you-cannot-view-or-change-the-read-only-or-the-system-attributes-of-fo - // The Read-only and System attributes is only used by Windows Explorer to determine - // whether the folder is a special folder, such as a system folder that has its view - // customized by Windows (for example, My Documents, Favorites, Fonts, Downloaded Program Files), - // or a folder that you customized by using the Customize tab of the folder's Properties dialog box. - // - // As such respecting it on a KIO level is actually wrong as it doesn't indicate actual - // readonlyness since the 90s and causes us to show readonly UI states when in fact - // the directory is perfectly writable. - // https://bugs.kde.org/show_bug.cgi?id=414482 - // - // Should we ever want to parse desktop.ini like we do .directory we'd only want to when a - // dir is readonly as per the above microsoft support article. - // Also see: - // https://docs.microsoft.com/en-us/windows/win32/shell/how-to-customize-folders-with-desktop-ini - udsentry.fastInsert(KIO::UDSEntry::UDS_ACCESS, -1); - - udsentry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, st.st_mode & S_IFMT); - udsentry.fastInsert(KIO::UDSEntry::UDS_SIZE, st.st_size); - udsentry.fastInsert(KIO::UDSEntry::UDS_MODIFICATION_TIME, st.st_mtime); - udsentry.fastInsert(KIO::UDSEntry::UDS_ACCESS_TIME, st.st_atime); - // No, st_ctime is not UDS_CREATION_TIME... - } - - return cacheStatErr; + int cacheStatErr = cache_stat(url, &st); + if (cacheStatErr == 0) { + if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode)) { + qCDebug(KIO_SMB_LOG) << "mode: " << st.st_mode; + warning( + i18n("%1:\n" + "Unknown file type, neither directory or file.", + url.toDisplayString())); + return EINVAL; + } + + if (!S_ISDIR(st.st_mode)) { + // Awkwardly documented at + // https://www.samba.org/samba/docs/using_samba/ch08.html + // libsmb_stat.c assigns special meaning to +x permissions + // (obviously only on files, all dirs are +x so this hacky representation + // wouldn't work!): + // - S_IXUSR = DOS archive: This file has been touched since the last DOS backup was performed on it. + // - S_IXGRP = DOS system: This file has a specific purpose required by the operating system. + // - S_IXOTH = DOS hidden: This file has been marked to be invisible to the user, unless the operating system is explicitly set to show it. + // Only hiding has backing through KIO right now. + if (st.st_mode & S_IXOTH) { // DOS hidden + udsentry.fastInsert(KIO::UDSEntry::UDS_HIDDEN, true); + } + } + + // UID and GID **must** not be mapped. The values returned by libsmbclient are + // simply the getuid/getgid of the process. They mean absolutely nothing. + // Also see libsmb_stat.c. + // Related: https://bugs.kde.org/show_bug.cgi?id=212801 + + // POSIX Access mode must not be mapped either! + // It's meaningless for smb shares and downright disadvantagous. + // The mode attributes outside the ones used and document above are + // useless. The only one actively set is readonlyness. + // + // BUT the READONLY attribute does nothing on NT systems: + // https://support.microsoft.com/en-us/help/326549/you-cannot-view-or-change-the-read-only-or-the-system-attributes-of-fo + // The Read-only and System attributes is only used by Windows Explorer to determine + // whether the folder is a special folder, such as a system folder that has its view + // customized by Windows (for example, My Documents, Favorites, Fonts, Downloaded Program Files), + // or a folder that you customized by using the Customize tab of the folder's Properties dialog box. + // + // As such respecting it on a KIO level is actually wrong as it doesn't indicate actual + // readonlyness since the 90s and causes us to show readonly UI states when in fact + // the directory is perfectly writable. + // https://bugs.kde.org/show_bug.cgi?id=414482 + // + // Should we ever want to parse desktop.ini like we do .directory we'd only want to when a + // dir is readonly as per the above microsoft support article. + // Also see: + // https://docs.microsoft.com/en-us/windows/win32/shell/how-to-customize-folders-with-desktop-ini + udsentry.fastInsert(KIO::UDSEntry::UDS_ACCESS, -1); + + udsentry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, st.st_mode & S_IFMT); + udsentry.fastInsert(KIO::UDSEntry::UDS_SIZE, st.st_size); + udsentry.fastInsert(KIO::UDSEntry::UDS_MODIFICATION_TIME, st.st_mtime); + udsentry.fastInsert(KIO::UDSEntry::UDS_ACCESS_TIME, st.st_atime); + // No, st_ctime is not UDS_CREATION_TIME... + } + + return cacheStatErr; } -//=========================================================================== -void SMBSlave::stat( const QUrl& kurl ) +void SMBSlave::stat(const QUrl &kurl) { qCDebug(KIO_SMB_LOG) << kurl; // make a valid URL QUrl url = checkURL(kurl); // if URL is not valid we have to redirect to correct URL - if (url != kurl) - { + if (url != kurl) { qCDebug(KIO_SMB_LOG) << "redirection " << url; redirection(url); finished(); return; } m_current_url = url; - UDSEntry udsentry; + UDSEntry udsentry; // Set name - udsentry.fastInsert( KIO::UDSEntry::UDS_NAME, kurl.fileName() ); + udsentry.fastInsert(KIO::UDSEntry::UDS_NAME, kurl.fileName()); - switch(m_current_url.getType()) - { + switch (m_current_url.getType()) { case SMBURLTYPE_UNKNOWN: error(ERR_MALFORMED_URL, url.toDisplayString()); return; @@ -167,49 +163,39 @@ finished(); return; - case SMBURLTYPE_SHARE_OR_PATH: - { - int ret = browse_stat_path(m_current_url, udsentry); - - if (ret == EPERM || ret == EACCES || workaroundEEXIST(ret)) - { - SMBUrl smbUrl(url); + case SMBURLTYPE_SHARE_OR_PATH: { + int ret = browse_stat_path(m_current_url, udsentry); - const int passwordError = checkPassword(smbUrl); - if (passwordError == KJob::NoError) - { - redirection(smbUrl); - finished(); - } - else if (passwordError == KIO::ERR_USER_CANCELED) - { - reportError(url, ret); - } - else - { - error(passwordError, url.toString()); - } + if (ret == EPERM || ret == EACCES || workaroundEEXIST(ret)) { + SMBUrl smbUrl(url); - return; - } - else if (ret != 0) - { - qCDebug(KIO_SMB_LOG) << "stat() error" << ret << url; + const int passwordError = checkPassword(smbUrl); + if (passwordError == KJob::NoError) { + redirection(smbUrl); + finished(); + } else if (passwordError == KIO::ERR_USER_CANCELED) { reportError(url, ret); - return; + } else { + error(passwordError, url.toString()); } - statEntry(udsentry); - finished(); + return; + } else if (ret != 0) { + qCDebug(KIO_SMB_LOG) << "stat() error" << ret << url; + reportError(url, ret); return; } + + statEntry(udsentry); + finished(); + return; + } } qCDebug(KIO_SMB_LOG) << "UNKNOWN " << url; finished(); } -//=========================================================================== // TODO: complete checking <-- what does that even mean? // TODO: why is this not part of SMBUrl or at the very least URL validation should // be 100% shared between this and SMBUrl. Notably SMBUrl has code that looks @@ -229,7 +215,7 @@ } QString surl = kurl.url(); - //transform any links in the form smb:/ into smb:// + // transform any links in the form smb:/ into smb:// if (surl.startsWith(QLatin1String("smb:/"))) { if (surl.length() == 5) { return QUrl("smb://"); @@ -241,26 +227,26 @@ } } if (surl == QLatin1String("smb://")) { - return kurl; //unchanged + return kurl; // unchanged } // smb:// normally have no userinfo // we must redirect ourself to remove the username and password if (surl.contains('@') && !surl.contains("smb://")) { QUrl url(kurl); - url.setPath('/'+kurl.url().right( kurl.url().length()-kurl.url().indexOf('@') -1)); - QString userinfo = kurl.url().mid(5, kurl.url().indexOf('@')-5); - if(userinfo.contains(':')) { + url.setPath('/' + kurl.url().right(kurl.url().length() - kurl.url().indexOf('@') - 1)); + QString userinfo = kurl.url().mid(5, kurl.url().indexOf('@') - 5); + if (userinfo.contains(':')) { url.setUserName(userinfo.left(userinfo.indexOf(':'))); - url.setPassword(userinfo.right(userinfo.length()-userinfo.indexOf(':')-1)); + url.setPassword(userinfo.right(userinfo.length() - userinfo.indexOf(':') - 1)); } else { url.setUserName(userinfo); } qCDebug(KIO_SMB_LOG) << "checkURL return2 " << url; return url; } - //if there's a valid host, don't have an empty path + // if there's a valid host, don't have an empty path QUrl url(kurl); if (url.path().isEmpty()) @@ -274,359 +260,327 @@ { qCDebug(KIO_SMB_LOG) << "errNum" << errNum; - switch(errNum) - { + switch (errNum) { case ENOENT: if (url.getType() == SMBURLTYPE_ENTIRE_NETWORK) - return SMBError{ ERR_SLAVE_DEFINED, i18n("Unable to find any workgroups in your local network. This might be caused by an enabled firewall.") }; + return SMBError {ERR_SLAVE_DEFINED, i18n("Unable to find any workgroups in your local network. This might be caused by an enabled firewall.")}; else - return SMBError{ ERR_DOES_NOT_EXIST, url.toDisplayString() }; + return SMBError {ERR_DOES_NOT_EXIST, url.toDisplayString()}; #ifdef ENOMEDIUM case ENOMEDIUM: - return SMBError{ ERR_SLAVE_DEFINED, i18n("No media in device for %1", url.toDisplayString()) }; + return SMBError {ERR_SLAVE_DEFINED, i18n("No media in device for %1", url.toDisplayString())}; #endif #ifdef EHOSTDOWN case EHOSTDOWN: #endif case ECONNREFUSED: - return SMBError{ ERR_SLAVE_DEFINED, i18n("Could not connect to host for %1", url.toDisplayString()) }; + return SMBError {ERR_SLAVE_DEFINED, i18n("Could not connect to host for %1", url.toDisplayString())}; case ENOTDIR: - return SMBError{ ERR_CANNOT_ENTER_DIRECTORY, url.toDisplayString() }; + return SMBError {ERR_CANNOT_ENTER_DIRECTORY, url.toDisplayString()}; case EFAULT: case EINVAL: - return SMBError{ ERR_DOES_NOT_EXIST, url.toDisplayString() }; + return SMBError {ERR_DOES_NOT_EXIST, url.toDisplayString()}; case EPERM: case EACCES: - return SMBError{ ERR_ACCESS_DENIED, url.toDisplayString() }; + return SMBError {ERR_ACCESS_DENIED, url.toDisplayString()}; case EIO: case ENETUNREACH: - if ( url.getType() == SMBURLTYPE_ENTIRE_NETWORK || url.getType() == SMBURLTYPE_WORKGROUP_OR_SERVER ) - return SMBError{ ERR_SLAVE_DEFINED, i18n("Error while connecting to server responsible for %1", url.toDisplayString()) }; + if (url.getType() == SMBURLTYPE_ENTIRE_NETWORK || url.getType() == SMBURLTYPE_WORKGROUP_OR_SERVER) + return SMBError {ERR_SLAVE_DEFINED, i18n("Error while connecting to server responsible for %1", url.toDisplayString())}; else - return SMBError{ ERR_CONNECTION_BROKEN, url.toDisplayString() }; + return SMBError {ERR_CONNECTION_BROKEN, url.toDisplayString()}; case ENOMEM: - return SMBError{ ERR_OUT_OF_MEMORY, url.toDisplayString() }; + return SMBError {ERR_OUT_OF_MEMORY, url.toDisplayString()}; case ENODEV: - return SMBError{ ERR_SLAVE_DEFINED, i18n("Share could not be found on given server") }; + return SMBError {ERR_SLAVE_DEFINED, i18n("Share could not be found on given server")}; case EBADF: - return SMBError{ ERR_INTERNAL, i18n("Bad file descriptor") }; + return SMBError {ERR_INTERNAL, i18n("Bad file descriptor")}; case ETIMEDOUT: - return SMBError{ ERR_SERVER_TIMEOUT, url.host() }; + return SMBError {ERR_SERVER_TIMEOUT, url.host()}; case ENOTEMPTY: - return SMBError{ ERR_CANNOT_RMDIR, url.toDisplayString() }; + return SMBError {ERR_CANNOT_RMDIR, url.toDisplayString()}; #ifdef ENOTUNIQ case ENOTUNIQ: - return SMBError{ ERR_SLAVE_DEFINED, i18n("The given name could not be resolved to a unique server. " - "Make sure your network is setup without any name conflicts " - "between names used by Windows and by UNIX name resolution." ) }; + return SMBError {ERR_SLAVE_DEFINED, + i18n("The given name could not be resolved to a unique server. " + "Make sure your network is setup without any name conflicts " + "between names used by Windows and by UNIX name resolution.")}; #endif case ECONNABORTED: - return SMBError{ ERR_CONNECTION_BROKEN, url.host() }; + return SMBError {ERR_CONNECTION_BROKEN, url.host()}; case EHOSTUNREACH: - return SMBError{ ERR_CANNOT_CONNECT, - i18nc("@info:status smb failed to reach the server (e.g. server offline or network failure). %1 is an ip address or hostname", - "%1: Host unreachable", - url.host()) }; + return SMBError {ERR_CANNOT_CONNECT, i18nc("@info:status smb failed to reach the server (e.g. server offline or network failure). %1 is an ip address or hostname", "%1: Host unreachable", url.host())}; case 0: // success - return SMBError{ ERR_INTERNAL, i18n("libsmbclient reported an error, but did not specify " - "what the problem is. This might indicate a severe problem " - "with your network - but also might indicate a problem with " - "libsmbclient.\n" - "If you want to help us, please provide a tcpdump of the " - "network interface while you try to browse (be aware that " - "it might contain private data, so do not post it if you are " - "unsure about that - you can send it privately to the developers " - "if they ask for it)") }; + return SMBError {ERR_INTERNAL, + i18n("libsmbclient reported an error, but did not specify " + "what the problem is. This might indicate a severe problem " + "with your network - but also might indicate a problem with " + "libsmbclient.\n" + "If you want to help us, please provide a tcpdump of the " + "network interface while you try to browse (be aware that " + "it might contain private data, so do not post it if you are " + "unsure about that - you can send it privately to the developers " + "if they ask for it)")}; default: - return SMBError{ ERR_INTERNAL, i18n("Unknown error condition in stat: %1", QString::fromLocal8Bit( strerror(errNum))) }; + return SMBError {ERR_INTERNAL, i18n("Unknown error condition in stat: %1", QString::fromLocal8Bit(strerror(errNum)))}; } } -void SMBSlave::reportError(const SMBUrl& url, const int errNum) +void SMBSlave::reportError(const SMBUrl &url, const int errNum) { const SMBError smbErr = errnumToKioError(url, errNum); error(smbErr.kioErrorId, smbErr.errorString); } -void SMBSlave::reportWarning(const SMBUrl& url, const int errNum) +void SMBSlave::reportWarning(const SMBUrl &url, const int errNum) { const SMBError smbErr = errnumToKioError(url, errNum); const QString errorString = buildErrorString(smbErr.kioErrorId, smbErr.errorString); warning(xi18n("Error occurred while trying to access %1%2", url.url(), errorString)); } -//=========================================================================== -void SMBSlave::listDir( const QUrl& kurl ) +void SMBSlave::listDir(const QUrl &kurl) { - qCDebug(KIO_SMB_LOG) << kurl; - int errNum = 0; - - // check (correct) URL - QUrl url = checkURL(kurl); - // if URL is not valid we have to redirect to correct URL - if (url != kurl) - { - redirection(url); - finished(); - return; - } - - m_current_url = kurl; - - struct smbc_dirent *dirp = nullptr; - UDSEntry udsentry; - bool dir_is_root = true; - - int dirfd = smbc_opendir( m_current_url.toSmbcUrl() ); - if (dirfd > 0){ - errNum = 0; - } else { - errNum = errno; - } - - qCDebug(KIO_SMB_LOG) << "open " << m_current_url.toSmbcUrl() << " " << m_current_url.getType() << " " << dirfd; - if(dirfd >= 0) - { - uint direntCount = 0; - do { - qCDebug(KIO_SMB_LOG) << "smbc_readdir "; - dirp = smbc_readdir(dirfd); - if(dirp == nullptr) - break; - - ++direntCount; - - // Set name - QString udsName; - const QString dirpName = QString::fromUtf8( dirp->name ); - // We cannot trust dirp->commentlen has it might be with or without the NUL character - // See KDE bug #111430 and Samba bug #3030 - const QString comment = QString::fromUtf8( dirp->comment ); - if ( dirp->smbc_type == SMBC_SERVER || dirp->smbc_type == SMBC_WORKGROUP ) { - udsName = dirpName.toLower(); - udsName[0] = dirpName.at( 0 ).toUpper(); - if ( !comment.isEmpty() && dirp->smbc_type == SMBC_SERVER ) - udsName += " (" + comment + ')'; - } else - udsName = dirpName; - - qCDebug(KIO_SMB_LOG) << "dirp->name " << dirp->name << " " << dirpName << " '" << comment << "'" << " " << dirp->smbc_type; - - udsentry.fastInsert( KIO::UDSEntry::UDS_NAME, udsName ); - udsentry.fastInsert(KIO::UDSEntry::UDS_COMMENT, QString::fromUtf8(dirp->comment)); - - // Mark all administrative shares, e.g ADMIN$, as hidden. #197903 - if (dirpName.endsWith(QLatin1Char('$'))) { - //qCDebug(KIO_SMB_LOG) << dirpName << "marked as hidden"; - udsentry.fastInsert(KIO::UDSEntry::UDS_HIDDEN, 1); - } - - if (udsName == ".") - { - // Skip the "." entry - // Mind the way m_current_url is handled in the loop - } - else if (udsName == "..") - { - dir_is_root = false; - // fprintf(stderr,"----------- hide: -%s-\n",dirp->name); - // do nothing and hide the hidden shares - } - else if (dirp->smbc_type == SMBC_FILE || - dirp->smbc_type == SMBC_DIR) - { - // Set stat information - m_current_url.addPath(dirpName); - const int statErr = browse_stat_path(m_current_url, udsentry); - if (statErr) - { - if (statErr == ENOENT || statErr == ENOTDIR) - { - reportWarning(m_current_url, statErr); - } - } - else - { - // Call base class to list entry - listEntry(udsentry); - } - m_current_url.cd(".."); - } - else if(dirp->smbc_type == SMBC_SERVER || - dirp->smbc_type == SMBC_FILE_SHARE) - { - // Set type - udsentry.fastInsert( KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR ); - - - if (dirp->smbc_type == SMBC_SERVER) { - udsentry.fastInsert(KIO::UDSEntry::UDS_ACCESS, (S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)); - - // QString workgroup = m_current_url.host().toUpper(); - QUrl u("smb://"); - u.setHost(dirpName); - - // when libsmbclient knows - // u = QString("smb://%1?WORKGROUP=%2").arg(dirpName).arg(workgroup.toUpper()); - qCDebug(KIO_SMB_LOG) << "list item " << u; - udsentry.fastInsert(KIO::UDSEntry::UDS_URL, u.url()); - - udsentry.fastInsert(KIO::UDSEntry::UDS_MIME_TYPE, QString::fromLatin1("application/x-smb-server")); - } else - udsentry.fastInsert(KIO::UDSEntry::UDS_ACCESS, (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); - - - // Call base class to list entry - listEntry(udsentry); - } - else if(dirp->smbc_type == SMBC_WORKGROUP) - { - // Set type - udsentry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); - - // Set permissions - udsentry.fastInsert(KIO::UDSEntry::UDS_ACCESS, (S_IRUSR | S_IRGRP | S_IROTH | S_IXUSR | S_IXGRP | S_IXOTH)); - - udsentry.fastInsert(KIO::UDSEntry::UDS_MIME_TYPE, QString::fromLatin1("application/x-smb-workgroup")); - - // QString workgroup = m_current_url.host().toUpper(); - QUrl u("smb://"); - u.setHost(dirpName); - udsentry.fastInsert(KIO::UDSEntry::UDS_URL, u.url()); - - // Call base class to list entry - listEntry(udsentry); - } - else - { - qCDebug(KIO_SMB_LOG) << "SMBC_UNKNOWN :" << dirpName; - // TODO: we don't handle SMBC_IPC_SHARE, SMBC_PRINTER_SHARE - // SMBC_LINK, SMBC_COMMS_SHARE - //SlaveBase::error(ERR_INTERNAL, TEXT_UNSUPPORTED_FILE_TYPE); - // continue; - } - udsentry.clear(); - } while (dirp); // checked already in the head - - // Run service discovery if the path is root. This augments - // "native" results from libsmbclient. - auto normalizedUrl = url.adjusted(QUrl::NormalizePathSegments); - if (normalizedUrl.path().isEmpty()) { - qCDebug(KIO_SMB_LOG) << "Trying modern discovery (dnssd/wsdiscovery)"; - - QEventLoop e; - - UDSEntryList list; - - const auto flushEntries = [this, &list]() { - if (list.isEmpty()) { - return; - } - listEntries(list); - list.clear(); - }; - - const auto quitLoop = [&e, &flushEntries]() { - flushEntries(); - e.quit(); - }; - - // Since slavebase has no eventloop it wont publish results - // on a timer, since we do not know how long our discovery - // will take this is super meh because we may appear - // stuck for a while. Implement our own listing system - // based on QTimer to mitigate. - QTimer sendTimer; - sendTimer.setInterval(300); - connect(&sendTimer, &QTimer::timeout, this, flushEntries); - sendTimer.start(); - - DNSSDDiscoverer d; - WSDiscoverer w; - - const QList discoverers {&d, &w}; - - auto appendDiscovery = [&](const Discovery::Ptr &discovery) { - list.append(discovery->toEntry()); - }; - - auto maybeFinished = [&] { // finishes if all discoveries finished - bool allFinished = true; - for (auto discoverer : discoverers) { - allFinished = allFinished && discoverer->isFinished(); - } - if (allFinished) { - quitLoop(); - } - }; - - connect(&d, &DNSSDDiscoverer::newDiscovery, this, appendDiscovery); - connect(&w, &WSDiscoverer::newDiscovery, this, appendDiscovery); - - connect(&d, &DNSSDDiscoverer::finished, this, maybeFinished); - connect(&w, &WSDiscoverer::finished, this, maybeFinished); - - d.start(); - w.start(); - - QTimer::singleShot(16000, &e, quitLoop); // max execution time! - e.exec(); - - qCDebug(KIO_SMB_LOG) << "Modern discovery finished."; - } - - if (dir_is_root) { - udsentry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); - udsentry.fastInsert(KIO::UDSEntry::UDS_NAME, "."); - udsentry.fastInsert(KIO::UDSEntry::UDS_ACCESS, (S_IRUSR | S_IRGRP | S_IROTH | S_IXUSR | S_IXGRP | S_IXOTH)); - } - else - { - udsentry.fastInsert(KIO::UDSEntry::UDS_NAME, "."); - const int statErr = browse_stat_path(m_current_url, udsentry); - if (statErr) - { - if (statErr == ENOENT || statErr == ENOTDIR) - { - reportWarning(m_current_url, statErr); - } - // Create a default UDSEntry if we could not stat the actual directory - udsentry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); - udsentry.fastInsert(KIO::UDSEntry::UDS_ACCESS, (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); - } - } - listEntry(udsentry); - udsentry.clear(); - - // clean up - smbc_closedir(dirfd); - } - else - { - if (errNum == EPERM || errNum == EACCES || workaroundEEXIST(errNum)) { - const int passwordError = checkPassword(m_current_url); - if (passwordError == KJob::NoError) { - redirection( m_current_url ); - finished(); - } else if (passwordError == KIO::ERR_USER_CANCELED) { - reportError(m_current_url, errNum); - } else { - error(passwordError, m_current_url.toString()); - } - - return; - } - - reportError(m_current_url, errNum); - return; - } - - finished(); + qCDebug(KIO_SMB_LOG) << kurl; + int errNum = 0; + + // check (correct) URL + QUrl url = checkURL(kurl); + // if URL is not valid we have to redirect to correct URL + if (url != kurl) { + redirection(url); + finished(); + return; + } + + m_current_url = kurl; + + struct smbc_dirent *dirp = nullptr; + UDSEntry udsentry; + bool dir_is_root = true; + + int dirfd = smbc_opendir(m_current_url.toSmbcUrl()); + if (dirfd > 0) { + errNum = 0; + } else { + errNum = errno; + } + + qCDebug(KIO_SMB_LOG) << "open " << m_current_url.toSmbcUrl() << " " << m_current_url.getType() << " " << dirfd; + if (dirfd >= 0) { + uint direntCount = 0; + do { + qCDebug(KIO_SMB_LOG) << "smbc_readdir "; + dirp = smbc_readdir(dirfd); + if (dirp == nullptr) + break; + + ++direntCount; + + // Set name + QString udsName; + const QString dirpName = QString::fromUtf8(dirp->name); + // We cannot trust dirp->commentlen has it might be with or without the NUL character + // See KDE bug #111430 and Samba bug #3030 + const QString comment = QString::fromUtf8(dirp->comment); + if (dirp->smbc_type == SMBC_SERVER || dirp->smbc_type == SMBC_WORKGROUP) { + udsName = dirpName.toLower(); + udsName[0] = dirpName.at(0).toUpper(); + if (!comment.isEmpty() && dirp->smbc_type == SMBC_SERVER) + udsName += " (" + comment + ')'; + } else + udsName = dirpName; + + qCDebug(KIO_SMB_LOG) << "dirp->name " << dirp->name << " " << dirpName << " '" << comment << "'" << " " << dirp->smbc_type; + + udsentry.fastInsert(KIO::UDSEntry::UDS_NAME, udsName); + udsentry.fastInsert(KIO::UDSEntry::UDS_COMMENT, QString::fromUtf8(dirp->comment)); + + // Mark all administrative shares, e.g ADMIN$, as hidden. #197903 + if (dirpName.endsWith(QLatin1Char('$'))) { + // qCDebug(KIO_SMB_LOG) << dirpName << "marked as hidden"; + udsentry.fastInsert(KIO::UDSEntry::UDS_HIDDEN, 1); + } + + if (udsName == ".") { + // Skip the "." entry + // Mind the way m_current_url is handled in the loop + } else if (udsName == "..") { + dir_is_root = false; + // fprintf(stderr,"----------- hide: -%s-\n",dirp->name); + // do nothing and hide the hidden shares + } else if (dirp->smbc_type == SMBC_FILE || dirp->smbc_type == SMBC_DIR) { + // Set stat information + m_current_url.addPath(dirpName); + const int statErr = browse_stat_path(m_current_url, udsentry); + if (statErr) { + if (statErr == ENOENT || statErr == ENOTDIR) { + reportWarning(m_current_url, statErr); + } + } else { + // Call base class to list entry + listEntry(udsentry); + } + m_current_url.cd(".."); + } else if (dirp->smbc_type == SMBC_SERVER || dirp->smbc_type == SMBC_FILE_SHARE) { + // Set type + udsentry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); + + if (dirp->smbc_type == SMBC_SERVER) { + udsentry.fastInsert(KIO::UDSEntry::UDS_ACCESS, (S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)); + + // QString workgroup = m_current_url.host().toUpper(); + QUrl u("smb://"); + u.setHost(dirpName); + + // when libsmbclient knows + // u = QString("smb://%1?WORKGROUP=%2").arg(dirpName).arg(workgroup.toUpper()); + qCDebug(KIO_SMB_LOG) << "list item " << u; + udsentry.fastInsert(KIO::UDSEntry::UDS_URL, u.url()); + + udsentry.fastInsert(KIO::UDSEntry::UDS_MIME_TYPE, QString::fromLatin1("application/x-smb-server")); + } else + udsentry.fastInsert(KIO::UDSEntry::UDS_ACCESS, (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); + + // Call base class to list entry + listEntry(udsentry); + } else if (dirp->smbc_type == SMBC_WORKGROUP) { + // Set type + udsentry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); + + // Set permissions + udsentry.fastInsert(KIO::UDSEntry::UDS_ACCESS, (S_IRUSR | S_IRGRP | S_IROTH | S_IXUSR | S_IXGRP | S_IXOTH)); + + udsentry.fastInsert(KIO::UDSEntry::UDS_MIME_TYPE, QString::fromLatin1("application/x-smb-workgroup")); + + // QString workgroup = m_current_url.host().toUpper(); + QUrl u("smb://"); + u.setHost(dirpName); + udsentry.fastInsert(KIO::UDSEntry::UDS_URL, u.url()); + + // Call base class to list entry + listEntry(udsentry); + } else { + qCDebug(KIO_SMB_LOG) << "SMBC_UNKNOWN :" << dirpName; + // TODO: we don't handle SMBC_IPC_SHARE, SMBC_PRINTER_SHARE + // SMBC_LINK, SMBC_COMMS_SHARE + // SlaveBase::error(ERR_INTERNAL, TEXT_UNSUPPORTED_FILE_TYPE); + // continue; + } + udsentry.clear(); + } while (dirp); // checked already in the head + + // Run service discovery if the path is root. This augments + // "native" results from libsmbclient. + auto normalizedUrl = url.adjusted(QUrl::NormalizePathSegments); + if (normalizedUrl.path().isEmpty()) { + qCDebug(KIO_SMB_LOG) << "Trying modern discovery (dnssd/wsdiscovery)"; + + QEventLoop e; + + UDSEntryList list; + + const auto flushEntries = [this, &list]() { + if (list.isEmpty()) { + return; + } + listEntries(list); + list.clear(); + }; + + const auto quitLoop = [&e, &flushEntries]() { + flushEntries(); + e.quit(); + }; + + // Since slavebase has no eventloop it wont publish results + // on a timer, since we do not know how long our discovery + // will take this is super meh because we may appear + // stuck for a while. Implement our own listing system + // based on QTimer to mitigate. + QTimer sendTimer; + sendTimer.setInterval(300); + connect(&sendTimer, &QTimer::timeout, this, flushEntries); + sendTimer.start(); + + DNSSDDiscoverer d; + WSDiscoverer w; + + const QList discoverers {&d, &w}; + + auto appendDiscovery = [&](const Discovery::Ptr &discovery) { list.append(discovery->toEntry()); }; + + auto maybeFinished = [&] { // finishes if all discoveries finished + bool allFinished = true; + for (auto discoverer : discoverers) { + allFinished = allFinished && discoverer->isFinished(); + } + if (allFinished) { + quitLoop(); + } + }; + + connect(&d, &DNSSDDiscoverer::newDiscovery, this, appendDiscovery); + connect(&w, &WSDiscoverer::newDiscovery, this, appendDiscovery); + + connect(&d, &DNSSDDiscoverer::finished, this, maybeFinished); + connect(&w, &WSDiscoverer::finished, this, maybeFinished); + + d.start(); + w.start(); + + QTimer::singleShot(16000, &e, quitLoop); // max execution time! + e.exec(); + + qCDebug(KIO_SMB_LOG) << "Modern discovery finished."; + } + + if (dir_is_root) { + udsentry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); + udsentry.fastInsert(KIO::UDSEntry::UDS_NAME, "."); + udsentry.fastInsert(KIO::UDSEntry::UDS_ACCESS, (S_IRUSR | S_IRGRP | S_IROTH | S_IXUSR | S_IXGRP | S_IXOTH)); + } else { + udsentry.fastInsert(KIO::UDSEntry::UDS_NAME, "."); + const int statErr = browse_stat_path(m_current_url, udsentry); + if (statErr) { + if (statErr == ENOENT || statErr == ENOTDIR) { + reportWarning(m_current_url, statErr); + } + // Create a default UDSEntry if we could not stat the actual directory + udsentry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); + udsentry.fastInsert(KIO::UDSEntry::UDS_ACCESS, (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); + } + } + listEntry(udsentry); + udsentry.clear(); + + // clean up + smbc_closedir(dirfd); + } else { + if (errNum == EPERM || errNum == EACCES || workaroundEEXIST(errNum)) { + const int passwordError = checkPassword(m_current_url); + if (passwordError == KJob::NoError) { + redirection(m_current_url); + finished(); + } else if (passwordError == KIO::ERR_USER_CANCELED) { + reportError(m_current_url, errNum); + } else { + error(passwordError, m_current_url.toString()); + } + + return; + } + + reportError(m_current_url, errNum); + return; + } + + finished(); } -void SMBSlave::fileSystemFreeSpace(const QUrl& url) +void SMBSlave::fileSystemFreeSpace(const QUrl &url) { qCDebug(KIO_SMB_LOG) << url; @@ -640,12 +594,13 @@ SMBUrl smbcUrl = url; - struct statvfs dirStat{}; + struct statvfs dirStat { + }; memset(&dirStat, 0, sizeof(struct statvfs)); const int err = smbc_statvfs(smbcUrl.toSmbcUrl().data(), &dirStat); if (err < 0) { - error(KIO::ERR_CANNOT_STAT, url.url()); - return; + error(KIO::ERR_CANNOT_STAT, url.url()); + return; } // libsmb_stat.c has very awkward conditional branching that results @@ -660,7 +615,7 @@ // at least behaving as described though. // https://bugs.kde.org/show_bug.cgi?id=298801 const auto frames = (dirStat.f_frsize == 0) ? 1 : dirStat.f_frsize; - const auto blockSize = dirStat.f_bsize * frames; + const auto blockSize = dirStat.f_bsize * frames; // Further more on older versions of samba f_bavail may not be set... const auto total = blockSize * dirStat.f_blocks; const auto available = blockSize * ((dirStat.f_bavail != 0) ? dirStat.f_bavail : dirStat.f_bfree); @@ -675,4 +630,3 @@ { return (errNum == EEXIST) && m_enableEEXISTWorkaround; } - diff --git a/smb/kio_smb_config.cpp b/smb/kio_smb_config.cpp --- a/smb/kio_smb_config.cpp +++ b/smb/kio_smb_config.cpp @@ -35,31 +35,30 @@ #include #include -//=========================================================================== + void SMBSlave::reparseConfiguration() { - KConfig cfg("kioslaverc", KConfig::NoGlobals); - const KConfigGroup group = cfg.group("Browser Settings/SMBro"); - m_default_user = group.readEntry("User"); -// m_default_workgroup=group.readEntry("Workgroup"); -// m_showHiddenShares=group.readEntry("ShowHiddenShares", QVariant(false)).toBool(); + KConfig cfg("kioslaverc", KConfig::NoGlobals); + const KConfigGroup group = cfg.group("Browser Settings/SMBro"); + m_default_user = group.readEntry("User"); + // m_default_workgroup=group.readEntry("Workgroup"); + // m_showHiddenShares=group.readEntry("ShowHiddenShares", QVariant(false)).toBool(); - QString m_encoding = QTextCodec::codecForLocale()->name(); - m_default_encoding = group.readEntry( "Encoding", m_encoding.toLower() ); + QString m_encoding = QTextCodec::codecForLocale()->name(); + m_default_encoding = group.readEntry("Encoding", m_encoding.toLower()); - // unscramble, taken from Nicola Brodu's smb ioslave - //not really secure, but better than storing the plain password - QString scrambled = group.readEntry( "Password" ); - m_default_password = ""; - for (int i=0; i #include #include -#include #include #include -//=========================================================================== -void SMBSlave::copy(const QUrl& src, const QUrl& dst, int permissions, KIO::JobFlags flags) +void SMBSlave::copy(const QUrl &src, const QUrl &dst, int permissions, KIO::JobFlags flags) { const bool isSourceLocal = src.isLocalFile(); const bool isDestinationLocal = dst.isLocalFile(); @@ -54,228 +53,190 @@ } } -void SMBSlave::smbCopy(const QUrl& ksrc, const QUrl& kdst, int permissions, KIO::JobFlags flags) +void SMBSlave::smbCopy(const QUrl &ksrc, const QUrl &kdst, int permissions, KIO::JobFlags flags) { - - SMBUrl src; - SMBUrl dst; - mode_t initialmode; - ssize_t n; - int dstflags; - int srcfd = -1; - int dstfd = -1; - int errNum = 0; + SMBUrl src; + SMBUrl dst; + mode_t initialmode; + ssize_t n; + int dstflags; + int srcfd = -1; + int dstfd = -1; + int errNum = 0; KIO::filesize_t processed_size = 0; - unsigned char buf[MAX_XFER_BUF_SIZE]; + unsigned char buf[MAX_XFER_BUF_SIZE]; qCDebug(KIO_SMB_LOG) << "SMBSlave::copy with src = " << ksrc << "and dest = " << kdst; // setup urls src = ksrc; dst = kdst; // Obtain information about source - errNum = cache_stat(src, &st ); - if( errNum != 0 ) - { - if ( errNum == EACCES ) - { - error( KIO::ERR_ACCESS_DENIED, src.toDisplayString()); - } - else - { - error( KIO::ERR_DOES_NOT_EXIST, src.toDisplayString()); + errNum = cache_stat(src, &st); + if (errNum != 0) { + if (errNum == EACCES) { + error(KIO::ERR_ACCESS_DENIED, src.toDisplayString()); + } else { + error(KIO::ERR_DOES_NOT_EXIST, src.toDisplayString()); } return; } - if ( S_ISDIR( st.st_mode ) ) - { - error( KIO::ERR_IS_DIRECTORY, src.toDisplayString() ); + if (S_ISDIR(st.st_mode)) { + error(KIO::ERR_IS_DIRECTORY, src.toDisplayString()); return; } totalSize(st.st_size); // Check to se if the destination exists errNum = cache_stat(dst, &st); - if( errNum == 0 ) - { - if(S_ISDIR(st.st_mode)) - { - error( KIO::ERR_DIR_ALREADY_EXIST, dst.toDisplayString()); - return; + if (errNum == 0) { + if (S_ISDIR(st.st_mode)) { + error(KIO::ERR_DIR_ALREADY_EXIST, dst.toDisplayString()); + return; + } + if (!(flags & KIO::Overwrite)) { + error(KIO::ERR_FILE_ALREADY_EXIST, dst.toDisplayString()); + return; } - if(!(flags & KIO::Overwrite)) - { - error( KIO::ERR_FILE_ALREADY_EXIST, dst.toDisplayString()); - return; - } } // Open the source file srcfd = smbc_open(src.toSmbcUrl(), O_RDONLY, 0); - if (srcfd < 0){ + if (srcfd < 0) { errNum = errno; } else { errNum = 0; } - if(srcfd < 0) - { - if(errNum == EACCES) - { - error( KIO::ERR_ACCESS_DENIED, src.toDisplayString() ); - } - else - { - error( KIO::ERR_DOES_NOT_EXIST, src.toDisplayString() ); + if (srcfd < 0) { + if (errNum == EACCES) { + error(KIO::ERR_ACCESS_DENIED, src.toDisplayString()); + } else { + error(KIO::ERR_DOES_NOT_EXIST, src.toDisplayString()); } - return; + return; } // Determine initial creation mode - if(permissions != -1) - { + if (permissions != -1) { initialmode = permissions | S_IWUSR; + } else { + initialmode = 0 | S_IWUSR; // 0666; } - else - { - initialmode = 0 | S_IWUSR;//0666; - } - // Open the destination file dstflags = O_CREAT | O_TRUNC | O_WRONLY; - if(!(flags & KIO::Overwrite)) - { + if (!(flags & KIO::Overwrite)) { dstflags |= O_EXCL; } dstfd = smbc_open(dst.toSmbcUrl(), dstflags, initialmode); - if (dstfd < 0){ + if (dstfd < 0) { errNum = errno; } else { errNum = 0; } - if(dstfd < 0) - { - if(errNum == EACCES) - { + if (dstfd < 0) { + if (errNum == EACCES) { error(KIO::ERR_WRITE_ACCESS_DENIED, dst.toDisplayString()); - } - else - { + } else { error(KIO::ERR_CANNOT_OPEN_FOR_READING, dst.toDisplayString()); } - if(srcfd >= 0 ) - { + if (srcfd >= 0) { smbc_close(srcfd); } return; } - // Perform copy while (true) { - n = smbc_read(srcfd, buf, MAX_XFER_BUF_SIZE ); - if(n > 0) - { + n = smbc_read(srcfd, buf, MAX_XFER_BUF_SIZE); + if (n > 0) { n = smbc_write(dstfd, buf, n); - if(n == -1) - { - qCDebug(KIO_SMB_LOG) << "SMBSlave::copy copy now KIO::ERR_CANNOT_WRITE"; - error( KIO::ERR_CANNOT_WRITE, dst.toDisplayString()); + if (n == -1) { + qCDebug(KIO_SMB_LOG) << "SMBSlave::copy copy now KIO::ERR_CANNOT_WRITE"; + error(KIO::ERR_CANNOT_WRITE, dst.toDisplayString()); break; } processed_size += n; - processedSize(processed_size); - } - else if(n == 0) - { - break; // finished - } - else - { - error( KIO::ERR_CANNOT_READ, src.toDisplayString()); - break; + processedSize(processed_size); + } else if (n == 0) { + break; // finished + } else { + error(KIO::ERR_CANNOT_READ, src.toDisplayString()); + break; } } - // FINISHED: - if(srcfd >= 0 ) - { + if (srcfd >= 0) { smbc_close(srcfd); } - if(dstfd >= 0) - { - if(smbc_close(dstfd) == 0) - { - + if (dstfd >= 0) { + if (smbc_close(dstfd) == 0) { // TODO: set final permissions - } - else - { - error( KIO::ERR_CANNOT_WRITE, dst.toDisplayString()); - return; + } else { + error(KIO::ERR_CANNOT_WRITE, dst.toDisplayString()); + return; } } finished(); } -void SMBSlave::smbCopyGet(const QUrl& ksrc, const QUrl& kdst, int permissions, KIO::JobFlags flags) +void SMBSlave::smbCopyGet(const QUrl &ksrc, const QUrl &kdst, int permissions, KIO::JobFlags flags) { qCDebug(KIO_SMB_LOG) << "src = " << ksrc << ", dest = " << kdst; // check if destination is ok ... const QString dstFile = kdst.toLocalFile(); - const QFileInfo dstInfo (dstFile); + const QFileInfo dstInfo(dstFile); - if(dstInfo.exists()) { - if(dstInfo.isDir()) { - error (ERR_IS_DIRECTORY, kdst.toDisplayString()); + if (dstInfo.exists()) { + if (dstInfo.isDir()) { + error(ERR_IS_DIRECTORY, kdst.toDisplayString()); return; } - if(!(flags & KIO::Overwrite)) { + if (!(flags & KIO::Overwrite)) { error(ERR_FILE_ALREADY_EXIST, kdst.toDisplayString()); return; } } bool bResume = false; - const QFileInfo partInfo (dstFile + QLatin1String(".part")); + const QFileInfo partInfo(dstFile + QLatin1String(".part")); const bool bPartExists = partInfo.exists(); const bool bMarkPartial = configValue(QStringLiteral("MarkPartial"), true); if (bMarkPartial && bPartExists && partInfo.size() > 0) { - if (partInfo.isDir()) { - error(ERR_IS_DIRECTORY, partInfo.absoluteFilePath()); - return; - } - bResume = canResume(partInfo.size()); + if (partInfo.isDir()) { + error(ERR_IS_DIRECTORY, partInfo.absoluteFilePath()); + return; + } + bResume = canResume(partInfo.size()); } - if (bPartExists && !bResume) // get rid of an unwanted ".part" file - QFile::remove(partInfo.absoluteFilePath()); + if (bPartExists && !bResume) // get rid of an unwanted ".part" file + QFile::remove(partInfo.absoluteFilePath()); // open the output file... QFile::OpenMode mode; QString filename; if (bResume) { filename = partInfo.absoluteFilePath(); mode = QFile::WriteOnly | QFile::Append; - } - else { + } else { filename = (bMarkPartial ? partInfo.absoluteFilePath() : dstFile); mode = QFile::WriteOnly | QFile::Truncate; } - QFile file (filename); + QFile file(filename); if (!bResume) { QFile::Permissions perms; if (permissions == -1) { @@ -289,47 +250,47 @@ if (!file.open(mode)) { qCDebug(KIO_SMB_LOG) << "could not write to" << dstFile; switch (file.error()) { - case QFile::OpenError: - if (bResume) { - error (ERR_CANNOT_RESUME, kdst.toDisplayString()); - } else { + case QFile::OpenError: + if (bResume) { + error(ERR_CANNOT_RESUME, kdst.toDisplayString()); + } else { error(ERR_CANNOT_OPEN_FOR_WRITING, kdst.toDisplayString()); - } - break; - case QFile::PermissionsError: - error(ERR_WRITE_ACCESS_DENIED, kdst.toDisplayString()); - break; - default: - error(ERR_CANNOT_OPEN_FOR_WRITING, kdst.toDisplayString()); - break; + } + break; + case QFile::PermissionsError: + error(ERR_WRITE_ACCESS_DENIED, kdst.toDisplayString()); + break; + default: + error(ERR_CANNOT_OPEN_FOR_WRITING, kdst.toDisplayString()); + break; } return; } // setup the source urls const SMBUrl src(ksrc); // Obtain information about source - int errNum = cache_stat (src, &st); + int errNum = cache_stat(src, &st); if (errNum != 0) { if (errNum == EACCES) { - error (KIO::ERR_ACCESS_DENIED, src.toDisplayString()); + error(KIO::ERR_ACCESS_DENIED, src.toDisplayString()); } else { - error (KIO::ERR_DOES_NOT_EXIST, src.toDisplayString()); + error(KIO::ERR_DOES_NOT_EXIST, src.toDisplayString()); } return; } - if (S_ISDIR( st.st_mode )) { - error (KIO::ERR_IS_DIRECTORY, src.toDisplayString()); + if (S_ISDIR(st.st_mode)) { + error(KIO::ERR_IS_DIRECTORY, src.toDisplayString()); return; } totalSize(st.st_size); // Open the source file KIO::filesize_t processed_size = 0; int srcfd = smbc_open(src.toSmbcUrl(), O_RDONLY, 0); - if (srcfd < 0){ + if (srcfd < 0) { errNum = errno; } else { errNum = 0; @@ -347,10 +308,10 @@ } if (srcfd < 0) { - if(errNum == EACCES) { - error( KIO::ERR_ACCESS_DENIED, src.toDisplayString() ); + if (errNum == EACCES) { + error(KIO::ERR_ACCESS_DENIED, src.toDisplayString()); } else { - error( KIO::ERR_DOES_NOT_EXIST, src.toDisplayString() ); + error(KIO::ERR_DOES_NOT_EXIST, src.toDisplayString()); } return; } @@ -363,16 +324,16 @@ const ssize_t bytesRead = smbc_read(srcfd, buf, MAX_XFER_BUF_SIZE); if (bytesRead <= 0) { if (bytesRead < 0) { - error( KIO::ERR_CANNOT_READ, src.toDisplayString()); + error(KIO::ERR_CANNOT_READ, src.toDisplayString()); isErr = true; } break; } const qint64 bytesWritten = file.write(buf, bytesRead); if (bytesWritten == -1) { qCDebug(KIO_SMB_LOG) << "copy now KIO::ERR_CANNOT_WRITE"; - error( KIO::ERR_CANNOT_WRITE, kdst.toDisplayString()); + error(KIO::ERR_CANNOT_WRITE, kdst.toDisplayString()); isErr = true; break; } @@ -389,7 +350,7 @@ const QString sPart = partInfo.absoluteFilePath(); if (bMarkPartial) { const int size = configValue(QStringLiteral("MinimumKeepSize"), DEFAULT_MINIMUM_KEEP_SIZE); - if (partInfo.size() < size) { + if (partInfo.size() < size) { QFile::remove(sPart); } } @@ -416,22 +377,23 @@ if (!mtimeStr.isEmpty()) { QDateTime dt = QDateTime::fromString(mtimeStr, Qt::ISODate); if (dt.isValid()) { - struct utimbuf utbuf{}; + struct utimbuf utbuf { + }; utbuf.actime = QFileInfo(dstFile).lastRead().toSecsSinceEpoch(); // access time, unchanged - utbuf.modtime = dt.toSecsSinceEpoch(); // modification time + utbuf.modtime = dt.toSecsSinceEpoch(); // modification time utime(QFile::encodeName(dstFile).constData(), &utbuf); } } finished(); } -void SMBSlave::smbCopyPut(const QUrl& ksrc, const QUrl& kdst, int permissions, KIO::JobFlags flags) +void SMBSlave::smbCopyPut(const QUrl &ksrc, const QUrl &kdst, int permissions, KIO::JobFlags flags) { qCDebug(KIO_SMB_LOG) << "src = " << ksrc << ", dest = " << kdst; - QFile srcFile (ksrc.toLocalFile()); - const QFileInfo srcInfo (srcFile); + QFile srcFile(ksrc.toLocalFile()); + const QFileInfo srcInfo(srcFile); if (srcInfo.exists()) { if (srcInfo.isDir()) { @@ -446,13 +408,13 @@ if (!srcFile.open(QFile::ReadOnly)) { qCDebug(KIO_SMB_LOG) << "could not read from" << ksrc; switch (srcFile.error()) { - case QFile::PermissionsError: - error(KIO::ERR_WRITE_ACCESS_DENIED, ksrc.toDisplayString()); - break; - case QFile::OpenError: - default: - error(KIO::ERR_CANNOT_OPEN_FOR_READING, ksrc.toDisplayString()); - break; + case QFile::PermissionsError: + error(KIO::ERR_WRITE_ACCESS_DENIED, ksrc.toDisplayString()); + break; + case QFile::OpenError: + default: + error(KIO::ERR_CANNOT_OPEN_FOR_READING, ksrc.toDisplayString()); + break; } return; } @@ -462,7 +424,7 @@ bool bResume = false; bool bPartExists = false; const bool bMarkPartial = configValue(QStringLiteral("MarkPartial"), true); - const SMBUrl dstOrigUrl (kdst); + const SMBUrl dstOrigUrl(kdst); if (bMarkPartial) { const int errNum = cache_stat(dstOrigUrl.partUrl(), &st); @@ -481,9 +443,9 @@ if (errNum == 0 && !(flags & KIO::Overwrite) && !(flags & KIO::Resume)) { if (S_ISDIR(st.st_mode)) { - error( KIO::ERR_IS_DIRECTORY, dstOrigUrl.toDisplayString()); + error(KIO::ERR_IS_DIRECTORY, dstOrigUrl.toDisplayString()); } else { - error( KIO::ERR_FILE_ALREADY_EXIST, dstOrigUrl.toDisplayString()); + error(KIO::ERR_FILE_ALREADY_EXIST, dstOrigUrl.toDisplayString()); } return; } @@ -494,7 +456,7 @@ if (bResume) { // append if resuming qCDebug(KIO_SMB_LOG) << "resume" << dstUrl; - dstfd = smbc_open(dstUrl.toSmbcUrl(), O_RDWR, 0 ); + dstfd = smbc_open(dstUrl.toSmbcUrl(), O_RDWR, 0); if (dstfd < 0) { errNum = errno; } else { @@ -525,11 +487,10 @@ if (dstfd < 0) { if (errNum == EACCES) { qCDebug(KIO_SMB_LOG) << "access denied"; - error( KIO::ERR_WRITE_ACCESS_DENIED, dstUrl.toDisplayString()); - } - else { + error(KIO::ERR_WRITE_ACCESS_DENIED, dstUrl.toDisplayString()); + } else { qCDebug(KIO_SMB_LOG) << "can not open for writing"; - error( KIO::ERR_CANNOT_OPEN_FOR_WRITING, dstUrl.toDisplayString()); + error(KIO::ERR_CANNOT_OPEN_FOR_WRITING, dstUrl.toDisplayString()); } return; } @@ -568,7 +529,7 @@ // FINISHED if (smbc_close(dstfd) < 0) { qCDebug(KIO_SMB_LOG) << dstUrl << "could not write"; - error( KIO::ERR_CANNOT_WRITE, dstUrl.toDisplayString()); + error(KIO::ERR_CANNOT_WRITE, dstUrl.toDisplayString()); return; } @@ -596,117 +557,99 @@ #ifdef HAVE_UTIME_H // set modification time - const QString mtimeStr = metaData( "modified" ); - if (!mtimeStr.isEmpty() ) { - QDateTime dt = QDateTime::fromString( mtimeStr, Qt::ISODate ); - if ( dt.isValid() ) { - struct utimbuf utbuf{}; - utbuf.actime = st.st_atime; // access time, unchanged + const QString mtimeStr = metaData("modified"); + if (!mtimeStr.isEmpty()) { + QDateTime dt = QDateTime::fromString(mtimeStr, Qt::ISODate); + if (dt.isValid()) { + struct utimbuf utbuf { + }; + utbuf.actime = st.st_atime; // access time, unchanged utbuf.modtime = dt.toSecsSinceEpoch(); // modification time - smbc_utime( dstOrigUrl.toSmbcUrl(), &utbuf ); + smbc_utime(dstOrigUrl.toSmbcUrl(), &utbuf); } } #endif // We have done our job => finish finished(); } -//=========================================================================== -void SMBSlave::del( const QUrl &kurl, bool isfile) +void SMBSlave::del(const QUrl &kurl, bool isfile) { qCDebug(KIO_SMB_LOG) << kurl; m_current_url = kurl; int errNum = 0; int retVal = 0; - if(isfile) - { + if (isfile) { // Delete file qCDebug(KIO_SMB_LOG) << "Deleting file" << kurl; retVal = smbc_unlink(m_current_url.toSmbcUrl()); - if ( retVal < 0 ){ + if (retVal < 0) { errNum = errno; } else { errNum = 0; } - } - else - { + } else { qCDebug(KIO_SMB_LOG) << "Deleting directory" << kurl; // Delete directory retVal = smbc_rmdir(m_current_url.toSmbcUrl()); - if( retVal < 0 ) { + if (retVal < 0) { errNum = errno; } else { errNum = 0; } } - if( errNum != 0 ) - { + if (errNum != 0) { reportError(kurl, errNum); - } - else - { + } else { finished(); } } -//=========================================================================== -void SMBSlave::mkdir( const QUrl &kurl, int permissions ) +void SMBSlave::mkdir(const QUrl &kurl, int permissions) { qCDebug(KIO_SMB_LOG) << kurl; int errNum = 0; int retVal = 0; m_current_url = kurl; retVal = smbc_mkdir(m_current_url.toSmbcUrl(), 0777); - if( retVal < 0 ){ + if (retVal < 0) { errNum = errno; } else { errNum = 0; } - if( retVal < 0 ) - { + if (retVal < 0) { if (errNum == EEXIST) { - errNum = cache_stat(m_current_url, &st ); - if (errNum == 0 && S_ISDIR(st.st_mode)) - { - error( KIO::ERR_DIR_ALREADY_EXIST, m_current_url.toDisplayString()); - } - else - { - error( KIO::ERR_FILE_ALREADY_EXIST, m_current_url.toDisplayString()); + errNum = cache_stat(m_current_url, &st); + if (errNum == 0 && S_ISDIR(st.st_mode)) { + error(KIO::ERR_DIR_ALREADY_EXIST, m_current_url.toDisplayString()); + } else { + error(KIO::ERR_FILE_ALREADY_EXIST, m_current_url.toDisplayString()); } - } - else - { + } else { reportError(kurl, errNum); } qCDebug(KIO_SMB_LOG) << "exit with error " << kurl; - } - else // success + } else // success { - if(permissions != -1) - { + if (permissions != -1) { // TODO enable the following when complete - //smbc_chmod( url.toSmbcUrl(), permissions ); + // smbc_chmod( url.toSmbcUrl(), permissions ); } finished(); } } - -//=========================================================================== -void SMBSlave::rename( const QUrl& ksrc, const QUrl& kdest, KIO::JobFlags flags ) +void SMBSlave::rename(const QUrl &ksrc, const QUrl &kdest, KIO::JobFlags flags) { - - SMBUrl src; - SMBUrl dst; - int errNum = 0; - int retVal = 0; + SMBUrl src; + SMBUrl dst; + int errNum = 0; + int retVal = 0; qCDebug(KIO_SMB_LOG) << "old name = " << ksrc << ", new name = " << kdest; @@ -717,65 +660,55 @@ qCDebug(KIO_SMB_LOG) << "stat dst"; errNum = cache_stat(dst, &st); - if( errNum == 0 ) - { - if(S_ISDIR(st.st_mode)) - { + if (errNum == 0) { + if (S_ISDIR(st.st_mode)) { qCDebug(KIO_SMB_LOG) << "KIO::ERR_DIR_ALREADY_EXIST"; - error( KIO::ERR_DIR_ALREADY_EXIST, dst.toDisplayString()); + error(KIO::ERR_DIR_ALREADY_EXIST, dst.toDisplayString()); return; } - if(!(flags & KIO::Overwrite)) - { + if (!(flags & KIO::Overwrite)) { qCDebug(KIO_SMB_LOG) << "KIO::ERR_FILE_ALREADY_EXIST"; - error( KIO::ERR_FILE_ALREADY_EXIST, dst.toDisplayString()); + error(KIO::ERR_FILE_ALREADY_EXIST, dst.toDisplayString()); return; } } qCDebug(KIO_SMB_LOG) << "smbc_rename " << src.toSmbcUrl() << " " << dst.toSmbcUrl(); retVal = smbc_rename(src.toSmbcUrl(), dst.toSmbcUrl()); - if( retVal < 0 ){ + if (retVal < 0) { errNum = errno; } else { errNum = 0; } - if( retVal < 0 ) - { - qCDebug(KIO_SMB_LOG) << "failed "; - switch(errNum) - { + if (retVal < 0) { + qCDebug(KIO_SMB_LOG) << "failed "; + switch (errNum) { case ENOENT: - errNum = cache_stat(src, &st); - if( errNum != 0 ) - { - if(errNum == EACCES) - { - qCDebug(KIO_SMB_LOG) << "KIO::ERR_ACCESS_DENIED"; - error(KIO::ERR_ACCESS_DENIED, src.toDisplayString()); - } - else - { - qCDebug(KIO_SMB_LOG) << "KIO::ERR_DOES_NOT_EXIST"; - error(KIO::ERR_DOES_NOT_EXIST, src.toDisplayString()); - } - } - break; + errNum = cache_stat(src, &st); + if (errNum != 0) { + if (errNum == EACCES) { + qCDebug(KIO_SMB_LOG) << "KIO::ERR_ACCESS_DENIED"; + error(KIO::ERR_ACCESS_DENIED, src.toDisplayString()); + } else { + qCDebug(KIO_SMB_LOG) << "KIO::ERR_DOES_NOT_EXIST"; + error(KIO::ERR_DOES_NOT_EXIST, src.toDisplayString()); + } + } + break; case EACCES: case EPERM: - qCDebug(KIO_SMB_LOG) << "KIO::ERR_ACCESS_DENIED"; - error( KIO::ERR_ACCESS_DENIED, dst.toDisplayString() ); - break; + qCDebug(KIO_SMB_LOG) << "KIO::ERR_ACCESS_DENIED"; + error(KIO::ERR_ACCESS_DENIED, dst.toDisplayString()); + break; default: - qCDebug(KIO_SMB_LOG) << "KIO::ERR_CANNOT_RENAME"; - error( KIO::ERR_CANNOT_RENAME, src.toDisplayString() ); - - } + qCDebug(KIO_SMB_LOG) << "KIO::ERR_CANNOT_RENAME"; + error(KIO::ERR_CANNOT_RENAME, src.toDisplayString()); + } - qCDebug(KIO_SMB_LOG) << "exit with error"; - return; + qCDebug(KIO_SMB_LOG) << "exit with error"; + return; } qCDebug(KIO_SMB_LOG) << "everything fine\n"; diff --git a/smb/kio_smb_file.cpp b/smb/kio_smb_file.cpp --- a/smb/kio_smb_file.cpp +++ b/smb/kio_smb_file.cpp @@ -29,28 +29,26 @@ // ///////////////////////////////////////////////////////////////////////////// - #include "kio_smb.h" #include "kio_smb_internal.h" -#include #include #include #include +#include -//=========================================================================== -void SMBSlave::get( const QUrl& kurl ) +void SMBSlave::get(const QUrl &kurl) { - char buf[MAX_XFER_BUF_SIZE]; - int filefd = 0; - int errNum = 0; - ssize_t bytesread = 0; + char buf[MAX_XFER_BUF_SIZE]; + int filefd = 0; + int errNum = 0; + ssize_t bytesread = 0; // time_t curtime = 0; // time_t lasttime = 0; // Disabled durint port to Qt5/KF5. Seems to be unused. // time_t starttime = 0; // Disabled durint port to Qt5/KF5. Seems to be unused. - KIO::filesize_t totalbytesread = 0; - QByteArray filedata; - SMBUrl url; + KIO::filesize_t totalbytesread = 0; + QByteArray filedata; + SMBUrl url; qCDebug(KIO_SMB_LOG) << kurl; @@ -63,56 +61,50 @@ return; } - if(!auth_initialize_smbc()) + if (!auth_initialize_smbc()) return; // Stat url = kurl; - errNum = cache_stat(url,&st); - if( errNum != 0 ) - { - if ( errNum == EACCES ) - error( KIO::ERR_ACCESS_DENIED, url.toDisplayString()); + errNum = cache_stat(url, &st); + if (errNum != 0) { + if (errNum == EACCES) + error(KIO::ERR_ACCESS_DENIED, url.toDisplayString()); else - error( KIO::ERR_DOES_NOT_EXIST, url.toDisplayString()); + error(KIO::ERR_DOES_NOT_EXIST, url.toDisplayString()); return; } - if ( S_ISDIR( st.st_mode ) ) { - error( KIO::ERR_IS_DIRECTORY, url.toDisplayString()); + if (S_ISDIR(st.st_mode)) { + error(KIO::ERR_IS_DIRECTORY, url.toDisplayString()); return; } // Set the total size - totalSize( st.st_size ); + totalSize(st.st_size); // Open and read the file - filefd = smbc_open(url.toSmbcUrl(),O_RDONLY,0); - if(filefd >= 0) - { + filefd = smbc_open(url.toSmbcUrl(), O_RDONLY, 0); + if (filefd >= 0) { bool isFirstPacket = true; // lasttime = starttime = time(NULL); // This seems to be unused.. while (true) { bytesread = smbc_read(filefd, buf, MAX_XFER_BUF_SIZE); - if(bytesread == 0) - { + if (bytesread == 0) { // All done reading break; - } - else if(bytesread < 0) - { - error( KIO::ERR_CANNOT_READ, url.toDisplayString()); + } else if (bytesread < 0) { + error(KIO::ERR_CANNOT_READ, url.toDisplayString()); return; } - filedata = QByteArray::fromRawData(buf,bytesread); - if (isFirstPacket) - { + filedata = QByteArray::fromRawData(buf, bytesread); + if (isFirstPacket) { QMimeDatabase db; QMimeType type = db.mimeTypeForFileNameAndData(url.fileName(), filedata); mimeType(type.name()); isFirstPacket = false; } - data( filedata ); + data(filedata); filedata.clear(); // increment total bytes read @@ -122,24 +114,20 @@ } smbc_close(filefd); - data( QByteArray() ); + data(QByteArray()); processedSize(static_cast(st.st_size)); - } - else - { - error( KIO::ERR_CANNOT_OPEN_FOR_READING, url.toDisplayString()); - return; + } else { + error(KIO::ERR_CANNOT_OPEN_FOR_READING, url.toDisplayString()); + return; } finished(); } - -//=========================================================================== -void SMBSlave::open( const QUrl& kurl, QIODevice::OpenMode mode) +void SMBSlave::open(const QUrl &kurl, QIODevice::OpenMode mode) { - int errNum = 0; + int errNum = 0; qCDebug(KIO_SMB_LOG) << kurl; // check (correct) URL @@ -152,8 +140,8 @@ return; } - if(!auth_initialize_smbc()) { - error( KIO::ERR_ACCESS_DENIED, kurl.toDisplayString()); + if (!auth_initialize_smbc()) { + error(KIO::ERR_ACCESS_DENIED, kurl.toDisplayString()); return; } @@ -164,22 +152,21 @@ m_openUrl = kurl; // Stat - errNum = cache_stat(m_openUrl,&st); - if( errNum != 0 ) - { - if ( errNum == EACCES ) - error( KIO::ERR_ACCESS_DENIED, m_openUrl.toDisplayString()); + errNum = cache_stat(m_openUrl, &st); + if (errNum != 0) { + if (errNum == EACCES) + error(KIO::ERR_ACCESS_DENIED, m_openUrl.toDisplayString()); else - error( KIO::ERR_DOES_NOT_EXIST, m_openUrl.toDisplayString()); + error(KIO::ERR_DOES_NOT_EXIST, m_openUrl.toDisplayString()); return; } - if ( S_ISDIR( st.st_mode ) ) { - error( KIO::ERR_IS_DIRECTORY, m_openUrl.toDisplayString()); + if (S_ISDIR(st.st_mode)) { + error(KIO::ERR_IS_DIRECTORY, m_openUrl.toDisplayString()); return; } // Set the total size - totalSize( st.st_size ); + totalSize(st.st_size); // Convert permissions int flags = 0; @@ -201,30 +188,26 @@ // Open the file m_openFd = smbc_open(m_openUrl.toSmbcUrl(), flags, 0); - if(m_openFd < 0) - { - error( KIO::ERR_CANNOT_OPEN_FOR_READING, m_openUrl.toDisplayString()); + if (m_openFd < 0) { + error(KIO::ERR_CANNOT_OPEN_FOR_READING, m_openUrl.toDisplayString()); return; } // Determine the mimetype of the file to be retrieved, and emit it. // This is mandatory in all slaves (for KRun/BrowserRun to work). // If we're not opening the file ReadOnly or ReadWrite, don't attempt to // read the file and send the mimetype. - if (mode & QIODevice::ReadOnly){ - ssize_t bytesRequested = 1024; - ssize_t bytesRead = 0; + if (mode & QIODevice::ReadOnly) { + ssize_t bytesRequested = 1024; + ssize_t bytesRead = 0; QVarLengthArray buffer(bytesRequested); bytesRead = smbc_read(m_openFd, buffer.data(), bytesRequested); - if(bytesRead < 0) - { - error( KIO::ERR_CANNOT_READ, m_openUrl.toDisplayString()); + if (bytesRead < 0) { + error(KIO::ERR_CANNOT_READ, m_openUrl.toDisplayString()); closeWithoutFinish(); return; - } - else - { - QByteArray fileData = QByteArray::fromRawData(buffer.data(),bytesRead); + } else { + QByteArray fileData = QByteArray::fromRawData(buffer.data(), bytesRead); QMimeDatabase db; QMimeType type = db.mimeTypeForFileNameAndData(m_openUrl.fileName(), fileData); mimeType(type.name()); @@ -238,45 +221,41 @@ } } - position( 0 ); + position(0); opened(); } - -void SMBSlave::read( KIO::filesize_t bytesRequested ) +void SMBSlave::read(KIO::filesize_t bytesRequested) { Q_ASSERT(m_openFd != -1); QVarLengthArray buffer(bytesRequested); - ssize_t bytesRead = 0; + ssize_t bytesRead = 0; bytesRead = smbc_read(m_openFd, buffer.data(), bytesRequested); Q_ASSERT(bytesRead <= static_cast(bytesRequested)); - if(bytesRead < 0) - { + if (bytesRead < 0) { qCDebug(KIO_SMB_LOG) << "Could not read " << m_openUrl; - error( KIO::ERR_CANNOT_READ, m_openUrl.toDisplayString()); + error(KIO::ERR_CANNOT_READ, m_openUrl.toDisplayString()); closeWithoutFinish(); return; } QByteArray fileData = QByteArray::fromRawData(buffer.data(), bytesRead); - data( fileData ); + data(fileData); } - void SMBSlave::write(const QByteArray &fileData) { Q_ASSERT(m_openFd != -1); QByteArray buf(fileData); ssize_t size = smbc_write(m_openFd, buf.data(), buf.size()); - if (size < 0) - { + if (size < 0) { qCDebug(KIO_SMB_LOG) << "Could not write to " << m_openUrl; - error( KIO::ERR_CANNOT_WRITE, m_openUrl.toDisplayString()); + error(KIO::ERR_CANNOT_WRITE, m_openUrl.toDisplayString()); closeWithoutFinish(); return; } @@ -292,7 +271,7 @@ closeWithoutFinish(); } else { qCDebug(KIO_SMB_LOG) << "res" << res; - position( res ); + position(res); } } @@ -303,7 +282,7 @@ error(KIO::ERR_CANNOT_TRUNCATE, m_openUrl.path()); closeWithoutFinish(); } else { - qCDebug( KIO_SMB_LOG ) << "res" << res; + qCDebug(KIO_SMB_LOG) << "res" << res; truncated(length); } } @@ -319,55 +298,44 @@ finished(); } -//=========================================================================== -void SMBSlave::put( const QUrl& kurl, - int permissions, - KIO::JobFlags flags ) +void SMBSlave::put(const QUrl &kurl, int permissions, KIO::JobFlags flags) { - void *buf; size_t bufsize; m_current_url = kurl; - int filefd; - bool exists; - int errNum = 0; - off_t retValLSeek = 0; - mode_t mode; - QByteArray filedata; + int filefd; + bool exists; + int errNum = 0; + off_t retValLSeek = 0; + mode_t mode; + QByteArray filedata; qCDebug(KIO_SMB_LOG) << kurl; errNum = cache_stat(m_current_url, &st); exists = (errNum == 0); - if ( exists && !(flags & KIO::Overwrite) && !(flags & KIO::Resume)) - { - if (S_ISDIR(st.st_mode)) - { - qCDebug(KIO_SMB_LOG) << kurl <<" already isdir !!"; - error( KIO::ERR_DIR_ALREADY_EXIST, m_current_url.toDisplayString()); - } - else - { - qCDebug(KIO_SMB_LOG) << kurl <<" already exist !!"; - error( KIO::ERR_FILE_ALREADY_EXIST, m_current_url.toDisplayString()); + if (exists && !(flags & KIO::Overwrite) && !(flags & KIO::Resume)) { + if (S_ISDIR(st.st_mode)) { + qCDebug(KIO_SMB_LOG) << kurl << " already isdir !!"; + error(KIO::ERR_DIR_ALREADY_EXIST, m_current_url.toDisplayString()); + } else { + qCDebug(KIO_SMB_LOG) << kurl << " already exist !!"; + error(KIO::ERR_FILE_ALREADY_EXIST, m_current_url.toDisplayString()); } return; } - if (exists && !(flags & KIO::Resume) && (flags & KIO::Overwrite)) - { + if (exists && !(flags & KIO::Resume) && (flags & KIO::Overwrite)) { qCDebug(KIO_SMB_LOG) << "exists try to remove " << m_current_url.toSmbcUrl(); // remove(m_current_url.url().toLocal8Bit()); } - - if (flags & KIO::Resume) - { + if (flags & KIO::Resume) { // append if resuming qCDebug(KIO_SMB_LOG) << "resume " << m_current_url.toSmbcUrl(); - filefd = smbc_open(m_current_url.toSmbcUrl(), O_RDWR, 0 ); + filefd = smbc_open(m_current_url.toSmbcUrl(), O_RDWR, 0); if (filefd < 0) { errNum = errno; } else { @@ -380,16 +348,11 @@ } else { errNum = 0; } - } - else - { - if (permissions != -1) - { + } else { + if (permissions != -1) { mode = permissions | S_IWUSR | S_IRUSR; - } - else - { - mode = 600;//0666; + } else { + mode = 600; // 0666; } qCDebug(KIO_SMB_LOG) << "NO resume " << m_current_url.toSmbcUrl(); @@ -401,17 +364,13 @@ } } - if ( filefd < 0 ) - { - if ( errNum == EACCES ) - { - qCDebug(KIO_SMB_LOG) << "error " << kurl <<" access denied !!"; - error( KIO::ERR_WRITE_ACCESS_DENIED, m_current_url.toDisplayString()); - } - else - { - qCDebug(KIO_SMB_LOG) << "error " << kurl <<" can not open for writing !!"; - error( KIO::ERR_CANNOT_OPEN_FOR_WRITING, m_current_url.toDisplayString()); + if (filefd < 0) { + if (errNum == EACCES) { + qCDebug(KIO_SMB_LOG) << "error " << kurl << " access denied !!"; + error(KIO::ERR_WRITE_ACCESS_DENIED, m_current_url.toDisplayString()); + } else { + qCDebug(KIO_SMB_LOG) << "error " << kurl << " can not open for writing !!"; + error(KIO::ERR_CANNOT_OPEN_FOR_WRITING, m_current_url.toDisplayString()); } return; } @@ -422,59 +381,52 @@ dataReq(); // Request for data qCDebug(KIO_SMB_LOG) << "write " << m_current_url.toSmbcUrl(); - if (readData(filedata) <= 0) - { + if (readData(filedata) <= 0) { qCDebug(KIO_SMB_LOG) << "readData <= 0"; break; } qCDebug(KIO_SMB_LOG) << "write " << m_current_url.toSmbcUrl(); - buf = filedata.data(); - bufsize = filedata.size(); + buf = filedata.data(); + bufsize = filedata.size(); ssize_t size = smbc_write(filefd, buf, bufsize); - if ( size < 0) - { + if (size < 0) { qCDebug(KIO_SMB_LOG) << "error " << kurl << "could not write !!"; - error( KIO::ERR_CANNOT_WRITE, m_current_url.toDisplayString()); + error(KIO::ERR_CANNOT_WRITE, m_current_url.toDisplayString()); return; } qCDebug(KIO_SMB_LOG) << "wrote " << size; } qCDebug(KIO_SMB_LOG) << "close " << m_current_url.toSmbcUrl(); - if(smbc_close(filefd) < 0) - { + if (smbc_close(filefd) < 0) { qCDebug(KIO_SMB_LOG) << kurl << "could not write !!"; - error( KIO::ERR_CANNOT_WRITE, m_current_url.toDisplayString()); + error(KIO::ERR_CANNOT_WRITE, m_current_url.toDisplayString()); return; } // set final permissions, if the file was just created - if ( permissions != -1 && !exists ) - { + if (permissions != -1 && !exists) { // TODO: did the smbc_chmod fail? // TODO: put in call to chmod when it is working! // smbc_chmod(url.toSmbcUrl(),permissions); } #ifdef HAVE_UTIME_H // set modification time - const QString mtimeStr = metaData( "modified" ); - if ( !mtimeStr.isEmpty() ) { - QDateTime dt = QDateTime::fromString( mtimeStr, Qt::ISODate ); - if ( dt.isValid() ) { - if (cache_stat( m_current_url, &st ) == 0) { - struct utimbuf utbuf{}; - utbuf.actime = st.st_atime; // access time, unchanged + const QString mtimeStr = metaData("modified"); + if (!mtimeStr.isEmpty()) { + QDateTime dt = QDateTime::fromString(mtimeStr, Qt::ISODate); + if (dt.isValid()) { + if (cache_stat(m_current_url, &st) == 0) { + struct utimbuf utbuf { + }; + utbuf.actime = st.st_atime; // access time, unchanged utbuf.modtime = dt.toSecsSinceEpoch(); // modification time - smbc_utime( m_current_url.toSmbcUrl(), &utbuf ); + smbc_utime(m_current_url.toSmbcUrl(), &utbuf); } } } #endif // We have done our job => finish finished(); } - - - - diff --git a/smb/kio_smb_internal.h b/smb/kio_smb_internal.h --- a/smb/kio_smb_internal.h +++ b/smb/kio_smb_internal.h @@ -31,9 +31,9 @@ #ifndef KIO_SMB_INTERNAL_H_INCLUDED #define KIO_SMB_INTERNAL_H_INCLUDED -#include #include #include +#include /** * Types of a SMBURL : @@ -61,11 +61,11 @@ public: SMBUrl(); - SMBUrl(const SMBUrl&); - SMBUrl(const QUrl & kurl); + SMBUrl(const SMBUrl &); + SMBUrl(const QUrl &kurl); ~SMBUrl(); - SMBUrl& operator=(const SMBUrl&); + SMBUrl &operator=(const SMBUrl &); /** * Appends the specified file and dir to this SMBUrl @@ -84,10 +84,10 @@ */ SMBUrlType getType() const; - void setPass( const QString& _txt ) { QUrl::setPassword(_txt); updateCache(); } - void setUser( const QString& _txt ) { QUrl::setUserName(_txt); updateCache(); } - void setHost( const QString& _txt ) { QUrl::setHost(_txt); updateCache(); } - void setPath( const QString& _txt ) { QUrl::setPath(_txt); updateCache(); } + void setPass(const QString &_txt) { QUrl::setPassword(_txt); updateCache(); } + void setUser(const QString &_txt) { QUrl::setUserName(_txt); updateCache(); } + void setHost(const QString &_txt) { QUrl::setHost(_txt); updateCache(); } + void setPath(const QString &_txt) { QUrl::setPath(_txt); updateCache(); } /** * Returns the workgroup if it given in url @@ -113,7 +113,7 @@ /** * Change from QString to QCString (MS Windows's character encoding) */ - QByteArray fromUnicode( const QString &_str ) const; + QByteArray fromUnicode(const QString &_str) const; void updateCache(); QByteArray m_surl; diff --git a/smb/kio_smb_internal.cpp b/smb/kio_smb_internal.cpp --- a/smb/kio_smb_internal.cpp +++ b/smb/kio_smb_internal.cpp @@ -31,14 +31,8 @@ #include "kio_smb_internal.h" #include "kio_smb.h" - -#include #include // for QDir::cleanPath - - -//=========================================================================== -// SMBUrl Function Implementation -//=========================================================================== +#include SMBUrl::SMBUrl(const QUrl &kurl) : QUrl(kurl) @@ -59,18 +53,16 @@ SMBUrl::~SMBUrl() = default; SMBUrl &SMBUrl::operator=(const SMBUrl &) = default; -//----------------------------------------------------------------------- void SMBUrl::addPath(const QString &filedir) { - if(path().length() > 0 && path().at(path().length() - 1) != QLatin1Char('/')) { + if (path().length() > 0 && path().at(path().length() - 1) != QLatin1Char('/')) { QUrl::setPath(path() + QLatin1Char('/') + filedir); } else { QUrl::setPath(path() + filedir); } updateCache(); } -//----------------------------------------------------------------------- bool SMBUrl::cd(const QString &filedir) { if (filedir == "..") { @@ -82,45 +74,34 @@ return true; } -//----------------------------------------------------------------------- void SMBUrl::updateCache() - //----------------------------------------------------------------------- { QUrl::setPath(QDir::cleanPath(path())); // SMB URLs are UTF-8 encoded qCDebug(KIO_SMB_LOG) << "updateCache " << QUrl::path(); - if ( QUrl::url() == "smb:/" ) - m_surl = "smb://"; + if (QUrl::url() == "smb:/") + m_surl = "smb://"; else - m_surl = toString(QUrl::PrettyDecoded).toUtf8(); - + m_surl = toString(QUrl::PrettyDecoded).toUtf8(); + m_type = SMBURLTYPE_UNKNOWN; // update m_type (void)getType(); } -//----------------------------------------------------------------------- SMBUrlType SMBUrl::getType() const - // Returns the type of this SMBUrl: - // SMBURLTYPE_UNKNOWN - Type could not be determined. Bad SMB Url. - // SMBURLTYPE_ENTIRE_NETWORK - "smb:/" is entire network - // SMBURLTYPE_WORKGROUP_OR_SERVER - "smb:/mygroup" or "smb:/myserver" - // SMBURLTYPE_SHARE_OR_PATH - "smb:/mygroupe/mymachine/myshare/mydir" - //----------------------------------------------------------------------- { - if(m_type != SMBURLTYPE_UNKNOWN) + if (m_type != SMBURLTYPE_UNKNOWN) return m_type; - if (scheme() != "smb") - { + if (scheme() != "smb") { m_type = SMBURLTYPE_UNKNOWN; return m_type; } - if (path().isEmpty() || path(QUrl::FullyDecoded) == "/") - { + if (path().isEmpty() || path(QUrl::FullyDecoded) == "/") { if (host().isEmpty()) m_type = SMBURLTYPE_ENTIRE_NETWORK; else @@ -137,7 +118,7 @@ SMBUrl SMBUrl::partUrl() const { if (m_type == SMBURLTYPE_SHARE_OR_PATH && !fileName().isEmpty()) { - SMBUrl url (*this); + SMBUrl url(*this); url.setPath(path() + QLatin1String(".part")); return url; } diff --git a/smb/kio_smb_mount.cpp b/smb/kio_smb_mount.cpp --- a/smb/kio_smb_mount.cpp +++ b/smb/kio_smb_mount.cpp @@ -20,177 +20,153 @@ #include "kio_smb.h" -#include -#include -#include -#include #include #include +#include +#include +#include #include +#include -void SMBSlave::special( const QByteArray & data) +void SMBSlave::special(const QByteArray &data) { - qCDebug(KIO_SMB_LOG)<<"Smb::special()"; - int tmp; - QDataStream stream(data); - stream >> tmp; - //mounting and umounting are both blocking, "guarded" by a SIGALARM in the future - switch (tmp) - { - case 1: - case 3: - { - QString remotePath; - QString mountPoint; - QString user; - stream >> remotePath >> mountPoint; - - QStringList sl=remotePath.split('/'); - QString share; - QString host; - if (sl.count()>=2) - { - host=sl.at(0).mid(2); - share=sl.at(1); - qCDebug(KIO_SMB_LOG)<<"special() host -"<< host <<"- share -" << share <<"-"; - } - - remotePath.replace('\\', '/'); // smbmounterplugin sends \\host/share - - qCDebug(KIO_SMB_LOG) << "mounting: " << remotePath.toLocal8Bit() << " to " << mountPoint.toLocal8Bit(); - - if (tmp==3) { - if (!QDir().mkpath(mountPoint)) { - error(KIO::ERR_CANNOT_MKDIR, mountPoint); - return; - } - } - - SMBUrl smburl(QUrl("smb:///")); - smburl.setHost(host); - smburl.setPath('/' + share); - - const int passwordError = checkPassword(smburl); - if (passwordError != KJob::NoError && passwordError != KIO::ERR_USER_CANCELED) { - error(passwordError, smburl.toString()); - return; - } - - // using smbmount instead of "mount -t smbfs", because mount does not allow a non-root - // user to do a mount, but a suid smbmnt does allow this - - KProcess proc; - proc.setOutputChannelMode(KProcess::SeparateChannels); - proc << "smbmount"; - - QString options; - - if ( smburl.userName().isEmpty() ) - { - user = "guest"; - options = "guest"; - } - else - { - options = "username=" + smburl.userName(); - user = smburl.userName(); - - if ( ! smburl.password().isEmpty() ) - options += ",password=" + smburl.password(); - } - - // TODO: check why the control center uses encodings with a blank char, e.g. "cp 1250" - //if ( ! m_default_encoding.isEmpty() ) - //options += ",codepage=" + KShell::quoteArg(m_default_encoding); - - proc << remotePath; - proc << mountPoint; - proc << "-o" << options; - - proc.start(); - if (!proc.waitForFinished()) - { - error(KIO::ERR_CANNOT_LAUNCH_PROCESS, - "smbmount"+i18n("\nMake sure that the samba package is installed properly on your system.")); + qCDebug(KIO_SMB_LOG) << "Smb::special()"; + int tmp; + QDataStream stream(data); + stream >> tmp; + // mounting and umounting are both blocking, "guarded" by a SIGALARM in the future + switch (tmp) { + case 1: + case 3: { + QString remotePath; + QString mountPoint; + QString user; + stream >> remotePath >> mountPoint; + + QStringList sl = remotePath.split('/'); + QString share; + QString host; + if (sl.count() >= 2) { + host = sl.at(0).mid(2); + share = sl.at(1); + qCDebug(KIO_SMB_LOG) << "special() host -" << host << "- share -" << share << "-"; + } + + remotePath.replace('\\', '/'); // smbmounterplugin sends \\host/share + + qCDebug(KIO_SMB_LOG) << "mounting: " << remotePath.toLocal8Bit() << " to " << mountPoint.toLocal8Bit(); + + if (tmp == 3) { + if (!QDir().mkpath(mountPoint)) { + error(KIO::ERR_CANNOT_MKDIR, mountPoint); + return; + } + } + + SMBUrl smburl(QUrl("smb:///")); + smburl.setHost(host); + smburl.setPath('/' + share); + + const int passwordError = checkPassword(smburl); + if (passwordError != KJob::NoError && passwordError != KIO::ERR_USER_CANCELED) { + error(passwordError, smburl.toString()); + return; + } + + // using smbmount instead of "mount -t smbfs", because mount does not allow a non-root + // user to do a mount, but a suid smbmnt does allow this + + KProcess proc; + proc.setOutputChannelMode(KProcess::SeparateChannels); + proc << "smbmount"; + + QString options; + + if (smburl.userName().isEmpty()) { + user = "guest"; + options = "guest"; + } else { + options = "username=" + smburl.userName(); + user = smburl.userName(); + + if (!smburl.password().isEmpty()) + options += ",password=" + smburl.password(); + } + + // TODO: check why the control center uses encodings with a blank char, e.g. "cp 1250" + // if ( ! m_default_encoding.isEmpty() ) + // options += ",codepage=" + KShell::quoteArg(m_default_encoding); + + proc << remotePath; + proc << mountPoint; + proc << "-o" << options; + + proc.start(); + if (!proc.waitForFinished()) { + error(KIO::ERR_CANNOT_LAUNCH_PROCESS, "smbmount" + i18n("\nMake sure that the samba package is installed properly on your system.")); + return; + } + + QString mybuf = QString::fromLocal8Bit(proc.readAllStandardOutput()); + QString mystderr = QString::fromLocal8Bit(proc.readAllStandardError()); + + qCDebug(KIO_SMB_LOG) << "mount exit " << proc.exitCode() << "stdout:" << mybuf << "\nstderr:" << mystderr; + + if (proc.exitCode() != 0) { + error(KIO::ERR_CANNOT_MOUNT, i18n("Mounting of share \"%1\" from host \"%2\" by user \"%3\" failed.\n%4", share, host, user, mybuf + '\n' + mystderr)); + return; + } + + finished(); + } break; + case 2: + case 4: { + QString mountPoint; + stream >> mountPoint; + + KProcess proc; + proc.setOutputChannelMode(KProcess::SeparateChannels); + proc << "smbumount"; + proc << mountPoint; + + proc.start(); + if (!proc.waitForFinished()) { + error(KIO::ERR_CANNOT_LAUNCH_PROCESS, "smbumount" + i18n("\nMake sure that the samba package is installed properly on your system.")); + return; + } + + QString mybuf = QString::fromLocal8Bit(proc.readAllStandardOutput()); + QString mystderr = QString::fromLocal8Bit(proc.readAllStandardError()); + + qCDebug(KIO_SMB_LOG) << "smbumount exit " << proc.exitCode() << "stdout:" << mybuf << "\nstderr:" << mystderr; + + if (proc.exitCode() != 0) { + error(KIO::ERR_CANNOT_UNMOUNT, i18n("Unmounting of mountpoint \"%1\" failed.\n%2", mountPoint, mybuf + '\n' + mystderr)); return; - } - - QString mybuf = QString::fromLocal8Bit(proc.readAllStandardOutput()); - QString mystderr = QString::fromLocal8Bit(proc.readAllStandardError()); - - qCDebug(KIO_SMB_LOG) << "mount exit " << proc.exitCode() - << "stdout:" << mybuf << "\nstderr:" << mystderr; - - if (proc.exitCode() != 0) - { - error( KIO::ERR_CANNOT_MOUNT, - i18n("Mounting of share \"%1\" from host \"%2\" by user \"%3\" failed.\n%4", - share, host, user, mybuf + '\n' + mystderr)); - return; - } - - finished(); - } - break; - case 2: - case 4: - { - QString mountPoint; - stream >> mountPoint; - - KProcess proc; - proc.setOutputChannelMode(KProcess::SeparateChannels); - proc << "smbumount"; - proc << mountPoint; - - proc.start(); - if ( !proc.waitForFinished() ) - { - error(KIO::ERR_CANNOT_LAUNCH_PROCESS, - "smbumount"+i18n("\nMake sure that the samba package is installed properly on your system.")); - return; - } - - QString mybuf = QString::fromLocal8Bit(proc.readAllStandardOutput()); - QString mystderr = QString::fromLocal8Bit(proc.readAllStandardError()); - - qCDebug(KIO_SMB_LOG) << "smbumount exit " << proc.exitCode() - << "stdout:" << mybuf << "\nstderr:" << mystderr; - - if (proc.exitCode() != 0) - { - error(KIO::ERR_CANNOT_UNMOUNT, - i18n("Unmounting of mountpoint \"%1\" failed.\n%2", - mountPoint, mybuf + '\n' + mystderr)); - return; - } - - if ( tmp == 4 ) - { - bool ok; - - QDir dir(mountPoint); - dir.cdUp(); - ok = dir.rmdir(mountPoint); - if ( ok ) - { - QString p=dir.path(); - dir.cdUp(); - ok = dir.rmdir(p); - } - - if ( !ok ) - { - error(KIO::ERR_CANNOT_RMDIR, mountPoint); - return; - } - } - - finished(); - } - break; - default: - break; - } - finished(); + } + + if (tmp == 4) { + bool ok; + + QDir dir(mountPoint); + dir.cdUp(); + ok = dir.rmdir(mountPoint); + if (ok) { + QString p = dir.path(); + dir.cdUp(); + ok = dir.rmdir(p); + } + + if (!ok) { + error(KIO::ERR_CANNOT_RMDIR, mountPoint); + return; + } + } + + finished(); + } break; + default: + break; + } + finished(); } diff --git a/smb/wsdiscoverer.h b/smb/wsdiscoverer.h --- a/smb/wsdiscoverer.h +++ b/smb/wsdiscoverer.h @@ -21,15 +21,16 @@ #ifndef WSDISCOVERER_H #define WSDISCOVERER_H +#include "discovery.h" #include #include -#include "discovery.h" class WSDiscoveryClient; class WSDiscoveryTargetService; class PBSDResolver; -namespace KIO { +namespace KIO +{ class UDSEntry; } diff --git a/smb/wsdiscoverer.cpp b/smb/wsdiscoverer.cpp --- a/smb/wsdiscoverer.cpp +++ b/smb/wsdiscoverer.cpp @@ -29,9 +29,9 @@ #include #include +#include #include #include -#include #include #include @@ -207,7 +207,7 @@ // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-pbsd KDQName type("wsdp:Device"); type.setNameSpace("http://schemas.xmlsoap.org/ws/2006/02/devprof"); - m_client->sendProbe({ type }, {}); + m_client->sendProbe({type}, {}); } void WSDiscoverer::stop()