// This is an example not a library
/***************************************************************************
 *   Copyright (C) 2008 Daniel Nicoletti <dantti85-pk@yahoo.com.br>        *
 *   Copyright (C) 2009 Radek Novacek    <rnovacek@redhat.com>             *
 *                                                                         *
 *   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.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA .        *
 ***************************************************************************/

#include "PkExampleHelper.h"

#include "polkit-tqt-authority.h"

#include <tqdbusdatalist.h>
#include <tqdbuserror.h>
#include <tqdbusmessage.h>
#include <tqdom.h>
#include <tqfile.h>
#include <tqtimer.h>
#include <tqsessionmanager.h>

using namespace PolkitTQt;


PkExampleHelper::PkExampleHelper(int argc, char **argv) : TQApplication(argc, argv, false)
{
  tqDebug("Creating Helper");
  // Register the DBus service
  m_connection = TQT_DBusConnection::systemBus();
  if (!m_connection.registerObject("/", this))
  {
    tqDebug("unable to register 'org.tqt.policykit.examples' service interface to dbus");
    tqDebug(m_connection.lastError().message());
    return;
  }
  if (!m_connection.requestName("org.tqt.policykit.examples"))
  {
    tqDebug("unable to acquire 'org.tqt.policykit.examples' service interface to dbus");
    tqDebug(m_connection.lastError().message());
    return;
  }
  // Exit if not used for 10 minutes
  TQTimer::singleShot(600000, this, TQ_SLOT(quit()));
  tqDebug("Register successful");
}

PkExampleHelper::~PkExampleHelper()
{
  tqDebug("Destroying Helper");
  m_connection.unregisterObject("org.tqt.policykit.examples");
}

void PkExampleHelper::commitData(TQSessionManager &sm)
{
  sm.setRestartHint(TQSessionManager::RestartNever);
}

bool PkExampleHelper::handleMethodCall(const TQT_DBusMessage& message)
{
  if (message.interface() != "org.tqt.policykit.examples")
  {
    return false;
  }

  if (message.member() == "set")
  {
    // check parameters
    if (message.count() != 1 || message[0].type() != TQT_DBusData::String)
    {
      // method signature not what we expected
      TQT_DBusError error = TQT_DBusError::stdInvalidArgs(
          "Expected one argument of type string");
      TQT_DBusMessage reply = TQT_DBusMessage::methodError(message, error);
      m_connection.send(reply);
      return true;
    }

    bool res = set(message[0].toString());
    TQT_DBusMessage reply = TQT_DBusMessage::methodReply(message);
    reply << TQT_DBusData::fromBool(res);
    m_connection.send(reply);
    return true;
  }

  TQT_DBusMessage reply = TQT_DBusMessage::methodReply(message);
  reply << TQT_DBusData::fromString("Bad request");
  m_connection.send(reply);
  return true;
}

bool PkExampleHelper::set(const TQString &action)
{
  // We can check if the caller is authorized to the following action
  SystemBusNameSubject subject(m_connection.uniqueName());
  Authority::Result result;
  result = Authority::instance()->checkAuthorizationSync("org.tqt.policykit.examples.set",
          subject , Authority::AllowUserInteraction);
  if (result == Authority::Yes)
  {
    // Caller is authorized so we can perform the action
    tqDebug(TQString("Implicit authorization set to %1").arg(action));
    return setValue(action);
  }
  else
  {
    // Caller is not authorized so the action can't be performed
    tqDebug(TQString("Can't set the implicit authorization to %1").arg(action));
    return false;
  }
}

bool PkExampleHelper::setValue(const TQString &action)
{
  // This action must be authorized first. It will set the implicit
  // authorization for the Shout action by editing the .policy file
  TQDomDocument doc = TQDomDocument("policy");
  TQFile file("/usr/share/polkit-1/actions/org.tqt.policykit.examples.policy");
  if (!file.open(IO_ReadOnly))
  {
    return false;
  }
  doc.setContent(&file);
  file.close();
  TQDomElement el = doc.namedItem("policyconfig").namedItem("action").toElement();
  while (!el.isNull() && el.attribute("id") != "org.tqt.policykit.examples.shout")
  {
    el = el.nextSibling().toElement();
  }
  el = el.namedItem("defaults").toElement();
  el = el.namedItem("allow_active").toElement();
  if (el.isNull())
  {
    return false;
  }
  el.firstChild().toText().setData(action);
  if (!file.open(IO_WriteOnly))
  {
    return false;
  }
  TQTextStream stream(&file);
  doc.save(stream, 2);
  file.close();
  return true;
}

#include "PkExampleHelper.moc"
