diff options
Diffstat (limited to 'src/tdeioslave/obex/tdeio_obex.cpp')
-rw-r--r-- | src/tdeioslave/obex/tdeio_obex.cpp | 548 |
1 files changed, 548 insertions, 0 deletions
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" |