diff options
Diffstat (limited to 'src/tdebluezioslave/obex')
-rw-r--r-- | src/tdebluezioslave/obex/CMakeLists.txt | 46 | ||||
-rw-r--r-- | src/tdebluezioslave/obex/README | 91 | ||||
-rw-r--r-- | src/tdebluezioslave/obex/obex.cpp | 312 | ||||
-rw-r--r-- | src/tdebluezioslave/obex/obex.h | 66 | ||||
-rw-r--r-- | src/tdebluezioslave/obex/obex_sidebarentry.desktop | 9 | ||||
-rw-r--r-- | src/tdebluezioslave/obex/obexftp.protocol | 19 | ||||
-rw-r--r-- | src/tdebluezioslave/obex/obexopp.protocol | 19 | ||||
-rw-r--r-- | src/tdebluezioslave/obex/tdeio_obex.cpp | 550 | ||||
-rw-r--r-- | src/tdebluezioslave/obex/tdeio_obex.h | 135 |
9 files changed, 1247 insertions, 0 deletions
diff --git a/src/tdebluezioslave/obex/CMakeLists.txt b/src/tdebluezioslave/obex/CMakeLists.txt new file mode 100644 index 0000000..13aa0f4 --- /dev/null +++ b/src/tdebluezioslave/obex/CMakeLists.txt @@ -0,0 +1,46 @@ +################################################# +# +# (C) 2018 Emanoil Kotsev +# deloptes (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR} + ${CMAKE_SOURCE_DIR}/src/libtdeobex + ${CMAKE_BINARY_DIR}/src/libtdeobex + ${CMAKE_SOURCE_DIR}/src/tdeioslave/obex + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} + ${DBUS_INCLUDE_DIRS} + ${DBUS_TQT_INCLUDE_DIRS} +) + + +##### tdeio_obex (part) ############################# +set( target tdeio_obex ) + +tde_add_kpart( ${target} AUTOMOC + SOURCES tdeio_obex.cpp obex.cpp + LINK ${DBUS_TQT_LIBRARIES} tdeio-shared tdeobex-shared obexinterfaces-static + DESTINATION ${PLUGIN_INSTALL_DIR} +) + +tde_create_translated_desktop( + SOURCE obexftp.protocol + DESTINATION ${SERVICES_INSTALL_DIR} +) +tde_create_translated_desktop( + SOURCE obexopp.protocol + DESTINATION ${SERVICES_INSTALL_DIR} +) +tde_create_translated_desktop( + SOURCE obex_sidebarentry.desktop + DESTINATION ${DATA_INSTALL_DIR}/konqsidebartng/virtual_folders/services +) diff --git a/src/tdebluezioslave/obex/README b/src/tdebluezioslave/obex/README new file mode 100644 index 0000000..a44d55f --- /dev/null +++ b/src/tdebluezioslave/obex/README @@ -0,0 +1,91 @@ + +OBEX tdeio slave. +--------------- + +At the moment it is mostly working with ober IP, IrDA and the Siemens BFB +transport protocol. The slave ues url's of the form + +obex://hostname:port/path + +for IP connections. It will use the standard OBEX port 650 if the port +argument is omitted. The IP transport also queries for the nss/netdb entry + +obex 650/tcp + +if registered in the services database. (see getent(1) or nsswitch.conf(5)) +The IP transport also tries the port 29650. This one is used in case of +a server running without root privileges. + +The IrDA Transport is accessed via the url format + +obex://irda/path + +In this case device discovery is done and the first device offering +the OBEX hint bit is connected. + +The Bluetooth Transport is accessed via the url format + +obex://bluetooth/path + +In this case device discovery is done and the first device offering +the filesystem browsing profile is connected. + +There exist serial transports for Siemens mobiles. It is currently untested. +In theory it should work. + +A serial transport for the ericcson mobiles is also in the works. It should be +easy to do. It is also difficult to test because I don't know anyone with an +ericsson phone ... + +I have removed the old url format using '!' to separate transport options. +There is now a kcontrol module for configuration. Using this module one can +define 'OBEX hosts' which can be used for hostnames in OBEX url's. Since there +are many configuration options i think this is the best method to access +specific devices. If you know the hardware addresses of your bluetooth or +irda device you can use url's of the form: + +obex://[ef:01:23:45]/ + +if your irda device has the address ef:01:23:45 or + +obex://[ab:cd:ef:01:23:45]/ + +if your bluetooth device has the hardware address ab:cd:ef:01:23:45. +For bluetooth you can also include the rfcomm channel of the folderbrowsing +profile in the usual port field. + +OBEX authentication is currently supported in url's. +More complete authentication configutation will come. + +DEVICE COMPATIBILITY + +The NOKIA 3650 mobile has a firmware bug in some versions. +Mobiles with this bug return invalid XML files for folder listings. This +leads to empty directories. Thie bug is reported to be in at least firmware +version 2.50. The firmware version 3.16 fixed this bug. +Thanks to Fred Schaettgen <[email protected]> for testing. + +My Siemens S45i works well with this implementation. + +Connections from and to openobex driven clients or servers will be refused, +since openobex uses a wrong protocol version value in connect +requests/responses. + +DOCUMENTATION + +Hmm, can someone tell me how to write kdehelp documentation? + +DEMO SERVER + +There is an example folderbowsing server in the subfolder +libqobex/qobexfbssrv/. This server and the server api is currently under +heavy development. It listens by default on localhost. You can change the +transport where it listens with -t <whatever>. It is also password protected +by the password 'fbsserver' For more information think of the wisdom of +the yedi: + +Use the source Luke + +:) + +Have fun! diff --git a/src/tdebluezioslave/obex/obex.cpp b/src/tdebluezioslave/obex/obex.cpp new file mode 100644 index 0000000..fb1d81b --- /dev/null +++ b/src/tdebluezioslave/obex/obex.cpp @@ -0,0 +1,312 @@ +/* + This file is part of tdeio_obex. + + Copyright (c) 2003 Mathias Froehlich <[email protected]> + + 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 Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + */ + +#include "obex.h" + +#include <kdebug.h> +#include <tqapplication.h> +#include <tqeventloop.h> +#include <tqregexp.h> + +#include <sys/stat.h> + +#include <tqdbusvariant.h> + +#define MINIMUM_UID 500 + +Obex::Obex(TQString &protocol) : + mProtocol(protocol) +{ + kdDebug() << k_funcinfo << endl; + KUser user; + m_effectiveUid = user.uid(); +} + +Obex::~Obex() +{ + kdDebug() << k_funcinfo << endl; +} + +bool Obex::parseURL(const KURL &url, TQString &address, TQString &name, TQString &path) const +{ + kdDebug() << k_funcinfo << endl; + TQString url_path = url.path(+1); + + if (url_path.find(TQRegExp("/\\[([0-9A-F]{2}:){5}[0-9A-F]{2}\\]"), 0) != -1) + { + address = url_path.remove(0, 2); + address = address.remove(17, url_path.length()); + url_path = url_path.remove(0, 18); + kdDebug() << "Obex::parseURL address : " << address << endl; + kdDebug() << "Obex::parseURL url_path : " << url_path << endl; + } + else + return false; + + int i = url_path.find('/', 1); + if (i > 0) + { + name = url_path.mid(1, i - 1); + } + else + { + name = url_path.mid(1); + } + path = url_path; + kdDebug() << "Obex::parseURL path : " << path << endl; + kdDebug() << "Obex::parseURL name : " << name << endl; + + return true; +} + +void Obex::addAtom(UDSEntry &entry, UDSAtomTypes type, const TQString &s) +{ + kdDebug() << k_funcinfo << endl; + UDSAtom atom; + atom.m_uds = type; + atom.m_str = s; + entry.append(atom); +} + +void Obex::addAtom(UDSEntry &entry, UDSAtomTypes type, const long l) +{ + kdDebug() << k_funcinfo << endl; + UDSAtom atom; + atom.m_uds = type; + atom.m_long = l; + entry.append(atom); +} + +void Obex::createTopLevelEntry(UDSEntry &entry) +{ + kdDebug() << k_funcinfo << endl; + + entry.clear(); + addAtom(entry, UDS_NAME, "."); + addAtom(entry, UDS_FILE_TYPE, S_IFDIR); + addAtom(entry, UDS_ACCESS, 0555); + addAtom(entry, UDS_MIME_TYPE, "inode/directory"); + addAtom(entry, UDS_ICON_NAME, "pda_blue"); + addAtom(entry, UDS_USER, "root"); + addAtom(entry, UDS_GROUP, "root"); +} + +void Obex::createDirEntry(UDSEntry &entry, const TQString dir) +{ + kdDebug() << k_funcinfo << endl; + entry.clear(); + addAtom(entry, UDS_NAME, "/" + dir); + addAtom(entry, UDS_FILE_TYPE, S_IFDIR); + addAtom(entry, UDS_ACCESS, 0755); + addAtom(entry, UDS_MIME_TYPE, "inode/directory"); + addAtom(entry, UDS_ICON_NAME, "pda_blue"); + addAtom(entry, UDS_USER, "root"); + addAtom(entry, UDS_GROUP, "root"); +} + +void Obex::slotStatResult(Job *job) +{ + kdDebug() << k_funcinfo << endl; + if (job->error() == 0) + { + StatJob *stat_job = static_cast<StatJob *>(job); + m_entryBuffer = stat_job->statResult(); + } + + tqApp->eventLoop()->exitLoop(); +} + +UDSEntry Obex::createUDSEntry(const TQMap<TQString, TQT_DBusData> &map) +{ + kdDebug() << k_funcinfo << endl; + + UDSEntry entry; + long mode; + uint isFile = 0; + + TQMap<TQString, TQT_DBusData>::const_iterator mit = map.begin(); + for (mit; mit != map.end(); ++mit) + { + + UDSAtom atom; + if (mit.key() == "Accessed") + { + TQString v = mit.data().toVariant().value.toString(); + atom.m_uds = UDS_ACCESS_TIME; + atom.m_long = stringToTime_t(v); + entry.append(atom); + } + if (mit.key() == "Created") + { + TQString v = mit.data().toVariant().value.toString(); + atom.m_uds = UDS_CREATION_TIME; + atom.m_long = stringToTime_t(v); + entry.append(atom); + } + if (mit.key() == "Group-perm") + { + TQString v = mit.data().toVariant().value.toString(); + if (v.contains('R', FALSE)) + mode |= S_IRGRP; + if (v.contains('W', FALSE)) + mode |= S_IWGRP; + } + if (mit.key() == "Modified") + { + TQString v = mit.data().toVariant().value.toString(); + atom.m_uds = UDS_MODIFICATION_TIME; + atom.m_long = stringToTime_t(v); + entry.append(atom); + } + if (mit.key() == "Size") + { + TQ_UINT64 v = mit.data().toVariant().value.toUInt64(); + atom.m_uds = UDS_SIZE; + atom.m_long = v; + entry.append(atom); + } + if (mit.key() == "Name") + { + TQString v = mit.data().toVariant().value.toString(); + atom.m_uds = UDS_NAME; + atom.m_str = v; + entry.append(atom); + } + if (mit.key() == "Other-perm") + { + TQString v = mit.data().toVariant().value.toString(); + if (v.contains('R', FALSE)) + mode |= S_IROTH; + if (v.contains('W', FALSE)) + mode |= S_IWOTH; + } + if (mit.key() == "Type") + { + TQString v = mit.data().toVariant().value.toString(); + if (v == "folder") + { + isFile = 1; + } + if (v == "file") + { + TQString v = mit.data().toVariant().value.toString(); + isFile = 2; + } + } + if (mit.key() == "User-perm") + { + TQString v = mit.data().toVariant().value.toString(); + if (v.contains('R', FALSE)) + mode |= S_IRUSR; + if (v.contains('W', FALSE)) + mode |= S_IWUSR; + } + } + + if (isFile == 1) + { + if (mode & S_IRUSR) + mode |= S_IXUSR; + if (mode & S_IRGRP) + mode |= S_IXGRP; + if (mode & S_IROTH) + mode |= S_IXOTH; + + UDSAtom atom; + atom.m_uds = UDS_ACCESS; + atom.m_long = mode; + entry.append(atom); + + // set the file type + atom.m_uds = UDS_FILE_TYPE; + atom.m_long = S_IFDIR; + entry.append(atom); + } + else if (isFile == 2) + { + UDSAtom atom; + atom.m_uds = UDS_ACCESS; + atom.m_long = mode; + entry.append(atom); + + // set the file type + atom.m_uds = UDS_FILE_TYPE; + atom.m_long = S_IFREG; + entry.append(atom); + } + else + { + //FIXME fall back + } + return entry; +} + +time_t Obex::stringToTime_t(TQString str) +{ + kdDebug() << k_funcinfo << endl; + + str.insert(13, ':'); + str.insert(11, ':'); + str.insert(6, '-'); + str.insert(4, '-'); + TQDateTime time = TQDateTime::fromString(str, TQt::ISODate); + + return time.toTime_t(); +} + +UDSEntry Obex::extractUrlInfos(const KURL &url) +{ + kdDebug() << k_funcinfo << endl; + + m_entryBuffer.clear(); + + StatJob *job = stat(url, false); + connect(job, TQT_SIGNAL(result(Job *)), this, TQT_SLOT(slotStatResult(Job *))); + tqApp->eventLoop()->enterLoop(); + + UDSEntry::iterator it = m_entryBuffer.begin(); + UDSEntry::iterator end = m_entryBuffer.end(); + + UDSEntry infos; + + for (; it != end; ++it) + { + switch ((*it).m_uds) + { + case UDS_ACCESS: + case UDS_USER: + case UDS_GROUP: + case UDS_CREATION_TIME: + case UDS_MODIFICATION_TIME: + case UDS_ACCESS_TIME: + infos.append(*it); + break; + default: + break; + } + } + + addAtom(infos, UDS_LOCAL_PATH, url.path()); + + return infos; +} + +#include "obex.moc" diff --git a/src/tdebluezioslave/obex/obex.h b/src/tdebluezioslave/obex/obex.h new file mode 100644 index 0000000..bc6d3cc --- /dev/null +++ b/src/tdebluezioslave/obex/obex.h @@ -0,0 +1,66 @@ +/* + This file is part of tdeio_obex. + + Copyright (c) 2003 Mathias Froehlich <[email protected]> + + 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 Steet, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef OBEX_H +#define OBEX_H + + +#include <tdeio/global.h> +#include <tdeio/job.h> +#include <kurl.h> +#include <kuser.h> + +#include <tqdbusdata.h> + +#include <tqstring.h> + +using namespace TDEIO; + +class Obex : public TQObject +{ + Q_OBJECT + +public: + Obex(TQString & mProtocol); + virtual ~Obex(); + bool parseURL(const KURL &url, TQString &address, TQString &name, TQString &path) const; + void createTopLevelEntry(UDSEntry &entry); + void createDirEntry(UDSEntry &entry, const TQString dir); + UDSEntry createUDSEntry( const TQMap< TQString, TQT_DBusData > &map ); + bool changeWorkingDirectory( const TQString& to ); + +private slots: + void slotStatResult(Job *job); + +private: + + UDSEntry extractUrlInfos(const KURL &url); + UDSEntry m_entryBuffer; + void addAtom(UDSEntry &entry, UDSAtomTypes type, const TQString &s); + void addAtom(UDSEntry &entry, UDSAtomTypes type, const long l); + + time_t stringToTime_t( TQString ); + + long m_effectiveUid; + TQString mProtocol; +}; + +#endif diff --git a/src/tdebluezioslave/obex/obex_sidebarentry.desktop b/src/tdebluezioslave/obex/obex_sidebarentry.desktop new file mode 100644 index 0000000..7d6dcae --- /dev/null +++ b/src/tdebluezioslave/obex/obex_sidebarentry.desktop @@ -0,0 +1,9 @@ +[Desktop Entry] +Name=Bluetooth Browser + +Type=Link +URL=obexftp:/ +Icon=tdebluez +Open=false +X-TDE-TreeModule=Directory +X-TDE-KonqSidebarModule=konqsidebar_tree diff --git a/src/tdebluezioslave/obex/obexftp.protocol b/src/tdebluezioslave/obex/obexftp.protocol new file mode 100644 index 0000000..744b07c --- /dev/null +++ b/src/tdebluezioslave/obex/obexftp.protocol @@ -0,0 +1,19 @@ +[Protocol] +Description=A tdeioslave for OBEX connections + +protocol=obexftp +exec=tdeio_obex +Icon=remote +maxInstances=1 +Parent=system:/ +input=none +output=filesystem +source=false +reading=true +writing=true +makedir=true +deleting=true +moving=false +linking=false +listing=Name,Type,Size,Date,AccessDate,Access,Owner,Group +DocPath=tdebluez/components.tdeio_obex.html diff --git a/src/tdebluezioslave/obex/obexopp.protocol b/src/tdebluezioslave/obex/obexopp.protocol new file mode 100644 index 0000000..f56b884 --- /dev/null +++ b/src/tdebluezioslave/obex/obexopp.protocol @@ -0,0 +1,19 @@ +[Protocol] +Description=A tdeioslave for OBEX connections + +protocol=obexopp +exec=tdeio_obex +Icon=remote +maxInstances=1 +Parent=system:/ +input=none +output=none +source=false +reading=false +writing=true +makedir=false +deleting=false +moving=false +linking=false +listing=Name,Type,Size,Date,AccessDate,Access,Owner,Group +DocPath=tdebluez/components.tdeio_obex.html diff --git a/src/tdebluezioslave/obex/tdeio_obex.cpp b/src/tdebluezioslave/obex/tdeio_obex.cpp new file mode 100644 index 0000000..4d682ca --- /dev/null +++ b/src/tdebluezioslave/obex/tdeio_obex.cpp @@ -0,0 +1,550 @@ +/* + This file is part of tdeio_obex. + + Copyright (c) 2003 Mathias Froehlich <[email protected]> + + 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 Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + */ + +#include <stdlib.h> +#include <unistd.h> +//#include <sys/stat.h> +#include <pwd.h> +#include <grp.h> + +#include <kdebug.h> + +#include <tdeapplication.h> +#include <dcopclient.h> +#include <tdecmdlineargs.h> + +#include <tqdbusvariant.h> +#include <tqdbusdatalist.h> +#include <tqdbusdatamap.h> + +#include "tdeio_obex.h" + +static const TDECmdLineOptions options[] = { { "+protocol", I18N_NOOP( + "Protocol name"), 0 }, { "+pool", I18N_NOOP("Socket name"), 0 }, { + "+app", I18N_NOOP("Socket name"), 0 }, TDECmdLineLastOption }; + +extern "C" { + int KDE_EXPORT kdemain( int argc, char **argv ) + { + // TDEApplication is necessary to use other ioslaves + putenv(strdup("SESSION_MANAGER=")); + TDECmdLineArgs::init(argc, argv, "tdeio_obex", 0, 0, 0, 0); + TDECmdLineArgs::addCmdLineOptions( options ); + TDEApplication app( false, false, false ); + TDELocale::setMainCatalogue("tdebluez"); + + // We want to be anonymous even if we use DCOP + app.dcopClient()->attach(); + + TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs(); + ObexProtocol slave( args->arg(0), args->arg(1), args->arg(2) ); + slave.dispatchLoop(); + return 0; + } +} + +ObexProtocol::ObexProtocol(const TQCString &protocol, const TQCString &pool_socket, const TQCString &app_socket) : + SlaveBase(protocol, pool_socket, app_socket) +{ + kdDebug() << k_funcinfo << endl; + mChannel = 0; + mAddress = TQString::null; + mSessionPath = TQString(); + mFileTransfer = 0; + mSessionProperties = 0; + mSession = 0; + mClient = 0; + mProtocol = protocol; + mHost = TQString::null; + mConnected = false; + + mManager = new TDEObex::ObexObjectManagerImpl("org.bluez.obex", "/"); + if (!mManager->isConnectedToDBUS()) + { + TQString err = i18n("ObexObjectManager is not connected to DBus"); + tqDebug(err); + // infoMessage(i18n("Error")); + TDEIO::SlaveBase::error(TDEIO::ERR_COULD_NOT_CONNECT, err); + exit(); + } + + kdDebug() << "ObexProtocol::ObexProtocol DBus connection: " << (*(mManager->getConnection())).uniqueName() << endl; + + if (mProtocol == "obexftp" || mProtocol == "obexopp") + { + obex = new Obex(mProtocol); + // mConnected = connectObex(); + } + else + exit(); + + if (!mClient) + mClient = mManager->getClient(); + if (!mClient) + { + TDEIO::SlaveBase::error(TDEIO::ERR_COULD_NOT_CONNECT, i18n("ObexClient was not created")); + exit(); + } + +} + +ObexProtocol::~ObexProtocol() +{ + kdDebug() << k_funcinfo << endl; + if (mConnected) + closeObex(); + if (obex) + delete obex; + if (mManager) + delete mManager; +} + +void ObexProtocol::closeConnection() +{ + kdDebug() << k_funcinfo << endl; + closeObex(); +} + +void ObexProtocol::closeObex() +{ + kdDebug() << k_funcinfo << endl; + + TQT_DBusError dbuserror; + if (mConnected && !mSessionPath.isEmpty()) + { + // infoMessage(i18n("Disconnecting")); + if (!mClient->RemoveSession(mSessionPath, dbuserror)) + { + if (dbuserror.isValid()) + TDEIO::SlaveBase::error(TDEIO::ERR_COULD_NOT_CONNECT, i18n(dbuserror.message().utf8())); + } + // infoMessage(i18n("Disconnected")); + } + + if (mFileTransfer) + delete mFileTransfer; + if (mSessionProperties) + delete mSessionProperties; + if (mSession) + delete mSession; + if (mClient) + delete mClient; + mConnected = false; + + exit(); +} + +//void ObexProtocol::openConnection() +//{ +// kdDebug() << k_funcinfo << endl; +// +//} + +bool ObexProtocol::connectObex() +{ + kdDebug() << k_funcinfo << endl; + + TQT_DBusError dbuserror; + + TQT_DBusVariant obexprot; + if (mProtocol == "obexftp") + obexprot.value = TQT_DBusData::fromString("00001106-0000-1000-8000-00805f9b34fb"); + else if (mProtocol == "obexopp") + obexprot.value = TQT_DBusData::fromString("00001105-0000-1000-8000-00805f9b34fb"); + else if (mProtocol == "obexmap") + obexprot.value = TQT_DBusData::fromString("00001134-0000-1000-8000-00805f9b34fb"); + else if (mProtocol == "obexpbap") + obexprot.value = TQT_DBusData::fromString("00001130-0000-1000-8000-00805f9b34fb"); + else if (mProtocol == "obexsync") + obexprot.value = TQT_DBusData::fromString("00001104-0000-1000-8000-00805f9b34fb"); + obexprot.signature = obexprot.value.buildDBusSignature(); + TQMap<TQString, TQT_DBusVariant> args; + args.insert(TQString("Target"), obexprot); + + if (mSessionPath.isEmpty()) + { + kdDebug() << "ObexProtocol::connectObex : trying to create session" << endl; + if (!mClient->CreateSession(mAddress, args, mSessionPath, dbuserror)) + { + TDEIO::SlaveBase::error(TDEIO::ERR_COULD_NOT_CONNECT, i18n("Could not create session for %1.").arg(mAddress)); + return false; + } + } + + kdDebug() << "ObexProtocol::connectObex mSessionPath: " << mSessionPath << endl; + if (!mSession) + { + mSession = new org::bluez::obex::Session1Proxy("org.bluez.obex", mSessionPath); + mSession->setConnection((*(mManager->getConnection()))); + + mSessionProperties = new org::freedesktop::DBus::PropertiesProxy("org.bluez", mSessionPath); + mSessionProperties->setConnection((*(mManager->getConnection()))); + + connect(mSessionProperties, SIGNAL(PropertiesChanged ( const TQString&, const TQMap< TQString, TQT_DBusVariant >&, const TQStringList& )), + this, SLOT(slotPropertiesChanged ( const TQString& , const TQMap< TQString, TQT_DBusVariant >&, const TQStringList& ))); + + mFileTransfer = new org::bluez::obex::FileTransfer1Proxy("org.bluez.obex", mSessionPath); + mFileTransfer->setConnection((*(mManager->getConnection()))); + + } + if (mClient != 0 && mSession != 0 && mFileTransfer != 0) + mConnected = true; + return mConnected; +} + +void ObexProtocol::listDir(const KURL &url) +{ + kdDebug() << k_funcinfo << endl; + kdDebug() << "utl: " << url.url() << endl; + kdDebug() << "path: " << url.path() << endl; + + if (url.path().length() <= 1) + { + TDEIO::SlaveBase::error(TDEIO::ERR_MALFORMED_URL, url.prettyURL()); + finished(); + return; + } + + TQString address, name, path; + bool ok = obex->parseURL(url, address, name, path); + + if (!ok || address.isEmpty()) + { + TDEIO::SlaveBase::error(TDEIO::ERR_MALFORMED_URL, url.prettyURL()); + finished(); + return; + } + mAddress = address; + + kdDebug() << k_funcinfo << " address " << mAddress << endl; + kdDebug() << k_funcinfo << " name " << name << endl; + kdDebug() << k_funcinfo << " path " << path << endl; + kdDebug() << k_funcinfo << " at line " << __LINE__ << endl; + + if (!mConnected) + { + if (!connectObex()) + { + finished(); + return; + } + } + + if (!path.isEmpty()) + { + if (!changeWorkingDirectory(path)) + { + TDEIO::SlaveBase::error(TDEIO::ERR_CANNOT_OPEN_FOR_READING, path); + + finished(); + closeObex(); + return; + } + } + + kdDebug() << k_funcinfo << " at line " << __LINE__ << endl; + TQT_DBusDataList folderinfo; + TQT_DBusError dbuserror; + if (!mFileTransfer->ListFolder(folderinfo, dbuserror)) + { + if (dbuserror.isValid()) + { + TDEIO::SlaveBase::error(TDEIO::ERR_CANNOT_OPEN_FOR_READING, i18n("%1.\n%2").arg(url.prettyURL()).arg(dbuserror.message())); + } + else + { + TDEIO::SlaveBase::error(TDEIO::ERR_CANNOT_OPEN_FOR_READING, url.prettyURL()); + } + + finished(); + closeObex(); + return; + } + + TDEIO::UDSEntryList entries; + entries.clear(); + + TQValueList<TQT_DBusData> vl = folderinfo.toTQValueList(); + TQValueList<TQT_DBusData>::Iterator dit = vl.begin(); + for (dit; dit != vl.end(); ++dit) + { + bool ok = false; + TQMap<TQString, TQT_DBusData> map = (*dit).toStringKeyMap(&ok).toTQMap(); + if (!ok) + { + kdDebug() << k_funcinfo << " failed " << endl; + continue; + } + TDEIO::UDSEntry entry = obex->createUDSEntry(map); + entries.append(entry); + kdDebug() << k_funcinfo << " at line " << __LINE__ << endl; + } + + listEntries(entries); + listEntry(UDSEntry(), true); // ready + + finished(); + closeObex(); +} + +void ObexProtocol::stat(const KURL &url) +{ + kdDebug() << k_funcinfo << " url: " << url << endl; + + TQString address, name, path; + bool ok = obex->parseURL(url, address, name, path); + kdDebug() << k_funcinfo << " addr: " << address << endl; + kdDebug() << k_funcinfo << " name: " << name << endl; + kdDebug() << k_funcinfo << " path: " << path << endl; + + if (!ok || address.isEmpty()) + { + error(TDEIO::ERR_MALFORMED_URL, url.prettyURL()); + return; + } + + TDEIO::UDSEntry entry; + if (path.isEmpty() || path == "/") + { + // The root is "virtual" - it's not a single physical directory + obex->createTopLevelEntry(entry); + } + else + { + obex->createDirEntry(entry, url.url()); + } + statEntry(entry); + finished(); +} + +void ObexProtocol::get(const KURL& url) +{ + kdDebug() << k_funcinfo << endl; + + if (!mFileTransfer) + { + TDEIO::SlaveBase::error(TDEIO::ERR_INTERNAL, i18n("Could not get file: %1. No file transport").arg(url.prettyURL())); + return; + } + if (!mConnected) + { + if (!connectObex()) + { + finished(); + return; + } + } +// TQT_DBusError dbuserror; +// if (!mFileTransfer->GetFile(url.url(), dbuserror)) { +// TDEIO::SlaveBase::error(TDEIO::ERR_INTERNAL, i18n("Could not get file: %1.").arg(dbuserror.message())); +// } +} + +void ObexProtocol::copy(const KURL &src, const KURL &dest, int permissions, bool overwrite) +{ + kdDebug() << k_funcinfo << endl; + // obex->copy(src, dest, permissions, overwrite); + if (!mConnected) + { + if (!connectObex()) + { + finished(); + return; + } + } +} + +void ObexProtocol::put(const KURL& url, int permissions, bool overwrite, bool resume) +{ + kdDebug() << k_funcinfo << endl; + if (!mConnected) + { + if (!connectObex()) + { + finished(); + return; + } + } + if (!mFileTransfer) + { + TDEIO::SlaveBase::error(TDEIO::ERR_INTERNAL, i18n("Could not put file: %1. No file transport").arg(url.prettyURL())); + return; + } + +// +// TQT_DBusError dbuserror; +// if (!mFileTransfer->PutFile(url.url(), dbuserror)) { +// TDEIO::SlaveBase::error(TDEIO::ERR_INTERNAL, i18n("Could not put file: %1.").arg(dbuserror.message())); +// } + +} + +void ObexProtocol::del(const KURL &url, bool isfile) +{ + kdDebug() << k_funcinfo << endl; + + if (!isfile) + { + TDEIO::SlaveBase::error(TDEIO::ERR_INTERNAL, i18n("Only files can be deleted. Request to delete: %1").arg(url.prettyURL())); + return; + } + if (!mConnected) + { + if (!connectObex()) + { + finished(); + return; + } + } + if (!mFileTransfer) + { + TDEIO::SlaveBase::error(TDEIO::ERR_INTERNAL, i18n("Could not delete file: %1. No file transport").arg(url.prettyURL())); + return; + } + + TQT_DBusError dbuserror; + if (!mFileTransfer->Delete(url.url(), dbuserror)) + { + TDEIO::SlaveBase::error(TDEIO::ERR_INTERNAL, i18n("Could not delete file: %1.").arg(dbuserror.message())); + } + +} + +//void ObexProtocol::rename(const KURL& src, const KURL& dest, bool overwrite) +//{ +// kdDebug() << k_funcinfo << endl; +// // obex->rename(src, dest, overwrite); +// +//} + +void ObexProtocol::mkdir(const KURL&url, int permissions) +{ + kdDebug() << k_funcinfo << endl; + if (!mConnected) + { + if (!connectObex()) + { + finished(); + return; + } + } + if (!mFileTransfer) + { + TDEIO::SlaveBase::error(TDEIO::ERR_INTERNAL, i18n("Could not create directory: %1. No file transport").arg(url.prettyURL())); + return; + } + + TQT_DBusError dbuserror; + if (!mFileTransfer->CreateFolder(url.url(), dbuserror)) + { + TDEIO::SlaveBase::error(TDEIO::ERR_INTERNAL, i18n("Could not create directory: %1.").arg(dbuserror.message())); + } + +} + +bool ObexProtocol::changeWorkingDirectory(const TQString& dir) +{ + kdDebug() << "ObexProtocol::changeWorkingDirectory( " << dir << " )" << endl; + if (!dir.startsWith("/")) + { + TDEIO::SlaveBase::error(TDEIO::ERR_MALFORMED_URL, i18n("Could not change directory: %1. Directory should start with \"/\"").arg(dir)); + return false; + } + if (!mConnected) + { + if (!connectObex()) + { + finished(); + return false; + } + } + if (!mFileTransfer) + { + TDEIO::SlaveBase::error(TDEIO::ERR_INTERNAL, i18n("Could not change directory: %1. No file transport").arg(dir)); + return false; + } + + TQT_DBusError dbuserror; + if (!mFileTransfer->ChangeFolder(dir, dbuserror)) + { + TDEIO::SlaveBase::error(TDEIO::ERR_INTERNAL, i18n("Could not change directory: %1.").arg(dbuserror.message())); + return false; + } + + return true; +} + +void ObexProtocol::slotPropertiesChanged(const TQString& interface, const TQMap< + TQString, TQT_DBusVariant>& changed_properties, const TQStringList& invalidated_properties) +{ + kdDebug() << k_funcinfo << endl; + kdDebug() << interface << endl; + + if (interface == "org.bluez.obex.Session1") + { + TQMap<TQString, TQT_DBusVariant>::const_iterator it; + for (it = changed_properties.begin(); it != changed_properties.end(); + ++it) + { + bool ok = false; + if (it.key() == "Source") + emit sessionSourceChanged(mSessionPath, it.data().value.toBool(&ok)); + else if (it.key() == "Destination") + emit sessionDestinationChanged(mSessionPath, it.data().value.toString(&ok)); + else if (it.key() == "Channel") + emit sessionChannelChanged(mSessionPath, it.data().value.toByte(&ok)); + else if (it.key() == "Target") + emit sessionTargetChanged(mSessionPath, it.data().value.toString(&ok)); + else if (it.key() == "Root") + emit sessionRootChanged(mSessionPath, it.data().value.toString(&ok)); + else + continue; + if (!ok) + tqDebug(i18n("ObjectManagerImpl::slotPropertiesChanged conversion failed")); + } + } + + if (interface == "org.bluez.obex.FileTransfer1" || interface == "org.bluez.obex.Transfer1") + { + TQMap<TQString, TQT_DBusVariant>::const_iterator it; + for (it = changed_properties.begin(); it != changed_properties.end(); + ++it) + { + bool ok = false; + if (it.key() == "Size") + emit transferSizeChanged(mSessionPath, it.data().value.toUInt64(&ok)); + else if (it.key() == "Status") + emit transferStatusChanged(mSessionPath, it.data().value.toString(&ok)); + else if (it.key() == "Transferred") + emit transferTransferredChanged(mSessionPath, it.data().value.toUInt64(&ok)); + else if (it.key() == "Time") + emit transferTimeChanged(mSessionPath, it.data().value.toUInt64(&ok)); + else if (it.key() == "Filename") + emit transferFilenameChanged(mSessionPath, it.data().value.toString(&ok)); + else + continue; + if (!ok) + tqDebug(i18n("ObjectManagerImpl::slotPropertiesChanged conversion failed")); + } + } +} + +#include "tdeio_obex.moc" diff --git a/src/tdebluezioslave/obex/tdeio_obex.h b/src/tdebluezioslave/obex/tdeio_obex.h new file mode 100644 index 0000000..afa4b2e --- /dev/null +++ b/src/tdebluezioslave/obex/tdeio_obex.h @@ -0,0 +1,135 @@ +/* + This file is part of tdeio_obex. + + Copyright (c) 2003 Mathias Froehlich <[email protected]> + + 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 Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + */ + +#ifndef TDEIO_OBEX_H +#define TDEIO_OBEX_H + +#include <tdeio/global.h> +#include <tdeio/job.h> +#include <tdeio/slavebase.h> + +#include <tqdbusobjectpath.h> + +#include <interfaces/client1Proxy.h> +#include <interfaces/session1Proxy.h> +#include <interfaces/propertiesProxy.h> +#include <obexobjectmanagerImpl.h> + +#include "obex.h" + +class ObexProtocol: public TQObject, public TDEIO::SlaveBase { + + Q_OBJECT + +public: + ObexProtocol(const TQCString &protcol, const TQCString &pool_socket, + const TQCString &app_socket); + virtual ~ObexProtocol(); +// virtual void openConnection(); + virtual void closeConnection(); + virtual void stat(const KURL& url); + virtual void listDir(const KURL& url); + virtual void get(const KURL& url); + virtual void copy(const KURL &src, const KURL &dest, int permissions, + bool overwrite); + virtual void put(const KURL& url, int permissions, bool overwrite, + bool resume); + virtual void del(const KURL &url, bool isfile); + // virtual void chmod(const KURL& url, int permissions); +// virtual void rename(const KURL& src, const KURL& dest, bool overwrite); + virtual void mkdir(const KURL&url, int permissions); + +private: + // Private variables + /** True if ioslave is connected to server. */ + bool mConnected; + + /** Host we are connected to. */ + TQString mHost; + + /** + The protocol to be used. + */ + TQString mProtocol; + + /** + Pointer to the obex obejct. + */ + Obex *obex; + + /** + Pointer to the obex client class. + */ + org::bluez::obex::Client1Proxy* mClient; + + /** + Pointer to the obex session class. + */ + org::bluez::obex::Session1Proxy* mSession; + org::freedesktop::DBus::PropertiesProxy* mSessionProperties; + org::bluez::obex::FileTransfer1Proxy* mFileTransfer; + TQT_DBusObjectPath mSessionPath; + TQString mAddress; + + /** + Pointer to the obex agent manager class. + */ + TDEObex::ObexObjectManagerImpl* mManager; + + /** Channel we are connected to. */ + int mChannel; + + struct Status { + int code; + TDEIO::filesize_t size; + TQString text; + }; + +private: + // private methods + + /** + Helper functions. + */ + bool connectObex(); + void closeObex(); + bool changeWorkingDirectory(const TQString& to); + +private slots: + void slotPropertiesChanged(const TQString& interface, + const TQMap<TQString, TQT_DBusVariant>& changed_properties, + const TQStringList& invalidated_properties); + +signals: + void sessionSourceChanged(TQT_DBusObjectPath &path,bool ok); + void sessionDestinationChanged(TQT_DBusObjectPath &path, TQString value); + void sessionChannelChanged(TQT_DBusObjectPath &path, TQ_UINT8 value); + void sessionTargetChanged(TQT_DBusObjectPath &path, TQString value); + void sessionRootChanged(TQT_DBusObjectPath &path, TQString value); + + void transferSizeChanged(TQT_DBusObjectPath &path, TQ_UINT64 value); + void transferStatusChanged(TQT_DBusObjectPath &path, TQString value); + void transferTransferredChanged(TQT_DBusObjectPath &path, TQ_UINT64 value); + void transferTimeChanged(TQT_DBusObjectPath &path, TQ_UINT64 value); + void transferFilenameChanged(TQT_DBusObjectPath &path, TQString value); +}; + +#endif |