/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */

/*
 * Caja
 *
 * Copyright (C) 2003 Red Hat, Inc.
 *
 * Caja 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.
 *
 * Caja 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; see the file COPYING.  If not,
 * write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include <config.h>
#include "caja-connect-server-dialog.h"

#include <string.h>
#include <eel/eel-gtk-macros.h>
#include <eel/eel-stock-dialogs.h>
#include <eel/eel-vfs-extensions.h>
#include <glib/gi18n.h>
#include <gio/gio.h>
#include <gtk/gtk.h>
#include "caja-location-entry.h"
#include <libcaja-private/caja-global-preferences.h>
#include <libcaja-private/caja-icon-names.h>

/* TODO:
 * - dns-sd fill out servers
 * - pre-fill user?
 * - name entry + pre-fill
 * - folder browse function
 */

/* TODO gio port:
 * - see FIXME here
 * - see FIXME in caja-connect-server-dialog-main.c
 */

struct _CajaConnectServerDialogDetails
{
    CajaApplication *application;

    GtkWidget *table;

    GtkWidget *type_combo;
    GtkWidget *uri_entry;
    GtkWidget *server_entry;
    GtkWidget *share_entry;
    GtkWidget *port_entry;
    GtkWidget *folder_entry;
    GtkWidget *domain_entry;
    GtkWidget *user_entry;

    GtkWidget *bookmark_check;
    GtkWidget *name_entry;
};

static void  caja_connect_server_dialog_class_init       (CajaConnectServerDialogClass *class);
static void  caja_connect_server_dialog_init             (CajaConnectServerDialog      *dialog);

EEL_CLASS_BOILERPLATE (CajaConnectServerDialog,
                       caja_connect_server_dialog,
                       GTK_TYPE_DIALOG)
enum
{
    RESPONSE_CONNECT
};

struct MethodInfo
{
    const char *scheme;
    guint flags;
};

/* A collection of flags for MethodInfo.flags */
enum
{
    DEFAULT_METHOD = 0x00000001,

    /* Widgets to display in setup_for_type */
    SHOW_SHARE     = 0x00000010,
    SHOW_PORT      = 0x00000020,
    SHOW_USER      = 0x00000040,
    SHOW_DOMAIN    = 0x00000080,

    IS_ANONYMOUS   = 0x00001000
};

/* Remember to fill in descriptions below */
static struct MethodInfo methods[] =
{
    /* FIXME: we need to alias ssh to sftp */
    { "sftp",  SHOW_PORT | SHOW_USER },
    { "ftp",  SHOW_PORT | SHOW_USER },
    { "ftp",  DEFAULT_METHOD | IS_ANONYMOUS | SHOW_PORT},
    { "smb",  SHOW_SHARE | SHOW_USER | SHOW_DOMAIN },
    { "dav",  SHOW_PORT | SHOW_USER },
    /* FIXME: hrm, shouldn't it work? */
    { "davs", SHOW_PORT | SHOW_USER },
    { NULL,   0 }, /* Custom URI method */
};

/* To get around non constant gettext strings */
static const char*
get_method_description (struct MethodInfo *meth)
{
    if (!meth->scheme)
    {
        return _("Custom Location");
    }
    else if (strcmp (meth->scheme, "sftp") == 0)
    {
        return _("SSH");
    }
    else if (strcmp (meth->scheme, "ftp") == 0)
    {
        if (meth->flags & IS_ANONYMOUS)
        {
            return _("Public FTP");
        }
        else
        {
            return _("FTP (with login)");
        }
    }
    else if (strcmp (meth->scheme, "smb") == 0)
    {
        return _("Windows share");
    }
    else if (strcmp (meth->scheme, "dav") == 0)
    {
        return _("WebDAV (HTTP)");
    }
    else if (strcmp (meth->scheme, "davs") == 0)
    {
        return _("Secure WebDAV (HTTPS)");

        /* No descriptive text */
    }
    else
    {
        return meth->scheme;
    }
}

