← Back to team overview

ubuntu-touch-coreapps-reviewers team mailing list archive

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