+++ /dev/null
-/*
- * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved.
- *
- * The contents of this file constitute Original Code as defined in and are
- * subject to the Apple Public Source License Version 1.2 (the 'License').
- * You may not use this file except in compliance with the License. Please obtain
- * a copy of the License at http://www.apple.com/publicsource and read it before
- * using this file.
- *
- * This Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
- * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
- * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
- * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
- * specific language governing rights and limitations under the License.
- */
-
-
-//
-// dliterators - DL/MDS table access as C++ iterators
-//
-// This is currently an almost read-only implementation.
-// (You can erase but you can't create or modify.)
-//
-#ifndef _H_CDSA_CLIENT_DLITERATORS
-#define _H_CDSA_CLIENT_DLITERATORS
-
-#include <security_utilities/threading.h>
-#include <security_utilities/globalizer.h>
-#include <security_utilities/refcount.h>
-#include <security_cdsa_utilities/cssmalloc.h>
-#include <security_cdsa_utilities/cssmpods.h>
-#include <security_cdsa_utilities/cssmerrors.h>
-#include <security_cdsa_utilities/cssmdb.h>
-#include <security_cdsa_client/dlquery.h>
-
-
-namespace Security {
-namespace CssmClient {
-
-
-//
-// An abstract interface to a (partial) DLDb-style object.
-// This is a particular (open) database that you can perform CSSM database
-// operations on.
-//
-class DLAccess {
-public:
- virtual ~DLAccess();
-
- virtual CSSM_HANDLE dlGetFirst(const CSSM_QUERY &query,
- CSSM_DB_RECORD_ATTRIBUTE_DATA &attributes, CSSM_DATA *data,
- CSSM_DB_UNIQUE_RECORD *&id) = 0;
- virtual bool dlGetNext(CSSM_HANDLE handle,
- CSSM_DB_RECORD_ATTRIBUTE_DATA &attributes, CSSM_DATA *data,
- CSSM_DB_UNIQUE_RECORD *&id) = 0;
- virtual void dlAbortQuery(CSSM_HANDLE handle) = 0;
- virtual void dlFreeUniqueId(CSSM_DB_UNIQUE_RECORD *id) = 0;
- virtual void dlDeleteRecord(CSSM_DB_UNIQUE_RECORD *id) = 0;
- virtual Allocator &allocator() = 0;
-};
-
-
-//
-// Abstract Database Records.
-// Each database record type has a subclass of this.
-// These are RefCounted; you can hang on to them as long as you like,
-// stick (RefPointers to) them into maps, and so on. Just go for it.
-//
-class Record : public RefCount, public CssmAutoData {
-public:
- Record() : CssmAutoData(Allocator::standard(Allocator::sensitive)) { }
- Record(const char * const * attributeNames); // sets mAttributes
- virtual ~Record();
- static const CSSM_DB_RECORDTYPE recordType = CSSM_DL_DB_RECORD_ANY;
-
- void addAttributes(const char * const * attributeNames); // add more
-
- // raw attribute access
- CssmDbRecordAttributeData &attributes() { return mAttributes; }
- const CssmDbRecordAttributeData &attributes() const { return mAttributes; }
- CSSM_DB_RECORDTYPE actualRecordType() const { return mAttributes.recordType(); }
-
- CssmAutoData &recordData() { return *this; } // my data nature
-
-protected:
- CssmAutoDbRecordAttributeData mAttributes;
-};
-
-
-//
-// TableBase is an implementation class for template Table below.
-// Do not use it directly (you'll be sorry).
-// Continue reading at template Table below.
-//
-class TableBase {
-public:
- DLAccess &database;
-
- CSSM_DB_RECORDTYPE recordType() const { return mRecordType; }
- void recordType(CSSM_DB_RECORDTYPE t) { mRecordType = t; } // override
-
- // erase all elements matching a query
- uint32 erase(const CSSM_QUERY &query);
- uint32 erase(const Query &query);
-
-protected:
- TableBase(DLAccess &source, CSSM_DB_RECORDTYPE type, bool getData = true);
-
- class AccessRef : public RefCount {
- protected:
- AccessRef() : mAccess(NULL) { }
- AccessRef(DLAccess *ac) : mAccess(ac) { }
- DLAccess *mAccess;
- };
-
- struct Handle : public AccessRef {
- CSSM_HANDLE query;
- Handle(DLAccess *ac, CSSM_HANDLE q) : AccessRef(ac), query(q) { }
- ~Handle();
- };
-
- struct Uid : public AccessRef {
- CSSM_DB_UNIQUE_RECORD *uid;
- Uid(DLAccess *ac, CSSM_DB_UNIQUE_RECORD *id) : AccessRef(ac), uid(id) { }
- ~Uid();
- };
-
- class Iterator {
- public:
- const CSSM_DB_UNIQUE_RECORD *recordHandle() const
- { assert(mUid); return mUid->uid; }
-
- protected:
- Iterator() { }
- Iterator(DLAccess *ac, CSSM_HANDLE query, CSSM_DB_UNIQUE_RECORD *id,
- Record *record, bool getData);
- void advance(Record *newRecord); // generic operator ++ helper
-
- DLAccess *mAccess; // data source
- RefPointer<Handle> mQuery; // DL/MDS query handle
- RefPointer<Uid> mUid; // record unique identifier
- RefPointer<Record> mRecord; // current record value
- bool mGetData; // ask for data on iteration
- };
-
-protected:
- CSSM_DB_RECORDTYPE mRecordType; // CSSM/MDS record type
- bool mGetData; // ask for record data on primary iteration
-};
-
-
-//
-// A Table represents a single relation in a database (of some kind)
-//
-template <class RecordType>
-class Table : private TableBase {
- typedef RefPointer<RecordType> RecPtr;
-public:
- Table(DLAccess &source) : TableBase(source, RecordType::recordType) { }
- Table(DLAccess &source, CSSM_DB_RECORDTYPE type) : TableBase(source, type) { }
- Table(DLAccess &source, bool getData) : TableBase(source, RecordType::recordType, getData) { }
-
-public:
- class iterator : public Iterator,
- public std::iterator<forward_iterator_tag, RefPointer<RecordType> > {
- friend class Table;
- public:
- iterator() { }
-
- bool operator == (const iterator &other) const
- { return mUid.get() == other.mUid.get(); }
- bool operator != (const iterator &other) const
- { return mUid.get() != other.mUid.get(); }
-
- RecPtr operator * () const { return static_cast<RecordType *>(mRecord.get()); }
- RecordType *operator -> () const { return static_cast<RecordType *>(mRecord.get()); }
- iterator operator ++ () { advance(new RecordType); return *this; }
- iterator operator ++ (int) { iterator old = *this; operator ++ (); return old; }
-
- void erase();
-
- private:
- iterator(DLAccess *ac, CSSM_HANDLE query, CSSM_DB_UNIQUE_RECORD *id,
- RecordType *record, bool getData)
- : Iterator(ac, query, id, record, getData) { }
- };
-
-public:
- iterator begin();
- iterator find(const CSSM_QUERY &query);
- iterator find(const Query &query);
- iterator end() { return iterator(); }
- RecPtr fetch(const Query &query, CSSM_RETURN err = CSSM_OK) // one-stop shopping
- { return fetchFirst(find(query), err); }
- RecPtr fetch(CSSM_RETURN err = CSSM_OK) // fetch first of type
- { return fetchFirst(begin(), err); }
-
- // erase all records matching a query
- void erase(const CSSM_QUERY &query);
- void erase(const Query &query);
-
- void erase(iterator it) { it.erase(); }
-
-private:
- iterator startQuery(const CssmQuery &query, bool getData);
- RecPtr fetchFirst(iterator it, CSSM_RETURN err);
-};
-
-
-//
-// Template out-of-line functions
-//
-template <class RecordType>
-typename Table<RecordType>::iterator Table<RecordType>::begin()
-{
- return startQuery(CssmQuery(mRecordType), mGetData);
-}
-
-template <class RecordType>
-typename Table<RecordType>::iterator Table<RecordType>::find(const CSSM_QUERY &query)
-{
- return startQuery(CssmQuery(CssmQuery::overlay(query), mRecordType), mGetData);
-}
-
-template <class RecordType>
-typename Table<RecordType>::iterator Table<RecordType>::find(const Query &query)
-{
- return startQuery(CssmQuery(query.cssmQuery(), mRecordType), mGetData);
-}
-
-template <class RecordType>
-RefPointer<RecordType> Table<RecordType>::fetchFirst(iterator it, CSSM_RETURN err)
-{
- if (it == end())
- if (err)
- CssmError::throwMe(err);
- else
- return NULL;
- else
- return *it;
-}
-
-
-template <class RecordType>
-typename Table<RecordType>::iterator Table<RecordType>::startQuery(const CssmQuery &query, bool getData)
-{
- RefPointer<RecordType> record = new RecordType;
- CSSM_DB_UNIQUE_RECORD *id;
- CssmAutoData data(database.allocator());
- CSSM_HANDLE queryHandle = database.dlGetFirst(query, record->attributes(),
- getData ? &data.get() : NULL, id);
- if (queryHandle == CSSM_INVALID_HANDLE)
- return end(); // not found
- if (getData)
- record->recordData() = data;
- return iterator(&database, queryHandle, id, record, getData);
-}
-
-
-template <class RecordType>
-void Table<RecordType>::iterator::erase()
-{
- mAccess->dlDeleteRecord(mUid->uid);
- mUid->uid = NULL;
-}
-
-
-} // end namespace CssmClient
-} // end namespace Security
-
-#endif // _H_CDSA_CLIENT_DLITERATORS