static void
caja_connect_server_dialog_finalize (GObject *object)
{
    CajaConnectServerDialog *dialog;

    dialog = CAJA_CONNECT_SERVER_DIALOG (object);

    g_object_unref (dialog->details->uri_entry);
    g_object_unref (dialog->details->server_entry);
    g_object_unref (dialog->details->share_entry);
    g_object_unref (dialog->details->port_entry);
    g_object_unref (dialog->details->folder_entry);
    g_object_unref (dialog->details->domain_entry);
    g_object_unref (dialog->details->user_entry);
    g_object_unref (dialog->details->bookmark_check);
    g_object_unref (dialog->details->name_entry);

    g_free (dialog->details);

    EEL_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
}

static void
caja_connect_server_dialog_destroy (GtkObject *object)
{
    CajaConnectServerDialog *dialog;

    dialog = CAJA_CONNECT_SERVER_DIALOG (object);

    EEL_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object));
}

static void
connect_to_server (CajaConnectServerDialog *dialog)
{
    struct MethodInfo *meth;
    char *uri;
    GFile *location;
    int index;
    GtkTreeIter iter;

    /* Get our method info */
    gtk_combo_box_get_active_iter (GTK_COMBO_BOX (dialog->details->type_combo), &iter);
    gtk_tree_model_get (gtk_combo_box_get_model (GTK_COMBO_BOX (dialog->details->type_combo)),
                        &iter, 0, &index, -1);
    g_assert (index < G_N_ELEMENTS (methods) && index >= 0);
    meth = &(methods[index]);

    uri = gtk_editable_get_chars (GTK_EDITABLE (dialog->details->server_entry), 0, -1);
    if (strlen (uri) == 0)
    {
        eel_show_error_dialog (_("Cannot Connect to Server. You must enter a name for the server."),
                               _("Please enter a name and try again."),
                               GTK_WINDOW (dialog));
        g_free (uri);
        return;
    }

    if (meth->scheme == NULL)
    {
        uri = gtk_editable_get_chars (GTK_EDITABLE (dialog->details->uri_entry), 0, -1);
        /* FIXME: we should validate it in some way? */
    }
    else
    {
        char *user, *port, *initial_path, *server, *folder, *domain;
        char *t, *join;
        gboolean free_initial_path, free_user, free_domain, free_port;

        server = uri;
        uri = NULL;

        user = "";
        port = "";
        initial_path = "";
        domain = "";
        free_initial_path = FALSE;
        free_user = FALSE;
        free_domain = FALSE;
        free_port = FALSE;

        /* FTP special case */
        if (meth->flags & IS_ANONYMOUS)
        {
            user = "anonymous";

            /* SMB special case */
        }
        else if (strcmp (meth->scheme, "smb") == 0)
        {
            t = gtk_editable_get_chars (GTK_EDITABLE (dialog->details->share_entry), 0, -1);
            initial_path = g_strconcat ("/", t, NULL);
            free_initial_path = TRUE;
            g_free (t);
        }

        if (gtk_widget_get_parent (dialog->details->port_entry) != NULL)
        {
            free_port = TRUE;
            port = gtk_editable_get_chars (GTK_EDITABLE (dialog->details->port_entry), 0, -1);
        }
        folder = gtk_editable_get_chars (GTK_EDITABLE (dialog->details->folder_entry), 0, -1);
        if (gtk_widget_get_parent (dialog->details->user_entry) != NULL)
        {
            free_user = TRUE;

            t = gtk_editable_get_chars (GTK_EDITABLE (dialog->details->user_entry), 0, -1);

            user = g_uri_escape_string (t, G_URI_RESERVED_CHARS_ALLOWED_IN_USERINFO, FALSE);

            g_free (t);
        }
        if (gtk_widget_get_parent (dialog->details->domain_entry) != NULL)
        {
            free_domain = TRUE;

            domain = gtk_editable_get_chars (GTK_EDITABLE (dialog->details->domain_entry), 0, -1);

            if (strlen (domain) != 0)
            {
                t = user;

                user = g_strconcat (domain , ";" , t, NULL);

                if (free_user)
                {
                    g_free (t);
                }

                free_user = TRUE;
            }
        }

        if (folder[0] != 0 &&
                folder[0] != '/')
        {
            join = "/";
        }
        else
        {
            join = "";
        }

        t = folder;
        folder = g_strconcat (initial_path, join, t, NULL);
        g_free (t);

        t = folder;
        folder = g_uri_escape_string (t, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, FALSE);
        g_free (t);

        uri = g_strdup_printf ("%s://%s%s%s%s%s%s",
                               meth->scheme,
                               user, (user[0] != 0) ? "@" : "",
                               server,
                               (port[0] != 0) ? ":" : "", port,
                               folder);

        if (free_initial_path)
        {
            g_free (initial_path);
        }
        g_free (server);
        if (free_port)
        {
            g_free (port);
        }
        g_free (folder);
        if (free_user)
        {
            g_free (user);
        }
        if (free_domain)
        {
            g_free (domain);
        }
    }

    gtk_widget_hide (GTK_WIDGET (dialog));

    location = g_file_new_for_uri (uri);
    g_free (uri);

    /* FIXME: sensitivity */
    if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->details->bookmark_check)))
    {
        char *name;
        CajaBookmark *bookmark;
        CajaBookmarkList *list;
        GIcon *icon;

        name = gtk_editable_get_chars (GTK_EDITABLE (dialog->details->name_entry), 0, -1);
        icon = g_themed_icon_new (CAJA_ICON_FOLDER_REMOTE);
        bookmark = caja_bookmark_new (location, strlen (name) ? name : NULL,
                                      TRUE, icon);
        list = caja_bookmark_list_new ();
        if (!caja_bookmark_list_contains (list, bookmark))
        {
            caja_bookmark_list_append (list, bookmark);
        }

        g_object_unref (bookmark);
        g_object_unref (list);
        g_object_unref (icon);
        g_free (name);
    }

    caja_connect_server_dialog_present_uri (dialog->details->application,
                                            location,
                                            GTK_WIDGET (dialog));
}

