[Pkg-owncloud-commits] [qtkeychain] 02/115: Initial OS X impl.

Sandro Knauß hefee-guest at moszumanska.debian.org
Sat Mar 15 19:25:41 UTC 2014


This is an automated email from the git hooks/post-receive script.

hefee-guest pushed a commit to branch master
in repository qtkeychain.

commit 492c9615baf4d6e424c933653d2e46cef8cedd8d
Author: Frank Osterfeld <frank.osterfeld at kdab.com>
Date:   Thu Oct 27 18:15:46 2011 +0200

    Initial OS X impl.
---
 COPYING          |  20 ++++++++++
 keychain.cpp     |  61 +++++++++++++++++++---------
 keychain.h       |  46 +++++++++++++--------
 keychain_mac.cpp | 120 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
 keychain_p.h     |  24 ++++++++++-
 keychain_win.cpp |   8 ++++
 lib.pro          |  16 ++++++++
 qtkeychain.pro   |  19 ++-------
 testclient.cpp   |  91 +++++++++++++++++++++++++++++++++++++++++
 testclient.pro   |  11 +++++
 10 files changed, 359 insertions(+), 57 deletions(-)

diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..cca2a5c
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,20 @@
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/keychain.cpp b/keychain.cpp
index db6ed8a..d7322be 100644
--- a/keychain.cpp
+++ b/keychain.cpp
@@ -1,34 +1,57 @@
+/******************************************************************************
+ *   Copyright (C) 2011 Frank Osterfeld <frank.osterfeld at gmail.com>           *
+ *                                                                            *
+ * This program 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. For licensing and distribution        *
+ * details, check the accompanying file 'COPYING'.                            *
+ *****************************************************************************/
 #include "keychain.h"
 #include "keychain_p.h"
 
-KeychainException::KeychainException( const QString& message )
-    : std::runtime_error( message.toStdString() )
-    , m_message( message )
-{}
+Keychain::Keychain( const QString& service )
+    : d( new Private( service ) )
+{
+}
 
