/***************************************************************************
 $RCSfile: mediumddv.h,v $
                             -------------------
    cvs         : $Id: mediumddv.h,v 1.20 2003/03/02 19:35:14 derzach Exp $
    begin       : Fri Nov 16 2001
    copyright   : (C) 2001 by Martin Preuss
    email       : openhbci@aquamaniac.de

 ***************************************************************************
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Lesser General Public            *
 *   License as published by the Free Software Foundation; either          *
 *   version 2.1 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     *
 *   Lesser General Public License for more details.                       *
 *                                                                         *
 *   You should have received a copy of the GNU Lesser General Public      *
 *   License along with this library; if not, write to the Free Software   *
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
 *   MA  02111-1307  USA                                                   *
 *                                                                         *
 ***************************************************************************/

/** @file mediumddv.h
 *
 * @short Chip card medium HBCI::MediumDDV with C wrapper
 * @ref HBCI_MediumDDV.
 */


#ifndef HBCIMEDIUMDDV_H
#define HBCIMEDIUMDDV_H

#ifdef HAS_LIBCHIPCARD

#ifdef __cplusplus
#include <chipcard.h>
#endif /* __cplusplus */

#include <openhbci/medium.h>

#ifdef __cplusplus
namespace HBCI {
/**
 * @short Implements access to HBCI chip cards.
 * This class implements access to hbci chip cards.
 * @author Martin Preuss<openhbci@aquamaniac.de>
 */
class DLLIMPORT MediumDDV : public HBCICard, public Medium {
private:
  bool _ismounted;
  int _mountcount;
  string _cid;

  string _cardnumber;
  string _userid;
  string _instcode;
  string _addr;
  int _country;

  /**
   * Reads the CID of the card and stores it internally.
   * @author Martin Preuss<openhbci@aquamaniac.de>
   */
  void readCID();

  /**
   * checks whether the inserted card is the one we wanted
   */
  Error _checkCard();
  Error _enterPin(Pointer<User> user,
		  const string &pin,
		  bool hasKeypad);

protected:
#if k_CHIPCARD_VERSION_MAJOR>0 || k_CHIPCARD_VERSION_MINOR>6
  virtual CallBackResult doCallBack(bool first);
#endif

public:
  /**
   * Constructor for automatic terminal mode.
   * @param hbci pointer to the program's HBCI object
   * @param cardnumber this is the cards serial number. It is strongly
   * advised to give this number here to let this class select the
   * proper HBCI card. This protects you from giving the incorrect pin for
   * the inserted card. That could occur this way: When not giving this
   * number here, then the first time the card is mounted, this number
   * gets read off the inserted chip card. But if the card is not the one
   * for the context to select, then giving the pin will maybe try to
   * verify a correct pin for the false card. That would decrement the
   * card's internal bad-counter, so after 3 times your card might get
   * invalid. You can avoid those problems by giving the number here.
   * You can initially read this number by opening the card
   * (@ref openHBCICard()) and then calling @ref getCardId().
   * Another way is to mount the card and read this number by caling
   * @ref cardNumber().
   * @param terminalName short name of the terminal in which the card is
   * expected. This is the short name as stated in "/etc/libchipcard.conf"
   * by the variable "shortname". If omitted the first terminal given in
   * that config file will be used.
   * @author Martin Preuss<openhbci@aquamaniac.de>
   */
  MediumDDV(const Hbci *hbci, const string& cardnumber="",
	    const string& terminalName="");
  ~MediumDDV();

  /** @name Medium Management */
  /*@{*/
  /**
   * Since some media (like hbci chip cards) are able to store multiple
   * account entries you have to select one.
   * @author Martin Preuss<openhbci@aquamaniac.de>
   */
  bool selectContext(int country,
		     const string& instcode,
		     const string& userid);

  /**
   * Mounts a medium and makes its crypto methods available.
   *
   * @param user Pointer to the user that wants to mount this
   * medium. Used only for information purposes in the
   * HBCI::Interactor. May be an invalid (NULL) pointer .
   *
   * @param pin The secret PIN that is needed to actually mount this
   * medium. If omitted the user will be asked for it when needed.
   *
   * @author Martin Preuss<openhbci@aquamaniac.de>
   *
   * @return An HBCI::Error, where Error.isOk()==true if medium mounted
   */
  Error mountMedium(Pointer<User> user = 0, const string& pin="");

  /**
   * Unmounts a medium so that it may be removed.
   * @author Martin Preuss<openhbci@aquamaniac.de>
   * @return true if medium unmounted
   */
  void unmountMedium(const string& pin="");

  /**
   * DDV cards do not support changing the PIN, a HBCI::Error is thrown!
   */
  virtual bool changePIN();
	
  /**
   * Change data that is stored on the medium.<br>
   * Note: Each paramter you don't specify is <b>not</b> changed.<br>
   * @param context DDV cards support multiple contexts, use this 
   * parameter to select it (1..n)
   * @param country The new country code (280 for Germany)
   * @param instcode The new institute code
   * @param userid The new user id
   * @param custid The new customer id
   * @param server The new server address
   */
  virtual bool changeContext(int context, int country=0, 
							 const string instcode="", 
							 const string userid="", const string custid="",
							 const string server="");

