/* This file is part of tdeio_obex. Copyright (c) 2003 Mathias Froehlich 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 #include //#include #include #include #include #include #include #include #include #include #include #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 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 vl = folderinfo.toTQValueList(); TQValueList::Iterator dit = vl.begin(); for (dit; dit != vl.end(); ++dit) { bool ok = false; TQMap 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::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::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"