/*
 * Mail Notification
 * Copyright (C) 2003-2008 Jean-Yves Lefort <jylefort@brutele.be>
 *
 * 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 3 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.
 */

%headertop{
#include "mn-webmail-mailbox.h"
%}

%{
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <glib/gi18n.h>
#include "mn-webmail-mailbox-private.h"
#include "mn-stock.h"
#include "mn-conf.h"
#include "mn-util.h"
%}

class MN:Yahoo:Mailbox from MN:Webmail:Mailbox
{
  class_init (class)
  {
    MN_MAILBOX_CLASS(class)->type = "yahoo";

    /* 5 minutes is a good default */
    MN_MAILBOX_CLASS(class)->default_check_delay = 60 * 5;

    MN_WEBMAIL_MAILBOX_CLASS(class)->default_domain = "yahoo.com";
  }

  init (self)
  {
    mn_mailbox_set_format(MN_MAILBOX(self), "Yahoo! Mail");
    mn_mailbox_set_stock_id(MN_MAILBOX(self), MN_STOCK_YAHOO);
  }

  private char *
    create_cookies_file (GError **err)
  {
    char *filename;

    /*
     * If the file already exists, ensure it has the proper
     * permissions. Otherwise, create it with the proper permissions.
     */

    filename = g_build_filename(mn_conf_dot_dir, "yahoo-cookies", NULL);
    if (g_file_test(filename, G_FILE_TEST_EXISTS))
      {
	if (chmod(filename, S_IRUSR | S_IWUSR) < 0)
	  {
	    g_set_error(err, 0, 0, _("unable to change the permissions of %s: %s"), filename, g_strerror(errno));
	    goto error;
	  }
      }
    else
      {
	int fd;

	fd = open(filename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
	if (fd < 0)
	  {
	    g_set_error(err, 0, 0, _("unable to create %s: %s"), filename, g_strerror(errno));
	    goto error;
	  }
	close(fd);
      }

    return filename;

  error:
    g_free(filename);
    return NULL;
  }

  private gboolean
    can_convert (const char *str (check null),
		 const char *encoding (check null))
  {
    char *converted;
    gboolean can;

    converted = g_convert(str, -1, encoding, "UTF-8", NULL, NULL, NULL);
    can = converted != NULL;
    g_free(converted);

    return can;
  }

  private const char *
    get_config_file_encoding (const char *folder (check null))
  {
    /*
     * fetchyahoo does not seem to deal with the folder name encoding
     * at all, and Yahoo apparently uses ISO8859-1 when possible, and
     * UTF-8 otherwise.
     */
    if (self_can_convert(folder, "ISO8859-1"))
      return "ISO8859-1";
    else
      return "UTF-8";
  }

  private char *
    create_config_file (self,
			const char *spool_file (check null),
			const char *cookies_file (check null),
			GError **err)
  {
    GString *contents;
    char *filename;

    contents = g_string_new(NULL);

    g_string_append_printf(contents,
			   "username = %s\n"
			   "password = %s\n"
			   "folder = %s\n"
			   "spool = %s\n"
			   "cookie-file = %s\n"
			   "new-messages-only = 1\n"
			   "no-delete = 1\n"
			   "leave-unread = 1\n",
			   MN_AUTHENTICATED_MAILBOX(self)->username,
			   MN_AUTHENTICATED_MAILBOX(self)->runtime_password,
			   MN_WEBMAIL_MAILBOX(self)->folder,
			   spool_file,
			   cookies_file);

    if (mn_conf_get_bool(MN_CONF_SYSTEM_HTTP_PROXY_USE_HTTP_PROXY))
      {
	char *host;

	host = mn_conf_get_string(MN_CONF_SYSTEM_HTTP_PROXY_HOST);
	if (host && *host)
	  {
	    g_string_append_printf(contents,
				   "use-proxy = 1\n"
				   "proxy-host = %s\n"
				   "proxy-port = %i\n",
				   host,
				   mn_conf_get_int(MN_CONF_SYSTEM_HTTP_PROXY_PORT));

	    if (mn_conf_get_bool(MN_CONF_SYSTEM_HTTP_PROXY_USE_AUTHENTICATION))
	      {
		char *user;
		char *password;

		user = mn_conf_get_string(MN_CONF_SYSTEM_HTTP_PROXY_AUTHENTICATION_USER);
		password = mn_conf_get_string(MN_CONF_SYSTEM_HTTP_PROXY_AUTHENTICATION_PASSWORD);

		if (user && *user && password && *password)
		  g_string_append_printf(contents,
					 "proxy-username = %s\n"
					 "proxy-password = %s\n",
					 user,
					 password);

		g_free(user);
		g_free(password);
	      }
	  }
	g_free(host);
      }

    mn_webmail_mailbox_print_config(MN_WEBMAIL_MAILBOX(self), contents->str);
    filename = mn_webmail_mailbox_write_temporary_file(contents->str, self_get_config_file_encoding(MN_WEBMAIL_MAILBOX(self)->folder), err);

    g_string_free(contents, TRUE);

    return filename;
  }

  override (MN:Webmail:Mailbox) char *
    get_error_message (MNWebmailMailbox *mailbox,
		       const char *helper_stdout,
		       const char *helper_stderr,
		       gboolean *is_auth_failure)
  {
    if (helper_stderr)
      {
	char **lines;
	int i;
	char *message = NULL;

	lines = g_strsplit(helper_stderr, "\n", 0);
	for (i = 0; lines[i]; i++)
	  if (g_str_has_prefix(lines[i], "Failed: "))
	    {
	      char *escaped;

	      if (mn_ascii_strcasestr(lines[i], "wrong password")
		  || mn_ascii_strcasestr(lines[i], "invalid ID")
		  || (mn_ascii_strcasestr(lines[i], "Yahoo user")
		      && mn_ascii_strcasestr(lines[i], "does not exist")))
		*is_auth_failure = TRUE;

	      escaped = mn_utf8_escape(lines[i] + 8);
	      message = g_strdup_printf(_("\"%s\""), escaped);
	      g_free(escaped);

	      break;
	    }
	g_strfreev(lines);

	if (message)
	  return message;

	if (mn_ascii_strcasestr(helper_stderr, "an image of text"))
	  return g_strdup(_("delay between mail checks too small"));
      }

    return NULL;
  }

  private gboolean
    run_fetchyahoo (self, const char *config_file (check null), GError **err)
  {
    char *command;
    gboolean status;

    command = g_strdup_printf("fetchyahoo --configfile=%s", config_file);
    status = mn_webmail_mailbox_run_helper(MN_WEBMAIL_MAILBOX(self), "fetchyahoo", command, err);
    g_free(command);

    return status;
  }

  override (MN:Webmail:Mailbox) gboolean
    webmail_check (MNWebmailMailbox *mailbox, GError **err)
  {
    Self *self = SELF(mailbox);
    char *spool_file;
    char *cookies_file;
    char *config_file = NULL;
    gboolean status = FALSE;

    /*
     * We create an empty spool file beforehand to make sure it is not
     * world-readable.
     */
    spool_file = mn_webmail_mailbox_create_spool_file(err);
    if (! spool_file)
      return FALSE;

    /*
     * Likewise, we create an empty cookies file beforehand to make
     * sure it is not world-readable.
     */
    cookies_file = self_create_cookies_file(err);
    if (! cookies_file)
      goto end;

    /*
     * We create a config file rather than use command line arguments
     * because for obvious reasons, we must not pass the password on
     * the command line.
     */
    config_file = self_create_config_file(self, spool_file, cookies_file, err);
    if (! config_file)
      goto end;

    if (! self_run_fetchyahoo(self, config_file, err))
      goto end;

    if (! mn_webmail_mailbox_read_spool_file(mailbox, spool_file, err))
      goto end;

    status = TRUE;

  end:
    unlink(spool_file);
    g_free(spool_file);

    g_free(cookies_file);

    if (config_file)
      {
	unlink(config_file);
	g_free(config_file);
      }

    return status;
  }
}