-KeychainException::~KeychainException() throw() {
+Keychain::~Keychain() {
+    delete d;
 }
 
-QString KeychainException::message() const {
-    return m_message;
+QString Keychain::service() const {
+    return d->service;
 }
 
-Keychain::Keychain( const QString& service )
-    : d( new Private( service ) )
-{
+Keychain::Error Keychain::error() const {
+    return d->error;
 }
 
-QString Keychain::service() const
-{
-    return d->service;
+QString Keychain::errorString() const {
+    return d->errorString;
 }
 
-void Keychain::writePassword( const QString& account, const QString& password )
-{
-    d->writePasswordImpl( account, password );
+void Keychain::writePassword( const QString& account, const QString& password, OverwriteMode om ) {
+    QString err;
+    const Error ret = d->writePasswordImpl( account, password, om, &err );
+    d->error = ret;
+    d->errorString = err;
 }
 
-QString Keychain::readPassword( const QString& account ) const
-{
-    return d->readPasswordImpl( account );
+QString Keychain::readPassword( const QString& account ) {
+    QString err;
+    QString pw;
+    const Error ret = d->readPasswordImpl( &pw, account, &err );
+    d->error = ret;
+    d->errorString = err;
+    if ( ret != NoError )
+        return QString();
+    else
+        return pw;
+}
+
+void Keychain::deletePassword( const QString& account ) {
+    QString err;
+    const Error ret = d->deletePasswordImpl( account, &err );
+    d->error = ret;
+    d->errorString = err;
 }
diff --git a/keychain.h b/keychain.h
index 52ee1de..544cc9b 100644
--- a/keychain.h
+++ b/keychain.h
@@ -1,29 +1,44 @@
+/******************************************************************************
+ *   Copyright (C) 2011 Frank Osterfeld <frank.osterfeld at gmail.com>           *
+ *                                                                            *
+ * This program 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. For licensing and distribution        *
+ * details, check the accompanying file 'COPYING'.                            *
+ *****************************************************************************/
 #ifndef KEYCHAIN_H
 #define KEYCHAIN_H
 
-#include <QString>
-
-#include <stdexcept>
-
-class KeychainException : public std::runtime_error {
-public:
-    explicit KeychainException( const QString& message );
-    ~KeychainException() throw();
-    QString message() const;
-
-private:
-    QString m_message;
-};
+#include <QtCore/QString>
 
 class Keychain {
 public:
     explicit Keychain( const QString& service );
     ~Keychain();
 
+    enum Error {
+        NoError=0,
+        PasswordNotFound,
+        CouldNotDeleteExistingPassword,
+        AccessDenied,
+        EntryAlreadyExists,
+        OtherError
+    };
+
+    enum OverwriteMode {
+        DoNotOverwrite,
+        ForceOverwrite
+    };
+
     QString service() const;
+    Error error() const;
+    QString errorString() const;
 
-    void writePassword( const QString& account, const QString& password );
-    QString readPassword( const QString& account ) const;
+    void writePassword( const QString& account,
+                        const QString& password,
+                        OverwriteMode om=DoNotOverwrite );
+    QString readPassword( const QString& account );
+    void deletePassword( const QString& account );
 
 private:
     class Private;
@@ -32,4 +47,3 @@ private:
 };
 
 #endif
-
diff --git a/keychain_mac.cpp b/keychain_mac.cpp
index b3a3722..0dd210a 100644
--- a/keychain_mac.cpp
+++ b/keychain_mac.cpp
@@ -1,10 +1,122 @@
+/******************************************************************************
+ *   Copyright (C) 2011 Frank Osterfeld <frank.osterfeld at gmail.com>           *
+ *                                                                            *
+ * This program 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. For licensing and distribution        *
+ * details, check the accompanying file 'COPYING'.                            *
+ *****************************************************************************/
 #include "keychain_p.h"
 
-QString Keychain::Private::readPasswordImpl( const QString& account ) const {
-    throw KeychainException( QLatin1String("not implemented") );
+#include <CoreFoundation/CoreFoundation.h>
+#include <Security/Security.h>
+#include <CoreServices/CoreServices.h>
+
+#include <QDebug>
+
+static OSStatus readPw( QString* pw,
+                        const QString& service,
+                        const QString& account,
+                        SecKeychainItemRef* ref ) {
+    Q_ASSERT( pw );
+    pw->clear();
+    const QByteArray serviceData = service.toUtf8();
+    const QByteArray accountData = account.toUtf8();
+
+    void* data = 0;
+    UInt32 len = 0;
+
+    const OSStatus ret = SecKeychainFindGenericPassword( NULL, // default keychain
+                                                         serviceData.size(),
+                                                         serviceData.constData(),
+                                                         accountData.size(),
+                                                         accountData.constData(),
+                                                         &len,
+                                                         &data,
+                                                         ref );
+    if ( ret == noErr ) {
+        *pw = QString::fromUtf8( reinterpret_cast<const char*>( data ), len );
+        const OSStatus ret2 = SecKeychainItemFreeContent ( 0, data );
+    }
+    return ret;
+}
+
+Keychain::Error Keychain::Private::readPasswordImpl( QString* pw,
+                                                     const QString& account,
+                                                     QString* err ) {
+    Q_ASSERT( pw );
+    Q_ASSERT( err );
+    err->clear();
+    const OSStatus ret = readPw( pw, service, account, 0 );
+    switch ( ret ) {
+    case noErr:
+        return NoError;
+    case errSecItemNotFound:
+        *err = tr("Password not found");
+        return PasswordNotFound;
+    default:
+        *err = QString::number( ret );
+        return OtherError;
+    }
+}
+
+Keychain::Error Keychain::Private::writePasswordImpl( const QString& account,
+                                                      const QString& password,
+                                                      Keychain::OverwriteMode ov,
+                                                      QString* err ) {
+    Q_ASSERT( err );
+    err->clear();
+    const QByteArray serviceData = service.toUtf8();
+    const QByteArray accountData = account.toUtf8();
+    const QByteArray passwordData = password.toUtf8();
+    const OSStatus ret = SecKeychainAddGenericPassword( NULL, //default keychain
+                                                        serviceData.size(),
+                                                        serviceData.constData(),
+                                                        accountData.size(),
+                                                        accountData.constData(),
+                                                        passwordData.size(),
+                                                        passwordData.constData(),
+                                                        NULL //item reference
+                                                        );
+    if ( ret != noErr ) {
+        switch ( ret ) {
+        case errSecDuplicateItem:
+        {
+            if ( ov == Keychain::DoNotOverwrite ) {
+                *err = tr("Entry already exists");
+                return EntryAlreadyExists;
+            }
+            Error derr = deletePasswordImpl( account, err );
+            if ( derr != NoError )
+                return CouldNotDeleteExistingPassword;
+            else
+                return writePasswordImpl( account, password, ov, err );
+        }
+        default:
+            *err = QString::number( ret );
+            return OtherError;
+        }
+    }
+
+    return NoError;
 }
 
-void Keychain::Private::writePasswordImpl( const QString& account, const QString& password ) {
-    throw KeychainException( QLatin1String("not implemented") );
+Keychain::Error Keychain::Private::deletePasswordImpl( const QString& account,
+                                                       QString* errorString ) {
+    SecKeychainItemRef ref;
+    QString pw;
+    const OSStatus ret1 = readPw( &pw, service, account, &ref );
+    if ( ret1 == errSecItemNotFound )
+        return NoError;
+    if ( ret1 != noErr ) {
+        //TODO map error code, set errstr
+        return OtherError;
+    }
+    const OSStatus ret2 = SecKeychainItemDelete( ref );
+    CFRelease(ref);
+    if ( ret2 == noErr )
+        return NoError;
+    //TODO map error code, set errstr
+    return OtherError;
 }
 
diff --git a/keychain_p.h b/keychain_p.h
index ab181af..853d2b8 100644
--- a/keychain_p.h
+++ b/keychain_p.h
@@ -1,16 +1,36 @@
+/******************************************************************************
+ *   Copyright (C) 2011 Frank Osterfeld <frank.osterfeld at gmail.com>           *
+ *                                                                            *
+ * This program 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. For licensing and distribution        *
+ * details, check the accompanying file 'COPYING'.                            *
+ *****************************************************************************/
 #ifndef KEYCHAIN_P_H
 #define KEYCHAIN_P_H
 
+#include <QCoreApplication>
+
 #include "keychain.h"
 
 class Keychain::Private {
+    Q_DECLARE_TR_FUNCTIONS(Keychain::Private)
 public:
     explicit Private( const QString& s ) : service( s ) {}
 
-    void writePasswordImpl( const QString& account, const QString& password );
-    QString readPasswordImpl( const QString& account ) const;
+    Keychain::Error writePasswordImpl( const QString& account,
+                                       const QString& password,
+                                       Keychain::OverwriteMode,
+                                       QString* errorString );
+    Keychain::Error deletePasswordImpl( const QString& account,
+                                        QString* errorString );
+    Keychain::Error readPasswordImpl( QString* password,
+                                      const QString& account,
+                                      QString* errorString );
 
     const QString service;
+    Keychain::Error error;
+    QString errorString;
 };
 
 #endif // KEYCHAIN_P_H
diff --git a/keychain_win.cpp b/keychain_win.cpp
index b3a3722..fc781d3 100644
--- a/keychain_win.cpp
+++ b/keychain_win.cpp
@@ -1,3 +1,11 @@
+/******************************************************************************
+ *   Copyright (C) 2011 Frank Osterfeld <frank.osterfeld at gmail.com>           *
+ *                                                                            *
+ * This program 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. For licensing and distribution        *
+ * details, check the accompanying file 'COPYING'.                            *
+ *****************************************************************************/
 #include "keychain_p.h"
 
 QString Keychain::Private::readPasswordImpl( const QString& account ) const {
diff --git a/lib.pro b/lib.pro
new file mode 100644
index 0000000..656c3d5
--- /dev/null
+++ b/lib.pro
@@ -0,0 +1,16 @@
+TEMPLATE = lib
+TARGET = qtkeychain
+DEPENDPATH += .
+INCLUDEPATH += .
+
+# Input
+HEADERS += keychain.h \
+    keychain_p.h
+SOURCES += keychain.cpp
+
+macx {
+    LIBS += -framework Security -framework CoreFoundation
+    SOURCES += keychain_mac.cpp
+}
+win32:SOURCES += keychain_win.cpp
+
diff --git a/qtkeychain.pro b/qtkeychain.pro
index a2a1c12..a5406ca 100644
--- a/qtkeychain.pro
+++ b/qtkeychain.pro
@@ -1,17 +1,4 @@
-######################################################################
-# Automatically generated by qmake (2.01a) Thu Oct 27 17:55:20 2011
-######################################################################
-
-TEMPLATE = lib
-TARGET = qtkeychain
-DEPENDPATH += .
-INCLUDEPATH += .
-
-# Input
-HEADERS += keychain.h \
-    keychain_p.h
-SOURCES += keychain.cpp
-
-macx:SOURCES += keychain_mac.cpp
-win32:SOURCES += keychain_win.cpp
+TEMPLATE = subdirs
+SUBDIRS += lib.pro testclient.pro
+CONFIG += ordered
 
diff --git a/testclient.cpp b/testclient.cpp
new file mode 100644
index 0000000..ae4071d
--- /dev/null
+++ b/testclient.cpp
@@ -0,0 +1,91 @@
+/*
+ * This file is part of the qtkeychain library
+ *
+ * Copyright (C) 2011 Frank Osterfeld <frank.osterfeld at gmail.com>
+ *
+ * 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 Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+#include <QCoreApplication>
+#include <QStringList>
+
+#include "keychain.h"
+#include <iostream>
+
+
+int printUsage() {
+    std::cerr << "testclient store <account> <password>" << std::endl;
+    std::cerr << "testclient restore <account>" << std::endl;
+    std::cerr << "testclient delete <account>" << std::endl;
+    return 1;
+}
+
+int main( int argc, char** argv ) {
+    QCoreApplication app( argc, argv );
+    const QStringList args = app.arguments();
+    if ( args.count() < 2 )
+        return printUsage();
+
+    QStringList::ConstIterator it = args.constBegin();
+    ++it;
+
+    if ( *it == QLatin1String("store") ) {
+        if ( ++it == args.constEnd() )
+            return printUsage();
+        const QString acc = *it;
+        if ( ++it == args.constEnd() )
+            return printUsage();
+        const QString pass = *it;
+        if ( ++it != args.constEnd() )
+            return printUsage();
+        Keychain k( QLatin1String("qtkeychain-testclient") );
+        k.writePassword( acc, pass, Keychain::ForceOverwrite );
+        if ( k.error() ) {
+            std::cerr << "Storing password failed: " << qPrintable(k.errorString()) << std::endl;
+            return 1;
+        }
+        std::cout << "Password stored successfully" << std::endl;
+    } else if ( *it == QLatin1String("restore") ) {
+        if ( ++it == args.constEnd() )
+            return printUsage();
+        const QString acc = *it;
+        if ( ++it != args.constEnd() )
+            return printUsage();
+        Keychain k( QLatin1String("qtkeychain-testclient") );
+        const QString pw = k.readPassword( acc );
+        if ( k.error() ) {
+            std::cerr << "Restoring password failed: " << qPrintable(k.errorString()) << std::endl;
+            return 1;
+        }
+        std::cout << qPrintable(pw) << std::endl;
+    } else if ( *it == QLatin1String("delete") ) {
+        if ( ++it == args.constEnd() )
+            return printUsage();
+        const QString acc = *it;
+        if ( ++it != args.constEnd() )
+            return printUsage();
+        Keychain k( QLatin1String("qtkeychain-testclient") );
+        k.deletePassword( acc );
+        if ( k.error() ) {
+            std::cerr << "Deleting password failed: " << qPrintable(k.errorString()) << std::endl;
+            return 1;
+        }
+        std::cout << "Password deleted successfully" << std::endl;
+    } else {
+        return printUsage();
+    }
+}
+
diff --git a/testclient.pro b/testclient.pro
new file mode 100644
index 0000000..912fdb1
--- /dev/null
+++ b/testclient.pro
@@ -0,0 +1,11 @@
+TEMPLATE = app
+TARGET = testclient
+
+SOURCES += testclient.cpp
+
+QT -= gui
+CONFIG += console
+macx:CONFIG -= app_bundle
+
+LIBS += -L$$OUT_PWD -lqtkeychain
+

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-owncloud/qtkeychain.git



More information about the Pkg-owncloud-commits mailing list