static void
response_callback (CajaConnectServerDialog *dialog,
                   int response_id,
                   gpointer data)
{
    GError *error;

    switch (response_id)
    {
    case RESPONSE_CONNECT:
        connect_to_server (dialog);
        break;
    case GTK_RESPONSE_NONE:
    case GTK_RESPONSE_DELETE_EVENT:
    case GTK_RESPONSE_CANCEL:
        gtk_widget_destroy (GTK_WIDGET (dialog));
        break;
    case GTK_RESPONSE_HELP :
        error = NULL;
        gtk_show_uri (gtk_window_get_screen (GTK_WINDOW (dialog)),
                      "ghelp:user-guide#caja-server-connect",
                      gtk_get_current_event_time (), &error);
        if (error)
        {
            eel_show_error_dialog (_("There was an error displaying help."), error->message,
                                   GTK_WINDOW (dialog));
            g_error_free (error);
        }
        break;
    default :
        g_assert_not_reached ();
    }
}

static void
caja_connect_server_dialog_class_init (CajaConnectServerDialogClass *class)
{
    GObjectClass *gobject_class;
    GtkObjectClass *object_class;

    gobject_class = G_OBJECT_CLASS (class);
    gobject_class->finalize = caja_connect_server_dialog_finalize;

    object_class = GTK_OBJECT_CLASS (class);
    object_class->destroy = caja_connect_server_dialog_destroy;
}

