Ejemplo n.º 1
0
GWEN_URL *GWEN_Url_fromCommandString(const char *str) {
  GWEN_URL *url;
  GWEN_DB_NODE *dbVars;
  const char *s;
  const char *p;

  url=GWEN_Url_new();
  dbVars=GWEN_DB_Group_new("vars");
  GWEN_Url_SetVars(url, dbVars);
  GWEN_DB_Group_free(dbVars);
  dbVars=0;

  s=str;

  /* get path */
  if (*s=='/') {
    p=s;
    while(*p && *p!='?')
      p++;
    if (p!=s) {
      char *buf;

      /* got path */
      buf=(char*)malloc(p-s+1);
      assert(buf);
      memmove(buf, s, p-s+1);
      buf[p-s]=0;
      GWEN_Url_SetPath(url, buf);
      free(buf);
      s=p;
    }
  }
  else {
    GWEN_Url_SetPath(url, "/");
    if (*s)
      s++;
  }

  /* read vars */
  while(*s && *s=='?') {
    GWEN_BUFFER *bName;
    GWEN_BUFFER *bValue;

    bName=GWEN_Buffer_new(0, 256, 0, 1);
    bValue=GWEN_Buffer_new(0, 256, 0, 1);
    s++;
    p=s;
    while(*p && *p!='?' && *p!='=')
      p++;
    if (p!=s)
      GWEN_Buffer_AppendBytes(bName, s, (p-s));
    s=p;
    if (*p=='=') {
      s++;
      p=s;
      while(*p && *p!='?')
        p++;
      if (p!=s)
        GWEN_Buffer_AppendBytes(bValue, s, (p-s));
      s=p;
    }
    /* store variable/value pair */
    if (GWEN_Buffer_GetUsedBytes(bName))
      GWEN_DB_SetCharValue(GWEN_Url_GetVars(url),
                           GWEN_DB_FLAGS_DEFAULT,
                           GWEN_Buffer_GetStart(bName),
                           GWEN_Buffer_GetStart(bValue));
    GWEN_Buffer_free(bValue);
    GWEN_Buffer_free(bName);
  }

  url->url=strdup(str);

  return url;
}
Ejemplo n.º 2
0
int AB_Banking_AddUser(AB_BANKING *ab, AB_USER *u) {
  int rv;
  AB_USER *uTmp;
  char groupName[32];
  GWEN_DB_NODE *db;
  GWEN_DB_NODE *dbP;
  const char *s;

  assert(ab);
  assert(u);

  s=AB_User_GetUserId(u);
  if (!s || *s==0) {
    DBG_ERROR(AQBANKING_LOGDOMAIN,
	      "Missing user id");
    return GWEN_ERROR_INVALID;
  }

  uTmp=AB_User_List_First(ab->users);
  while(uTmp) {
    if (uTmp==u) {
      DBG_INFO(AQBANKING_LOGDOMAIN,
	       "User already added!");
      return GWEN_ERROR_INVALID;
    }
    uTmp=AB_User_List_Next(uTmp);
  }

  rv=AB_Provider_ExtendUser(AB_User_GetProvider(u), u,
			    AB_ProviderExtendMode_Add,
			    NULL);
  if (rv)
    return rv;

  db=GWEN_DB_Group_new("user");
  AB_User_toDb(u, db);
  dbP=GWEN_DB_GetGroup(db, GWEN_DB_FLAGS_DEFAULT,
		       "data/backend");
  rv=AB_Provider_ExtendUser(AB_User_GetProvider(u), u,
			    AB_ProviderExtendMode_Save,
			    dbP);
  if (rv) {
    DBG_INFO(AQBANKING_LOGDOMAIN, "here (%d)", rv);
    GWEN_DB_Group_free(db);
    return rv;
  }

  rv=GWEN_ConfigMgr_GetUniqueId(ab->configMgr,
				AB_CFG_GROUP_USERS,
				groupName, sizeof(groupName)-1);
  if (rv<0) {
    DBG_ERROR(AQBANKING_LOGDOMAIN,
	      "Unable to create a unique id for user [%08x] (%d)",
	      AB_User_GetUniqueId(u), rv);
    GWEN_DB_Group_free(db);
    return rv;
  }
  groupName[sizeof(groupName)-1]=0;

  rv=GWEN_ConfigMgr_LockGroup(ab->configMgr,
			      AB_CFG_GROUP_USERS,
			      groupName);
  if (rv<0) {
    DBG_ERROR(AQBANKING_LOGDOMAIN,
	      "Unable to lock user config [%08x] (%d)",
	      AB_User_GetUniqueId(u), rv);
    GWEN_DB_Group_free(db);
    return rv;
  }

  rv=GWEN_ConfigMgr_SetGroup(ab->configMgr,
			     AB_CFG_GROUP_USERS,
			     groupName,
			     db);
  GWEN_DB_Group_free(db);
  if (rv<0) {
    DBG_ERROR(AQBANKING_LOGDOMAIN,
	      "Unable to save user config [%08x] (%d)",
	      AB_User_GetUniqueId(u), rv);
    GWEN_ConfigMgr_UnlockGroup(ab->configMgr,
			       AB_CFG_GROUP_USERS,
			       groupName);
    return rv;
  }

  /* unlock */
  rv=GWEN_ConfigMgr_UnlockGroup(ab->configMgr,
				AB_CFG_GROUP_USERS,
				groupName);
  if (rv<0) {
    DBG_ERROR(AQBANKING_LOGDOMAIN,
	      "Unable to unlock user config [%08x] (%d)",
	      AB_User_GetUniqueId(u), rv);
    return rv;
  }

  AB_User_SetDbId(u, groupName);
  AB_User_List_Add(u, ab->users);
  return 0;
}
Ejemplo n.º 3
0
GWEN_URL *GWEN_Url_fromString(const char *str) {
  GWEN_URL *url;
  GWEN_DB_NODE *dbVars;
  const char *s;
  const char *p;
  int starts_with_drive_letter = 0;

  url=GWEN_Url_new();
  dbVars=GWEN_DB_Group_new("vars");
  GWEN_Url_SetVars(url, dbVars);
  GWEN_DB_Group_free(dbVars);
  dbVars=0;

  s=str;

  /* Check for a drive letter, which occurs on windows, but this will
     always be one single alpha character followed by a colon followed
     by a directory separator. */
  if (s && isalpha(s[0]) && s[1] == ':'
      && (s[2] == '/' || s[2] == '\\')) {
    starts_with_drive_letter = 1;
  }

  /* read protocol (if any) */
  p = starts_with_drive_letter ? s : strchr(s, ':');
  if (p) {
    if (p[1]=='/' && p[2]=='/') {
      char *buf;

      /* got protocol settings */
      buf=(char*)malloc(p-s+1);
      assert(buf);
      memmove(buf, s, p-s+1);
      buf[p-s]=0;
      GWEN_Url_SetProtocol(url, buf);
      free(buf);
      s=p+3;
    }
  }

  if (!*s) {
    DBG_ERROR(GWEN_LOGDOMAIN, "No server or path given in url \"%s\"", str);
    GWEN_Url_free(url);
    return 0;
  }

  /* read user/password */
  p=strchr(s, '@');
  if (p) {
    char *upw;
    char *pw;
    char *pat;

    upw=(char*)malloc(p-s+1);
    assert(upw);
    memmove(upw, s, p-s);
    upw[p-s]=0;
    pw=strchr(upw, ':');
    if (pw) {
      /* there is also a password */
      *pw=0;
      pw++;
    }
    pat=strchr(upw, '%');
    if (pat)
      *pat='@';
    GWEN_Url_SetUserName(url, upw);
    if (pw)
      GWEN_Url_SetPassword(url, pw);
    free(upw);
    s=p+1;
  }

  /* Do we now have a drive letter? (After the protocol?) */
  if (!starts_with_drive_letter
      && s && isalpha(s[0]) && s[1] == ':'
      && (s[2] == '/' || s[2] == '\\')) {
    starts_with_drive_letter = 1;
  }

  /* read server */
  if (!*s) {
    DBG_ERROR(GWEN_LOGDOMAIN, "No server given in url \"%s\"", str);
    GWEN_Url_free(url);
    return 0;
  }
  p=s;
  while(!starts_with_drive_letter && *p && *p!=':' && *p!='/' && *p!='?')
    p++;
  if (p!=s) {
    char *buf;

    /* got server */
    buf=(char*)malloc(p-s+1);
    assert(buf);
    memmove(buf, s, p-s+1);
    buf[p-s]=0;
    GWEN_Url_SetServer(url, buf);
    DBG_DEBUG(GWEN_LOGDOMAIN, "Server: [%s]", buf);
    free(buf);
    s=p;
  }

  /* get port */
  if (*s==':') {
    p=++s;
    while(*p && *p!='?' && *p!='/')
      p++;
    if (p!=s) {
      char *buf;
      int port;

      /* got port */
      buf=(char*)malloc(p-s+1);
      assert(buf);
      memmove(buf, s, p-s+1);
      buf[p-s]=0;
      if (sscanf(buf, "%d", &port)!=1) {
        DBG_ERROR(GWEN_LOGDOMAIN, "Bad port (%s) in url \"%s\"", buf, str);
        free(buf);
        GWEN_Url_free(url);
        return 0;
      }
      url->port=port;
      free(buf);
      s=p;
    }
  }
  else {
    if (url->protocol) {
      if (strcasecmp(url->protocol, "http")==0)
        url->port=80;
      else if (strcasecmp(url->protocol, "https")==0)
        url->port=443;
    }
  }

  /* get path */
  if (starts_with_drive_letter || *s=='/') {
    p=s;
    while(*p && *p!='?')
      p++;
    if (p!=s) {
      char *buf;

      /* got path */
      buf=(char*)malloc(p-s+1);
      assert(buf);
      memmove(buf, s, p-s+1);
      buf[p-s]=0;
      GWEN_Url_SetPath(url, buf);
      DBG_DEBUG(GWEN_LOGDOMAIN, "Path: [%s]", buf);
      free(buf);
      s=p;
    }
  }
  else {
    GWEN_Url_SetPath(url, "/");
    if (*s)
      s++;
  }

  /* read vars */
  while(*s && *s=='?') {
    GWEN_BUFFER *bName;
    GWEN_BUFFER *bValue;

    bName=GWEN_Buffer_new(0, 256, 0, 1);
    bValue=GWEN_Buffer_new(0, 256, 0, 1);
    s++;
    p=s;
    while(*p && *p!='?' && *p!='=')
      p++;
    if (p!=s)
      GWEN_Buffer_AppendBytes(bName, s, (p-s));
    s=p;
    if (*p=='=') {
      s++;
      p=s;
      while(*p && *p!='?')
        p++;
      if (p!=s)
        GWEN_Buffer_AppendBytes(bValue, s, (p-s));
      s=p;
    }
    /* store variable/value pair */
    if (GWEN_Buffer_GetUsedBytes(bName))
      GWEN_DB_SetCharValue(GWEN_Url_GetVars(url),
                           GWEN_DB_FLAGS_DEFAULT,
                           GWEN_Buffer_GetStart(bName),
                           GWEN_Buffer_GetStart(bValue));
    GWEN_Buffer_free(bValue);
    GWEN_Buffer_free(bName);
  }

  url->url=strdup(str);
  url->_modified=0;
  return url;
}
Ejemplo n.º 4
0
LC_CLIENT_RESULT LC_DDVCard_ReadInstituteData(LC_CARD *card,
                                              int idx,
                                              GWEN_DB_NODE *dbData){
  LC_DDVCARD *ddv;
  LC_CLIENT_RESULT res;
  GWEN_DB_NODE *dbCurr;
  int i;
  unsigned int ctxCount;
  GWEN_BUFFER *buf;

  assert(card);
  ddv=GWEN_INHERIT_GETDATA(LC_CARD, LC_DDVCARD, card);
  assert(ddv);

  res=LC_Card_SelectEf(card, "EF_BNK");
  if (res!=LC_Client_ResultOk) {
    DBG_INFO(LC_LOGDOMAIN, "here");
    return res;
  }

  ctxCount=0;
  buf=GWEN_Buffer_new(0, 256, 0, 1);
  for (i=1; i<6; i++) {
    GWEN_Buffer_Reset(buf);
    res=LC_Card_IsoReadRecord(card, LC_CARD_ISO_FLAGS_RECSEL_GIVEN,
                              idx?idx:i, buf);
    if (res!=LC_Client_ResultOk)
      break;
    dbCurr=GWEN_DB_Group_new("context");
    GWEN_Buffer_Rewind(buf);
    if (LC_Card_ParseRecord(card, idx?idx:i, buf, dbCurr)) {
      DBG_ERROR(LC_LOGDOMAIN, "Error parsing record %d", idx?idx:i);
      GWEN_DB_Group_free(dbCurr);
    }
    else {
      const char *p1;

      p1=GWEN_DB_GetCharValue(dbCurr, "bankCode", 0, "");
      if (p1) {
	char *p2;
        char *p3;

	p2=strdup(p1);
	while ( (p3=strchr(p2, '=')) ) {
          *p3='2';
	}
	GWEN_DB_SetCharValue(dbCurr, GWEN_DB_FLAGS_OVERWRITE_VARS,
			     "bankCode", p2);
        free(p2);
      }
      GWEN_DB_AddGroup(dbData, dbCurr);
      ctxCount++;
    }
    if (idx)
      break;
  } /* for */
  GWEN_Buffer_free(buf);

  if (!ctxCount) {
    return LC_Client_ResultDataError;
  }
  return LC_Client_ResultOk;
}
Ejemplo n.º 5
0
LC_CLIENT_RESULT LC_DDVCard_SignHash1(LC_CARD *card,
                                      GWEN_BUFFER *hbuf,
                                      GWEN_BUFFER *obuf){
  LC_DDVCARD *ddv;
  GWEN_DB_NODE *dbReq;
  GWEN_DB_NODE *dbResp;
  LC_CLIENT_RESULT res;
  const void *p;
  unsigned int bs;

  assert(card);
  ddv=GWEN_INHERIT_GETDATA(LC_CARD, LC_DDVCARD, card);
  assert(ddv);

  if (GWEN_Buffer_GetUsedBytes(hbuf)!=20) {
    DBG_ERROR(LC_LOGDOMAIN, "Hash must exactly be 20 bytes in length (is %d)",
              GWEN_Buffer_GetUsedBytes(hbuf));
    return LC_Client_ResultDataError;
  }

  /* write right part of the hash */
  dbReq=GWEN_DB_Group_new("WriteHashR");
  dbResp=GWEN_DB_Group_new("response");
  GWEN_DB_SetBinValue(dbReq, GWEN_DB_FLAGS_DEFAULT,
                      "hashR",
                      GWEN_Buffer_GetStart(hbuf)+8, 12);

  res=LC_Card_ExecCommand(card, "WriteHashR", dbReq, dbResp);
  if (res!=LC_Client_ResultOk) {
    DBG_INFO(LC_LOGDOMAIN, "Error while executing WriteHashR");
    GWEN_DB_Group_free(dbReq);
    GWEN_DB_Group_free(dbResp);
    return res;
  }
  GWEN_DB_Group_free(dbReq);
  GWEN_DB_Group_free(dbResp);


  /* write left part of hash and retrieve signed hash */
  dbReq=GWEN_DB_Group_new("SignHash");
  dbResp=GWEN_DB_Group_new("response");
  GWEN_DB_SetBinValue(dbReq, GWEN_DB_FLAGS_DEFAULT,
                      "hashL",
                      GWEN_Buffer_GetStart(hbuf), 8);
  res=LC_Card_ExecCommand(card, "SignHash", dbReq, dbResp);
  if (res!=LC_Client_ResultOk) {
    DBG_INFO(LC_LOGDOMAIN, "Error while executing SignHash");
    GWEN_DB_Group_free(dbReq);
    GWEN_DB_Group_free(dbResp);
    return res;
  }


  p=GWEN_DB_GetBinValue(dbResp,
                        "response/signedHash",
                        0,
                        0, 0,
                        &bs);
  if ( p && bs==8)
    GWEN_Buffer_AppendBytes(obuf, p, bs);
  else {
    DBG_ERROR(LC_LOGDOMAIN, "Expected 8 bytes response, got %d bytes", bs);
    GWEN_DB_Group_free(dbReq);
    GWEN_DB_Group_free(dbResp);
    return LC_Client_ResultDataError;
  }

  GWEN_DB_Group_free(dbReq);
  GWEN_DB_Group_free(dbResp);
  return LC_Client_ResultOk;
}
Ejemplo n.º 6
0
LC_CLIENT_RESULT LC_DDVCard_Reopen(LC_CARD *card){
  LC_CLIENT_RESULT res;
  LC_DDVCARD *ddv;
  GWEN_BUFFER *mbuf;
  GWEN_DB_NODE *dbRecord;

  DBG_INFO(LC_LOGDOMAIN, "Opening DDV card");

  assert(card);
  ddv=GWEN_INHERIT_GETDATA(LC_CARD, LC_DDVCARD, card);
  assert(ddv);

  ddv->ddvType=-1;
  GWEN_DB_Group_free(ddv->db_ef_id_1);
  ddv->db_ef_id_1=0;
  GWEN_Buffer_free(ddv->bin_ef_id_1);
  ddv->bin_ef_id_1=0;

  res=LC_Card_SelectCard(card, "ProcessorCard");
  if (res!=LC_Client_ResultOk) {
    DBG_INFO(LC_LOGDOMAIN, "here");
    return res;
  }

  res=LC_Card_SelectApp(card, "ddv");
  if (res!=LC_Client_ResultOk) {
    DBG_INFO(LC_LOGDOMAIN, "here");
    return res;
  }

  DBG_INFO(LC_LOGDOMAIN, "Selecting MF...");
  res=LC_Card_SelectMf(card);
  if (res!=LC_Client_ResultOk) {
    DBG_INFO(LC_LOGDOMAIN, "here");
    return res;
  }

  DBG_INFO(LC_LOGDOMAIN, "Selecting EF...");
  res=LC_Card_SelectEf(card, "EF_ID");
  if (res!=LC_Client_ResultOk) {
    DBG_INFO(LC_LOGDOMAIN, "here");
    return res;
  }

  DBG_INFO(LC_LOGDOMAIN, "Reading record...");
  mbuf=GWEN_Buffer_new(0, 256, 0, 1);
  res=LC_Card_IsoReadRecord(card, LC_CARD_ISO_FLAGS_RECSEL_GIVEN, 1, mbuf);
  if (res!=LC_Client_ResultOk) {
    DBG_INFO(LC_LOGDOMAIN, "here");
    GWEN_Buffer_free(mbuf);
    return res;
  }

  DBG_INFO(LC_LOGDOMAIN, "Parsing record...");
  GWEN_Buffer_Rewind(mbuf);
  dbRecord=GWEN_DB_Group_new("record");
  if (LC_Card_ParseRecord(card, 1, mbuf, dbRecord)) {
    DBG_ERROR(LC_LOGDOMAIN, "Error in EF_ID");
    GWEN_DB_Group_free(dbRecord);
    GWEN_Buffer_free(mbuf);
    return LC_Client_ResultDataError;
  }

  if (GWEN_Buffer_GetUsedBytes(mbuf)>22) {
    /* assume DDV1, perform some checks */

    /* check for currency (DDV1 allows EUR only) */
    if (strcasecmp(GWEN_DB_GetCharValue(dbRecord,
                                        "currency",
                                        0, ""),
                   "EUR")!=0) {
      DBG_ERROR(LC_LOGDOMAIN, "Bad currency, this does not seem to be DDV1 card");
      GWEN_DB_Group_free(dbRecord);
      GWEN_Buffer_free(mbuf);
      return LC_Client_ResultDataError;
    }

    /* check for OS version on the chip card (DDV1 needs 1 or higher) */
    if (GWEN_DB_GetIntValue(dbRecord, "OSVersion",0, 0)<1) {
      DBG_ERROR(LC_LOGDOMAIN, "Bad CardOS version, this does not seem to be DDV1 card");
      GWEN_DB_Group_free(dbRecord);
      GWEN_Buffer_free(mbuf);
      return LC_Client_ResultDataError;
    }

    /* check for filler (DDV1 needs 0) */
    if (GWEN_DB_GetIntValue(dbRecord, "filler",0, 0)!=0) {
      DBG_ERROR(LC_LOGDOMAIN, "Bad byte at pos 23, this does not seem to be DDV1 card");
      GWEN_DB_Group_free(dbRecord);
      GWEN_Buffer_free(mbuf);
      return LC_Client_ResultDataError;
    }

    /* check for factor (DDV1 needs 1) */
    if (GWEN_DB_GetIntValue(dbRecord, "factor", 0, 1)!=1) {
      DBG_ERROR(LC_LOGDOMAIN, "Bad byte at pos 24, this does not seem to be DDV1 card");
      GWEN_DB_Group_free(dbRecord);
      GWEN_Buffer_free(mbuf);
      return LC_Client_ResultDataError;
    }

    /* select DDV1 card and app */
    res=LC_Card_SelectCard(card, "ddv1");
    if (res!=LC_Client_ResultOk) {
      DBG_INFO(LC_LOGDOMAIN, "here");
      return res;
    }
    res=LC_Card_SelectApp(card, "ddv1");
    if (res!=LC_Client_ResultOk) {
      DBG_INFO(LC_LOGDOMAIN, "here");
      return res;
    }

    /* select correct banking DF */
    res=LC_Card_SelectDf(card, "DF_BANKING_20");
    if (res!=LC_Client_ResultOk) {
      DBG_INFO(LC_LOGDOMAIN, "here");
      GWEN_DB_Group_free(dbRecord);
      GWEN_Buffer_free(mbuf);
      return res;
    }

    DBG_INFO(LC_LOGDOMAIN, "Card type is DDV 1");
    ddv->ddvType=1;
  }
  else {
    /* assume DDV0, perform some checks */

    /* check for currency (DDV0 allows DEM only) */
    if (strcasecmp(GWEN_DB_GetCharValue(dbRecord,
                                        "currency",
                                        0, ""),
                   "DEM")!=0) {
      DBG_ERROR(LC_LOGDOMAIN, "Bad currency, this does not seem to be DDV0 card");
      GWEN_DB_Group_free(dbRecord);
      GWEN_Buffer_free(mbuf);
      return LC_Client_ResultDataError;
    }

    /* select DDV0 card and app */
    res=LC_Card_SelectCard(card, "ddv0");
    if (res!=LC_Client_ResultOk) {
      DBG_INFO(LC_LOGDOMAIN, "here");
      return res;
    }
    res=LC_Card_SelectApp(card, "ddv0");
    if (res!=LC_Client_ResultOk) {
      DBG_INFO(LC_LOGDOMAIN, "here");
      return res;
    }

    /* select correct banking DF */
    res=LC_Card_SelectDf(card, "DF_BANKING");
    if (res!=LC_Client_ResultOk) {
      DBG_INFO(LC_LOGDOMAIN, "here");
      GWEN_DB_Group_free(dbRecord);
      GWEN_Buffer_free(mbuf);
      return res;
    }

    DBG_INFO(LC_LOGDOMAIN, "Card type is DDV 0");
    ddv->ddvType=0;
  }

  ddv->db_ef_id_1=dbRecord;
  ddv->bin_ef_id_1=mbuf;
  return LC_Client_ResultOk;
}
Ejemplo n.º 7
0
int main(int argc, char **argv) {
  GWEN_DB_NODE *db;
  const char *cmd;
  int rv;
  AB_BANKING *ab;
  GWEN_GUI *gui;
  int nonInteractive=0;
  int acceptValidCerts=0;
  const char *pinFile;
  const char *cfgDir;
  const char *s;
  const GWEN_ARGS args[]={
  {
    GWEN_ARGS_FLAGS_HAS_ARGUMENT, /* flags */
    GWEN_ArgsType_Char,           /* type */
    "cfgdir",                     /* name */
    0,                            /* minnum */
    1,                            /* maxnum */
    "D",                          /* short option */
    "cfgdir",                     /* long option */
    I18S("Specify the configuration folder"),
    I18S("Specify the configuration folder")
  },
  {
    0,                            /* flags */
    GWEN_ArgsType_Int,            /* type */
    "nonInteractive",             /* name */
    0,                            /* minnum */
    1,                            /* maxnum */
    "n",                          /* short option */
    "noninteractive",             /* long option */
    "Select non-interactive mode",/* short description */
    "Select non-interactive mode.\n"        /* long description */
    "This automatically returns a confirmative answer to any non-critical\n"
    "message."
  },
  {
    0,                            /* flags */
    GWEN_ArgsType_Int,            /* type */
    "acceptValidCerts",           /* name */
    0,                            /* minnum */
    1,                            /* maxnum */
    "A",                          /* short option */
    "acceptvalidcerts",           /* long option */
    "Automatically accept all valid TLS certificate",
    "Automatically accept all valid TLS certificate"
  },
  {
    GWEN_ARGS_FLAGS_HAS_ARGUMENT, /* flags */
    GWEN_ArgsType_Char,           /* type */
    "charset",                    /* name */
    0,                            /* minnum */
    1,                            /* maxnum */
    0,                            /* short option */
    "charset",                    /* long option */
    "Specify the output character set",       /* short description */
    "Specify the output character set"        /* long description */
  },
  {
    GWEN_ARGS_FLAGS_HAS_ARGUMENT, /* flags */
    GWEN_ArgsType_Char,           /* type */
    "pinfile",                    /* name */
    0,                            /* minnum */
    1,                            /* maxnum */
    "P",                          /* short option */
    "pinfile",                    /* long option */
    "Specify the PIN file",       /* short description */
    "Specify the PIN file"        /* long description */
  },
  {
    GWEN_ARGS_FLAGS_HELP | GWEN_ARGS_FLAGS_LAST, /* flags */
    GWEN_ArgsType_Int,            /* type */
    "help",                       /* name */
    0,                            /* minnum */
    0,                            /* maxnum */
    "h",                          /* short option */
    "help",
    I18S("Show this help screen. For help on commands, "
	 "run aqbanking-cli <COMMAND> --help."),
    I18S("Show this help screen. For help on commands, run aqbanking-cli <COMMAND> --help.")
  }
  };

  rv=GWEN_Init();
  if (rv) {
    fprintf(stderr, "ERROR: Unable to init Gwen.\n");
    exit(2);
  }

  GWEN_Logger_Open(0, "aqbanking-cli", 0,
		   GWEN_LoggerType_Console,
		   GWEN_LoggerFacility_User);
  GWEN_Logger_SetLevel(0, GWEN_LoggerLevel_Warning);

  rv=GWEN_I18N_BindTextDomain_Dir(PACKAGE, LOCALEDIR);
  if (rv) {
    DBG_ERROR(0, "Could not bind textdomain (%d)", rv);
  }
  else {
    rv=GWEN_I18N_BindTextDomain_Codeset(PACKAGE, "UTF-8");
    if (rv) {
      DBG_ERROR(0, "Could not set codeset (%d)", rv);
    }
  }

  db=GWEN_DB_Group_new("arguments");
  rv=GWEN_Args_Check(argc, argv, 1,
		     GWEN_ARGS_MODE_ALLOW_FREEPARAM |
		     GWEN_ARGS_MODE_STOP_AT_FREEPARAM,
		     args,
		     db);
  if (rv==GWEN_ARGS_RESULT_ERROR) {
    fprintf(stderr, "ERROR: Could not parse arguments main\n");
    GWEN_DB_Group_free(db);
    return 1;
  }
  else if (rv==GWEN_ARGS_RESULT_HELP) {
    GWEN_BUFFER *ubuf;

    ubuf=GWEN_Buffer_new(0, 1024, 0, 1);
    GWEN_Buffer_AppendString(ubuf, I18N("This is version "));
    GWEN_Buffer_AppendString(ubuf, AQHBCI_VERSION_STRING "\n");
    GWEN_Buffer_AppendString(ubuf,
                             I18N("Usage: "));
    GWEN_Buffer_AppendString(ubuf, argv[0]);
    GWEN_Buffer_AppendString(ubuf,
                             I18N(" [GLOBAL OPTIONS] COMMAND "
                                  "[LOCAL OPTIONS]\n"));
    GWEN_Buffer_AppendString(ubuf,
                             I18N("\nGlobal Options:\n"));
    if (GWEN_Args_Usage(args, ubuf, GWEN_ArgsOutType_Txt)) {
      fprintf(stderr, "ERROR: Could not create help string\n");
      GWEN_DB_Group_free(db);
      return 1;
    }
    GWEN_Buffer_AppendString(ubuf,
                             I18N("\nCommands:\n"));
    cmdAddHelpStr(ubuf, "senddtazv",
                  I18N("Sends a DTAZV file to the bank"));

    cmdAddHelpStr(ubuf, "listaccs",
                  I18N("Prints the list of accounts"));

    cmdAddHelpStr(ubuf, "listbal",
                  I18N("Export balances from a context file."));

    cmdAddHelpStr(ubuf, "listtrans",
                  I18N("Export transactions from a context file."));

    cmdAddHelpStr(ubuf, "listtransfers",
                  I18N("Export transactions from a context file which match certain status."));

    cmdAddHelpStr(ubuf, "request",
                  I18N("Requests transactions, balances, standing orders etc."));

    cmdAddHelpStr(ubuf, "chkacc",
                  I18N("Check a combination of bank id and account number"));

    cmdAddHelpStr(ubuf, "chkiban",
                  I18N("Check an IBAN"));

    cmdAddHelpStr(ubuf, "import",
                  I18N("Import a file into an import context file"));

    cmdAddHelpStr(ubuf, "transfer",
                  I18N("Issue a single transfer (data from command line)"));

    cmdAddHelpStr(ubuf, "transfers",
                  I18N("Issue a number of transfers (data from a file)"));

    cmdAddHelpStr(ubuf, "sepatransfer",
                  I18N("Issue a single SEPA transfer (data from command line)"));

    cmdAddHelpStr(ubuf, "sepatransfers",
                  I18N("Issue a number of SEPA transfers (data from a file)"));

    cmdAddHelpStr(ubuf, "debitnote",
                  I18N("Issue a single debit note (data from command line)"));

    cmdAddHelpStr(ubuf, "debitnotes",
                  I18N("Issue a number of debit notes (data from a file)"));

    cmdAddHelpStr(ubuf, "sepadebitnote",
                  I18N("Issue a single SEPA debit note (data from command line)"));

    cmdAddHelpStr(ubuf, "sepaflashdebitnote",
                  I18N("Issue a single flash SEPA debit note COR1 (data from command line)"));

    cmdAddHelpStr(ubuf, "sepadebitnotes",
                  I18N("Issue a number of SEPA debit notes (data from a file)"));

    cmdAddHelpStr(ubuf, "addtrans",
                  I18N("Add a transfer to an existing import context file"));

    cmdAddHelpStr(ubuf, "addsepadebitnote",
                  I18N("Add a SEPA debit note to an existing import context file"));

    cmdAddHelpStr(ubuf, "sepasto",
                  I18N("Manage SEPA standing orders"));

    cmdAddHelpStr(ubuf, "fillgaps",
                  I18N("Fill gaps in an import context file from configuration settings"));

    cmdAddHelpStr(ubuf, "updateconf",
                  I18N("Update configuration from previous AqBanking versions"));

    cmdAddHelpStr(ubuf, "listprofiles",
                  I18N("Print existing profiles"));

    cmdAddHelpStr(ubuf, "versions",
                  I18N("Print the program and library versions"));

    GWEN_Buffer_AppendString(ubuf, "\n");

    fprintf(stderr, "%s\n", GWEN_Buffer_GetStart(ubuf));
    GWEN_Buffer_free(ubuf);
    GWEN_DB_Group_free(db);
    return 0;
  }
  if (rv) {
    argc-=rv-1;
    argv+=rv-1;
  }

  nonInteractive=GWEN_DB_GetIntValue(db, "nonInteractive", 0, 0);
  acceptValidCerts=GWEN_DB_GetIntValue(db, "acceptValidCerts", 0, 0);
  cfgDir=GWEN_DB_GetCharValue(db, "cfgdir", 0, 0);

  cmd=GWEN_DB_GetCharValue(db, "params", 0, 0);
  if (!cmd) {
    fprintf(stderr, "ERROR: Command needed.\n");
    GWEN_DB_Group_free(db);
    return 1;
  }

  gui=GWEN_Gui_CGui_new();
  s=GWEN_DB_GetCharValue(db, "charset", 0, NULL);
  if (s && *s)
    GWEN_Gui_SetCharSet(gui, s);

  if (nonInteractive)
    GWEN_Gui_AddFlags(gui, GWEN_GUI_FLAGS_NONINTERACTIVE);
  else
    GWEN_Gui_SubFlags(gui, GWEN_GUI_FLAGS_NONINTERACTIVE);

  if (acceptValidCerts)
    GWEN_Gui_AddFlags(gui, GWEN_GUI_FLAGS_ACCEPTVALIDCERTS);
  else
    GWEN_Gui_SubFlags(gui, GWEN_GUI_FLAGS_ACCEPTVALIDCERTS);

  pinFile=GWEN_DB_GetCharValue(db, "pinFile", 0, NULL);
  if (pinFile) {
    GWEN_DB_NODE *dbPins;

    dbPins=GWEN_DB_Group_new("pins");
    if (GWEN_DB_ReadFile(dbPins, pinFile,
			 GWEN_DB_FLAGS_DEFAULT |
			 GWEN_PATH_FLAGS_CREATE_GROUP)) {
      fprintf(stderr, "Error reading pinfile \"%s\"\n", pinFile);
      GWEN_DB_Group_free(dbPins);
      GWEN_DB_Group_free(db);
      return 2;
    }
    GWEN_Gui_SetPasswordDb(gui, dbPins, 1);
  }
				    
  GWEN_Gui_SetGui(gui);

  ab=AB_Banking_new("aqbanking-cli", cfgDir, 0);
  AB_Gui_Extend(gui, ab);

  if (strcasecmp(cmd, "senddtazv")==0) {
    rv=sendDtazv(ab, db, argc, argv);
  }
  else if (strcasecmp(cmd, "listaccs")==0) {
    rv=listAccs(ab, db, argc, argv);
  }
  else if (strcasecmp(cmd, "listbal")==0) {
    rv=listBal(ab, db, argc, argv);
  }
  else if (strcasecmp(cmd, "listtrans")==0) {
    rv=listTrans(ab, db, argc, argv);
  }
  else if (strcasecmp(cmd, "listtransfers")==0) {
    rv=listTransfers(ab, db, argc, argv);
  }
  else if (strcasecmp(cmd, "request")==0) {
    rv=request(ab, db, argc, argv);
  }
  else if (strcasecmp(cmd, "chkacc")==0) {
    rv=chkAcc(ab, db, argc, argv);
  }
  else if (strcasecmp(cmd, "chkiban")==0) {
    rv=chkIban(ab, db, argc, argv);
  }
  else if (strcasecmp(cmd, "import")==0) {
    rv=import(ab, db, argc, argv);
  }
  else if (strcasecmp(cmd, "transfer")==0) {
    rv=transfer(ab, db, argc, argv);
  }
  else if (strcasecmp(cmd, "transfers")==0) {
    rv=transfers(ab, db, argc, argv);
  }
  else if (strcasecmp(cmd, "sepatransfer")==0) {
    rv=sepaTransfer(ab, db, argc, argv);
  }
  else if (strcasecmp(cmd, "sepatransfers")==0) {
    rv=sepaMultiJobs(ab, db, argc, argv, AQBANKING_TOOL_SEPA_TRANSFERS);
  }
  else if (strcasecmp(cmd, "debitnote")==0) {
    rv=debitNote(ab, db, argc, argv);
  }
  else if (strcasecmp(cmd, "debitnotes")==0) {
    rv=debitNotes(ab, db, argc, argv);
  }
  else if (strcasecmp(cmd, "sepadebitnote")==0) {
    rv=sepaDebitNote(ab, db, argc, argv, 0);
  }
  else if (strcasecmp(cmd, "sepaFlashDebitNote")==0) {
    rv=sepaDebitNote(ab, db, argc, argv, 1);
  }
  else if (strcasecmp(cmd, "sepadebitnotes")==0) {
    rv=sepaMultiJobs(ab, db, argc, argv, AQBANKING_TOOL_SEPA_DEBITNOTES);
  }
  else if (strcasecmp(cmd, "addtrans")==0) {
    rv=addTransaction(ab, db, argc, argv);
  }
  else if (strcasecmp(cmd, "addsepadebitnote")==0) {
    rv=addSepaDebitNote(ab, db, argc, argv);
  }
  else if (strcasecmp(cmd, "sepasto")==0) {
    rv=sepaRecurTransfer(ab, db, argc, argv);
  }
  else if (strcasecmp(cmd, "fillgaps")==0) {
    rv=fillGaps(ab, db, argc, argv);
  }
  else if (strcasecmp(cmd, "updateconf")==0) {
    rv=updateConf(ab, db, argc, argv);
  }
  else if (strcasecmp(cmd, "listprofiles")==0) {
    rv=listProfiles(ab, db, argc, argv);
  }
  else if (strcasecmp(cmd, "versions")==0) {
    rv=versions(ab, db, argc, argv);
  }
  else {
    fprintf(stderr, "ERROR: Unknown command \"%s\".\n", cmd);
    rv=1;
  }

  GWEN_DB_Group_free(db);
  return rv;
}