summaryrefslogtreecommitdiffstats
path: root/tdeioslave/smb
diff options
context:
space:
mode:
Diffstat (limited to 'tdeioslave/smb')
-rw-r--r--tdeioslave/smb/CMakeLists.txt43
-rw-r--r--tdeioslave/smb/ConfigureChecks.cmake26
-rw-r--r--tdeioslave/smb/Makefile.am37
-rw-r--r--tdeioslave/smb/configure.in.bot9
-rw-r--r--tdeioslave/smb/configure.in.in34
-rw-r--r--tdeioslave/smb/kio_smb.cpp77
-rw-r--r--tdeioslave/smb/kio_smb.h301
-rw-r--r--tdeioslave/smb/kio_smb_auth.cpp207
-rw-r--r--tdeioslave/smb/kio_smb_browse.cpp476
-rw-r--r--tdeioslave/smb/kio_smb_config.cpp66
-rw-r--r--tdeioslave/smb/kio_smb_dir.cpp345
-rw-r--r--tdeioslave/smb/kio_smb_file.cpp279
-rw-r--r--tdeioslave/smb/kio_smb_internal.cpp135
-rw-r--r--tdeioslave/smb/kio_smb_internal.h118
-rw-r--r--tdeioslave/smb/kio_smb_mount.cpp211
-rw-r--r--tdeioslave/smb/libsmbclient-HOWTO.txt11
-rw-r--r--tdeioslave/smb/smb-network.desktop80
-rw-r--r--tdeioslave/smb/smb.protocol12
-rw-r--r--tdeioslave/smb/x-smb-server.desktop76
-rw-r--r--tdeioslave/smb/x-smb-workgroup.desktop74
20 files changed, 2617 insertions, 0 deletions
diff --git a/tdeioslave/smb/CMakeLists.txt b/tdeioslave/smb/CMakeLists.txt
new file mode 100644
index 000000000..2493c2a85
--- /dev/null
+++ b/tdeioslave/smb/CMakeLists.txt
@@ -0,0 +1,43 @@
+#################################################
+#
+# (C) 2010-2011 Serghei Amelian
+# serghei (DOT) amelian (AT) gmail.com
+#
+# Improvements and feedback are welcome
+#
+# This file is released under GPL >= 2
+#
+#################################################
+
+include( ConfigureChecks.cmake )
+
+include_directories(
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}
+ ${TDE_INCLUDE_DIR}
+ ${TQT_INCLUDE_DIRS}
+ ${SMBCLIENT_INCLUDE_DIRS}
+)
+
+link_directories(
+ ${TQT_LIBRARY_DIRS}
+)
+
+
+##### other data ################################
+
+install( FILES smb.protocol DESTINATION ${SERVICES_INSTALL_DIR} )
+install( FILES smb-network.desktop DESTINATION ${DATA_INSTALL_DIR}/konqueror/dirtree/remote )
+install( FILES smb-network.desktop DESTINATION ${DATA_INSTALL_DIR}/remoteview )
+install( FILES x-smb-workgroup.desktop x-smb-server.desktop DESTINATION ${MIME_INSTALL_DIR}/application )
+
+
+##### kio_smb (module) ##########################
+
+tde_add_kpart( kio_smb AUTOMOC
+ SOURCES
+ kio_smb.cpp kio_smb_auth.cpp kio_smb_browse.cpp kio_smb_config.cpp
+ kio_smb_dir.cpp kio_smb_file.cpp kio_smb_internal.cpp kio_smb_mount.cpp
+ LINK tdeio-shared ${SMBCLIENT_LIBRARIES}
+ DESTINATION ${PLUGIN_INSTALL_DIR}
+)
diff --git a/tdeioslave/smb/ConfigureChecks.cmake b/tdeioslave/smb/ConfigureChecks.cmake
new file mode 100644
index 000000000..da4d1a942
--- /dev/null
+++ b/tdeioslave/smb/ConfigureChecks.cmake
@@ -0,0 +1,26 @@
+#################################################
+#
+# (C) 2010-2011 Serghei Amelian
+# serghei (DOT) amelian (AT) gmail.com
+#
+# Improvements and feedback are welcome
+#
+# This file is released under GPL >= 2
+#
+#################################################
+
+pkg_search_module ( SMBCLIENT smbclient )
+if( SMBCLIENT_FOUND )
+ set( HAVE_LIBSMBCLIENT_H 1 )
+else( )
+ check_include_file( libsmbclient.h HAVE_LIBSMBCLIENT_H )
+endif( )
+
+if( HAVE_LIBSMBCLIENT_H )
+ set( SMBCLIENT_LIBRARIES smbclient )
+ check_library_exists( ${SMBCLIENT_LIBRARIES} smbc_new_context "" HAVE_SMBCLIENT )
+endif( )
+
+if( NOT HAVE_LIBSMBCLIENT_H OR NOT HAVE_SMBCLIENT )
+ tde_message_fatal( "smbclient is requested, but was not found on your system." )
+endif( )
diff --git a/tdeioslave/smb/Makefile.am b/tdeioslave/smb/Makefile.am
new file mode 100644
index 000000000..97a4034da
--- /dev/null
+++ b/tdeioslave/smb/Makefile.am
@@ -0,0 +1,37 @@
+## Makefile.am of tdebase/tdeioslave/man
+
+INCLUDES=$(all_includes)
+
+kde_module_LTLIBRARIES = kio_smb.la
+kio_smb_la_SOURCES = kio_smb.cpp \
+ kio_smb_auth.cpp \
+ kio_smb_browse.cpp \
+ kio_smb_config.cpp \
+ kio_smb_dir.cpp \
+ kio_smb_file.cpp \
+ kio_smb_internal.cpp \
+ kio_smb_mount.cpp
+
+kio_smb_la_LIBADD = -lkio -lsmbclient $(SMBCLIENT_EXTRA_LIBS)
+
+kio_smb_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN)
+
+noinst_HEADERS = kio_smb.h kio_smb_internal.h
+
+kdelnk_DATA = smb.protocol
+
+kdelnkdir = $(kde_servicesdir)
+
+dirtree_DATA = smb-network.desktop
+dirtreedir = $(kde_datadir)/konqueror/dirtree/remote
+
+remote_DATA = smb-network.desktop
+remotedir = $(kde_datadir)/remoteview
+
+METASOURCES = AUTO
+
+mimetypedir = $(kde_mimedir)/application
+mimetype_DATA = x-smb-workgroup.desktop x-smb-server.desktop
+
+messages:
+ $(XGETTEXT) *.cpp -o $(podir)/tdeio_smb.pot
diff --git a/tdeioslave/smb/configure.in.bot b/tdeioslave/smb/configure.in.bot
new file mode 100644
index 000000000..a8a95566c
--- /dev/null
+++ b/tdeioslave/smb/configure.in.bot
@@ -0,0 +1,9 @@
+if test "x$with_samba" = xcheck && test "x$have_libsmbclient" = xno; then
+ echo ""
+ echo "You're missing libsmbclient from samba 3.0"
+ echo "KDE will not be able to browse windows shares without it,"
+ echo "consider installing it."
+ echo "Look at tdeioslave/smb/libsmbclient-HOWTO.txt"
+ echo ""
+ all_tests=bad
+fi
diff --git a/tdeioslave/smb/configure.in.in b/tdeioslave/smb/configure.in.in
new file mode 100644
index 000000000..59b8272c8
--- /dev/null
+++ b/tdeioslave/smb/configure.in.in
@@ -0,0 +1,34 @@
+AC_DEFUN([SMB_CHECK],
+[
+AC_REQUIRE([KDE_CHECK_LARGEFILE])
+
+AC_ARG_WITH(samba,
+ [AC_HELP_STRING(--with-samba,
+ [enable the samba ioslave @<:@default=check@:>@])],
+ [], with_samba=check)
+
+have_libsmbclient=no
+if test "x$with_samba" != xno; then
+ have_libsmbclient=yes
+ KDE_CHECK_HEADER(libsmbclient.h, [], [have_libsmbclient=no])
+ KDE_CHECK_LIB(smbclient, smbc_new_context, [], [have_libsmbclient=no])
+
+ SMBCLIENT_EXTRA_LIBS=""
+ AC_CHECK_FUNC(yp_get_default_domain, [],
+ [
+ KDE_CHECK_LIB(nsl, yp_get_default_domain,
+ [SMBCLIENT_EXTRA_LIBS="-lnsl"] )
+ ])
+
+ AC_SUBST(SMBCLIENT_EXTRA_LIBS)
+
+ if test "x$with_samba" != xcheck && test "x$have_libsmbclient" = xno; then
+ AC_MSG_ERROR([--with-samba was given, but test for libsmbclient failed])
+ fi
+fi
+
+AM_CONDITIONAL(include_tdeioslave_smb, test "x$have_libsmbclient" = xyes)
+
+])
+
+SMB_CHECK
diff --git a/tdeioslave/smb/kio_smb.cpp b/tdeioslave/smb/kio_smb.cpp
new file mode 100644
index 000000000..193df965f
--- /dev/null
+++ b/tdeioslave/smb/kio_smb.cpp
@@ -0,0 +1,77 @@
+/////////////////////////////////////////////////////////////////////////////
+//
+// Project: SMB tdeioslave for KDE2
+//
+// File: Top level implementation file for kio_smb.cpp
+//
+// Abstract: member function implementations for SMBSlave
+//
+// Author(s): Matthew Peterson <mpeterson@caldera.com>
+//
+//---------------------------------------------------------------------------
+//
+// Copyright (c) 2000 Caldera Systems, Inc.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2.1 of the License, or
+// (at your option) any later version.
+//
+// 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 General Public License
+// along with this program; see the file COPYING. If not, please obtain
+// a copy from http://www.gnu.org/copyleft/gpl.html
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#include "kio_smb.h"
+#include "kio_smb_internal.h"
+
+//===========================================================================
+SMBSlave::SMBSlave(const TQCString& pool, const TQCString& app)
+ : SlaveBase( "smb", pool, app )
+{
+ m_initialized_smbc = false;
+
+ //read in the default workgroup info...
+ reparseConfiguration();
+
+ //initialize the library...
+ auth_initialize_smbc();
+}
+
+
+//===========================================================================
+SMBSlave::~SMBSlave()
+{
+}
+
+
+//===========================================================================
+// pointer to the slave created in kdemain
+SMBSlave* G_TheSlave;
+
+//===========================================================================
+int KDE_EXPORT kdemain( int argc, char **argv )
+{
+
+ TDEInstance instance( "kio_smb" );
+ if( argc != 4 )
+ {
+ kdDebug(KIO_SMB) << "Usage: kio_smb protocol domain-socket1 domain-socket2"
+ << endl;
+ return -1;
+ }
+
+ SMBSlave slave( argv[2], argv[3] );
+
+ G_TheSlave = &slave;
+ slave.dispatchLoop();
+
+ return 0;
+}
+
diff --git a/tdeioslave/smb/kio_smb.h b/tdeioslave/smb/kio_smb.h
new file mode 100644
index 000000000..34ad0200a
--- /dev/null
+++ b/tdeioslave/smb/kio_smb.h
@@ -0,0 +1,301 @@
+/////////////////////////////////////////////////////////////////////////////
+//
+// Project: SMB tdeioslave for KDE2
+//
+// File: kio_smb.h
+//
+// Abstract: The main kio slave class declaration. For convenience,
+// in concurrent devlopment, the implementation for this class
+// is separated into several .cpp files -- the file containing
+// the implementation should be noted in the comments for each
+// member function.
+//
+// Author(s): Matthew Peterson <mpeterson@caldera.com>
+//
+//---------------------------------------------------------------------------
+//
+// Copyright (c) 2000 Caldera Systems, Inc.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2.1 of the License, or
+// (at your option) any later version.
+//
+// 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 General Public License
+// along with this program; see the file COPYING. If not, please obtain
+// a copy from http://www.gnu.org/copyleft/gpl.html
+//
+/////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef KIO_SMB_H_INCLUDED
+#define KIO_SMB_H_INCLUDED
+
+//-------------
+// QT includes
+//-------------
+#include <tqstring.h>
+#include <tqptrlist.h>
+#include <tqstringlist.h>
+#include <tqtextstream.h>
+#include <tqstrlist.h>
+
+//--------------
+// KDE includes
+//--------------
+#include <kdebug.h>
+#include <kinstance.h>
+#include <tdeio/global.h>
+#include <tdeio/slavebase.h>
+#include <kurl.h>
+#include <klocale.h>
+
+//-----------------------------
+// Standard C library includes
+//-----------------------------
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <errno.h>
+#include <time.h>
+#include <tqobject.h>
+
+//-------------------------------
+// Samba client library includes
+//-------------------------------
+extern "C"
+{
+#include <libsmbclient.h>
+}
+
+//---------------------------
+// kio_smb internal includes
+//---------------------------
+#include "kio_smb_internal.h"
+
+#define MAX_XFER_BUF_SIZE 16348
+#define KIO_SMB 7106
+
+using namespace TDEIO;
+class TDEProcess;
+
+//===========================================================================
+
+
+class SMBSlave : public TQObject, public TDEIO::SlaveBase
+{
+ Q_OBJECT
+
+private:
+ //---------------------------------------------------------------------
+ // please make sure your private data does not duplicate existing data
+ //---------------------------------------------------------------------
+ bool m_initialized_smbc;
+
+ /**
+ * From Controlcenter
+ */
+ TQString m_default_user;
+// TQString m_default_workgroup; //currently unused, Alex <neundorf@kde.org>
+ TQString m_default_password;
+ TQString m_default_encoding;
+
+ /**
+ * we store the current url, it's needed for
+ * callback authorisation method
+ */
+ SMBUrl m_current_url;
+
+ /**
+ * From Controlcenter, show SHARE$ or not
+ */
+// bool m_showHiddenShares; //currently unused, Alex <neundorf@kde.org>
+
+ /**
+ * libsmbclient need global variables to store in,
+ * else it crashes on exit next method after use cache_stat,
+ * looks like gcc (C/C++) failure
+ */
+ struct stat st;
+protected:
+ //---------------------------------------------
+ // Authentication functions (kio_smb_auth.cpp)
+ //---------------------------------------------
+ // (please prefix functions with auth)
+
+
+ /**
+ * Description : Initilizes the libsmbclient
+ * Return : true on success false with errno set on error
+ */
+ bool auth_initialize_smbc();
+
+ bool checkPassword(SMBUrl &url);
+
+
+ //---------------------------------------------
+ // Cache functions (kio_smb_auth.cpp)
+ //---------------------------------------------
+
+ //Stat methods
+
+ //-----------------------------------------
+ // Browsing functions (kio_smb_browse.cpp)
+ //-----------------------------------------
+ // (please prefix functions with browse)
+
+ /**
+ * Description : Return a stat of given SMBUrl. Calls cache_stat and
+ * pack it in UDSEntry. UDSEntry will not be cleared
+ * Parameter : SMBUrl the url to stat
+ * ignore_errors do not call error(), but warning()
+ * Return : false if any error occoured (errno), else true
+ */
+ bool browse_stat_path(const SMBUrl& url, UDSEntry& udsentry, bool ignore_errors);
+
+ /**
+ * Description : call smbc_stat and return stats of the url
+ * Parameter : SMBUrl the url to stat
+ * Return : stat* of the url
+ * Note : it has some problems with stat in method, looks like
+ * something leave(or removed) on the stack. If your
+ * method segfault on returning try to change the stat*
+ * variable
+ */
+ int cache_stat( const SMBUrl& url, struct stat* st );
+
+ //---------------------------------------------
+ // Configuration functions (kio_smb_config.cpp)
+ //---------------------------------------------
+ // (please prefix functions with config)
+
+
+ //---------------------------------------
+ // Directory functions (kio_smb_dir.cpp)
+ //---------------------------------------
+ // (please prefix functions with dir)
+
+
+ //--------------------------------------
+ // File IO functions (kio_smb_file.cpp)
+ //--------------------------------------
+ // (please prefix functions with file)
+
+ //----------------------------
+ // Misc functions (this file)
+ //----------------------------
+
+
+ /**
+ * Description : correct a given URL
+ * valid URL's are
+ *
+ * smb://[[domain;]user[:password]@]server[:port][/share[/path[/file]]]
+ * smb:/[[domain;]user[:password]@][group/[server[/share[/path[/file]]]]]
+ * domain = workgroup(domain) of the user
+ * user = username
+ * password = password of useraccount
+ * group = workgroup(domain) of server
+ * server = host to connect
+ * share = a share of the server (host)
+ * path = a path of the share
+ * Parameter : KURL the url to check
+ * Return : new KURL if its corrected. else the same KURL
+ */
+ KURL checkURL(const KURL& kurl) const;
+
+ void reportError(const SMBUrl &kurl);
+
+public:
+
+ //-----------------------------------------------------------------------
+ // smbclient authentication callback (note that this is called by the
+ // global ::auth_smbc_get_data() call.
+ void auth_smbc_get_data(const char *server,const char *share,
+ char *workgroup, int wgmaxlen,
+ char *username, int unmaxlen,
+ char *password, int pwmaxlen);
+
+
+ //-----------------------------------------------------------------------
+ // Overwritten functions from the base class that define the operation of
+ // this slave. (See the base class headerfile slavebase.h for more
+ // details)
+ //-----------------------------------------------------------------------
+
+ // Functions overwritten in kio_smb.cpp
+ SMBSlave(const TQCString& pool, const TQCString& app);
+ virtual ~SMBSlave();
+
+ // Functions overwritten in kio_smb_browse.cpp
+ virtual void listDir( const KURL& url );
+ virtual void stat( const KURL& url );
+
+ // Functions overwritten in kio_smb_config.cpp
+ virtual void reparseConfiguration();
+
+ // Functions overwritten in kio_smb_dir.cpp
+ virtual void copy( const KURL& src, const KURL &dest, int permissions, bool overwrite );
+ virtual void del( const KURL& kurl, bool isfile);
+ virtual void mkdir( const KURL& kurl, int permissions );
+ virtual void rename( const KURL& src, const KURL& dest, bool overwrite );
+
+ // Functions overwritten in kio_smb_file.cpp
+ virtual void get( const KURL& kurl );
+ virtual void put( const KURL& kurl, int permissions, bool overwrite, bool resume );
+
+ // Functions not implemented (yet)
+ //virtual void setHost(const TQString& host, int port, const TQString& user, const TQString& pass);
+ //virtual void openConnection();
+ //virtual void closeConnection();
+ //virtual void slave_status();
+ virtual void special( const TQByteArray & );
+
+private slots:
+ void readOutput(TDEProcess *proc, char *buffer, int buflen);
+ void readStdErr(TDEProcess *proc, char *buffer, int buflen);
+
+private:
+ TQString mybuf, mystderr;
+
+};
+
+//===========================================================================
+// pointer to the slave created in kdemain
+extern SMBSlave* G_TheSlave;
+
+
+//==========================================================================
+// the global libsmbclient authentication callback function
+extern "C"
+{
+
+void auth_smbc_get_data(const char *server,const char *share,
+ char *workgroup, int wgmaxlen,
+ char *username, int unmaxlen,
+ char *password, int pwmaxlen);
+
+}
+
+
+//===========================================================================
+// Main slave entrypoint (see kio_smb.cpp)
+extern "C"
+{
+
+int kdemain( int argc, char **argv );
+
+}
+
+
+#endif //#endif KIO_SMB_H_INCLUDED
diff --git a/tdeioslave/smb/kio_smb_auth.cpp b/tdeioslave/smb/kio_smb_auth.cpp
new file mode 100644
index 000000000..f11d80b3a
--- /dev/null
+++ b/tdeioslave/smb/kio_smb_auth.cpp
@@ -0,0 +1,207 @@
+/////////////////////////////////////////////////////////////////////////////
+//
+// Project: SMB tdeioslave for KDE2
+//
+// File: kio_smb_auth.cpp
+//
+// Abstract: member function implementations for SMBSlave that deal with
+// SMB directory access
+//
+// Author(s): Matthew Peterson <mpeterson@caldera.com>
+//
+//---------------------------------------------------------------------------
+//
+// Copyright (c) 2000 Caldera Systems, Inc.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2.1 of the License, or
+// (at your option) any later version.
+//
+// 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 General Public License
+// along with this program; see the file COPYING. If not, please obtain
+// a copy from http://www.gnu.org/copyleft/gpl.html
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#include "kio_smb.h"
+#include "kio_smb_internal.h"
+
+#include <ksimpleconfig.h>
+#include <tqdir.h>
+#include <stdlib.h>
+
+// call for libsmbclient
+//==========================================================================
+void auth_smbc_get_data(const char *server,const char *share,
+ char *workgroup, int wgmaxlen,
+ char *username, int unmaxlen,
+ char *password, int pwmaxlen)
+//==========================================================================
+{
+ G_TheSlave->auth_smbc_get_data(server, share,
+ workgroup,wgmaxlen,
+ username, unmaxlen,
+ password, pwmaxlen);
+}
+
+//--------------------------------------------------------------------------
+void SMBSlave::auth_smbc_get_data(const char *server,const char *share,
+ char *workgroup, int wgmaxlen,
+ char *username, int unmaxlen,
+ char *password, int pwmaxlen)
+//--------------------------------------------------------------------------
+{
+ //check this to see if we "really" need to authenticate...
+ SMBUrlType t = m_current_url.getType();
+ if( t == SMBURLTYPE_ENTIRE_NETWORK )
+ {
+ kdDebug(KIO_SMB) << "we don't really need to authenticate for this top level url, returning" << endl;
+ return;
+ }
+ kdDebug(KIO_SMB) << "AAAAAAAAAAAAAA auth_smbc_get_dat: set user=" << username << ", workgroup=" << workgroup
+ << " server=" << server << ", share=" << share << endl;
+
+ TQString s_server = TQString::fromUtf8(server);
+ TQString s_share = TQString::fromUtf8(share);
+ workgroup[wgmaxlen - 1] = 0;
+ TQString s_workgroup = TQString::fromUtf8(workgroup);
+ username[unmaxlen - 1] = 0;
+ TQString s_username = TQString::fromUtf8(username);
+ password[pwmaxlen - 1] = 0;
+ TQString s_password = TQString::fromUtf8(password);
+
+ TDEIO::AuthInfo info;
+ info.url = KURL("smb:///");
+ info.url.setHost(s_server);
+ info.url.setPath("/" + s_share);
+
+ info.username = s_username;
+ info.password = s_password;
+ info.verifyPath = true;
+
+ kdDebug(KIO_SMB) << "libsmb-auth-callback URL:" << info.url << endl;
+
+ if ( !checkCachedAuthentication( info ) )
+ {
+ if ( m_default_user.isEmpty() )
+ {
+ // ok, we do not know the password. Let's try anonymous before we try for real
+ info.username = "anonymous";
+ info.password = TQString::null;
+ }
+ else
+ {
+ // user defined a default username/password in kcontrol; try this
+ info.username = m_default_user;
+ info.password = m_default_password;
+ }
+
+ } else
+ kdDebug(KIO_SMB) << "got password through cache" << endl;
+
+ strncpy(username, info.username.utf8(), unmaxlen - 1);
+ strncpy(password, info.password.utf8(), pwmaxlen - 1);
+}
+
+bool SMBSlave::checkPassword(SMBUrl &url)
+{
+ kdDebug(KIO_SMB) << "checkPassword for " << url << endl;
+
+ TDEIO::AuthInfo info;
+ info.url = KURL("smb:///");
+ info.url.setHost(url.host());
+
+ TQString share = url.path();
+ int index = share.find('/', 1);
+ if (index > 1)
+ share = share.left(index);
+ if (share.at(0) == '/')
+ share = share.mid(1);
+ info.url.setPath("/" + share);
+ info.verifyPath = true;
+
+ if ( share.isEmpty() )
+ info.prompt = i18n(
+ "<qt>Please enter authentication information for <b>%1</b></qt>" )
+ .arg( url.host() );
+ else
+ info.prompt = i18n(
+ "Please enter authentication information for:\n"
+ "Server = %1\n"
+ "Share = %2" )
+ .arg( url.host() )
+ .arg( share );
+
+ info.username = url.user();
+ kdDebug(KIO_SMB) << "call openPassDlg for " << info.url << endl;
+
+ if ( openPassDlg(info) ) {
+ kdDebug(KIO_SMB) << "openPassDlg returned " << info.username << endl;
+ url.setUser(info.username);
+ url.setPass(info.password);
+ return true;
+ }
+ kdDebug(KIO_SMB) << "no value from openPassDlg\n";
+ return false;
+}
+
+//--------------------------------------------------------------------------
+// Initalizes the smbclient library
+//
+// Returns: 0 on success -1 with errno set on error
+bool SMBSlave::auth_initialize_smbc()
+{
+ SMBCCTX *smb_context = NULL;
+
+ kdDebug(KIO_SMB) << "auth_initialize_smbc " << endl;
+ if(m_initialized_smbc == false)
+ {
+ kdDebug(KIO_SMB) << "smbc_init call" << endl;
+ KSimpleConfig cfg( "tdeioslaverc", true );
+
+ cfg.setGroup( "SMB" );
+ int debug_level = cfg.readNumEntry( "DebugLevel", 0 );
+
+#if 0
+ /* old API initialisation routine does not allow to set flags */
+
+ if(smbc_init(::auth_smbc_get_data,debug_level) == -1)
+ {
+ SlaveBase::error(ERR_INTERNAL, i18n("libsmbclient failed to initialize"));
+ return false;
+ }
+#endif
+ smb_context = smbc_new_context();
+ if (smb_context == NULL) {
+ SlaveBase::error(ERR_INTERNAL, i18n("libsmbclient failed to create context"));
+ return false;
+ }
+
+ smb_context->debug = debug_level;
+ smb_context->callbacks.auth_fn = ::auth_smbc_get_data;
+
+ if (!smbc_init_context(smb_context)) {
+ smbc_free_context(smb_context, false);
+ smb_context = NULL;
+ SlaveBase::error(ERR_INTERNAL, i18n("libsmbclient failed to initialize context"));
+ return false;
+ }
+
+#if defined(SMB_CTX_FLAG_USE_KERBEROS) && defined(SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS)
+ smb_context->flags |= SMB_CTX_FLAG_USE_KERBEROS | SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS;
+#endif
+
+ smbc_set_context(smb_context);
+
+ m_initialized_smbc = true;
+ }
+
+ return true;
+}
+
diff --git a/tdeioslave/smb/kio_smb_browse.cpp b/tdeioslave/smb/kio_smb_browse.cpp
new file mode 100644
index 000000000..26c379bde
--- /dev/null
+++ b/tdeioslave/smb/kio_smb_browse.cpp
@@ -0,0 +1,476 @@
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Project: SMB tdeioslave for KDE2
+//
+// File: kio_smb_browse.cpp
+//
+// Abstract: member function implementations for SMBSlave that deal with
+// SMB browsing
+//
+// Author(s): Matthew Peterson <mpeterson@caldera.com>
+//
+//---------------------------------------------------------------------------
+//
+// Copyright (c) 2000 Caldera Systems, Inc.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2.1 of the License, or
+// (at your option) any later version.
+//
+// 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 General Public License
+// along with this program; see the file COPYING. If not, please obtain
+// a copy from http://www.gnu.org/copyleft/gpl.html
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#include <config.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include <tqtextcodec.h>
+
+#include <kglobal.h>
+
+#include "kio_smb.h"
+#include "kio_smb_internal.h"
+
+using namespace TDEIO;
+
+int SMBSlave::cache_stat(const SMBUrl &url, struct stat* st )
+{
+ int result = smbc_stat( url.toSmbcUrl(), st);
+ kdDebug(KIO_SMB) << "smbc_stat " << url << " " << errno << " " << result << endl;
+ kdDebug(KIO_SMB) << "size " << (TDEIO::filesize_t)st->st_size << endl;
+ return result;
+}
+
+//---------------------------------------------------------------------------
+bool SMBSlave::browse_stat_path(const SMBUrl& _url, UDSEntry& udsentry, bool ignore_errors)
+ // Returns: true on success, false on failure
+{
+ UDSAtom udsatom;
+
+ SMBUrl url = _url;
+
+ if(cache_stat(url, &st) == 0)
+ {
+ if(!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode))
+ {
+ kdDebug(KIO_SMB)<<"SMBSlave::browse_stat_path mode: "<<st.st_mode<<endl;
+ warning(i18n("%1:\n"
+ "Unknown file type, neither directory or file.").arg(url.prettyURL()));
+ return false;
+ }
+
+ udsatom.m_uds = TDEIO::UDS_FILE_TYPE;
+ udsatom.m_long = st.st_mode & S_IFMT;
+ udsentry.append(udsatom);
+
+ udsatom.m_uds = TDEIO::UDS_SIZE;
+ udsatom.m_long = st.st_size;
+ udsentry.append(udsatom);
+
+ udsatom.m_uds = TDEIO::UDS_USER;
+ uid_t uid = st.st_uid;
+ struct passwd *user = getpwuid( uid );
+ if ( user )
+ udsatom.m_str = user->pw_name;
+ else
+ udsatom.m_str = TQString::number( uid );
+ udsentry.append(udsatom);
+
+ udsatom.m_uds = TDEIO::UDS_GROUP;
+ gid_t gid = st.st_gid;
+ struct group *grp = getgrgid( gid );
+ if ( grp )
+ udsatom.m_str = grp->gr_name;
+ else
+ udsatom.m_str = TQString::number( gid );
+ udsentry.append(udsatom);
+
+ udsatom.m_uds = TDEIO::UDS_ACCESS;
+ udsatom.m_long = st.st_mode & 07777;
+ udsentry.append(udsatom);
+
+ udsatom.m_uds = UDS_MODIFICATION_TIME;
+ udsatom.m_long = st.st_mtime;
+ udsentry.append(udsatom);
+
+ udsatom.m_uds = UDS_ACCESS_TIME;
+ udsatom.m_long = st.st_atime;
+ udsentry.append(udsatom);
+
+ udsatom.m_uds = UDS_CREATION_TIME;
+ udsatom.m_long = st.st_ctime;
+ udsentry.append(udsatom);
+
+ }
+ else
+ {
+ if (!ignore_errors) {
+ if (errno == EPERM || errno == EACCES)
+ if (checkPassword(url)) {
+ redirection( url );
+ return false;
+ }
+
+ reportError(url);
+ } else if (errno == ENOENT || errno == ENOTDIR) {
+ warning(i18n("File does not exist: %1").arg(url.url()));
+ }
+ kdDebug(KIO_SMB) << "SMBSlave::browse_stat_path ERROR!!"<< endl;
+ return false;
+ }
+
+ return true;
+}
+
+//===========================================================================
+void SMBSlave::stat( const KURL& kurl )
+{
+ kdDebug(KIO_SMB) << "SMBSlave::stat on "<< kurl << endl;
+ // make a valid URL
+ KURL url = checkURL(kurl);
+
+ // if URL is not valid we have to redirect to correct URL
+ if (url != kurl)
+ {
+ kdDebug() << "redirection " << url << endl;
+ redirection(url);
+ finished();
+ return;
+ }
+
+ m_current_url = url;
+
+ UDSAtom udsatom;
+ UDSEntry udsentry;
+ // Set name
+ udsatom.m_uds = TDEIO::UDS_NAME;
+ udsatom.m_str = kurl.fileName();
+ udsentry.append( udsatom );
+
+ switch(m_current_url.getType())
+ {
+ case SMBURLTYPE_UNKNOWN:
+ error(ERR_MALFORMED_URL,m_current_url.prettyURL());
+ finished();
+ return;
+
+ case SMBURLTYPE_ENTIRE_NETWORK:
+ case SMBURLTYPE_WORKGROUP_OR_SERVER:
+ udsatom.m_uds = TDEIO::UDS_FILE_TYPE;
+ udsatom.m_long = S_IFDIR;
+ udsentry.append(udsatom);
+ break;
+
+ case SMBURLTYPE_SHARE_OR_PATH:
+ if (browse_stat_path(m_current_url, udsentry, false))
+ break;
+ else {
+ kdDebug(KIO_SMB) << "SMBSlave::stat ERROR!!"<< endl;
+ finished();
+ return;
+ }
+ default:
+ kdDebug(KIO_SMB) << "SMBSlave::stat UNKNOWN " << url << endl;
+ finished();
+ return;
+ }
+
+ statEntry(udsentry);
+ finished();
+}
+
+//===========================================================================
+// TODO: complete checking
+KURL SMBSlave::checkURL(const KURL& kurl) const
+{
+ kdDebug(KIO_SMB) << "checkURL " << kurl << endl;
+ TQString surl = kurl.url();
+ if (surl.startsWith("smb:/")) {
+ if (surl.length() == 5) // just the above
+ return kurl; // unchanged
+
+ if (surl.at(5) != '/') {
+ surl = "smb://" + surl.mid(5);
+ kdDebug(KIO_SMB) << "checkURL return1 " << surl << " " << KURL(surl) << endl;
+ return KURL(surl);
+ }
+ }
+
+ // smb:/ normaly have no userinfo
+ // we must redirect ourself to remove the username and password
+ if (surl.contains('@') && !surl.contains("smb://")) {
+ KURL url(kurl);
+ url.setPath("/"+kurl.url().right( kurl.url().length()-kurl.url().find('@') -1));
+ TQString userinfo = kurl.url().mid(5, kurl.url().find('@')-5);
+ if(userinfo.contains(':')) {
+ url.setUser(userinfo.left(userinfo.find(':')));
+ url.setPass(userinfo.right(userinfo.length()-userinfo.find(':')-1));
+ } else {
+ url.setUser(userinfo);
+ }
+ kdDebug(KIO_SMB) << "checkURL return2 " << url << endl;
+ return url;
+ }
+
+ // no emtpy path
+ KURL url(kurl);
+
+ if (url.path().isEmpty())
+ url.setPath("/");
+
+ kdDebug(KIO_SMB) << "checkURL return3 " << url << endl;
+ return url;
+}
+
+void SMBSlave::reportError(const SMBUrl &url)
+{
+ kdDebug(KIO_SMB) << "reportError " << url << " " << perror << endl;
+ switch(errno)
+ {
+ case ENOENT:
+ if (url.getType() == SMBURLTYPE_ENTIRE_NETWORK)
+ error( ERR_SLAVE_DEFINED, i18n("Unable to find any workgroups in your local network. This might be caused by an enabled firewall."));
+ else
+ error( ERR_DOES_NOT_EXIST, url.prettyURL());
+ break;
+#ifdef ENOMEDIUM
+ case ENOMEDIUM:
+ error( ERR_SLAVE_DEFINED,
+ i18n( "No media in device for %1" ).arg( url.prettyURL() ) );
+ break;
+#endif
+#ifdef EHOSTDOWN
+ case EHOSTDOWN:
+#endif
+ case ECONNREFUSED:
+ error( ERR_SLAVE_DEFINED,
+ i18n( "Could not connect to host for %1" ).arg( url.prettyURL() ) );
+ break;
+ case ENOTDIR:
+ error( ERR_CANNOT_ENTER_DIRECTORY, url.prettyURL());
+ break;
+ case EFAULT:
+ case EINVAL:
+ error( ERR_DOES_NOT_EXIST, url.prettyURL());
+ break;
+ case EPERM:
+ case EACCES:
+ error( ERR_ACCESS_DENIED, url.prettyURL() );
+ break;
+ case EIO:
+ case ENETUNREACH:
+ if ( url.getType() == SMBURLTYPE_ENTIRE_NETWORK || url.getType() == SMBURLTYPE_WORKGROUP_OR_SERVER )
+ error( ERR_SLAVE_DEFINED, i18n( "Error while connecting to server responsible for %1" ).arg( url.prettyURL() ) );
+ else
+ error( ERR_CONNECTION_BROKEN, url.prettyURL());
+ break;
+ case ENOMEM:
+ error( ERR_OUT_OF_MEMORY, url.prettyURL() );
+ break;
+ case ENODEV:
+ error( ERR_SLAVE_DEFINED, i18n("Share could not be found on given server"));
+ break;
+ case EBADF:
+ error( ERR_INTERNAL, i18n("BAD File descriptor"));
+ break;
+ case ETIMEDOUT:
+ error( ERR_SERVER_TIMEOUT, url.host() );
+ break;
+#ifdef ENOTUNIQ
+ case ENOTUNIQ:
+ error( ERR_SLAVE_DEFINED, i18n( "The given name could not be resolved to a unique server. "
+ "Make sure your network is setup without any name conflicts "
+ "between names used by Windows and by UNIX name resolution." ) );
+ break;
+#endif
+ case 0: // success
+ error( ERR_INTERNAL, i18n("libsmbclient reported an error, but did not specify "
+ "what the problem is. This might indicate a severe problem "
+ "with your network - but also might indicate a problem with "
+ "libsmbclient.\n"
+ "If you want to help us, please provide a tcpdump of the "
+ "network interface while you try to browse (be aware that "
+ "it might contain private data, so do not post it if you are "
+ "unsure about that - you can send it privately to the developers "
+ "if they ask for it)") );
+ break;
+ default:
+ error( ERR_INTERNAL, i18n("Unknown error condition in stat: %1").arg(TQString::fromLocal8Bit( strerror(errno))) );
+ }
+}
+
+//===========================================================================
+void SMBSlave::listDir( const KURL& kurl )
+{
+ kdDebug(KIO_SMB) << "SMBSlave::listDir on " << kurl << endl;
+
+ // check (correct) URL
+ KURL url = checkURL(kurl);
+ // if URL is not valid we have to redirect to correct URL
+ if (url != kurl)
+ {
+ redirection(url);
+ finished();
+ return;
+ }
+
+ m_current_url = kurl;
+
+ int dirfd;
+ struct smbc_dirent *dirp = NULL;
+ UDSEntry udsentry;
+ UDSAtom atom;
+
+ dirfd = smbc_opendir( m_current_url.toSmbcUrl() );
+ kdDebug(KIO_SMB) << "SMBSlave::listDir open " << m_current_url.toSmbcUrl() << " " << m_current_url.getType() << " " << dirfd << endl;
+ if(dirfd >= 0)
+ {
+ do {
+ kdDebug(KIO_SMB) << "smbc_readdir " << endl;
+ dirp = smbc_readdir(dirfd);
+ if(dirp == 0)
+ break;
+
+ // Set name
+ atom.m_uds = TDEIO::UDS_NAME;
+ TQString dirpName = TQString::fromUtf8( dirp->name );
+ // We cannot trust dirp->commentlen has it might be with or without the NUL character
+ // See KDE bug #111430 and Samba bug #3030
+ TQString comment = TQString::fromUtf8( dirp->comment );
+ if ( dirp->smbc_type == SMBC_SERVER || dirp->smbc_type == SMBC_WORKGROUP ) {
+ atom.m_str = dirpName.lower();
+ atom.m_str.at( 0 ) = dirpName.at( 0 ).upper();
+ if ( !comment.isEmpty() && dirp->smbc_type == SMBC_SERVER )
+ atom.m_str += " (" + comment + ")";
+ } else
+ atom.m_str = dirpName;
+
+ kdDebug(KIO_SMB) << "dirp->name " << dirp->name << " " << dirpName << " '" << comment << "'" << " " << dirp->smbc_type << endl;
+
+ udsentry.append( atom );
+ if (atom.m_str.upper()=="IPC$" || atom.m_str=="." || atom.m_str == ".." ||
+ atom.m_str.upper() == "ADMIN$" || atom.m_str.lower() == "printer$" || atom.m_str.lower() == "print$" )
+ {
+// fprintf(stderr,"----------- hide: -%s-\n",dirp->name);
+ // do nothing and hide the hidden shares
+ }
+ else if(dirp->smbc_type == SMBC_FILE)
+ {
+ // Set stat information
+ m_current_url.addPath(dirpName);
+ browse_stat_path(m_current_url, udsentry, true);
+ m_current_url.cd("..");
+
+ // Call base class to list entry
+ listEntry(udsentry, false);
+ }
+ else if(dirp->smbc_type == SMBC_DIR)
+ {
+ m_current_url.addPath(dirpName);
+ browse_stat_path(m_current_url, udsentry, true);
+ m_current_url.cd("..");
+
+ // Call base class to list entry
+ listEntry(udsentry, false);
+ }
+ else if(dirp->smbc_type == SMBC_SERVER ||
+ dirp->smbc_type == SMBC_FILE_SHARE)
+ {
+ // Set type
+ atom.m_uds = TDEIO::UDS_FILE_TYPE;
+ atom.m_long = S_IFDIR;
+ udsentry.append( atom );
+
+ // Set permissions
+ atom.m_uds = TDEIO::UDS_ACCESS;
+ atom.m_long = (S_IRUSR | S_IRGRP | S_IROTH | S_IXUSR | S_IXGRP | S_IXOTH);
+ udsentry.append(atom);
+
+ if (dirp->smbc_type == SMBC_SERVER) {
+ atom.m_uds = TDEIO::UDS_URL;
+ // TQString workgroup = m_current_url.host().upper();
+ KURL u("smb:/");
+ u.setHost(dirpName);
+ atom.m_str = u.url();
+
+ // when libsmbclient knows
+ // atom.m_str = TQString("smb://%1?WORKGROUP=%2").arg(dirpName).arg(workgroup.upper());
+ kdDebug(KIO_SMB) << "list item " << atom.m_str << endl;
+ udsentry.append(atom);
+
+ atom.m_uds = TDEIO::UDS_MIME_TYPE;
+ atom.m_str = TQString::fromLatin1("application/x-smb-server");
+ udsentry.append(atom);
+ }
+
+ // Call base class to list entry
+ listEntry(udsentry, false);
+ }
+ else if(dirp->smbc_type == SMBC_WORKGROUP)
+ {
+ // Set type
+ atom.m_uds = TDEIO::UDS_FILE_TYPE;
+ atom.m_long = S_IFDIR;
+ udsentry.append( atom );
+
+ // Set permissions
+ atom.m_uds = TDEIO::UDS_ACCESS;
+ atom.m_long = (S_IRUSR | S_IRGRP | S_IROTH | S_IXUSR | S_IXGRP | S_IXOTH);
+ udsentry.append(atom);
+
+ atom.m_uds = TDEIO::UDS_MIME_TYPE;
+ atom.m_str = TQString::fromLatin1("application/x-smb-workgroup");
+ udsentry.append(atom);
+
+ atom.m_uds = TDEIO::UDS_URL;
+ // TQString workgroup = m_current_url.host().upper();
+ KURL u("smb:/");
+ u.setHost(dirpName);
+ atom.m_str = u.url();
+ udsentry.append(atom);
+
+ // Call base class to list entry
+ listEntry(udsentry, false);
+ }
+ else
+ {
+ kdDebug(KIO_SMB) << "SMBSlave::listDir SMBC_UNKNOWN :" << dirpName << endl;
+ // TODO: we don't handle SMBC_IPC_SHARE, SMBC_PRINTER_SHARE
+ // SMBC_LINK, SMBC_COMMS_SHARE
+ //SlaveBase::error(ERR_INTERNAL, TEXT_UNSUPPORTED_FILE_TYPE);
+ // continue;
+ }
+ udsentry.clear();
+ } while (dirp); // checked already in the head
+
+ // clean up
+ smbc_closedir(dirfd);
+ }
+ else
+ {
+ if (errno == EPERM || errno == EACCES)
+ if (checkPassword(m_current_url)) {
+ redirection( m_current_url );
+ finished();
+ return;
+ }
+
+ reportError(m_current_url);
+ finished();
+ return;
+ }
+
+ listEntry(udsentry, true);
+ finished();
+}
+
diff --git a/tdeioslave/smb/kio_smb_config.cpp b/tdeioslave/smb/kio_smb_config.cpp
new file mode 100644
index 000000000..8179371e7
--- /dev/null
+++ b/tdeioslave/smb/kio_smb_config.cpp
@@ -0,0 +1,66 @@
+/////////////////////////////////////////////////////////////////////////////
+//
+// Project: SMB tdeioslave for KDE2
+//
+// File: kio_smb_config.cpp
+//
+// Abstract: member function implementations for SMBSlave that deal with
+// KDE/SMB slave configuration
+//
+// Author(s): Matthew Peterson <mpeterson@caldera.com>
+//
+//---------------------------------------------------------------------------
+//
+// Copyright (c) 2000 Caldera Systems, Inc.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2.1 of the License, or
+// (at your option) any later version.
+//
+// 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 General Public License
+// along with this program; see the file COPYING. If not, please obtain
+// a copy from http://www.gnu.org/copyleft/gpl.html
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#include "kio_smb.h"
+#include "kio_smb_internal.h"
+#include <tdeconfig.h>
+
+#include <tqtextcodec.h>
+//===========================================================================
+void SMBSlave::reparseConfiguration()
+{
+ TDEConfig *cfg = new TDEConfig("tdeioslaverc", true);
+ cfg->setGroup("Browser Settings/SMBro");
+ m_default_user=cfg->readEntry("User");
+// m_default_workgroup=cfg->readEntry("Workgroup");
+// m_showHiddenShares=cfg->readBoolEntry("ShowHiddenShares",false);
+
+ TQString m_encoding = TQTextCodec::codecForLocale()->name();
+ m_default_encoding = cfg->readEntry( "Encoding", m_encoding.lower() );
+
+ // unscramble, taken from Nicola Brodu's smb ioslave
+ //not really secure, but better than storing the plain password
+ TQString scrambled = cfg->readEntry( "Password" );
+ m_default_password = "";
+ for (uint i=0; i<scrambled.length()/3; i++)
+ {
+ TQChar qc1 = scrambled[i*3];
+ TQChar qc2 = scrambled[i*3+1];
+ TQChar qc3 = scrambled[i*3+2];
+ unsigned int a1 = qc1.latin1() - '0';
+ unsigned int a2 = qc2.latin1() - 'A';
+ unsigned int a3 = qc3.latin1() - '0';
+ unsigned int num = ((a1 & 0x3F) << 10) | ((a2& 0x1F) << 5) | (a3 & 0x1F);
+ m_default_password[i] = TQChar((uchar)((num - 17) ^ 173)); // restore
+ }
+
+ delete cfg;
+}
diff --git a/tdeioslave/smb/kio_smb_dir.cpp b/tdeioslave/smb/kio_smb_dir.cpp
new file mode 100644
index 000000000..02dfc8100
--- /dev/null
+++ b/tdeioslave/smb/kio_smb_dir.cpp
@@ -0,0 +1,345 @@
+/////////////////////////////////////////////////////////////////////////////
+//
+// Project: SMB tdeioslave for KDE2
+//
+// File: kio_smb_dir.cpp
+//
+// Abstract: member function implementations for SMBSlave that deal with
+// SMB directory access
+//
+// Author(s): Matthew Peterson <mpeterson@caldera.com>
+//
+////---------------------------------------------------------------------------
+//
+// Copyright (c) 2000 Caldera Systems, Inc.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2.1 of the License, or
+// (at your option) any later version.
+//
+// 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 General Public License
+// along with this program; see the file COPYING. If not, please obtain
+// a copy from http://www.gnu.org/copyleft/gpl.html
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#include "kio_smb.h"
+#include "kio_smb_internal.h"
+
+
+//===========================================================================
+// TODO: add when libsmbclient supports it
+void SMBSlave::copy( const KURL& ksrc,
+ const KURL& kdst,
+ int permissions,
+ bool overwrite)
+{
+
+ SMBUrl src;
+ SMBUrl dst;
+ mode_t initialmode;
+ int n;
+ int dstflags;
+ int srcfd = -1;
+ int dstfd = -1;
+ TDEIO::filesize_t processed_size = 0;
+ unsigned char buf[MAX_XFER_BUF_SIZE];
+
+ kdDebug(KIO_SMB) << "SMBSlave::copy with src = " << ksrc << "and dest = " << kdst << endl;
+
+ // setup urls
+ src = ksrc;
+ dst = kdst;
+
+ // Obtain information about source
+ if(cache_stat(src, &st ) == -1)
+ {
+ if ( errno == EACCES )
+ {
+ error( TDEIO::ERR_ACCESS_DENIED, src.prettyURL());
+ }
+ else
+ {
+ error( TDEIO::ERR_DOES_NOT_EXIST, src.prettyURL());
+ }
+ return;
+ }
+ if ( S_ISDIR( st.st_mode ) )
+ {
+ error( TDEIO::ERR_IS_DIRECTORY, src.prettyURL() );
+ return;
+ }
+ totalSize(st.st_size);
+
+ // Check to se if the destination exists
+ if(cache_stat(dst, &st) != -1)
+ {
+ if(S_ISDIR(st.st_mode))
+ {
+ error( TDEIO::ERR_DIR_ALREADY_EXIST, dst.prettyURL());
+ return;
+ }
+ if(!overwrite)
+ {
+ error( TDEIO::ERR_FILE_ALREADY_EXIST, dst.prettyURL());
+ return;
+ }
+ }
+
+ // Open the source file
+ srcfd = smbc_open(src.toSmbcUrl(), O_RDONLY, 0);
+ if(srcfd < 0)
+ {
+ if(errno == EACCES)
+ {
+ error( TDEIO::ERR_ACCESS_DENIED, src.prettyURL() );
+ }
+ else
+ {
+ error( TDEIO::ERR_DOES_NOT_EXIST, src.prettyURL() );
+ }
+ return;
+ }
+
+ // Determine initial creation mode
+ if(permissions != -1)
+ {
+ initialmode = permissions | S_IWUSR;
+ }
+ else
+ {
+ initialmode = 0 | S_IWUSR;//0666;
+ }
+
+
+ // Open the destination file
+ dstflags = O_CREAT | O_TRUNC | O_WRONLY;
+ if(!overwrite)
+ {
+ dstflags |= O_EXCL;
+ }
+ dstfd = smbc_open(dst.toSmbcUrl(), dstflags, initialmode);
+ if(dstfd < 0)
+ {
+ if(errno == EACCES)
+ {
+ error(TDEIO::ERR_WRITE_ACCESS_DENIED, dst.prettyURL());
+ }
+ else
+ {
+ error(TDEIO::ERR_CANNOT_OPEN_FOR_READING, dst.prettyURL());
+ }
+ if(srcfd >= 0 )
+ {
+ smbc_close(srcfd);
+ }
+ return;
+ }
+
+
+ // Perform copy
+ while(1)
+ {
+ n = smbc_read(srcfd, buf, MAX_XFER_BUF_SIZE );
+ if(n > 0)
+ {
+ n = smbc_write(dstfd, buf, n);
+ if(n == -1)
+ {
+ kdDebug(KIO_SMB) << "SMBSlave::copy copy now TDEIO::ERR_COULD_NOT_WRITE" << endl;
+ error( TDEIO::ERR_COULD_NOT_WRITE, dst.prettyURL());
+ break;
+ }
+
+ processed_size += n;
+ processedSize(processed_size);
+ }
+ else if(n == 0)
+ {
+ break; // finished
+ }
+ else
+ {
+ error( TDEIO::ERR_COULD_NOT_READ, src.prettyURL());
+ break;
+ }
+ }
+
+
+ // FINISHED:
+
+ if(srcfd >= 0 )
+ {
+ smbc_close(srcfd);
+ }
+
+ if(dstfd >= 0)
+ {
+ if(smbc_close(dstfd) == 0)
+ {
+
+ // TODO: set final permissions
+ }
+ else
+ {
+ error( TDEIO::ERR_COULD_NOT_WRITE, dst.prettyURL());
+ return;
+ }
+ }
+
+ finished();
+}
+
+//===========================================================================
+void SMBSlave::del( const KURL &kurl, bool isfile)
+{
+ kdDebug(KIO_SMB) << "SMBSlave::del on " << kurl << endl;
+ m_current_url = kurl;
+
+ if(isfile)
+ {
+ // Delete file
+ kdDebug(KIO_SMB) << "SMBSlave:: unlink " << kurl << endl;
+ if(smbc_unlink(m_current_url.toSmbcUrl()) == -1)
+ {
+ switch(errno)
+ {
+ case EISDIR:
+ error( TDEIO::ERR_IS_DIRECTORY, m_current_url.prettyURL());
+ break;
+ default:
+ reportError(kurl);
+ }
+ }
+ }
+ else
+ {
+ kdDebug(KIO_SMB) << "SMBSlave:: rmdir " << kurl << endl;
+ // Delete directory
+ if(smbc_rmdir(m_current_url.toSmbcUrl()) == -1)
+ {
+ reportError(kurl);
+ }
+ }
+
+ finished();
+}
+
+//===========================================================================
+void SMBSlave::mkdir( const KURL &kurl, int permissions )
+{
+ kdDebug(KIO_SMB) << "SMBSlave::mkdir on " << kurl << endl;
+ m_current_url = kurl;
+
+ if(smbc_mkdir(m_current_url.toSmbcUrl(), 0777) != 0)
+ {
+ if (errno == EEXIST) {
+ if(cache_stat(m_current_url, &st ) == 0)
+ {
+ if(S_ISDIR(st.st_mode ))
+ {
+ error( TDEIO::ERR_DIR_ALREADY_EXIST, m_current_url.prettyURL());
+ }
+ }
+ else
+ {
+ error( TDEIO::ERR_FILE_ALREADY_EXIST, m_current_url.prettyURL());
+ }
+ } else
+ reportError(kurl);
+ kdDebug(KIO_SMB) << "SMBSlave::mkdir exit with error " << kurl << endl;
+ }
+ else
+ {
+ if(permissions != -1)
+ {
+ // TODO enable the following when complete
+ //smbc_chmod( url.toSmbcUrl(), permissions );
+ }
+ }
+
+ finished();
+}
+
+
+//===========================================================================
+void SMBSlave::rename( const KURL& ksrc, const KURL& kdest, bool overwrite )
+{
+
+ SMBUrl src;
+ SMBUrl dst;
+
+ kdDebug(KIO_SMB) << "SMBSlave::rename, old name = " << ksrc << ", new name = " << kdest << endl;
+
+ src = ksrc;
+ dst = kdest;
+
+ // Check to se if the destination exists
+
+ kdDebug(KIO_SMB) << "SMBSlave::rename stat dst" << endl;
+ if(cache_stat(dst, &st) != -1)
+ {
+ if(S_ISDIR(st.st_mode))
+ {
+ kdDebug(KIO_SMB) << "SMBSlave::rename TDEIO::ERR_DIR_ALREADY_EXIST" << endl;
+ error( TDEIO::ERR_DIR_ALREADY_EXIST, dst.prettyURL());
+ finished();
+ return;
+ }
+ if(!overwrite)
+ {
+ kdDebug(KIO_SMB) << "SMBSlave::rename TDEIO::ERR_FILE_ALREADY_EXIST" << endl;
+ error( TDEIO::ERR_FILE_ALREADY_EXIST, dst.prettyURL());
+ finished();
+ return;
+ }
+ }
+ kdDebug(KIO_SMB ) << "smbc_rename " << src.toSmbcUrl() << " " << dst.toSmbcUrl() << endl;
+ if(smbc_rename(src.toSmbcUrl(), dst.toSmbcUrl())!=0)
+ {
+ kdDebug(KIO_SMB ) << "failed " << perror << endl;
+ switch(errno)
+ {
+ case ENOENT:
+ if(cache_stat(src, &st) == -1)
+ {
+ if(errno == EACCES)
+ {
+ kdDebug(KIO_SMB) << "SMBSlave::rename TDEIO::ERR_ACCESS_DENIED" << endl;
+ error(TDEIO::ERR_ACCESS_DENIED, src.prettyURL());
+ }
+ else
+ {
+ kdDebug(KIO_SMB) << "SMBSlave::rename TDEIO::ERR_DOES_NOT_EXIST" << endl;
+ error(TDEIO::ERR_DOES_NOT_EXIST, src.prettyURL());
+ }
+ }
+ break;
+
+ case EACCES:
+ case EPERM:
+ kdDebug(KIO_SMB) << "SMBSlave::rename TDEIO::ERR_ACCESS_DENIED" << endl;
+ error( TDEIO::ERR_ACCESS_DENIED, dst.prettyURL() );
+ break;
+
+ default:
+ kdDebug(KIO_SMB) << "SMBSlave::rename TDEIO::ERR_CANNOT_RENAME" << endl;
+ error( TDEIO::ERR_CANNOT_RENAME, src.prettyURL() );
+
+ }
+
+ kdDebug(KIO_SMB) << "SMBSlave::rename exit with error" << endl;
+ return;
+ }
+
+ kdDebug(KIO_SMB ) << "everything fine\n";
+ finished();
+}
+
+
diff --git a/tdeioslave/smb/kio_smb_file.cpp b/tdeioslave/smb/kio_smb_file.cpp
new file mode 100644
index 000000000..b65f79f42
--- /dev/null
+++ b/tdeioslave/smb/kio_smb_file.cpp
@@ -0,0 +1,279 @@
+////////////////////////////////////////////////////////////////////////////
+//
+// Project: SMB tdeioslave for KDE2
+//
+// File: kio_smb_file.cpp
+//
+// Abstract: member function implementations for SMBSlave that deal with
+// SMB file access
+//
+// Author(s): Matthew Peterson <mpeterson@caldera.com>
+//
+//---------------------------------------------------------------------------
+//
+// Copyright (c) 2000 Caldera Systems, Inc.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2.1 of the License, or
+// (at your option) any later version.
+//
+// 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 General Public License
+// along with this program; see the file COPYING. If not, please obtain
+// a copy from http://www.gnu.org/copyleft/gpl.html
+//
+/////////////////////////////////////////////////////////////////////////////
+
+
+#include "kio_smb.h"
+#include "kio_smb_internal.h"
+
+#include <kmimetype.h>
+
+//===========================================================================
+void SMBSlave::get( const KURL& kurl )
+{
+ char buf[MAX_XFER_BUF_SIZE];
+ int filefd = 0;
+ ssize_t bytesread = 0;
+ // time_t curtime = 0;
+ time_t lasttime = 0;
+ time_t starttime = 0;
+ TDEIO::filesize_t totalbytesread = 0;
+ TQByteArray filedata;
+ SMBUrl url;
+
+ kdDebug(KIO_SMB) << "SMBSlave::get on " << kurl << endl;
+
+ // check (correct) URL
+ KURL kvurl = checkURL(kurl);
+ // if URL is not valid we have to redirect to correct URL
+ if (kvurl != kurl) {
+ redirection(kvurl);
+ finished();
+ return;
+ }
+
+ if(!auth_initialize_smbc())
+ return;
+
+
+ // Stat
+ url = kurl;
+ if(cache_stat(url,&st) == -1 )
+ {
+ if ( errno == EACCES )
+ error( TDEIO::ERR_ACCESS_DENIED, url.prettyURL());
+ else
+ error( TDEIO::ERR_DOES_NOT_EXIST, url.prettyURL());
+ return;
+ }
+ if ( S_ISDIR( st.st_mode ) ) {
+ error( TDEIO::ERR_IS_DIRECTORY, url.prettyURL());
+ return;
+ }
+
+ // Set the total size
+ totalSize( st.st_size );
+
+ // Open and read the file
+ filefd = smbc_open(url.toSmbcUrl(),O_RDONLY,0);
+ if(filefd >= 0)
+ {
+ if(buf)
+ {
+ bool isFirstPacket = true;
+ lasttime = starttime = time(NULL);
+ while(1)
+ {
+ bytesread = smbc_read(filefd, buf, MAX_XFER_BUF_SIZE);
+ if(bytesread == 0)
+ {
+ // All done reading
+ break;
+ }
+ else if(bytesread < 0)
+ {
+ error( TDEIO::ERR_COULD_NOT_READ, url.prettyURL());
+ return;
+ }
+
+ filedata.setRawData(buf,bytesread);
+ if (isFirstPacket)
+ {
+ // We need a KMimeType::findByNameAndContent(filename,data)
+ // For now we do: find by extension, and if not found (or extension not reliable)
+ // then find by content.
+ bool accurate = false;
+ KMimeType::Ptr mime = KMimeType::findByURL( kurl, st.st_mode, false, true, &accurate );
+ if ( !mime || mime->name() == KMimeType::defaultMimeType()
+ || !accurate )
+ {
+ KMimeType::Ptr p_mimeType = KMimeType::findByContent(filedata);
+ if ( p_mimeType && p_mimeType->name() != KMimeType::defaultMimeType() )
+ mime = p_mimeType;
+ }
+ mimeType(mime->name());
+ isFirstPacket = false;
+ }
+ data( filedata );
+ filedata.resetRawData(buf,bytesread);
+
+ // increment total bytes read
+ totalbytesread += bytesread;
+
+ processedSize(totalbytesread);
+ }
+ }
+
+ smbc_close(filefd);
+ data( TQByteArray() );
+ processedSize(static_cast<TDEIO::filesize_t>(st.st_size));
+
+ }
+ else
+ {
+ error( TDEIO::ERR_CANNOT_OPEN_FOR_READING, url.prettyURL());
+ return;
+ }
+
+ finished();
+}
+
+
+//===========================================================================
+void SMBSlave::put( const KURL& kurl,
+ int permissions,
+ bool overwrite,
+ bool resume )
+{
+
+ void *buf;
+ size_t bufsize;
+
+ m_current_url = kurl;
+
+ int filefd;
+ bool exists;
+ mode_t mode;
+ TQByteArray filedata;
+
+ kdDebug(KIO_SMB) << "SMBSlave::put on " << kurl << endl;
+
+
+ exists = (cache_stat(m_current_url, &st) != -1 );
+ if ( exists && !overwrite && !resume)
+ {
+ if (S_ISDIR(st.st_mode))
+ {
+ kdDebug(KIO_SMB) << "SMBSlave::put on " << kurl <<" already isdir !!"<< endl;
+ error( TDEIO::ERR_DIR_ALREADY_EXIST, m_current_url.prettyURL());
+ }
+ else
+ {
+ kdDebug(KIO_SMB) << "SMBSlave::put on " << kurl <<" already exist !!"<< endl;
+ error( TDEIO::ERR_FILE_ALREADY_EXIST, m_current_url.prettyURL());
+ }
+ return;
+ }
+
+ if (exists && !resume && overwrite)
+ {
+ kdDebug(KIO_SMB) << "SMBSlave::put exists try to remove " << m_current_url.toSmbcUrl()<< endl;
+ // remove(m_current_url.url().local8Bit());
+ }
+
+
+ if (resume)
+ {
+ // append if resuming
+ kdDebug(KIO_SMB) << "SMBSlave::put resume " << m_current_url.toSmbcUrl()<< endl;
+ filefd = smbc_open(m_current_url.toSmbcUrl(), O_RDWR, 0 );
+ smbc_lseek(filefd, 0, SEEK_END);
+ }
+ else
+ {
+ if (permissions != -1)
+ {
+ mode = permissions | S_IWUSR | S_IRUSR;
+ }
+ else
+ {
+ mode = 600;//0666;
+ }
+
+ kdDebug(KIO_SMB) << "SMBSlave::put NO resume " << m_current_url.toSmbcUrl()<< endl;
+ filefd = smbc_open(m_current_url.toSmbcUrl(), O_CREAT | O_TRUNC | O_WRONLY, mode);
+ }
+
+ if ( filefd < 0 )
+ {
+ if ( errno == EACCES )
+ {
+ kdDebug(KIO_SMB) << "SMBSlave::put error " << kurl <<" access denied !!"<< endl;
+ error( TDEIO::ERR_WRITE_ACCESS_DENIED, m_current_url.prettyURL());
+ }
+ else
+ {
+ kdDebug(KIO_SMB) << "SMBSlave::put error " << kurl <<" can not open for writing !!"<< endl;
+ error( TDEIO::ERR_CANNOT_OPEN_FOR_WRITING, m_current_url.prettyURL());
+ }
+ finished();
+ return;
+ }
+
+ // Loop until we got 0 (end of data)
+ while(1)
+ {
+ kdDebug(KIO_SMB) << "SMBSlave::put request data "<< endl;
+ dataReq(); // Request for data
+ kdDebug(KIO_SMB) << "SMBSlave::put write " << m_current_url.toSmbcUrl()<< endl;
+
+ if (readData(filedata) <= 0)
+ {
+ kdDebug(KIO_SMB) << "readData <= 0" << endl;
+ break;
+ }
+ kdDebug(KIO_SMB) << "SMBSlave::put write " << m_current_url.toSmbcUrl()<< endl;
+ buf = filedata.data();
+ bufsize = filedata.size();
+ int size = smbc_write(filefd, buf, bufsize);
+ if ( size < 0)
+ {
+ kdDebug(KIO_SMB) << "SMBSlave::put error " << kurl <<" could not write !!"<< endl;
+ error( TDEIO::ERR_COULD_NOT_WRITE, m_current_url.prettyURL());
+ finished();
+ return;
+ }
+ kdDebug(KIO_SMB ) << "wrote " << size << endl;
+ }
+ kdDebug(KIO_SMB) << "SMBSlave::put close " << m_current_url.toSmbcUrl()<< endl;
+
+ if(smbc_close(filefd))
+ {
+ kdDebug(KIO_SMB) << "SMBSlave::put on " << kurl <<" could not write !!"<< endl;
+ error( TDEIO::ERR_COULD_NOT_WRITE, m_current_url.prettyURL());
+ finished();
+ return;
+ }
+
+ // set final permissions, if the file was just created
+ if ( permissions != -1 && !exists )
+ {
+ // TODO: did the smbc_chmod fail?
+ // TODO: put in call to chmod when it is working!
+ // smbc_chmod(url.toSmbcUrl(),permissions);
+ }
+
+ // We have done our job => finish
+ finished();
+}
+
+
+
+
diff --git a/tdeioslave/smb/kio_smb_internal.cpp b/tdeioslave/smb/kio_smb_internal.cpp
new file mode 100644
index 000000000..8f56a8f62
--- /dev/null
+++ b/tdeioslave/smb/kio_smb_internal.cpp
@@ -0,0 +1,135 @@
+/////////////////////////////////////////////////////////////////////////////
+//
+// Project: SMB tdeioslave for KDE2
+//
+// File: kio_smb_internal.cpp
+//
+// Abstract: Utility class implementation used by SMBSlave
+//
+// Author(s): Matthew Peterson <mpeterson@caldera.com>
+//
+//---------------------------------------------------------------------------
+//
+// Copyright (c) 2000 Caldera Systems, Inc.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2.1 of the License, or
+// (at your option) any later version.
+//
+// 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 General Public License
+// along with this program; see the file COPYING. If not, please obtain
+// a copy from http://www.gnu.org/copyleft/gpl.html
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#include "kio_smb.h"
+#include "kio_smb_internal.h"
+
+#include <tqtextcodec.h>
+
+#include <tdeconfig.h>
+#include <kglobal.h>
+
+
+//===========================================================================
+// SMBUrl Function Implementation
+//===========================================================================
+
+//-----------------------------------------------------------------------
+SMBUrl::SMBUrl()
+{
+ m_type = SMBURLTYPE_UNKNOWN;
+}
+
+//-----------------------------------------------------------------------
+SMBUrl::SMBUrl(const KURL& kurl)
+ : KURL(kurl)
+ //-----------------------------------------------------------------------
+{
+ updateCache();
+}
+
+
+//-----------------------------------------------------------------------
+void SMBUrl::addPath(const TQString &filedir)
+{
+ KURL::addPath(filedir);
+ updateCache();
+}
+
+//-----------------------------------------------------------------------
+bool SMBUrl::cd(const TQString &filedir)
+{
+ if (!KURL::cd(filedir))
+ return false;
+ updateCache();
+ return true;
+}
+
+//-----------------------------------------------------------------------
+void SMBUrl::updateCache()
+ //-----------------------------------------------------------------------
+{
+ cleanPath();
+
+ // SMB URLs are UTF-8 encoded
+ kdDebug(KIO_SMB) << "updateCache " << KURL::path() << endl;
+ if (KURL::url() == "smb:/")
+ m_surl = "smb://";
+ else {
+ TQString surl = "smb://";
+ if (KURL::hasUser()) {
+ surl += KURL::encode_string(KURL::user(), 106);
+ if (KURL::hasPass()) {
+ surl += ":" + KURL::encode_string(KURL::pass(), 106);
+ }
+ surl += "@";
+ }
+ surl += KURL::encode_string(KURL::host().upper(), 106);
+ surl += KURL::encode_string(KURL::path(), 106);
+ m_surl = surl.utf8();
+ }
+ m_type = SMBURLTYPE_UNKNOWN;
+ // update m_type
+ (void)getType();
+}
+
+//-----------------------------------------------------------------------
+SMBUrlType SMBUrl::getType() const
+ // Returns the type of this SMBUrl:
+ // SMBURLTYPE_UNKNOWN - Type could not be determined. Bad SMB Url.
+ // SMBURLTYPE_ENTIRE_NETWORK - "smb:/" is entire network
+ // SMBURLTYPE_WORKGROUP_OR_SERVER - "smb:/mygroup" or "smb:/myserver"
+ // SMBURLTYPE_SHARE_OR_PATH - "smb:/mygroupe/mymachine/myshare/mydir"
+ //-----------------------------------------------------------------------
+{
+ if(m_type != SMBURLTYPE_UNKNOWN)
+ return m_type;
+
+ if (protocol() != "smb")
+ {
+ m_type = SMBURLTYPE_UNKNOWN;
+ return m_type;
+ }
+
+ if (path(1) == "/")
+ {
+ if (host().isEmpty())
+ m_type = SMBURLTYPE_ENTIRE_NETWORK;
+ else
+ m_type = SMBURLTYPE_WORKGROUP_OR_SERVER;
+ return m_type;
+ }
+
+ // Check for the path if we get this far
+ m_type = SMBURLTYPE_SHARE_OR_PATH;
+
+ return m_type;
+}
+
diff --git a/tdeioslave/smb/kio_smb_internal.h b/tdeioslave/smb/kio_smb_internal.h
new file mode 100644
index 000000000..2d97aee31
--- /dev/null
+++ b/tdeioslave/smb/kio_smb_internal.h
@@ -0,0 +1,118 @@
+/////////////////////////////////////////////////////////////////////////////
+//
+// Project: SMB tdeioslave for KDE2
+//
+// File: kio_smb_internal.h
+//
+// Abstract: Utility classes used by SMBSlave
+//
+// Author(s): Matthew Peterson <mpeterson@caldera.com>
+// Frank Schwanz <schwanz@fh-brandenburg.de>
+//---------------------------------------------------------------------------
+//
+// Copyright (c) 2000 Caldera Systems, Inc.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2.1 of the License, or
+// (at your option) any later version.
+//
+// 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 General Public License
+// along with this program; see the file COPYING. If not, please obtain
+// a copy from http://www.gnu.org/copyleft/gpl.html
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef KIO_SMB_INTERNAL_H_INCLUDED
+#define KIO_SMB_INTERNAL_H_INCLUDED
+
+#include <tdeio/authinfo.h>
+
+/**
+ * Types of a SMBURL :
+ * SMBURLTYPE_UNKNOWN - Type could not be determined. Bad SMB Url.
+ * SMBURLTYPE_ENTIRE_NETWORK - "smb:/" is entire network
+ * SMBURLTYPE_WORKGROUP_OR_SERVER - "smb:/mygroup" or "smb:/myserver"
+ * URLTYPE_SHARE_OR_PATH - "smb:/mygroupe/mymachine/myshare/mydir"
+ */
+enum SMBUrlType {
+ SMBURLTYPE_UNKNOWN = 0, SMBURLTYPE_ENTIRE_NETWORK = 1,
+ SMBURLTYPE_WORKGROUP_OR_SERVER = 2, SMBURLTYPE_SHARE_OR_PATH = 3
+};
+
+
+//===========================================================================
+/**
+ * Class to handle URL's
+ * it can convert KURL to smbUrl
+ * and Handle UserInfo
+ * it also check the correctness of the URL
+ */
+class SMBUrl : public KURL
+{
+
+
+public:
+ SMBUrl();
+ SMBUrl(const KURL & kurl);
+
+ /**
+ * Appends the specified file and dir to this SMBUrl
+ * "smb://server/share" --> "smb://server/share/filedir"
+ */
+ void addPath(const TQString &filedir);
+
+ bool cd(const TQString &dir);
+
+ /**
+ * Returns the type of this SMBUrl:
+ * SMBURLTYPE_UNKNOWN - Type could not be determined. Bad SMB Url.
+ * SMBURLTYPE_ENTIRE_NETWORK - "smb:/" is entire network
+ * SMBURLTYPE_WORKGROUP_OR_SERVER - "smb:/mygroup" or "smb:/myserver"
+ * URLTYPE_SHARE_OR_PATH - "smb:/mygroupe/mymachine/myshare/mydir"
+ */
+ SMBUrlType getType() const;
+
+ void setPass( const TQString& _txt ) { KURL::setPass(_txt); updateCache(); }
+ void setUser( const TQString& _txt ) { KURL::setUser(_txt); updateCache(); }
+ void setHost( const TQString& _txt ) { KURL::setHost(_txt); updateCache(); }
+
+ /**
+ * Returns the workgroup if it given in url
+ */
+// TQString getWorkgroup() const;
+
+ /**
+ * Returns path after workgroup
+ */
+// TQString getServerShareDir() const;
+
+ /**
+ * Return a URL that is suitable for libsmbclient
+ */
+ TQCString toSmbcUrl() const { return m_surl; }
+
+private:
+ /**
+ * Change from TQString to TQCString (MS Windows's character encoding)
+ */
+ TQCString fromUnicode( const TQString &_str ) const;
+
+ void updateCache();
+ TQCString m_surl;
+
+ /**
+ * Type of URL
+ * @see _SMBUrlType
+ */
+ mutable SMBUrlType m_type;
+};
+
+
+#endif
+
diff --git a/tdeioslave/smb/kio_smb_mount.cpp b/tdeioslave/smb/kio_smb_mount.cpp
new file mode 100644
index 000000000..ad421f631
--- /dev/null
+++ b/tdeioslave/smb/kio_smb_mount.cpp
@@ -0,0 +1,211 @@
+/* This file is part of the KDE project
+
+ Copyright (C) 2000 Alexander Neundorf <neundorf@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kio_smb.h"
+#include <kstandarddirs.h>
+#include <tqcstring.h>
+#include <unistd.h>
+#include <tqdir.h>
+#include <kprocess.h>
+
+void SMBSlave::readOutput(TDEProcess *, char *buffer, int buflen)
+{
+ mybuf += TQString::fromLocal8Bit(buffer, buflen);
+}
+
+void SMBSlave::readStdErr(TDEProcess *, char *buffer, int buflen)
+{
+ mystderr += TQString::fromLocal8Bit(buffer, buflen);
+}
+
+void SMBSlave::special( const TQByteArray & data)
+{
+ kdDebug(KIO_SMB)<<"Smb::special()"<<endl;
+ int tmp;
+ TQDataStream stream(data, IO_ReadOnly);
+ stream >> tmp;
+ //mounting and umounting are both blocking, "guarded" by a SIGALARM in the future
+ switch (tmp)
+ {
+ case 1:
+ case 3:
+ {
+ TQString remotePath, mountPoint, user;
+ stream >> remotePath >> mountPoint;
+
+ TQStringList sl=TQStringList::split("/",remotePath);
+ TQString share,host;
+ if (sl.count()>=2)
+ {
+ host=(*sl.at(0)).mid(2);
+ share=(*sl.at(1));
+ kdDebug(KIO_SMB)<<"special() host -"<< host <<"- share -" << share <<"-"<<endl;
+ }
+
+ remotePath.replace('\\', '/'); // smbmounterplugin sends \\host/share
+
+ kdDebug(KIO_SMB) << "mounting: " << remotePath.local8Bit() << " to " << mountPoint.local8Bit() << endl;
+
+ if (tmp==3) {
+ if (!KStandardDirs::makeDir(mountPoint)) {
+ error(TDEIO::ERR_COULD_NOT_MKDIR, mountPoint);
+ return;
+ }
+ }
+ mybuf.truncate(0);
+ mystderr.truncate(0);
+
+ SMBUrl smburl("smb:///");
+ smburl.setHost(host);
+ smburl.setPath("/" + share);
+
+ if ( !checkPassword(smburl) )
+ {
+ finished();
+ return;
+ }
+
+ // using smbmount instead of "mount -t smbfs", because mount does not allow a non-root
+ // user to do a mount, but a suid smbmnt does allow this
+
+ TDEProcess proc;
+ proc.setUseShell(true); // to have the path to smbmnt (which is used by smbmount); see man smbmount
+ proc << "smbmount";
+
+ TQString options;
+
+ if ( smburl.user().isEmpty() )
+ {
+ user = "guest";
+ options = "-o guest";
+ }
+ else
+ {
+ options = "-o username=" + TDEProcess::quote(smburl.user());
+ user = smburl.user();
+
+ if ( ! smburl.pass().isEmpty() )
+ options += ",password=" + TDEProcess::quote(smburl.pass());
+ }
+
+ // TODO: check why the control center uses encodings with a blank char, e.g. "cp 1250"
+ //if ( ! m_default_encoding.isEmpty() )
+ //options += ",codepage=" + TDEProcess::quote(m_default_encoding);
+
+ proc << TDEProcess::quote(remotePath.local8Bit());
+ proc << TDEProcess::quote(mountPoint.local8Bit());
+ proc << options;
+
+ connect(&proc, TQT_SIGNAL( receivedStdout(TDEProcess *, char *, int )),
+ TQT_SLOT(readOutput(TDEProcess *, char *, int)));
+
+ connect(&proc, TQT_SIGNAL( receivedStderr(TDEProcess *, char *, int )),
+ TQT_SLOT(readStdErr(TDEProcess *, char *, int)));
+
+ if (!proc.start( TDEProcess::Block, TDEProcess::AllOutput ))
+ {
+ error(TDEIO::ERR_CANNOT_LAUNCH_PROCESS,
+ "smbmount"+i18n("\nMake sure that the samba package is installed properly on your system."));
+ return;
+ }
+
+ kdDebug(KIO_SMB) << "mount exit " << proc.exitStatus() << endl
+ << "stdout:" << mybuf << endl << "stderr:" << mystderr << endl;
+
+ if (proc.exitStatus() != 0)
+ {
+ error( TDEIO::ERR_COULD_NOT_MOUNT,
+ i18n("Mounting of share \"%1\" from host \"%2\" by user \"%3\" failed.\n%4")
+ .arg(share).arg(host).arg(user).arg(mybuf + "\n" + mystderr));
+ return;
+ }
+
+ finished();
+ }
+ break;
+ case 2:
+ case 4:
+ {
+ TQString mountPoint;
+ stream >> mountPoint;
+
+ TDEProcess proc;
+ proc.setUseShell(true);
+ proc << "smbumount";
+ proc << TDEProcess::quote(mountPoint);
+
+ mybuf.truncate(0);
+ mystderr.truncate(0);
+
+ connect(&proc, TQT_SIGNAL( receivedStdout(TDEProcess *, char *, int )),
+ TQT_SLOT(readOutput(TDEProcess *, char *, int)));
+
+ connect(&proc, TQT_SIGNAL( receivedStderr(TDEProcess *, char *, int )),
+ TQT_SLOT(readStdErr(TDEProcess *, char *, int)));
+
+ if ( !proc.start( TDEProcess::Block, TDEProcess::AllOutput ) )
+ {
+ error(TDEIO::ERR_CANNOT_LAUNCH_PROCESS,
+ "smbumount"+i18n("\nMake sure that the samba package is installed properly on your system."));
+ return;
+ }
+
+ kdDebug(KIO_SMB) << "smbumount exit " << proc.exitStatus() << endl
+ << "stdout:" << mybuf << endl << "stderr:" << mystderr << endl;
+
+ if (proc.exitStatus() != 0)
+ {
+ error(TDEIO::ERR_COULD_NOT_UNMOUNT,
+ i18n("Unmounting of mountpoint \"%1\" failed.\n%2")
+ .arg(mountPoint).arg(mybuf + "\n" + mystderr));
+ return;
+ }
+
+ if ( tmp == 4 )
+ {
+ bool ok;
+
+ TQDir dir(mountPoint);
+ dir.cdUp();
+ ok = dir.rmdir(mountPoint);
+ if ( ok )
+ {
+ TQString p=dir.path();
+ dir.cdUp();
+ ok = dir.rmdir(p);
+ }
+
+ if ( !ok )
+ {
+ error(TDEIO::ERR_COULD_NOT_RMDIR, mountPoint);
+ return;
+ }
+ }
+
+ finished();
+ }
+ break;
+ default:
+ break;
+ }
+ finished();
+}
+
+#include "kio_smb.moc"
diff --git a/tdeioslave/smb/libsmbclient-HOWTO.txt b/tdeioslave/smb/libsmbclient-HOWTO.txt
new file mode 100644
index 000000000..65ed7d086
--- /dev/null
+++ b/tdeioslave/smb/libsmbclient-HOWTO.txt
@@ -0,0 +1,11 @@
+HOWTO get the libsmbclient built, so that you can get the new smb ioslave built...
+
+1. Check out the samba sources from cvs with ( full directions are at: http://www.samba.org/samba/cvs.html
+ cvs -d :pserver:cvs@pserver.samba.org:/cvsroot login
+ use "cvs" as the password
+ cvs -z5 -d :pserver:cvs@pserver.samba.org:/cvsroot co -r SAMBA_3_0 samba/source
+2. cd samba/source
+3. sh autogen.sh
+4. run ./configure && make
+5. when compiling is done- shouldn't take more than 5-15 minutes depending on your machine,
+ you need to "make installclientlib installdat" - if you want all of samba, do "make install"
diff --git a/tdeioslave/smb/smb-network.desktop b/tdeioslave/smb/smb-network.desktop
new file mode 100644
index 000000000..de5406775
--- /dev/null
+++ b/tdeioslave/smb/smb-network.desktop
@@ -0,0 +1,80 @@
+[Desktop Entry]
+Icon=network
+Name=Samba Shares
+Name[af]=Samba Hulpbronne
+Name[ar]=مشاركات Samba
+Name[az]=Samba Sahələri
+Name[be]=Агульныя тэчкі Samba
+Name[bg]=Ресурси на Samba
+Name[bn]=সাম্বা শেয়ার
+Name[br]=Rannadoù Samba
+Name[bs]=Samba dijeljenje
+Name[ca]=Recurs compartit de Samba
+Name[cs]=Sdílené disky Samby
+Name[csb]=Dostónczi Sambë
+Name[cy]=Cydranniad Samba
+Name[da]=Samba-shares
+Name[de]=Samba-Freigaben
+Name[el]=Κοινόχρηστοι πόροι Samba
+Name[eo]=Sambo-opuzaĵoj
+Name[es]=Comparticiones Samba
+Name[et]=SMB jagatud ressursid
+Name[eu]=Samba partekaketak
+Name[fa]=مشترکات Samba
+Name[fi]=Samba-jaot
+Name[fr]=Partages Samba
+Name[fy]=Sambanetwurk
+Name[ga]=Comhranna Samba
+Name[gl]=Comparticións de Samba
+Name[he]=שיתופי Samba
+Name[hi]=साम्बा साझेदारी
+Name[hr]=Samba dijeljenja
+Name[hu]=Samba-megosztások
+Name[is]=Samba sameignir
+Name[it]=Condivisioni Samba
+Name[ja]=Samba 共有
+Name[ka]=Samba-ს საზიაროები
+Name[kk]=Samba ресурстары
+Name[ko]=삼바 공유
+Name[lo]=ສັບພະຍາກອນທີ່ໃຊ້ຮ່ວມກັນຂອງ Samba
+Name[lt]=Samba bendri diskai
+Name[lv]=Samba Šāres
+Name[mk]=Samba-заеднички
+Name[mn]=Samba-Нөөцүүд
+Name[ms]=Perkongsian Samba
+Name[mt]=Riżorsi Samba
+Name[nb]=Samba-ressurser
+Name[nds]=Samba-Freegaven
+Name[ne]=साम्बा साझेदारी
+Name[nl]=Sambanetwerk
+Name[nn]=Samba-ressursar
+Name[nso]=Dikabagano tsa Samba
+Name[pa]=ਸਾਂਬਾ ਸਾਂਝ
+Name[pl]=Zasoby Samby
+Name[pt]=Partilhas de Samba
+Name[pt_BR]=Compartilhamentos do Samba
+Name[ro]=Partajări Samba
+Name[ru]=Ресурсы Samba
+Name[rw]=Imigabane Samba
+Name[se]=Samba-resurssat
+Name[sk]=Stav Samby
+Name[sl]=Souporabe Sambe
+Name[sr]=Samba дељења
+Name[sr@Latn]=Samba deljenja
+Name[sv]=Samba-utdelningar
+Name[ta]=சம்பா பங்குகள்
+Name[tg]=Иштирокоти Samba
+Name[th]=ทรัพยากร Samba ที่ใช้ร่วมกัน
+Name[tr]=Samba Payları
+Name[tt]=Samba Urtaqları
+Name[uk]=Спільні ресурси Samba
+Name[ven]=Mikovhe ya Samba
+Name[vi]=Chia sẻ Samba
+Name[wa]=Pårtaedjes Samba
+Name[xh]=Izahlulo ze Samba
+Name[zh_CN]=Samba 共享
+Name[zh_TW]=Samba 資源分享
+Name[zu]=Izabelo ze-Samba
+Open=false
+Type=Link
+URL=smb:/
diff --git a/tdeioslave/smb/smb.protocol b/tdeioslave/smb/smb.protocol
new file mode 100644
index 000000000..2c0bda020
--- /dev/null
+++ b/tdeioslave/smb/smb.protocol
@@ -0,0 +1,12 @@
+[Protocol]
+exec=kio_smb
+protocol=smb
+input=none
+output=filesystem
+listing=Name,Type,Size,Date,Access,Owner,Group
+reading=true
+writing=true
+makedir=true
+deleting=true
+DocPath=tdeioslave/smb.html
+Icon=samba
diff --git a/tdeioslave/smb/x-smb-server.desktop b/tdeioslave/smb/x-smb-server.desktop
new file mode 100644
index 000000000..6990e1634
--- /dev/null
+++ b/tdeioslave/smb/x-smb-server.desktop
@@ -0,0 +1,76 @@
+[Desktop Entry]
+Comment=Windows Server
+Comment[af]=Windows Bediener
+Comment[ar]=خادم Windows
+Comment[be]=Сервер Windows
+Comment[bg]=Сървър Windows
+Comment[bn]=উইণ্ডোস সার্ভার
+Comment[br]=Servijer Windows
+Comment[bs]=Windows server
+Comment[ca]=Servidor Windows
+Comment[cs]=Windows server
+Comment[csb]=Serwera Windowsa
+Comment[cy]=Grŵp Gwaith Windows
+Comment[da]=Windows server
+Comment[de]=Windows-Server
+Comment[el]=Διακομιστής των Windows
+Comment[eo]=Vindoza servilo
+Comment[es]=Servidor Windows
+Comment[et]=Windowsi server
+Comment[eu]=Windows zerbitzaria
+Comment[fa]=کارساز ویندوز
+Comment[fi]=Windows-palvelin
+Comment[fr]=Serveur Windows
+Comment[fy]=Windows-tsjinner
+Comment[ga]=Freastalaí Windows
+Comment[he]=שרת Windows
+Comment[hi]=विंडोज़ सर्वर
+Comment[hr]=Windows poslužitelj
+Comment[hu]=Windows kiszolgáló
+Comment[is]=Windows þjónn
+Comment[it]=Server Windows
+Comment[ja]=Windows サーバ
+Comment[ka]=Windows სერვერი
+Comment[kk]=Windows сервері
+Comment[km]=ម៉ាស៊ីន​បម្រើ Windows
+Comment[ko]=윈도 공유
+Comment[lt]=Windows serveris
+Comment[lv]=Windows serveris
+Comment[mk]=Windows-сервер
+Comment[ms]=Pelayan Windows
+Comment[mt]=Server tal-Windows
+Comment[nb]=Windows-tjener
+Comment[nds]=Windows-Server
+Comment[ne]=सञ्झ्याल सर्भर
+Comment[nl]=Windows-server
+Comment[nn]=Windows-tenar
+Comment[pa]=ਵਿੰਡੋ ਸਰਵਰ
+Comment[pl]=Serwer Windows
+Comment[pt]=Servidor de Windows
+Comment[pt_BR]=Servidor Windows
+Comment[ro]=Servere Windows
+Comment[ru]=Сервер Windows
+Comment[rw]=Windows Seriveri
+Comment[se]=Windows-bálvá
+Comment[sk]=Server Windows
+Comment[sl]=Strežnik za Windows
+Comment[sr]=Windows сервер
+Comment[sr@Latn]=Windows server
+Comment[sv]=Windows server
+Comment[ta]=சாளர சேவகன்
+Comment[te]=విండొస్ సెర్వర్
+Comment[tg]=Хидматгоҳи Windows
+Comment[th]=เครื่องให้บริการวินโดว์ส
+Comment[tr]=Windows Sunucusu
+Comment[uk]=Сервер Windows
+Comment[uz]=Windows serveri
+Comment[uz@cyrillic]=Windows сервери
+Comment[vi]=Máy phục vụ Windows
+Comment[wa]=Sierveu Windows
+Comment[zh_CN]=Windows 服务器
+Comment[zh_TW]=視窗伺服器
+Icon=server
+Type=MimeType
+MimeType=application/x-smb-server
+X-TDE-AutoEmbed=true
+X-TDE-IsAlso=inode/directory
diff --git a/tdeioslave/smb/x-smb-workgroup.desktop b/tdeioslave/smb/x-smb-workgroup.desktop
new file mode 100644
index 000000000..2b6d571b9
--- /dev/null
+++ b/tdeioslave/smb/x-smb-workgroup.desktop
@@ -0,0 +1,74 @@
+[Desktop Entry]
+Comment=Windows Workgroup
+Comment[af]=Windows Werkgroep
+Comment[ar]=مجموعة عمل Windows
+Comment[be]=Працоўная група Windows
+Comment[bg]=Работна група на Windows
+Comment[bn]=উইণ্ডোস ওয়ার্কগ্রুপ
+Comment[br]=Strollad labour Windows
+Comment[bs]=Windows radna grupa
+Comment[ca]=Grup de treball de Windows
+Comment[cs]=Pracovní skupina Windows
+Comment[csb]=Robòczé karno Windowsa
+Comment[cy]=Gr?p Gwaith Windows
+Comment[de]=Windows-Arbeitsgruppe
+Comment[el]=Ομάδα εργασίας Windows
+Comment[eo]=Vindoza laborgrupo
+Comment[es]=Grupo de trabajo de Windows
+Comment[et]=Windowsi töögrupp
+Comment[eu]=Windows lan taldea
+Comment[fa]=گروه کاری ویندوز
+Comment[fi]=Windows-työryhmä
+Comment[fr]=Groupe de travail Windows
+Comment[fy]=Windows-wurkkeppel
+Comment[ga]=Grúpa Oibre Windows
+Comment[gl]=Grupo de Traballo de Windows
+Comment[he]=קבוצת עבודה של חלונות
+Comment[hi]=विंडोज़ वर्क बुक
+Comment[hr]=Windows radna grupa
+Comment[hu]=Windows-os munkacsoport
+Comment[is]=Windows vinnuhópur
+Comment[it]=Gruppo di lavoro di Windows
+Comment[ja]=Windows ワークグループ
+Comment[ka]=Windows სამუშაო გჯუფი
+Comment[kk]=Windows жұмыс тобы
+Comment[lt]=Windows darbo grupė
+Comment[lv]=Windows darba grupa
+Comment[mk]=Windows работна група
+Comment[mn]=Цонхтой ажиллах бүлэг
+Comment[ms]=Kumpulan Kerja Windows
+Comment[mt]=Workgroup tal-Windows
+Comment[nb]=Windows-arbeidsgruppe
+Comment[nds]=Windows-Arbeitkoppel
+Comment[ne]=सञ्झ्याल कार्य समूह
+Comment[nl]=Windows-werkgroep
+Comment[nn]=Windows-arbeidsgruppe
+Comment[pa]=ਵਿੰਡੋ ਵਰਕਗਰੁੱਪ
+Comment[pl]=Grupa robocza Windows
+Comment[pt]=Grupos de Trabalho do Windows
+Comment[pt_BR]=Grupo de trabalho do Windows
+Comment[ro]=Grupuri de lucru Windows
+Comment[ru]=Рабочая группа Windows
+Comment[rw]=Itsindaumurimo Windows
+Comment[se]=Windows-bargojoavku
+Comment[sk]=Pracovná skupina Windows
+Comment[sl]=Delovna skupina Windows
+Comment[sv]=Windows arbetsgrupp
+Comment[ta]=சாளரங்கள் பணிகுழு
+Comment[te]=విండొస్ వర్క్ గ్రూప్
+Comment[tg]=Гурӯҳи кори Windows
+Comment[th]=กลุ่มงานวินโดว์ส
+Comment[tr]=Windows Çalışma Grubu
+Comment[tt]=Windows Eştörkeme
+Comment[uk]=Робоча група Windows
+Comment[uz]=Windows ishchi guruhi
+Comment[uz@cyrillic]=Windows ишчи гуруҳи
+Comment[vi]=Nhóm làm việc Windows
+Comment[wa]=Groupe d' ovraedje Windows
+Comment[zh_CN]=Windows 工作组
+Comment[zh_TW]=視窗工作群組
+Icon=network_local
+Type=MimeType
+MimeType=application/x-smb-workgroup
+X-TDE-AutoEmbed=true
+X-TDE-IsAlso=inode/directory