static void
setup_for_type (CajaConnectServerDialog *dialog)
{
    struct MethodInfo *meth;
    int index, i;
    GtkWidget *label, *table;
    GtkTreeIter iter;

    /* Get our method info */
    gtk_combo_box_get_active_iter (GTK_COMBO_BOX (dialog->details->type_combo), &iter);
    gtk_tree_model_get (gtk_combo_box_get_model (GTK_COMBO_BOX (dialog->details->type_combo)),
                        &iter, 0, &index, -1);
    g_assert (index < G_N_ELEMENTS (methods) && index >= 0);
    meth = &(methods[index]);

    if (gtk_widget_get_parent (dialog->details->uri_entry) != NULL)
    {
        gtk_container_remove (GTK_CONTAINER (dialog->details->table),
                              dialog->details->uri_entry);
    }
    if (gtk_widget_get_parent (dialog->details->server_entry) != NULL)
    {
        gtk_container_remove (GTK_CONTAINER (dialog->details->table),
                              dialog->details->server_entry);
    }
    if (gtk_widget_get_parent (dialog->details->share_entry) != NULL)
    {
        gtk_container_remove (GTK_CONTAINER (dialog->details->table),
                              dialog->details->share_entry);
    }
    if (gtk_widget_get_parent (dialog->details->port_entry) != NULL)
    {
        gtk_container_remove (GTK_CONTAINER (dialog->details->table),
                              dialog->details->port_entry);
    }
    if (gtk_widget_get_parent (dialog->details->folder_entry) != NULL)
    {
        gtk_container_remove (GTK_CONTAINER (dialog->details->table),
                              dialog->details->folder_entry);
    }
    if (gtk_widget_get_parent (dialog->details->user_entry) != NULL)
    {
        gtk_container_remove (GTK_CONTAINER (dialog->details->table),
                              dialog->details->user_entry);
    }
    if (gtk_widget_get_parent (dialog->details->domain_entry) != NULL)
    {
        gtk_container_remove (GTK_CONTAINER (dialog->details->table),
                              dialog->details->domain_entry);
    }
    if (gtk_widget_get_parent (dialog->details->bookmark_check) != NULL)
    {
        gtk_container_remove (GTK_CONTAINER (dialog->details->table),
                              dialog->details->bookmark_check);
    }
    if (gtk_widget_get_parent (dialog->details->name_entry) != NULL)
    {
        gtk_container_remove (GTK_CONTAINER (dialog->details->table),
                              dialog->details->name_entry);
    }
    /* Destroy all labels */
    gtk_container_foreach (GTK_CONTAINER (dialog->details->table),
                           (GtkCallback) gtk_widget_destroy, NULL);


    i = 1;
    table = dialog->details->table;

    if (meth->scheme == NULL)
    {
        label = gtk_label_new_with_mnemonic (_("_Location (URI):"));
        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
        gtk_widget_show (label);
        gtk_table_attach (GTK_TABLE (table), label,
                          0, 1,
                          i, i+1,
                          GTK_FILL, GTK_FILL,
                          0, 0);

        gtk_label_set_mnemonic_widget (GTK_LABEL (label), dialog->details->uri_entry);
        gtk_widget_show (dialog->details->uri_entry);
        gtk_table_attach (GTK_TABLE (table), dialog->details->uri_entry,
                          1, 2,
                          i, i+1,
                          GTK_FILL | GTK_EXPAND, GTK_FILL,
                          0, 0);

        i++;

        goto connection_name;
    }

    label = gtk_label_new_with_mnemonic (_("_Server:"));
    gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
    gtk_widget_show (label);
    gtk_table_attach (GTK_TABLE (table), label,
                      0, 1,
                      i, i+1,
                      GTK_FILL, GTK_FILL,
                      0, 0);

    gtk_label_set_mnemonic_widget (GTK_LABEL (label), dialog->details->server_entry);
    gtk_widget_show (dialog->details->server_entry);
    gtk_table_attach (GTK_TABLE (table), dialog->details->server_entry,
                      1, 2,
                      i, i+1,
                      GTK_FILL | GTK_EXPAND, GTK_FILL,
                      0, 0);

    i++;

    label = gtk_label_new (_("Optional information:"));
    gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
    gtk_widget_show (label);
    gtk_table_attach (GTK_TABLE (table), label,
                      0, 2,
                      i, i+1,
                      GTK_FILL, GTK_FILL,
                      0, 0);

    i++;

    if (meth->flags & SHOW_SHARE)
    {
        label = gtk_label_new_with_mnemonic (_("_Share:"));
        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
        gtk_widget_show (label);
        gtk_table_attach (GTK_TABLE (table), label,
                          0, 1,
                          i, i+1,
                          GTK_FILL, GTK_FILL,
                          0, 0);

        gtk_label_set_mnemonic_widget (GTK_LABEL (label), dialog->details->share_entry);
        gtk_widget_show (dialog->details->share_entry);
        gtk_table_attach (GTK_TABLE (table), dialog->details->share_entry,
                          1, 2,
                          i, i+1,
                          GTK_FILL | GTK_EXPAND, GTK_FILL,
                          0, 0);

        i++;
    }

    if (meth->flags & SHOW_PORT)
    {
        label = gtk_label_new_with_mnemonic (_("_Port:"));
        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
        gtk_widget_show (label);
        gtk_table_attach (GTK_TABLE (table), label,
                          0, 1,
                          i, i+1,
                          GTK_FILL, GTK_FILL,
                          0, 0);

        gtk_label_set_mnemonic_widget (GTK_LABEL (label), dialog->details->port_entry);
        gtk_widget_show (dialog->details->port_entry);
        gtk_table_attach (GTK_TABLE (table), dialog->details->port_entry,
                          1, 2,
                          i, i+1,
                          GTK_FILL | GTK_EXPAND, GTK_FILL,
                          0, 0);

        i++;
    }

    label = gtk_label_new_with_mnemonic (_("_Folder:"));
    gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
    gtk_widget_show (label);
    gtk_table_attach (GTK_TABLE (table), label,
                      0, 1,
                      i, i+1,
                      GTK_FILL, GTK_FILL,
                      0, 0);

    gtk_label_set_mnemonic_widget (GTK_LABEL (label), dialog->details->folder_entry);
    gtk_widget_show (dialog->details->folder_entry);
    gtk_table_attach (GTK_TABLE (table), dialog->details->folder_entry,
                      1, 2,
                      i, i+1,
                      GTK_FILL | GTK_EXPAND, GTK_FILL,
                      0, 0);

    i++;

    if (meth->flags & SHOW_USER)
    {
        label = gtk_label_new_with_mnemonic (_("_User Name:"));
        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
        gtk_widget_show (label);
        gtk_table_attach (GTK_TABLE (table), label,
                          0, 1,
                          i, i+1,
                          GTK_FILL, GTK_FILL,
                          0, 0);

        gtk_label_set_mnemonic_widget (GTK_LABEL (label), dialog->details->user_entry);
        gtk_widget_show (dialog->details->user_entry);
        gtk_table_attach (GTK_TABLE (table), dialog->details->user_entry,
                          1, 2,
                          i, i+1,
                          GTK_FILL | GTK_EXPAND, GTK_FILL,
                          0, 0);

        i++;
    }

    if (meth->flags & SHOW_DOMAIN)
    {
        label = gtk_label_new_with_mnemonic (_("_Domain Name:"));
        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
        gtk_widget_show (label);
        gtk_table_attach (GTK_TABLE (table), label,
                          0, 1,
                          i, i+1,
                          GTK_FILL, GTK_FILL,
                          0, 0);

        gtk_label_set_mnemonic_widget (GTK_LABEL (label), dialog->details->domain_entry);
        gtk_widget_show (dialog->details->domain_entry);
        gtk_table_attach (GTK_TABLE (table), dialog->details->domain_entry,
                          1, 2,
                          i, i+1,
                          GTK_FILL | GTK_EXPAND, GTK_FILL,
                          0, 0);

        i++;
    }



connection_name:

    gtk_widget_show (dialog->details->bookmark_check);
    gtk_table_attach (GTK_TABLE (table), dialog->details->bookmark_check,
                      0, 1,
                      i, i+1,
                      GTK_FILL, GTK_FILL,
                      0, 0);
    i++;

    label = gtk_label_new_with_mnemonic (_("Bookmark _name:"));
    gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
    gtk_widget_show (label);
    gtk_table_attach (GTK_TABLE (table), label,
                      0, 1,
                      i, i+1,
                      GTK_FILL, GTK_FILL,
                      0, 0);

    gtk_label_set_mnemonic_widget (GTK_LABEL (label), dialog->details->name_entry);
    gtk_widget_show (dialog->details->name_entry);
    gtk_table_attach (GTK_TABLE (table), dialog->details->name_entry,
                      1, 2,
                      i, i+1,
                      GTK_FILL | GTK_EXPAND, GTK_FILL,
                      0, 0);

    i++;

}

