
/* main.cpp - Secure KDE dialog for PIN entry.
   Copyright (C) 2002 Klarälvdalens Datakonsult AB
   Copyright (C) 2003 g10 Code GmbH
   Copyright (C) 2007-2015 X2Go Project
   Written by Steffen Hansen <steffen@klaralvdalens-datakonsult.se>.
   Modified by Marcus Brinkmann <marcus@g10code.de>.
   Modified for X2Go by Oleksandr Shneyder <oleksandr.shneyder@obviously-nice.de>
   and Mike Gabriel <mike.gabriel@das-netzwerkteam.de>

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License as
   published by the Free Software Foundation; either version 2 of the
   License, or (at your option) any later version.

   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.  See the GNU
   General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
   02111-1307, USA  */

//#ifdef HAVE_CONFIG_H
#include "config.h"
//#endif

#include <stdlib.h>
#include <errno.h>

#include <QApplication>
#include <QWidget>
#include <QDebug>
#include <QFile>
#include <QDir>
#include <QMessageBox>

#include <QTranslator>
#include <QLocale>

#if QT_VERSION < 0x050000
#include <QPlastiqueStyle>
#else
#include <QStyleFactory>
#endif

#include "pinentrydialog.h"

#include "pinentry.h"

bool pin_is_known;
QString default_pin;

/* Hack for creating a QWidget with a "foreign" window ID */
class ForeignWidget : public QWidget
{
public:
    ForeignWidget( WId wid ) : QWidget( 0 )
    {
        QWidget::destroy();
        create( wid, false, false );
    }

    ~ForeignWidget()
    {
        destroy( false, false );
    }
};

static int
qt_cmd_handler (pinentry_t pe)
{
    QWidget *parent = 0;

    int want_pass = !!pe->pin;


    if (want_pass)
    {
        char *pin;
        if(!pin_is_known)
        {
            /* FIXME: Add parent window ID to pinentry and GTK.  */
            if (pe->parent_wid)
                parent = new ForeignWidget (pe->parent_wid);

            PinEntryDialog pinentry (parent, 0, true);

            pinentry.setPrompt (QString::fromUtf8 (pe->prompt));
            pinentry.setDescription (QString::fromUtf8 (pe->description));

            if (pe->ok)
                pinentry.setOkText (QString::fromUtf8 (pe->ok));
            if (pe->cancel)
                pinentry.setCancelText (QString::fromUtf8 (pe->cancel));
            if (pe->error)
                pinentry.setError (QString::fromUtf8 (pe->error));

            bool ret = pinentry.exec ();
            if (!ret)
                return -1;
            pin = (char *) pinentry.text().toUtf8().data();
        }
        else
            pin=(char *)default_pin.toUtf8().data();
        if (!pin)
            return -1;


        int len = strlen (pin);
        if (len >= 0)
        {
            pinentry_setbufferlen (pe, len + 1);
            if (pe->pin)
            {
                strcpy (pe->pin, pin);
                //	      ::secmem_free (pin);
                return len;
            }
        }
        //      ::secmem_free (pin);
        return -1;
    }
    else
    {
        bool ret = QMessageBox::information (parent, "", pe->description,
                                             pe->ok ? pe->ok : "OK",
                                             pe->cancel ? pe->cancel : "Cancel");
        return !ret;
    }
}

pinentry_cmd_handler_t pinentry_cmd_handler = qt_cmd_handler;

int
main (int argc, char *argv[])
{
    pin_is_known=false;
    pinentry_init ("pinentry-x2go");
    QString gpghome=getenv("GNUPGHOME");
    QString cardid=getenv("CARDAPPID");
    if(QFile::exists(gpghome+"/pins"))
    {
        QFile file(gpghome+"/pins");
        if (file.open(QIODevice::ReadOnly | QIODevice::Text))
        {
            QTextStream in(&file);
            while(!in.atEnd())
            {
                QString line = in.readLine();
                if(line.length()>0)
                {
		    QStringList lst=line.split(" ");
		    if(lst[0]==cardid)
		    {
                      default_pin=lst[1];
                      pin_is_known=true;
		      break;
		    }
                }
            }
        }
    }


    /* Qt does only understand -display but not --display; thus we
       are fixing that here.  The code is pretty simply and may get
       confused if an argument is called "--display". */
    char **new_argv, *p;
    size_t n;
    int i, done;

    for (n=0,i=0; i < argc; i++)
        n += strlen (argv[i])+1;
    n++;
    new_argv = (char**)calloc (argc+1, sizeof *new_argv);
    if (new_argv)
        *new_argv = (char*)malloc (n);
    if (!new_argv || !*new_argv)
    {
        fprintf (stderr, "pinentry-x2go: can't fixup argument list: %s\n",
                 strerror (errno));
        exit (EXIT_FAILURE);

    }
    for (done=0,p=*new_argv,i=0; i < argc; i++)
        if (!done && !strcmp (argv[i], "--display"))
        {
            new_argv[i] = "-display";
            done = 1;
        }
        else
        {
            new_argv[i] = strcpy (p, argv[i]);
            p += strlen (argv[i]) + 1;
        }

    /* We use a modal dialog window, so we don't need the application
       window anymore.  */
    i = argc;
    QApplication* app=new QApplication (i, new_argv);
    QTranslator pinTranslator;
    QString filename=QString(":/pinentry-x2go_%1").arg(QLocale::system().name());
    filename=filename.toLower();
    if(!pinTranslator.load(filename))
    {
         qDebug("Can't load translator (%s) !\n",filename.toLocal8Bit().data());
    }
    else
        app->installTranslator(&pinTranslator);



    QTranslator qtTranslator;
    filename=QString(":/qt_%1").arg(QLocale::system().name());
    if(!qtTranslator.load(filename))
    {
         qDebug("Can't load translator (%s) !\n",filename.toLocal8Bit().data());
    }
    else
      app->installTranslator(&qtTranslator);

#if QT_VERSION < 0x050000
    app->setStyle(new QPlastiqueStyle());
#else
    app->setStyle(QStyleFactory::create("fusion"));
#endif

    /* Consumes all arguments.  */
    if (pinentry_parse_opts (argc, argv))
    {
        printf ("pinentry-x2go (pinentry) " VERSION "\n");
        exit (EXIT_SUCCESS);
    }

    if (pinentry_loop ())
        return 1;

    return 0;
}
