diff options
Diffstat (limited to 'kmobile/kmobiledevice.cpp')
-rw-r--r-- | kmobile/kmobiledevice.cpp | 470 |
1 files changed, 470 insertions, 0 deletions
diff --git a/kmobile/kmobiledevice.cpp b/kmobile/kmobiledevice.cpp new file mode 100644 index 000000000..dc3039f2b --- /dev/null +++ b/kmobile/kmobiledevice.cpp @@ -0,0 +1,470 @@ +/* This file is part of the KDE KMobile library + Copyright (C) 2003 Helge Deller <deller@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> +#include <time.h> +#include <errno.h> +#include <signal.h> +#include <fcntl.h> + +#include <qstring.h> +#include <qstringlist.h> +#include <qfile.h> + +#include <klibloader.h> +#include <kstandarddirs.h> +#include "kmobiledevice.h" +#include <kmessagebox.h> +#include <kconfig.h> + +#include <kio/global.h> +#include <kdebug.h> +#include <klocale.h> + +#define KMOBILEDEVICE_DEBUG_AREA 5730 +#define PRINT_DEBUG kdDebug(KMOBILEDEVICE_DEBUG_AREA) << "KMobileDevice: " + +/** + * The base plugin class of all mobile device drivers. + */ + +KMobileDevice::KMobileDevice(QObject *obj, const char *name, const QStringList &args) + : KLibFactory(obj,name), + m_config(0L), d(0L) +{ + setClassType(Unclassified); + setCapabilities(hasNothing); + m_deviceName = i18n("Unknown Device"); + m_deviceRevision = i18n("n/a"); /* not available */ + m_connectionName = i18n("Unknown Connection"); + + // set the config file name + m_configFileName = args[0]; + if (m_configFileName.isEmpty()) + m_config = new KConfig(); + else + m_config = new KConfig(m_configFileName); + PRINT_DEBUG << QString("name of config file is %1\n").arg(m_configFileName); +} + +KMobileDevice::~KMobileDevice() +{ + delete m_config; +} + + +bool KMobileDevice::connected() +{ + return m_connected; +} + +// returns e.g. "Nokia mobile phone", "MP3 Player", "Handspring Organizer" +QString KMobileDevice::deviceClassName() const +{ + return m_deviceClassName; +} + +// returns real device name, e.g. "Nokia 6310" or "Rio MP3 Player" +QString KMobileDevice::deviceName() const +{ + return m_deviceName; +} + +QString KMobileDevice::revision() const +{ + return m_deviceRevision; +} + +bool KMobileDevice::isSlowDevice() const +{ + return false; +} + +bool KMobileDevice::isReadOnly() const +{ + return false; +} + +bool KMobileDevice::configDialog( QWidget *parent ) +{ + KMessageBox::information( parent, + i18n("This device does not need any configuration."), + deviceName() ); + return true; +} + +void KMobileDevice::setClassType( enum ClassType ct ) +{ + m_classType = ct; + m_deviceClassName = defaultClassName(ct); +} + +enum KMobileDevice::ClassType KMobileDevice::classType() const +{ + return m_classType; +} + +QString KMobileDevice::iconFileName() const +{ + return defaultIconFileName( classType() ); +} + +QString KMobileDevice::defaultIconFileName( ClassType ct ) +{ + QString name; + switch (ct) { + case Phone: name = "mobile_phone"; break; + case Organizer: name = "mobile_organizer"; break; + case Camera: name = "mobile_camera"; break; + case MusicPlayer: name = "mobile_mp3player"; break; + case Unclassified: + default: name = KMOBILE_ICON_UNKNOWN; break; + } + return name; +} + +QString KMobileDevice::defaultClassName( ClassType ct ) +{ + QString name; + switch (ct) { + case Phone: name = i18n("Cellular Mobile Phone"); break; + case Organizer: name = i18n("Organizer"); break; + case Camera: name = i18n("Digital Camera"); break; + case MusicPlayer: name = i18n("Music/MP3 Player"); break; + case Unclassified: + default: name = i18n("Unclassified Device"); break; + } + return name; +} + +void KMobileDevice::setCapabilities( int caps ) +{ + m_caps = caps; +} + +int KMobileDevice::capabilities() const +{ + return m_caps; +} + +const QString KMobileDevice::nameForCap(int cap) const +{ + switch (cap) { + case hasAddressBook: return i18n("Contacts"); + case hasCalendar: return i18n("Calendar"); + case hasNotes: return i18n("Notes"); + case hasFileStorage: return i18n("Files"); + default: return i18n("Unknown"); + } +} + +// returns an error string for the given error code +QString KMobileDevice::buildErrorString(KIO::Error err, const QString &errorText) const +{ + return KIO::buildErrorString( err, errorText); +} + +/* + * Addressbook / Phonebook support + */ +int KMobileDevice::numAddresses() +{ + return 0; +} + +int KMobileDevice::readAddress( int, KABC::Addressee & ) +{ + return KIO::ERR_UNSUPPORTED_ACTION; +} + +int KMobileDevice::storeAddress( int, const KABC::Addressee &, bool ) +{ + return KIO::ERR_UNSUPPORTED_ACTION; +} + +/* + * Calendar support + */ +int KMobileDevice::numCalendarEntries() +{ + return 0; +} + +int KMobileDevice::readCalendarEntry( int, KCal::Event & ) +{ + return KIO::ERR_UNSUPPORTED_ACTION; +} + +int KMobileDevice::storeCalendarEntry( int, const KCal::Event & ) +{ + return KIO::ERR_UNSUPPORTED_ACTION; +} + +/* + * Notes support + */ +int KMobileDevice::numNotes() +{ + return 0; +} + +int KMobileDevice::readNote( int, QString & ) +{ + return KIO::ERR_UNSUPPORTED_ACTION; +} + +int KMobileDevice::storeNote( int, const QString & ) +{ + return KIO::ERR_UNSUPPORTED_ACTION; +} + +/* + * File storage support + * @param fileName path and name of a file in the mobile device, e.g. "/MYFILE.TXT", "/mp3/song1.mp3" + */ + +static +void addAtom(KIO::UDSEntry& entry, unsigned int ID, long l, const QString& s = QString::null) +{ + KIO::UDSAtom atom; + atom.m_uds = ID; + atom.m_long = l; + atom.m_str = s; + entry.append(atom); +} + +void KMobileDevice::createDirEntry(KIO::UDSEntry& entry, const QString& name, const QString& url, const QString& mime) const +{ + entry.clear(); + addAtom(entry, KIO::UDS_NAME, 0, name); + addAtom(entry, KIO::UDS_FILE_TYPE, S_IFDIR); + addAtom(entry, KIO::UDS_ACCESS, 0500); + addAtom(entry, KIO::UDS_MIME_TYPE, 0, mime); + addAtom(entry, KIO::UDS_URL, 0, url); + PRINT_DEBUG << QString("createDirEntry: File: %1 MIME: %2 URL: %3\n").arg(name).arg(mime).arg(url); +// addAtom(entry, KIO::UDS_SIZE, 0); + addAtom(entry, KIO::UDS_GUESSED_MIME_TYPE, 0, mime); +} + +void KMobileDevice::createFileEntry(KIO::UDSEntry& entry, const QString& name, const QString& url, const QString& mime, + const unsigned long size) const +{ + entry.clear(); + addAtom(entry, KIO::UDS_NAME, 0, name); + addAtom(entry, KIO::UDS_FILE_TYPE, S_IFREG); + addAtom(entry, KIO::UDS_URL, 0, url); + addAtom(entry, KIO::UDS_ACCESS, 0400); + addAtom(entry, KIO::UDS_MIME_TYPE, 0, mime); + if (size) addAtom(entry, KIO::UDS_SIZE, size); + addAtom(entry, KIO::UDS_GUESSED_MIME_TYPE, 0, mime); + PRINT_DEBUG << QString("createFileEntry: File: %1, Size: %2, MIME: %3\n").arg(name).arg(size).arg(mime); +} + + +void KMobileDevice::listDir( const QString & ) +{ + emit error(KIO::ERR_CANNOT_ENTER_DIRECTORY,QString::null); +} + +void KMobileDevice::mkdir( const QString &, int ) +{ + emit error(KIO::ERR_COULD_NOT_MKDIR, QString::null); +} + +void KMobileDevice::rename( const QString &, const QString &, bool ) +{ + emit error(KIO::ERR_UNSUPPORTED_ACTION, QString::null); +} + +void KMobileDevice::symlink( const QString &, const QString &, bool ) +{ + emit error(KIO::ERR_UNSUPPORTED_ACTION, QString::null); +} + +void KMobileDevice::del( const QString &, bool ) +{ + emit error(KIO::ERR_UNSUPPORTED_ACTION, QString::null); +} + +void KMobileDevice::stat( const QString & ) +{ + emit error(KIO::ERR_UNSUPPORTED_ACTION, QString::null); +} + +void KMobileDevice::chmod( const QString &, int ) +{ + emit error(KIO::ERR_UNSUPPORTED_ACTION, QString::null); +} + +void KMobileDevice::get( const QString & ) +{ + emit error(KIO::ERR_UNSUPPORTED_ACTION, QString::null); +} + +void KMobileDevice::put( const QString &, int, bool, bool ) +{ + emit error(KIO::ERR_UNSUPPORTED_ACTION, QString::null); +} + +void KMobileDevice::mimetype( const QString & ) +{ + emit error(KIO::ERR_UNSUPPORTED_ACTION, QString::null); +} + +void KMobileDevice::special( const QByteArray & ) +{ + emit error(KIO::ERR_UNSUPPORTED_ACTION, QString::null); +} + + + + +/* + * device locking/unlocking functions + */ + +#ifdef HAVE_BAUDBOY_H +// Header shipped with newer RedHat distributions. +// We have to use this here, because /var/lock is owned by root:lock +// and no one is in this group. Only the binary /usr/sbin/lockdev is +// owned by this group and has the setgid flag set. This binary is called +// in ttylock etc ... +# include <sys/types.h> +# include <sys/stat.h> +# include <fcntl.h> +# include <baudboy.h> +# include <cstdlib> +#else +# ifdef HAVE_LOCKDEV_H +// Library shipped with newer RedHat and Debian(?) distributions. +// Use this if bauddev is not available. +# include <lockdev.h> +# include <sys/types.h> +# include <unistd.h> +# else +// If lockdev.h is also unavailable do locking +// like described in the serial HOWTO. +# include <sys/types.h> +# include <sys/stat.h> +# include <unistd.h> +# include <qfile.h> +# include <signal.h> +# include <errno.h> +# endif +#endif + +#define DEVICE_LOCK_PATH_PREFIX "/var/lock/LCK.." + +bool KMobileDevice::lockDevice(const QString &device, QString &err_reason) +{ +#ifdef HAVE_BAUDBOY_H + return ttylock(device.local8bit()) == EXIT_SUCCESS; +#else +# ifdef HAVE_LOCKDEV_H + return !dev_lock(device.local8bit()); +# else + int pid = -1; + QStringList all = QStringList::split('/', device); + if (!all.count()) { + err_reason = i18n("Invalid device (%1)").arg(device); + return false; + } + QString lockName = DEVICE_LOCK_PATH_PREFIX + all[all.count()-1]; + QFile file(lockName); + if (file.exists() && file.open(IO_ReadOnly)) { + if (file.size() == 0) { + err_reason = i18n("Unable to read lockfile %s. Please check for reason and " + "remove the lockfile by hand.").arg(lockName); + PRINT_DEBUG << err_reason; + return false; + } + if (file.size() == 4 && sizeof(int)==4) { + file.readLine((char *)(&pid), 4); /* Kermit-style lockfile */ + } else { + QTextStream ts(&file); + ts >> pid; /* Ascii lockfile */ + } + file.close(); + + if (pid > 0 && kill((pid_t)pid, 0) < 0 && errno == ESRCH) { + PRINT_DEBUG << QString("Lockfile %1 is stale. Overriding it..\n").arg(lockName); + sleep(1); + if (!file.remove()) { + PRINT_DEBUG << QString("Overriding failed, please check the permissions\n"); + PRINT_DEBUG << QString("Cannot lock device %1\n").arg(device); + err_reason = i18n("Lockfile %1 is stale. Please check permissions.").arg(lockName); + return false; + } + } else { + err_reason = i18n("Device %1 already locked.").arg(device); + return false; + } + } + + /* Try to create a new file, with 0644 mode */ + int fd = open(lockName.local8Bit(), O_CREAT | O_EXCL | O_WRONLY, 0644); + if (fd == -1) { + if (errno == EEXIST) + err_reason = i18n("Device %1 seems to be locked by unknown process.").arg(device); + else if (errno == EACCES) + err_reason = i18n("Please check permission on lock directory."); + else if (errno == ENOENT) + err_reason = i18n("Cannot create lockfile %1. Please check for existence of path.").arg(lockName); + else + err_reason = i18n("Could not create lockfile %1. Error-Code is %2.").arg(lockName).arg(errno); + return false; + } + QString lockText; + lockText = QString("%1 kmobile\n").arg(getpid(),10); + write(fd, lockText.utf8(), lockText.utf8().length()); + close(fd); + + PRINT_DEBUG << QString("%1: Device %2 locked with lockfile %3.\n") + .arg(deviceName()).arg(device).arg(lockName); + + err_reason = QString::null; + + return true; +# endif +#endif +} + +bool KMobileDevice::unlockDevice(const QString &device) +{ +#ifdef HAVE_BAUDBOY_H + return ttyunlock(device.local8bit()) == EXIT_SUCCESS; +#else +# ifdef HAVE_LOCKDEV_H + return 0 <= dev_unlock(device.local8bit(), getpid()); +# else + QStringList all = QStringList::split('/', device); + if (!all.count()) return false; + QString lockName = DEVICE_LOCK_PATH_PREFIX + all[all.count()-1]; + QFile file(lockName); + if (!file.exists()) + return true; + return file.remove(); +# endif +#endif +} + +#include "kmobiledevice.moc" |