static void
display_server_location (CajaConnectServerDialog *dialog, GFile *location)
{
#if 0 /*FIXME */
    struct MethodInfo *meth = NULL;
    char *scheme;
    int i, index = 0;
    char *folder;
    const char *t;

    /* Find an appropriate method */
    scheme = g_file_get_uri_scheme (location);
    g_return_if_fail (scheme != NULL);

    for (i = 0; i < G_N_ELEMENTS (methods); i++)
    {

        /* The default is 'Custom URI' */
        if (methods[i].scheme == NULL)
        {
            meth = &(methods[i]);
            index = i;

        }
        else if (strcmp (methods[i].scheme, scheme) == 0)
        {

            /* FTP Special case: If no user keep searching for public ftp */
            if (strcmp (scheme, "ftp") == 0)
            {
                t = mate_vfs_uri_get_user_name (uri);
                if ((!t || !t[0] || strcmp (t, "anonymous") == 0) &&
                        (!(methods[i].flags & IS_ANONYMOUS)))
                {
                    continue;
                }
            }

            meth = &(methods[i]);
            index = i;
            break;
        }
    }

    g_free (scheme);
    g_assert (meth);

    gtk_combo_box_set_active (GTK_COMBO_BOX (dialog->details->type_combo), index);
    setup_for_type (dialog);

    /* Custom URI */
    if (meth->scheme == NULL)
    {
        gchar *uri;

        /* FIXME: with mate-vfs, we had MATE_VFS_URI_HIDE_PASSWORD |
         * MATE_VFS_URI_HIDE_FRAGMENT_IDENTIFIER */
        uri = g_file_get_uri (location)
              gtk_entry_set_text (GTK_ENTRY (dialog->details->uri_entry), uri);
        g_free (uri);

    }
    else
    {

        folder = g_file_get_path (location);
        if (!folder)
        {
            folder = "";
        }
        else if (folder[0] == '/')
        {
            folder++;
        }

        /* Server */
        t = mate_vfs_uri_get_host_name (uri);
        gtk_entry_set_text (GTK_ENTRY (dialog->details->server_entry),
                            t ? t : "");

        /* Share */
        if (meth->flags & SHOW_SHARE)
        {
            t = strchr (folder, '/');
            if (t)
            {
                char *share = g_strndup (folder, t - folder);
                gtk_entry_set_text (GTK_ENTRY (dialog->details->share_entry), share);
                g_free (share);
                folder = t + 1;
            }

        }

        /* Port */
        if (meth->flags & SHOW_PORT)
        {
            guint port = mate_vfs_uri_get_host_port (uri);
            if (port != 0)
            {
                char sport[32];
                g_snprintf (sport, sizeof (sport), "%d", port);
                gtk_entry_set_text (GTK_ENTRY (dialog->details->port_entry), sport);
            }
        }

        /* Folder */
        gtk_entry_set_text (GTK_ENTRY (dialog->details->folder_entry), folder);
        g_free (folder);

        /* User */
        if (meth->flags & SHOW_USER)
        {
            const char *user = mate_vfs_uri_get_user_name (uri);
            if (user)
            {
                t = strchr (user, ';');
                if (t)
                {
                    user = t + 1;
                }
                gtk_entry_set_text (GTK_ENTRY (dialog->details->user_entry), user);
            }
        }

        /* Domain */
        if (meth->flags & SHOW_DOMAIN)
        {
            const char *user = mate_vfs_uri_get_user_name (uri);
            if (user)
            {
                t = strchr (user, ';');
                if (t)
                {
                    char *domain = g_strndup (user, t - user);
                    gtk_entry_set_text (GTK_ENTRY (dialog->details->domain_entry), domain);
                    g_free (domain);
                }
            }
        }
    }
#endif
}

