← 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

 

Thanks. I will do small changes to match what you requested. Please wait.

Regarding SmbUtil comment:    "No users no password" - "If no user or no password is provided"
At line 336/337 from this listing there is:
      static QByteArray   s_user("guest");
      static QByteArray   s_passwd;
SmbUtil itself uses the "s_user" and "s_passwd" static variables.
There are different constructors to provide some flexibility, the SmbUtil::SmbUtil(void) from here in lines 346-349 initializes with the current user. It is only necessary when'guests' are not allowed in shares.
SmbLocation will provide its authentication function to SmbUtil, this function will use an array of pairs user/password.

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

At line 45/46/47 of the line there is:
    static QByteArray   s_user("guest");
    static QByteArray   s_passwd;

But later in LocationSmb class will have an array of the pair user/passsword starting the user with the current user instead of 'guest'

> + *
> + * \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));
> +    StatReturn 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;
> +        }
> +        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 )
> +    {
> +        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