  /**
   * Returns a unique sequence number.
   * This method MUST never return a sequence number it returned
   * before !
   */
  unsigned int nextSEQ();
  /*@}*/

  /** @name Medium Information */
  /*@{*/
  /**
   * Checks whether the medium is mounted.
   * @author Martin Preuss<openhbci@aquamaniac.de>
   * @return true if medium unmounted, false if not (or on error)
   */
  bool isMounted();

  /**
   * Returns the id of the medium. For DDV this is the CID of the chip
   * card, for RDH this is the system ID assigned to us by an institute.
   * @author Martin Preuss<openhbci@aquamaniac.de>
   */
  string mediumId() const;

  /**
   * Returns the security mode of this medium (DDV, RDH)
   * @author Martin Preuss<openhbci@aquamaniac.de>
   */
  int securityMode() const { return HBCI_SECURITY_DDV;} ;

  /**
   * Returns the name of the medium.
   * For DDV this is the card number, for RDH this is the name of the file.
   * CHANGED !!
   */
  const string& mediumName() const { return _cardnumber; } ;
  //string mediumName() const { return _cid; } ;

  /**
   * Returns the type this medium is of.
   *
   * @author Martin Preuss<openhbci@aquamaniac.de>
   */
  MediumType mediumType() const { return MediumDDVCard;};

  /**
   * Returns the number of the sign key. RDH-media should return
   * the number of the users private sign key.
   * @author Martin Preuss<openhbci@aquamaniac.de>
   */
  int signKeyNumber() const;

  /**
   * Returns the version of the sign key. RDH-media should return
   * the version of the users private sign key.
   * @author Martin Preuss<openhbci@aquamaniac.de>
   */
  int signKeyVersion() const;

  /**
   * Returns the number of the crypt key. RDH-media should return
   * the number of the institutes public crypt key.
   * @author Martin Preuss<openhbci@aquamaniac.de>
   */
  int cryptKeyNumber() const;

  /**
   * Returns the version of the crypt key. RDH-media should return
   * the version of the institutes public crypt key.
   * @author Martin Preuss<openhbci@aquamaniac.de>
   */
  int cryptKeyVersion() const;

  /**
   * Returns the context with the given number.
   * Some media are able of storing multiple contexts (like chip cards).
   * Please note that the medium has to be mounted prior to calling this
   * method.
   * @author Martin Preuss<openhbci@aquamaniac.de>
   * @return true if a context with that number exists, false on error
   * @param num number of the context (starting with 1)
   * @param countrycode reference to an int var to receive the country code
   * of the context (280 for Germany)
   * @param instcode reference to a string variable to receive the institute
   * code of that context (German "Bankleitzahl")
   * @param userid reference to a string variable to receive the user id of
   * the context (assigned to you by the institute)
   * @param server reference to a string to receive the server address
   */
  bool getContext(int num,
		  int &countrycode,
		  string& instcode,
		  string& userid,
		  string& server) const;

  /**
   * Returns the internally stored cardnumber. This can be set by the
   * constructor or by the card itself when mounting the card.
   * @author Martin Preuss<openhbci@aquamaniac.de>
   */
  const string& cardNumber() const { return _cardnumber; };
  /*@}*/

  /** @name Cryptographic Methods */
  /*@{*/
  /**
   * Creates a key for encryption of data.
   * @author Martin Preuss<openhbci@aquamaniac.de>
   * @return false on error
   */
  string createMessageKey() const;

  /**
   * Lets the card encrypt the key.
   * @author Martin Preuss<openhbci@aquamaniac.de>
   * @return false on error
   * @param srckey the key to encode
   */
  string encryptKey(const string& srckey);

  /**
   * Lets the card decrypt the key.
   * @author Martin Preuss<openhbci@aquamaniac.de>
   * @return false on error
   * @param srckey the key to decode
   */
  string decryptKey(const string& srckey);

  /**
   * Verify the signature of given data
   * @author Martin Preuss<openhbci@aquamaniac.de>
   * @return false on error
   * @param data data whose signatur is to be verified
   * @param signature signature to compare against
   */
  bool verify(const string& data, const string& signature);

  /**
   * sign data
   * @author Martin Preuss<openhbci@aquamaniac.de>
   * @return false on error
   * @param data data whose signatur is to be created
   */
  string sign(const string& data);

  /*@}*/
};

} /* namespace HBCI */

/** @ingroup HBCI_Mediumg */
typedef HBCI::MediumDDV HBCI_MediumDDV;
extern "C" {
#else /* __cplusplus */
typedef struct HBCI_MediumDDV HBCI_MediumDDV;
#endif /* __cplusplus */

  /** @name HBCI_MediumDDV methods
   * @ingroup HBCI_Mediumg */
  /*@{*/
  /** Upcast. */
  extern HBCI_Medium *HBCI_MediumDDV_Medium(HBCI_MediumDDV *h);

  /** Downcast.
   *
   * Returns the dynamic_cast<> downcast pointer. If dynamic_cast
   * fails, a message is printed on stderr and NULL is returned.
   *
   * @returns The HBCI_MediumDDV, or NULL if this is not a
   * HBCI_MediumDDV. */
  extern HBCI_MediumDDV *HBCI_Medium_MediumDDV(HBCI_Medium *h);

  /*@}*/

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif // ifdef HAS_LIBCHIPCARD
#endif