static void
combo_changed_callback (GtkComboBox *combo_box,
                        CajaConnectServerDialog *dialog)
{
    setup_for_type (dialog);
}

static void
port_insert_text (GtkEditable *editable,
                  const gchar *new_text,
                  gint         new_text_length,
                  gint        *position)
{
    int pos;

    if (new_text_length < 0)
    {
        new_text_length = strlen (new_text);
    }

    /* Only allow digits to be inserted as port number */
    for (pos = 0; pos < new_text_length; pos++)
    {
        if (!g_ascii_isdigit (new_text[pos]))
        {
            GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (editable));
            if (toplevel != NULL)
            {
                gdk_window_beep (gtk_widget_get_window (toplevel));
            }
            g_signal_stop_emission_by_name (editable, "insert_text");
            return;
        }
    }
}

static void
bookmark_checkmark_toggled (GtkToggleButton *toggle, CajaConnectServerDialog *dialog)
{
    gtk_widget_set_sensitive (GTK_WIDGET(dialog->details->name_entry),
                              gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (toggle)));
}

static void
caja_connect_server_dialog_init (CajaConnectServerDialog *dialog)
{
    GtkWidget *label;
    GtkWidget *table;
    GtkWidget *combo;
    GtkWidget *hbox;
    GtkWidget *vbox;
    GtkListStore *store;
    GtkCellRenderer *renderer;
    int i;

    dialog->details = g_new0 (CajaConnectServerDialogDetails, 1);

    gtk_window_set_title (GTK_WINDOW (dialog), _("Connect to Server"));
    gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
    gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
    gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), 2);
    gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);

    vbox = gtk_vbox_new (FALSE, 6);
    gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
    gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
                        vbox, FALSE, TRUE, 0);
    gtk_widget_show (vbox);

    hbox = gtk_hbox_new (FALSE, 6);
    gtk_box_pack_start (GTK_BOX (vbox),
                        hbox, FALSE, TRUE, 0);
    gtk_widget_show (hbox);

    label = gtk_label_new_with_mnemonic (_("Service _type:"));
    gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
    gtk_widget_show (label);
    gtk_box_pack_start (GTK_BOX (hbox),
                        label, FALSE, FALSE, 0);

    dialog->details->type_combo = combo = gtk_combo_box_new ();

    /* each row contains: method index, textual description */
    store = gtk_list_store_new (2, G_TYPE_INT, G_TYPE_STRING);
    gtk_combo_box_set_model (GTK_COMBO_BOX (combo), GTK_TREE_MODEL (store));
    g_object_unref (G_OBJECT (store));

    renderer = gtk_cell_renderer_text_new ();
    gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, TRUE);
    gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combo), renderer, "text", 1);

    for (i = 0; i < G_N_ELEMENTS (methods); i++)
    {
        GtkTreeIter iter;
        const gchar * const *supported;
        int j;

        /* skip methods that don't have corresponding MateVFSMethods */
        supported = g_vfs_get_supported_uri_schemes (g_vfs_get_default ());

        if (methods[i].scheme != NULL)
        {
            gboolean found;

            found = FALSE;
            for (j = 0; supported[j] != NULL; j++)
            {
                if (strcmp (methods[i].scheme, supported[j]) == 0)
                {
                    found = TRUE;
                    break;
                }
            }

            if (!found)
            {
                continue;
            }
        }

        gtk_list_store_append (store, &iter);
        gtk_list_store_set (store, &iter,
                            0, i,
                            1, get_method_description (&(methods[i])),
                            -1);


        if (methods[i].flags & DEFAULT_METHOD)
        {
            gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combo), &iter);
        }
    }

    if (gtk_combo_box_get_active (GTK_COMBO_BOX (combo)) < 0)
    {
        /* default method not available, use any other */
        gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
    }

    gtk_widget_show (combo);
    gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
    gtk_box_pack_start (GTK_BOX (hbox),
                        combo, TRUE, TRUE, 0);
    g_signal_connect (combo, "changed",
                      G_CALLBACK (combo_changed_callback),
                      dialog);


    hbox = gtk_hbox_new (FALSE, 6);
    gtk_box_pack_start (GTK_BOX (vbox),
                        hbox, FALSE, TRUE, 0);
    gtk_widget_show (hbox);

    label = gtk_label_new_with_mnemonic ("    ");
    gtk_widget_show (label);
    gtk_box_pack_start (GTK_BOX (hbox),
                        label, FALSE, FALSE, 0);


    dialog->details->table = table = gtk_table_new (5, 2, FALSE);
    gtk_table_set_row_spacings (GTK_TABLE (table), 6);
    gtk_table_set_col_spacings (GTK_TABLE (table), 12);
    gtk_widget_show (table);
    gtk_box_pack_start (GTK_BOX (hbox),
                        table, TRUE, TRUE, 0);

    dialog->details->uri_entry = caja_location_entry_new ();
    /* hide the clean icon, as it doesn't make sense here */
    g_object_set (dialog->details->uri_entry, "secondary-icon-name", NULL, NULL);
    dialog->details->server_entry = gtk_entry_new ();
    dialog->details->share_entry = gtk_entry_new ();
    dialog->details->port_entry = gtk_entry_new ();
    g_signal_connect (dialog->details->port_entry, "insert_text", G_CALLBACK (port_insert_text),
                      NULL);
    dialog->details->folder_entry = gtk_entry_new ();
    dialog->details->domain_entry = gtk_entry_new ();
    dialog->details->user_entry = gtk_entry_new ();
    dialog->details->bookmark_check = gtk_check_button_new_with_mnemonic (_("Add _bookmark"));
    dialog->details->name_entry = gtk_entry_new ();

    g_signal_connect (dialog->details->bookmark_check, "toggled",
                      G_CALLBACK (bookmark_checkmark_toggled), dialog);

    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->details->bookmark_check), FALSE);
    gtk_widget_set_sensitive (GTK_WIDGET(dialog->details->name_entry), FALSE);

    gtk_entry_set_activates_default (GTK_ENTRY (dialog->details->uri_entry), TRUE);
    gtk_entry_set_activates_default (GTK_ENTRY (dialog->details->server_entry), TRUE);
    gtk_entry_set_activates_default (GTK_ENTRY (dialog->details->share_entry), TRUE);
    gtk_entry_set_activates_default (GTK_ENTRY (dialog->details->port_entry), TRUE);
    gtk_entry_set_activates_default (GTK_ENTRY (dialog->details->folder_entry), TRUE);
    gtk_entry_set_activates_default (GTK_ENTRY (dialog->details->domain_entry), TRUE);
    gtk_entry_set_activates_default (GTK_ENTRY (dialog->details->user_entry), TRUE);
    gtk_entry_set_activates_default (GTK_ENTRY (dialog->details->name_entry), TRUE);

    /* We need an extra ref so we can remove them from the table */
    g_object_ref (dialog->details->uri_entry);
    g_object_ref (dialog->details->server_entry);
    g_object_ref (dialog->details->share_entry);
    g_object_ref (dialog->details->port_entry);
    g_object_ref (dialog->details->folder_entry);
    g_object_ref (dialog->details->domain_entry);
    g_object_ref (dialog->details->user_entry);
    g_object_ref (dialog->details->bookmark_check);
    g_object_ref (dialog->details->name_entry);

    setup_for_type (dialog);

    gtk_dialog_add_button (GTK_DIALOG (dialog),
                           GTK_STOCK_HELP,
                           GTK_RESPONSE_HELP);
    gtk_dialog_add_button (GTK_DIALOG (dialog),
                           GTK_STOCK_CANCEL,
                           GTK_RESPONSE_CANCEL);
    gtk_dialog_add_button (GTK_DIALOG (dialog),
                           _("C_onnect"),
                           RESPONSE_CONNECT);
    gtk_dialog_set_default_response (GTK_DIALOG (dialog),
                                     RESPONSE_CONNECT);

    g_signal_connect (dialog, "response",
                      G_CALLBACK (response_callback),
                      dialog);


}

GtkWidget *
caja_connect_server_dialog_new (CajaWindow *window, GFile *location)
{
    CajaConnectServerDialog *conndlg;
    GtkWidget *dialog;

    dialog = gtk_widget_new (CAJA_TYPE_CONNECT_SERVER_DIALOG, NULL);
    conndlg = CAJA_CONNECT_SERVER_DIALOG (dialog);

    if (window)
    {
        gtk_window_set_screen (GTK_WINDOW (dialog),
                               gtk_window_get_screen (GTK_WINDOW (window)));
        conndlg->details->application = window->application;
    }

    if (location)
    {
        /* If it's a remote URI, then load as the default */
        if (!g_file_is_native (location))
        {
            display_server_location (conndlg, location);
        }
    }

    return dialog;
}