summaryrefslogtreecommitdiffstats
path: root/src/tdeioslave/obex
diff options
context:
space:
mode:
Diffstat (limited to 'src/tdeioslave/obex')
-rw-r--r--src/tdeioslave/obex/CMakeLists.txt38
-rw-r--r--src/tdeioslave/obex/README91
-rw-r--r--src/tdeioslave/obex/obex.cpp312
-rw-r--r--src/tdeioslave/obex/obex.h66
-rw-r--r--src/tdeioslave/obex/obex_sidebarentry.desktop10
-rw-r--r--src/tdeioslave/obex/obexftp.protocol52
-rw-r--r--src/tdeioslave/obex/obexopp.protocol52
-rw-r--r--src/tdeioslave/obex/tdeio_obex.cpp548
-rw-r--r--src/tdeioslave/obex/tdeio_obex.h135
9 files changed, 1304 insertions, 0 deletions
diff --git a/src/tdeioslave/obex/CMakeLists.txt b/src/tdeioslave/obex/CMakeLists.txt
new file mode 100644
index 0000000..d31aa6f
--- /dev/null
+++ b/src/tdeioslave/obex/CMakeLists.txt
@@ -0,0 +1,38 @@
+#################################################
+#
+# (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_bluetooth (static) #############################
+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}
+)
+
+install( FILES obexftp.protocol
+ DESTINATION ${SERVICES_INSTALL_DIR} )
+install( FILES obexopp.protocol
+ DESTINATION ${SERVICES_INSTALL_DIR} )
+install( FILES obex_sidebarentry.desktop
+ DESTINATION ${DATA_INSTALL_DIR}/konqsidebartng/virtual_folders/services ) \ No newline at end of file
diff --git a/src/tdeioslave/obex/README b/src/tdeioslave/obex/README
new file mode 100644
index 0000000..a44d55f
--- /dev/null
+++ b/src/tdeioslave/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 <Sch@ttgen.net> 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/tdeioslave/obex/obex.cpp b/src/tdeioslave/obex/obex.cpp
new file mode 100644
index 0000000..fb1d81b
--- /dev/null
+++ b/src/tdeioslave/obex/obex.cpp
@@ -0,0 +1,312 @@
+/*
+ This file is part of tdeio_obex.
+
+ Copyright (c) 2003 Mathias Froehlich <Mathias.Froehlich@web.de>
+
+ 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/tdeioslave/obex/obex.h b/src/tdeioslave/obex/obex.h
new file mode 100644
index 0000000..bc6d3cc
--- /dev/null
+++ b/src/tdeioslave/obex/obex.h
@@ -0,0 +1,66 @@
+/*
+ This file is part of tdeio_obex.
+
+ Copyright (c) 2003 Mathias Froehlich <Mathias.Froehlich@web.de>
+
+ 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/tdeioslave/obex/obex_sidebarentry.desktop b/src/tdeioslave/obex/obex_sidebarentry.desktop
new file mode 100644
index 0000000..9bc0178
--- /dev/null
+++ b/src/tdeioslave/obex/obex_sidebarentry.desktop
@@ -0,0 +1,10 @@
+[Desktop Entry]
+Encoding=UTF-8
+Type=Link
+URL=obexftp:/
+Icon=tdebluez
+Name=Bluetooth Browser
+Name[et]=Bluetoothi brauser
+Open=false
+X-TDE-TreeModule=Directory
+X-TDE-KonqSidebarModule=konqsidebar_tree
diff --git a/src/tdeioslave/obex/obexftp.protocol b/src/tdeioslave/obex/obexftp.protocol
new file mode 100644
index 0000000..3262d4b
--- /dev/null
+++ b/src/tdeioslave/obex/obexftp.protocol
@@ -0,0 +1,52 @@
+[Protocol]
+# The executable
+exec=tdeio_obex
+# This protocol name
+protocol=obexftp
+Parent=system:/
+
+# input/output can be one of: filesystem, stream, none
+input=none
+output=filesystem
+maxInstances=1
+
+# capabilities for this protocol
+reading=true
+writing=true
+makedir=true
+deleting=true
+moving=false
+linking=false
+
+# What to list ... FIXME work out how ...
+listing=Name,Type,Size,Date,AccessDate,Access,Owner,Group
+
+# Can be source protocol
+source=false
+
+Description=A tdeioslave for OBEX connections
+Description[bg]=tdeioslave за OBEX връзки
+Description[br]=Ur c'hioslave evit ar c'hevreadennoù OBEX
+Description[ca]=Un tdeioslave per a les connexions OBEX
+Description[da]=En tdeioslave til OBEX-forbindelser
+Description[de]=Ein tdeioslave für OBEX-Verbindungen
+Description[el]=Ένας υπηρέτης tdeio για συνδέσεις OBEX
+Description[es]=Un 'tdeioslave' para conexiones OBEX
+Description[et]=OBEX-ühenduste I/O-moodul
+Description[fr]=Un tdeioslave pour les connexions OBEX
+Description[it]=Un tdeioslave per connessioni OBEX
+Description[ja]=OBEX 接続のための tdeioslave
+Description[ka]=tdeioslave OBEX კავშირებისთვის
+Description[nl]=Een tdeioslave for OBEX-verbindingen
+Description[pl]=Wtyczka protokołu dla połączeń OBEX
+Description[pt]=Um 'tdeioslave' para ligações OBEX
+Description[pt_BR]=Um 'tdeioslave' para ligações OBEX
+Description[sr]=tdeioslave за OBEX везе
+Description[sr@Latn]=tdeioslave za OBEX veze
+Description[sv]=En I/O-slav för OBEX-anslutningar
+Description[ta]=ஒரு OBEX இணைப்பிற்க்காண tdeioslave.
+Description[tr]=OBEX bağlantıları için bir tdeioslave
+Description[xx]=xxA tdeioslave for OBEX connectionsxx
+Icon=remote
+
+DocPath=tdebluez/components.tdeio_obex.html
diff --git a/src/tdeioslave/obex/obexopp.protocol b/src/tdeioslave/obex/obexopp.protocol
new file mode 100644
index 0000000..964bab9
--- /dev/null
+++ b/src/tdeioslave/obex/obexopp.protocol
@@ -0,0 +1,52 @@
+[Protocol]
+# The executable
+exec=tdeio_obex
+# This protocol name
+protocol=obexopp
+Parent=system:/
+
+# input/output can be one of: filesystem, stream, none
+input=none
+output=none
+maxInstances=1
+
+# capabilities for this protocol
+reading=false
+writing=true
+makedir=false
+deleting=false
+moving=false
+linking=false
+
+# What to list ... FIXME work out how ...
+listing=Name,Type,Size,Date,AccessDate,Access,Owner,Group
+
+# Can be source protocol
+source=false
+
+Description=A tdeioslave for OBEX connections
+Description[bg]=tdeioslave за OBEX връзки
+Description[br]=Ur c'hioslave evit ar c'hevreadennoù OBEX
+Description[ca]=Un tdeioslave per a les connexions OBEX
+Description[da]=En tdeioslave til OBEX-forbindelser
+Description[de]=Ein tdeioslave für OBEX-Verbindungen
+Description[el]=Ένας υπηρέτης tdeio για συνδέσεις OBEX
+Description[es]=Un 'tdeioslave' para conexiones OBEX
+Description[et]=OBEX-ühenduste I/O-moodul
+Description[fr]=Un tdeioslave pour les connexions OBEX
+Description[it]=Un tdeioslave per connessioni OBEX
+Description[ja]=OBEX 接続のための tdeioslave
+Description[ka]=tdeioslave OBEX კავშირებისთვის
+Description[nl]=Een tdeioslave for OBEX-verbindingen
+Description[pl]=Wtyczka protokołu dla połączeń OBEX
+Description[pt]=Um 'tdeioslave' para ligações OBEX
+Description[pt_BR]=Um 'tdeioslave' para ligações OBEX
+Description[sr]=tdeioslave за OBEX везе
+Description[sr@Latn]=tdeioslave za OBEX veze
+Description[sv]=En I/O-slav för OBEX-anslutningar
+Description[ta]=ஒரு OBEX இணைப்பிற்க்காண tdeioslave.
+Description[tr]=OBEX bağlantıları için bir tdeioslave
+Description[xx]=xxA tdeioslave for OBEX connectionsxx
+Icon=remote
+
+DocPath=tdebluez/components.tdeio_obex.html
diff --git a/src/tdeioslave/obex/tdeio_obex.cpp b/src/tdeioslave/obex/tdeio_obex.cpp
new file mode 100644
index 0000000..fbd2fb5
--- /dev/null
+++ b/src/tdeioslave/obex/tdeio_obex.cpp
@@ -0,0 +1,548 @@
+/*
+ This file is part of tdeio_obex.
+
+ Copyright (c) 2003 Mathias Froehlich <Mathias.Froehlich@web.de>
+
+ 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 );
+ // 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 = "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, "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, dbuserror.message());
+ }
+ // 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("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("ObjectManagerImpl::slotPropertiesChanged conversion failed");
+ }
+ }
+}
+
+#include "tdeio_obex.moc"
diff --git a/src/tdeioslave/obex/tdeio_obex.h b/src/tdeioslave/obex/tdeio_obex.h
new file mode 100644
index 0000000..afa4b2e
--- /dev/null
+++ b/src/tdeioslave/obex/tdeio_obex.h
@@ -0,0 +1,135 @@
+/*
+ This file is part of tdeio_obex.
+
+ Copyright (c) 2003 Mathias Froehlich <Mathias.Froehlich@web.de>
+
+ 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