summaryrefslogtreecommitdiffstats
path: root/kmobile/kmobiledevice.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kmobile/kmobiledevice.cpp')
-rw-r--r--kmobile/kmobiledevice.cpp470
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"