ubuntu-touch-coreapps-reviewers team mailing list archive
-
ubuntu-touch-coreapps-reviewers team
-
Mailing list archive
-
Message #01373
Re: [Merge] lp:~carlos-mazieri/ubuntu-filemanager-app/samba-browsing-04 into lp:ubuntu-filemanager-app
Review: Approve
Few comments. But nothing blocking.
Diff comments:
> === modified file 'debian/control'
> --- debian/control 2014-11-11 13:28:07 +0000
> +++ debian/control 2015-03-10 21:53:38 +0000
> @@ -11,6 +11,7 @@
> python3-all,
> libtag1-dev,
> libpam0g-dev,
> + libsmbclient-dev,
> Standards-Version: 3.9.5
> Section: misc
> Homepage: https://launchpad.net/ubuntu-filemanager-app
> @@ -29,6 +30,7 @@
> qtdeclarative5-u1db1.0,
> qtdeclarative5-ubuntu-ui-toolkit-plugin | qt-components-ubuntu,
> qtdeclarative5-ubuntu-content0.1,
> + libsmbclient,
> Description: File Manager application
> Core File Manager application
>
>
> === modified file 'src/plugin/folderlistmodel/CMakeLists.txt'
> --- src/plugin/folderlistmodel/CMakeLists.txt 2015-03-10 21:53:38 +0000
> +++ src/plugin/folderlistmodel/CMakeLists.txt 2015-03-10 21:53:38 +0000
> @@ -3,6 +3,8 @@
> disk
> trash
> net
> + smb
> + smb/qsambaclient/src
> )
>
> set(PLUGIN_DIR org/nemomobile/folderlistmodel)
> @@ -55,8 +57,12 @@
> trash/trashiteminfo.h
> trash/trashlocation.cpp
> trash/trashlocation.h
> + smb/qsambaclient/src/smbutil.cpp
> + smb/qsambaclient/src/smbutil.h
> net/netauthenticationdata.cpp
> - net/netauthenticationdata.h
> + net/netauthenticationdata.h
> + net/netutil.cpp
> + net/netutil.h
> )
>
> add_library(nemofolderlistmodel MODULE
> @@ -65,6 +71,24 @@
>
> qt5_use_modules(nemofolderlistmodel Gui Qml Quick Widgets)
>
> +## samba requires libsmbclient
> +find_path(SAMBA_INCLUDE_DIR
> + NAMES libsmbclient.h
> + HINTS /usr/include/smbclient /usr/include/samba /usr/include/samba-3.0 /usr/include/samba-4.0
> + )
> +find_library(SAMBA_LIBRARIES NAMES smbclient )
> +message(STATUS "samba include=${SAMBA_INCLUDE_DIR}")
> +message(STATUS "samba lib=${SAMBA_LIBRARIES}=${SAMBA_LIBRARIES}")
> +
> +if(SAMBA_INCLUDE_DIR AND SAMBA_LIBRARIES)
> + message(STATUS "Found samba: include=${SAMBA_INCLUDE_DIR} library=${SAMBA_LIBRARIES}")
> + INCLUDE_DIRECTORIES(${SAMBA_INCLUDE_DIR})
> + TARGET_LINK_LIBRARIES(nemofolderlistmodel ${SAMBA_LIBRARIES})
> +else(SAMBA_INCLUDE_DIR AND SAMBA_LIBRARIES)
> + message(FATAL_ERROR "Could not find Samba libsmbclient")
> +endif(SAMBA_INCLUDE_DIR AND SAMBA_LIBRARIES)
> +mark_as_advanced(SAMBA_INCLUDE_DIR SAMBA_LIBRARIES)
> +## end samba confiuration
>
> # Copy the plugin, the qmldir file and other assets to the build dir for running in QtCreator
> if(NOT "${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}")
>
> === modified file 'src/plugin/folderlistmodel/folderlistmodel.pri'
> --- src/plugin/folderlistmodel/folderlistmodel.pri 2015-03-10 21:53:38 +0000
> +++ src/plugin/folderlistmodel/folderlistmodel.pri 2015-03-10 21:53:38 +0000
> @@ -40,8 +40,8 @@
> HEADERS += $$PWD/trash/qtrashdir.h $$PWD/trash/trashiteminfo.h \
> $$PWD/trash/qtrashutilinfo.h $$PWD/trash/trashlocation.h
>
> -SOURCES += $$PWD/net/netauthenticationdata.cpp
> -HEADERS += $$PWD/net/netauthenticationdata.h
> +SOURCES += $$PWD/net/netutil.cpp $$PWD/net/netauthenticationdata.cpp
> +HEADERS += $$PWD/net/netutil.h $$PWD/net/netauthenticationdata.h
>
> INCLUDEPATH += $$PWD $$PWD/trash $$PWD/disk $$PWD/net
>
>
> === modified file 'src/plugin/folderlistmodel/location.cpp'
> --- src/plugin/folderlistmodel/location.cpp 2015-03-10 21:53:38 +0000
> +++ src/plugin/folderlistmodel/location.cpp 2015-03-10 21:53:38 +0000
> @@ -43,6 +43,8 @@
> #include "ioworkerthread.h"
> #include "netauthenticationdata.h"
>
> +#include <QDebug>
> +
> Q_GLOBAL_STATIC(IOWorkerThread, ioWorkerThread)
>
>
>
> === modified file 'src/plugin/folderlistmodel/locationurl.cpp'
> --- src/plugin/folderlistmodel/locationurl.cpp 2014-05-02 10:42:48 +0000
> +++ src/plugin/folderlistmodel/locationurl.cpp 2015-03-10 21:53:38 +0000
> @@ -23,8 +23,9 @@
>
> const QString LocationUrl::TrashRootURL("trash:///");
> const QString LocationUrl::DiskRootURL("file:///");
> +const QString LocationUrl::SmbURL("smb://");
> +const QString LocationUrl::CifsURL("cifs://");
> #if 0
> -QString LocationURL::SmbURL("smb://");
> QString LocationURL::FishURL("fish:///");
> #endif
>
>
> === modified file 'src/plugin/folderlistmodel/locationurl.h'
> --- src/plugin/folderlistmodel/locationurl.h 2014-05-02 10:42:48 +0000
> +++ src/plugin/folderlistmodel/locationurl.h 2015-03-10 21:53:38 +0000
> @@ -29,8 +29,9 @@
> public:
> static const QString DiskRootURL;
> static const QString TrashRootURL;
> + static const QString SmbURL;
> + static const QString CifsURL;
> #if 0
> - static const QString SmbURL;
> static const QString FishURL;
> #endif
> private:
>
> === added file 'src/plugin/folderlistmodel/net/netutil.cpp'
> --- src/plugin/folderlistmodel/net/netutil.cpp 1970-01-01 00:00:00 +0000
> +++ src/plugin/folderlistmodel/net/netutil.cpp 2015-03-10 21:53:38 +0000
> @@ -0,0 +1,89 @@
> +/**************************************************************************
> + *
> + * Copyright 2014 Canonical Ltd.
> + * Copyright 2014 Carlos J Mazieri <carlos.mazieri@xxxxxxxxx>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU Lesser General Public License as published by
> + * the Free Software Foundation; version 3.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
> + *
> + * File: netutil.cpp
> + * Date: 29/11/2014
> + */
> +
> +#include "netutil.h"
> +#include <QHostAddress>
> +#include <QHostInfo>
> +#include <QUrl>
> +
> +#include <QDebug>
> +
> +NetUtil::NetUtil()
> +{
> +}
> +
> +
> +QString NetUtil::normalizeHostName(const QString& name)
> +{
> + QString host(name.toLower());
> + bool isLoopBack = false;
> + QHostInfo info = QHostInfo::fromName(host);
> + // take advantage of network with Bonjour/Avahi
> + // as winbind looks like harder to configure or does not work
> + if (info.error() == QHostInfo::HostNotFound)
> + {
> + host += QLatin1String(".local");
> + info = QHostInfo::fromName(host);
> + }
> + if (info.error() == QHostInfo::NoError)
> + {
> + host = info.hostName();
> + QList<QHostAddress> addrs = info.addresses();
> + int counter = addrs.count();
> + while (!isLoopBack && counter--)
> + {
> + isLoopBack = addrs.at(counter).isLoopback();
> + }
> + }
> + if (isLoopBack)
> + {
> + host = QLatin1String("localhost");
> + }
> + return host;
> +}
> +
> +/*!
> + * \brief NetUtil::urlConvertHostnameToIP() Tries to convert an url like protocol://hostname/blavbla to protocol://ip-address/blavbla
> + * \param url
> + * \return the url using IP numbers or an empty string saying that was not possible to get its IP number
> + */
> +QString NetUtil::urlConvertHostnameToIP(const QString &url)
> +{
> + QString ret;
> + QUrl tmpUrl(url);
> + if (tmpUrl.isValid() && !tmpUrl.host().isEmpty() && tmpUrl.host() != QLatin1String("localhost"))
> + {
> + QString host = tmpUrl.host();
> + QHostInfo info = QHostInfo::fromName(host);
> + if (info.error() == QHostInfo::HostNotFound)
> + {
> + // take advantage of network with Bonjour/Avahi
> + // as winbind looks like harder to configure or does not work
> + info = QHostInfo::fromName(host + QLatin1String(".local"));
> + }
> + if (info.error() == QHostInfo::NoError)
> + {
> + tmpUrl.setHost(info.addresses().at(0).toString());
> + ret = tmpUrl.toString();
> + }
> + }
> + return ret;
> +}
>
> === added file 'src/plugin/folderlistmodel/net/netutil.h'
> --- src/plugin/folderlistmodel/net/netutil.h 1970-01-01 00:00:00 +0000
> +++ src/plugin/folderlistmodel/net/netutil.h 2015-03-10 21:53:38 +0000
> @@ -0,0 +1,36 @@
> +/**************************************************************************
> + *
> + * Copyright 2014 Canonical Ltd.
> + * Copyright 2014 Carlos J Mazieri <carlos.mazieri@xxxxxxxxx>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU Lesser General Public License as published by
> + * the Free Software Foundation; version 3.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
> + *
> + * File: netutil.h
> + * Date: 29/11/2014
> + */
> +
> +#ifndef NETUTIL_H
> +#define NETUTIL_H
> +
> +#include <QString>
> +
> +class NetUtil
> +{
> +private:
> + NetUtil();
> +public:
> + static QString normalizeHostName(const QString& name);
> + static QString urlConvertHostnameToIP(const QString& url);
> +};
> +
> +#endif // NETUTIL_H
>
> === added directory 'src/plugin/folderlistmodel/smb'
> === added directory 'src/plugin/folderlistmodel/smb/qsambaclient'
> === added file 'src/plugin/folderlistmodel/smb/qsambaclient/qsambaclient.pri'
> --- src/plugin/folderlistmodel/smb/qsambaclient/qsambaclient.pri 1970-01-01 00:00:00 +0000
> +++ src/plugin/folderlistmodel/smb/qsambaclient/qsambaclient.pri 2015-03-10 21:53:38 +0000
> @@ -0,0 +1,14 @@
> +
> +SOURCES += $$PWD/src/smbutil.cpp
> +
> +
> +
> +HEADERS += $$PWD/src/smbutil.h
> +
> +
> +QT *= core network
> +
> +CONFIG *= link_pkgconfig
> +PKGCONFIG *= smbclient
> +
> +INCLUDEPATH += $$PWD/src
>
> === added directory 'src/plugin/folderlistmodel/smb/qsambaclient/src'
> === added file 'src/plugin/folderlistmodel/smb/qsambaclient/src/smbutil.cpp'
> --- src/plugin/folderlistmodel/smb/qsambaclient/src/smbutil.cpp 1970-01-01 00:00:00 +0000
> +++ src/plugin/folderlistmodel/smb/qsambaclient/src/smbutil.cpp 2015-03-10 21:53:38 +0000
> @@ -0,0 +1,704 @@
> +/**************************************************************************
> + *
> + * Copyright 2014 Canonical Ltd.
> + * Copyright 2014 Carlos J Mazieri <carlos.mazieri@xxxxxxxxx>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU Lesser General Public License as published by
> + * the Free Software Foundation; version 3.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
> + *
> + * File: smbutil.cpp
> + * Date: 20/11/2014
> + */
> +
> +#include "smbutil.h"
> +#include "locationurl.h"
> +#include "netutil.h"
> +#include <sys/stat.h>
> +#include <sys/statfs.h>
> +#include <errno.h>
> +
> +#include <QUrl>
> +#include <QDebug>
> +#include <QRegExp>
> +
> +// set debug level at compilation time
> +#ifndef SMB_DEBUG_LEVEL
> +#define SMB_DEBUG_LEVEL 0
> +#endif
> +
> +
> +#if defined(SHOW_MESSAGES)
> +# define DBG(more_items) qDebug() << Q_FUNC_INFO more_items
> +#else
> +#define DBG(none)
> +#endif
> +
> +static QByteArray s_user("guest");
> +static QByteArray s_passwd;
> +static QByteArray s_workGroup("WORKGROUP");
> +
> +//===============================================================================================
> +/*!
> + * \brief SmbUtil::SmbUtil() This is the default constructor that provides the default authentication method
> + *
> + * The user is the current user, password is "passwd" and the authentication function is \ref authenticateCallBack()
> + */
> +SmbUtil::SmbUtil()
> +{
> + init(::qgetenv("USER"), QLatin1String("passwd"), &SmbUtil::authenticateCallBack);
> +}
> +
> +
> +//===============================================================================================
> +/*!
> + * \brief SmbUtil::SmbUtil() This constructor accepts an \a user and \a password for authentication
> + *
> + * The authentication function is \ref authenticateCallBack()
> + *
> + * \param authUser
> + * \param authPassword
> + */
> +SmbUtil::SmbUtil(const QString& authUser, const QString& authPassword)
> +{
> + init(authUser, authPassword, &SmbUtil::authenticateCallBack);
> +}
> +
> +
> +//===============================================================================================
> +/*!
> + * \brief SmbUtil::SmbUtil() This constructor accepts another authentication function other than the default
> + *
> + * No users no password is providedm the function should be able to provide everything
"No users no password" - "If no user or no password is provided" ?
> + *
> + * \param ptAuthenticateCallBack
> + */
> +SmbUtil::SmbUtil(Smb::AuthenticationFunction ptAuthenticateCallBack):
> + m_authCallBack(ptAuthenticateCallBack)
> +{
> +
> +}
> +
> +
> +//===============================================================================================
> +/*!
> + * \brief SmbUtil::SmbUtil() This is the more complete constructor where user and password can come from the \a smbUrl
> + * \param smbUrl
> + * \param fn
> + */
> +SmbUtil::SmbUtil(const QUrl& smbUrl, Smb::AuthenticationFunction fn)
> +{
> + m_authCallBack = fn ? fn : &SmbUtil::authenticateCallBack;
> + if (!smbUrl.userName().isEmpty())
> + {
> + init(smbUrl.userName(), smbUrl.password(), m_authCallBack);
> + }
> +}
> +
> +
> +//===============================================================================================
> +/*!
> + * \brief SmbUtil::~SmbUtil() destructor
> + */
> +SmbUtil::~SmbUtil()
> +{
> +}
> +
> +
> +//===============================================================================================
> +/*!
> + * \brief SmbUtil::authenticateCallBack() Default authentication function, it uses static variables to keep user/password
> + * \param server
> + * \param share
> + * \param wrkgrp
> + * \param wrkgrplen
> + * \param user
> + * \param userlen
> + * \param passwd
> + * \param passwdlen
> + */
> +void SmbUtil::authenticateCallBack( const char *server,
> + const char *share,
> + char *wrkgrp,
> + int wrkgrplen,
> + char *user,
> + int userlen,
> + char *passwd,
> + int passwdlen)
> +{
> + Q_UNUSED(server);
> + Q_UNUSED(share);
> + DBG(<< "server:" << server << "share:" << share << "wrkgrp:" << wrkgrp << "user:" << user << "passwd:" << passwd);
> +
> +#if 0
> + //this may not be necessary
> + ::strncpy(wrkgrp, s_workGroup.constData(), --wrkgrplen);
> +#else
> + Q_UNUSED(wrkgrp);
> + Q_UNUSED(wrkgrplen);
> +#endif
> +
> + // check some environment variables to help test authentication
> +#if defined(REGRESSION_TEST_QSAMBACLIENT)
> + QByteArray env = ::qgetenv("SMB_DEFAULT_USER");
> + if (env.size() > 0)
> + {
> + s_user = env;
> + }
> + env = ::qgetenv("SMB_DEFAULT_PASSWORD");
> + if (env.size() > 0)
> + {
> + s_passwd = env;
> + }
> +#endif
> +
> + ::strncpy(user, s_user.constData(), --userlen);
> + ::strncpy(passwd, s_passwd.constData(), --passwdlen);
> +}
> +
> +
> +
> +//===============================================================================================
> +/*!
> + * \brief SmbUtil::init() Just stores user/password and authentication function
> + * \param user
> + * \param password
> + * \param fn
> + */
> +void SmbUtil::init(const QString &user, const QString &password, Smb::AuthenticationFunction fn)
> +{
> + s_user = user.toLocal8Bit();
> + s_passwd = password.toLocal8Bit();
> + m_authCallBack = fn;
> +}
> +
> +
> +
> +//===============================================================================================
> +/*!
> + * \brief SmbUtil::createContext() It creates a SMB context which is necessary to all operations
> + *
> + * It sets the current authentication function callback
> + *
> + * \return the context created
> + */
> +Smb::Context SmbUtil::createContext()
> +{
> + Smb::Context ctx = smbc_new_context();
> + if (ctx)
> + {
> + smbc_setDebug(ctx, SMB_DEBUG_LEVEL);
> + smbc_setFunctionAuthData(ctx, m_authCallBack);
> + if (smbc_init_context(ctx) == NULL)
> + {
> + smbc_free_context(ctx, 1);
> + ctx = 0;
> + }
> + }
> + DBG(<< "ctx:" << ctx);
> + return ctx;
> +}
> +
> +
> +//===============================================================================================
> +/*!
> + * \brief SmbUtil::deleteContext() Just deletes a context created by \ref createContext()
> + * \param context
> + */
> +void SmbUtil::deleteContext(Smb::Context context)
> +{
> + smbc_getFunctionPurgeCachedServers(context)(context);
> + smbc_free_context(context, 1);
> + DBG();
> +}
> +
> +
> +//===============================================================================================
> +/*!
> + * \brief SmbUtil::openFile() opens a file
> + * \param context
> + * \param smb_path it must point to a file full pathname
> + * \param flags
> + * \param mode
> + * \return the FileHandler or NULL when it is not possible to open the file
> + */
> +Smb::FileHandler
> +SmbUtil::openFile(Smb::Context context, const QString &smb_path, int flags , mode_t mode)
> +{
> + Smb::FileHandler fd = ::smbc_getFunctionOpen(context)
> + (context, smb_path.toLocal8Bit().constData(), flags, mode);
> +
> + if (fd == 0 && errno != EISDIR)
> + {
> + QString ipUrl = NetUtil::urlConvertHostnameToIP(smb_path);
> + if (!ipUrl.isEmpty())
> + {
> + fd = ::smbc_getFunctionOpen(context)
> + (context, ipUrl.toLocal8Bit().constData(), flags, mode);
> + }
> + }
> + if (fd == 0)
> + {
> + qWarning() << Q_FUNC_INFO << "errno:" << errno << smb_path;
> + }
> + return fd;
> +}
> +
> +
> +//===============================================================================================
> +/*!
> + * \brief SmbUtil::openDir() opens a directory
> + * \param context
> + * \param smb_string it must point to a directory full pathname
> + * \return the FileHandler or NULL when it is not possible to open the directory
> + */
> +Smb::FileHandler
> +SmbUtil::openDir(Smb::Context context, const QString &smb_string)
> +{
> + Smb::FileHandler fd = ::smbc_getFunctionOpendir(context)
> + (context, smb_string.toLocal8Bit().constData());
> +
> + if (fd == 0)
> + {
> + //try to use an IP address if possible
> + QString ipUrl = NetUtil::urlConvertHostnameToIP(smb_string);
> + if (!ipUrl.isEmpty())
> + {
> + fd = ::smbc_getFunctionOpendir(context)
> + (context, ipUrl.toLocal8Bit().constData());
> + }
> + }
> + if (fd == 0)
> + {
> + qWarning() << Q_FUNC_INFO << "errno:" << errno << smb_string;
> + }
> + return fd;
> +}
> +
> +
> +//===============================================================================================
> +/*!
> + * \brief SmbUtil::closeHandle() closes a open FileHandler created by \ref openDir() or \ref openFile()
> + * \param context
> + * \param fd
> + */
> +void SmbUtil::closeHandle(Smb::Context context, Smb::FileHandler fd)
> +{
> + if (fd)
> + {
> + ::smbc_getFunctionClose(context)(context, fd);
> + }
> +}
> +
> +//===============================================================================================
> +/*!
> + * \brief SmbUtil::setAuthenticationCallback() Just sets the authentication function
> + * \param fn
> + */
> +void SmbUtil::setAuthenticationCallback(Smb::AuthenticationFunction fn)
> +{
> + m_authCallBack = fn;
> +}
> +
> +//===============================================================================================
> +/*!
> + * \brief SmbUtil::getStatInfo() It gets information about files and directories, similar to POSIX stat(2)
> + *
> + * It looks like smbclient brings no information for directories, it works only for files, in this case the caller
> + * must set valid information in the struct stat.
> + *
> + * The distintion between files and directories is made by \ref openDir() and \ref openFile(), as just one
> + * of them should open the \a smb_path.
> + * For directories which it is supposed to have a content it is necessary to know if it is a
> + * host/share/workgroup or a single directory, for this the \ref guessDirType() is used.
> + *
> + * \param smb_path it must point to a file full pathname file or directory
> + * \param st pointer to a struct stat which will receive the information
> + * \return one of the \ref StatReturn
> + */
> +SmbUtil::StatReturn
> +SmbUtil::getStatInfo(const QString &smb_path, struct stat* st)
> +{
> + Smb::Context context = createContext();
> + Q_ASSERT(context);
> + ::memset(st, 0 , sizeof(struct stat));
extra space: 0, sizeof
> + StatReturn ret = StatInvalid;
too many spaces: ret = StatInvalid;
> + int slashes = smb_path.count(QDir::separator());
> + Smb::FileHandler fd = 0;
> + // smb:// -> slahes=2 smb/workgroup -> slahes=2 smb://host/share -> slashes=3
> + if ((fd=openDir(context, smb_path)))
> + {
> + if ((ret = guessDirType(context,fd)) == StatDir && slashes == 3)
> + {
> + ret = StatShare;
Too muh indentation
> + }
> + if (slashes > 2 && (ret == StatShare || ret == StatDir))
> + {
> + /* smbc_getFunctionFstatdir does not work
> + ret = static_cast<StatReturn>(::smbc_getFunctionFstatdir(context)(context,fd, st));
> + */
> + QString ipUrl = NetUtil::urlConvertHostnameToIP(smb_path);
> + if (ipUrl.isEmpty())
> + {
> + ipUrl = smb_path;
> + }
> + (void)static_cast<StatReturn> (::smbc_getFunctionStat(context)(context,ipUrl.toLocal8Bit().constData(), st));
> + }
> + }
> + else
> + if (errno != EACCES && errno != ECONNREFUSED )
A bit confusing. Maybe rather else if(...)
> + {
> + if ((fd = openFile(context,smb_path)))
> + {
> + ret = static_cast<StatReturn> (::smbc_getFunctionFstat(context)(context,fd, st));
> + }
> + }
> +
> + if (fd)
> + {
> + closeHandle(context, fd);
> + }
> + else
> + {
> + qDebug() << Q_FUNC_INFO << "path:" << smb_path << "errno:" << errno << strerror(errno);
> + switch(errno)
> + {
> + case EACCES:
> + ret = StatNoAccess;
> + break;
> + case ENOENT:
> + case ENODEV:
> + case ECONNREFUSED:
> + ret = StatDoesNotExist;
> + break;
> + default:
> + break;
> + }
> + }
> + deleteContext(context);
> + return ret;
> +}
> +
> +
> +//===============================================================================================
> +/*!
> + * \brief SmbUtil::guessDirType() gets the first directory item to guess the content type
> + * \param context
> + * \param fd an already opened FileHandler of a directory
> + * \return the item type in \ref StatReturn
> + */
> +SmbUtil::StatReturn
> +SmbUtil::guessDirType(Smb::Context context, Smb::FileHandler fd)
> +{
> + struct smbc_dirent *dirent=0;
> + StatReturn ret = StatDone;
> + while (ret == StatDone &&
> + (dirent = smbc_getFunctionReaddir(context)(context, fd)) )
> + {
> + if (!dirent->name[0] && dirent->smbc_type != SMBC_SERVER )
> + {
> + continue;
> + }
> + switch(dirent->smbc_type)
> + {
> + //current item is a Host
> + case SMBC_FILE_SHARE:
> + ret = StatHost;
> + break;
> + //current item is a Workgroup
> + case SMBC_SERVER:
> + ret = StatWorkgroup;
> + break;
> + //current item is Root smb://
> + case SMBC_WORKGROUP:
> + break;
> + //ignore system shares
> + case SMBC_PRINTER_SHARE:
> + case SMBC_COMMS_SHARE:
> + case SMBC_IPC_SHARE:
> + break;
> + //current item is Common directory
> + // or a share, shares are handdled by the caller
> + default:
> + ret = StatDir;
> + break;
> + }
> + }
> + return ret;
> +}
> +
> +//===============================================================================================
> +/*!
> + * \brief SmbUtil::listContent() Just lists the content of a directory/share/workgroup/hostname
> + * \param smb_path it must point to full pathname directory/share/workgroup/hostname
> + * \param recursive
> + * \param filters a QDir like filter
> + * \return The string list that matches \a filters
> + */
> +QStringList SmbUtil::listContent(QString smb_path, bool recursive, QDir::Filters filters , const QStringList &filterNames)
> +{
> + QStringList content;
> + Smb::Context context = createContext();
> + Q_ASSERT(context);
> + Smb::FileHandler fd = openDir(context,smb_path);
> + if (fd)
> + {
> + struct smbc_dirent *dirent = 0;
> + const char *cur_name = 0;
> + while ((dirent = smbc_getFunctionReaddir(context)(context, fd)) )
> + {
> + //first check for hidden files
> + if (!(filters & QDir::Hidden) && dirent->name[0] == '.')
> + {
> + continue;
> + }
> + if ( !dirent->name[0] && dirent->smbc_type != SMBC_SERVER)
> + {
> + //it may be a libsmbclient bug
> + continue;
> + }
> + cur_name = dirent->name;
> + QString path;
> + bool itemHasContent = false;
> + switch(dirent->smbc_type)
> + {
> + case SMBC_PRINTER_SHARE:
> + case SMBC_COMMS_SHARE:
> + case SMBC_IPC_SHARE:
> + continue;
> + break;
> + case SMBC_WORKGROUP:
> + case SMBC_SERVER:
> + itemHasContent = true;
> + path = LocationUrl::SmbURL;
> + if (dirent->smbc_type == SMBC_SERVER)
> + {
> + QString goodHostName = findSmBServer(*dirent);
> + //path += NetUtil::normalizeHostName(goodHostName);
> + path += goodHostName;
> + }
> + else
> + {
> + path += cur_name;
> + }
> + break;
> + case SMBC_DIR:
> + if (filters & QDir::Dirs)
> + {
> + bool isDot = ::strcmp(".", cur_name) == 0;
> + bool isDotDot = ::strcmp("..", cur_name) == 0;
> + if( !((filters & QDir::NoDot) && isDot)
> + && !((filters & QDir::NoDotDot) && isDotDot) )
> + {
> + path = smb_path + QDir::separator() + cur_name;
> + if (!isDot && !isDotDot)
> + {
> + itemHasContent = true;
> + }
> + }
> + }
> + break;
> + case SMBC_FILE:
> + case SMBC_LINK:
> + if (filters & QDir::Files)
> + {
> + path = smb_path + QDir::separator() + cur_name;
> + }
> + break;
> + case SMBC_FILE_SHARE:
> + if (checkValidShareName(cur_name))
> + {
> + itemHasContent = true;
> + path = smb_path + QDir::separator() + cur_name;
> + }
> + break;
> + }//switch
> + if (!path.isEmpty())
> + {
> + if (filterNames.isEmpty() || namesMatchFilter(cur_name, filterNames))
> + {
> + content.append(path);
> + }
> + if (recursive && itemHasContent )
> + {
> + content += listContent(path, true, filters, filterNames);
> + }
> + }
> + }//while
> + closeHandle(context, fd);
> + }//if (fd)
> + else
> + {
> + qDebug() << Q_FUNC_INFO << "could not open directory" << smb_path << "errno:" << errno;
> + }
> + deleteContext(context);
> + return content;
> +}
> +
> +
> +//===============================================================================================
> +/*!
> + * \brief SmbUtil::lisShares() Brings the list of all available file shares in the network
> + * \return all available file shares
> + */
> +QStringList SmbUtil::lisShares()
> +{
> + return walkForShares(LocationUrl::SmbURL);
> +}
> +
> +//===============================================================================================
> +/*!
> + * \brief SmbUtil::walkForShares() Just a helper function that can be recursive, called by \ref lisShares()
> + * \param smb_path
> + * \return list of shares from a single hostname
> + */
> +QStringList SmbUtil::walkForShares(QString smb_path)
> +{
> + QStringList content;
> + Smb::Context context = createContext();
> + Q_ASSERT(context);
> + Smb::FileHandler fd = openDir(context,smb_path);
> + if (fd)
> + {
> + struct smbc_dirent *dirent = 0;
> + const char *cur_name = 0;
> + QString path;
> + while ((dirent = smbc_getFunctionReaddir(context)(context, fd)))
> + {
> + cur_name = dirent->name;
> + if ( !dirent->name[0] && dirent->smbc_type != SMBC_SERVER)
> + {
> + //it may be a libsmbclient bug
> + continue;
> + }
> + switch(dirent->smbc_type)
> + {
> + case SMBC_WORKGROUP:
> + case SMBC_SERVER:
> + path = LocationUrl::SmbURL;
> + if (dirent->smbc_type == SMBC_SERVER)
> + {
> + QString goodHostName = findSmBServer(*dirent);
> + //path += NetUtil::normalizeHostName(goodHostName);
> + path += goodHostName;
> + }
> + else
> + {
> + path += cur_name;
> + }
> + content += walkForShares(path);
> + break;
> + case SMBC_FILE_SHARE:
> + if (checkValidShareName(cur_name))
> + {
> + path = smb_path + QDir::separator() + cur_name;
> + content.append(path);
> + }
> + break;
> + }//switch
> + }//while
> + }//if (fd)
> + deleteContext(context);
> + return content;
> +}
> +
> +
> +//===============================================================================================
> +/*!
> + * \brief SmbUtil::checkValidShareName() Helper function to ignore some system shares that should not contain any file
> + *
> + * It is used for \ref lisShares() and \ref listContent()
> + *
> + * \param shareName
> + * \return TRUE if the share has a good name (should contain files), FALSE if it is supposed to be a system share
> + */
> +bool SmbUtil::checkValidShareName(const char *shareName)
> +{
> + if (::strcmp(shareName, "print$") == 0)
> + {
> + return false;
> + }
> +
> + return true;
> +}
> +
> +
> +//===============================================================================================
> +/*!
> + * \brief SmbUtil::getStatvfsInfo
> + * \param smb_path it must point to a file full pathname file or directory
> + * \param st pointer to a struct statvfs
> + * \return StatDone in case of success or StatInvalid.
> + */
> +SmbUtil::StatReturn
> +SmbUtil::getStatvfsInfo(const QString &smb_path, struct statvfs *st)
> +{
> + Smb::Context context = createContext();
> + Q_ASSERT(context);
> + ::memset(st, 0 , sizeof(struct statvfs));
> + StatReturn ret = StatInvalid;
> + Smb::FileHandler fd = openDir(context,smb_path);
> + if (fd == 0)
> + {
> + fd = openFile(context, smb_path);
> + }
> + if (fd)
> + {
> + ret = static_cast<StatReturn> (::smbc_getFunctionFstatVFS(context)(context,fd, st));
> + closeHandle(context, fd);
> + }
> + deleteContext(context);
> + return ret;
> +}
> +
> +
> +bool SmbUtil::namesMatchFilter(const QString & str, const QStringList &filterNames)
> +{
> + bool ret = true;
> + int counter = filterNames.count();
> + while (ret && counter--)
> + {
> + QRegExp regExp(filterNames.at(counter), Qt::CaseSensitive, QRegExp::Wildcard);
> + ret = regExp.exactMatch(str);
> + }
> + return ret;
> +}
> +
> +/*!
> + * \brief SmbUtil::findSmBServer() Helper function to find the server name
> + * \param dirent smbc_dirent & dirent result of smbc_getFunctionReaddir()
> + *
> + * 1. Some smbclient versions (or host configuration) bring dirent.name empty when browsing localhost
> + *
> + * 2. When dirent.name brings the hostname, usually it is limited to 16 characters which will not reacheable in the network
> + * in this case try to get the name from the comment
> + *
> + * \return the hostname
> + */
> +QString SmbUtil::findSmBServer(const smbc_dirent & dirent)
> +{
> + QString host("localhost");
> + if (dirent.name[0] != 0)
> + {
> + QString name(dirent.name);
> + host = name;
> + QString comment(dirent.comment);
> + if (!comment.isEmpty())
> + {
> + QString fullName = comment.split(QLatin1Char(' '), QString::SkipEmptyParts).first();
> + if (!fullName.isEmpty() && fullName.startsWith(name), Qt::CaseSensitive)
> + {
> + host = fullName;
> + }
> + }
> + }
> + return host.toLower();
> +}
>
> === added file 'src/plugin/folderlistmodel/smb/qsambaclient/src/smbutil.h'
> --- src/plugin/folderlistmodel/smb/qsambaclient/src/smbutil.h 1970-01-01 00:00:00 +0000
> +++ src/plugin/folderlistmodel/smb/qsambaclient/src/smbutil.h 2015-03-10 21:53:38 +0000
> @@ -0,0 +1,130 @@
> +/**************************************************************************
> + *
> + * Copyright 2014 Canonical Ltd.
> + * Copyright 2014 Carlos J Mazieri <carlos.mazieri@xxxxxxxxx>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU Lesser General Public License as published by
> + * the Free Software Foundation; version 3.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
> + *
> + * File: smbutil.h
> + * Date: 20/11/2014
> + */
> +
> +#ifndef SMBUTIL_H
> +#define SMBUTIL_H
> +
> +#include <libsmbclient.h>
> +
> +#include <QStringList>
> +#include <QDir>
> +
> +class QUrl;
> +class NetAuthenticationData;
> +class NetAuthenticationDataList;
> +struct stat;
> +
> +
> +namespace Smb
> +{
> + typedef SMBCCTX * Context;
> + typedef SMBCFILE * FileHandler;
> + typedef void (*AuthenticationFunction) (const char *server,
> + const char *share,
> + char *wrkgrp,
> + int wrkgrplen,
> + char *user,
> + int userlen,
> + char *passwd,
> + int passwdlen);
> +}
> +
> +
> +/*!
> + * \brief The SmbUtil class provides the interface through the libsmbclient functions
> + *
> + * Some documentation can found at:
> + * \link http://www.samba.org/samba/docs/man/manpages-3/libsmbclient.7.html
> + * \link https://github.com/Zentyal/samba/tree/master/examples/libsmbclient
> + *
> + */
> +class SmbUtil
> +{
> +public:
> + SmbUtil();
> + SmbUtil(Smb::AuthenticationFunction fn);
> + SmbUtil(const QString& authUser, const QString& authPassword);
> + SmbUtil(const QUrl& smbUrl, Smb::AuthenticationFunction fn = 0); //may have smb:://user::password@host/..
> + ~SmbUtil();
> +
> +public:
> + enum StatReturn
> + {
> + StatInvalid = -3,
> + StatDoesNotExist= -2,
> + StatNoAccess= -1,
> + StatDone=0, // already done
> + StatDir,
> + StatHost,
> + StatWorkgroup,
> + StatShare
> + };
> +
> +public:
> + Smb::Context createContext();
> + void deleteContext(Smb::Context context);
> + void setAuthenticationCallback(Smb::AuthenticationFunction fn);
> + StatReturn getStatInfo(const QString &smb_path, struct stat *st);
> + StatReturn getStatvfsInfo(const QString& smb_path, struct statvfs *st);
> + Smb::FileHandler openDir(Smb::Context context, const QString& smb_string);
> + Smb::FileHandler openFile(Smb::Context context,const QString& smb_path,
> + int flags = O_RDONLY, mode_t mode = 0);
> + void closeHandle(Smb::Context context, Smb::FileHandler fd);
> + QStringList lisShares();
> + QStringList listContent(QString smb_path,
> + bool recursive = false,
> + QDir::Filters filters = QDir::AllEntries | QDir::NoDotAndDotDot,
> + const QStringList& filterNames = QStringList());
> +
> +
> +private:
> + StatReturn guessDirType(Smb::Context context, Smb::FileHandler fd);
> + bool checkValidShareName(const char *shareName);
> + QStringList walkForShares(QString smb_path);
> + QString findSmBServer(const smbc_dirent&);
> +
> +
> +private:
> + static void authenticateCallBack(
> + const char *server,
> + const char *share,
> + char *wrkgrp,
> + int wrkgrplen,
> + char *user,
> + int userlen,
> + char *passwd,
> + int passwdlen);
> +
> +protected:
> + void init(const QString& user, const QString& password, Smb::AuthenticationFunction fn);
> + bool namesMatchFilter(const QString& str, const QStringList& filterNames);
> +
> +private:
> + Smb::AuthenticationFunction m_authCallBack;
> +
> +
> +#if defined(REGRESSION_TEST_QSAMBACLIENT)
> + friend class TestQSambaSuite;
> +#endif
> +
> +};
> +
> +#endif // SMBUTIL_H
>
--
https://code.launchpad.net/~carlos-mazieri/ubuntu-filemanager-app/samba-browsing-04/+merge/252220
Your team Ubuntu File Manager Developers is subscribed to branch lp:ubuntu-filemanager-app.
References