# Description: Auto install samba and libpam-samba if needed.
# Origin: vendor
# Forwarded: not-needed
# Author: Michael Vogt <mvo@ubuntu.com>
# Reviewed-By: Sebastien Bacher <seb128@canonical.com>
# Reviewed-By: Didier Roche <didrocks@ubuntu.com>
# Reviewed-By: Chow Loong Jin <hyperair@ubuntu.com>
# Reviewed-By: Michael Terry <michael.terry@canonical.com>
Index: nautilus-share/src/nautilus-share.c
===================================================================
--- nautilus-share.orig/src/nautilus-share.c	2011-07-08 10:45:31.000000000 +0800
+++ nautilus-share/src/nautilus-share.c	2011-07-08 10:47:55.845693427 +0800
@@ -39,6 +39,9 @@
 
 #include <gtk/gtk.h>
 
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+
 #include <string.h>
 #include <time.h>
 
@@ -46,6 +49,7 @@
 #include <sys/stat.h>
 #include <unistd.h>
 #include <stdlib.h>
+#include <sys/wait.h>
 
 #include "shares.h"
 
@@ -579,8 +583,279 @@
   page->is_dirty = TRUE;
   property_page_check_sensitivity (page);
 }
-
 /*--------------------------------------------------------------------------*/
+/*---------------------begin samba auto-install code------------------------*/
+static gboolean
+check_samba_installed ()
+{
+  return g_file_test ("/usr/sbin/smbd", G_FILE_TEST_IS_EXECUTABLE);
+}
+
+/* a linked list of PropertyPages waiting for samba to be installed */
+static GList *pages_waiting_for_samba = NULL;
+/* TRUE if currently installing samba, FALSE otherwise */
+static gboolean is_installing_samba = FALSE;
+
+static void
+finish_samba_installation (gboolean success)
+{
+  gint response;
+  GtkWidget* dialog_ask_restart;
+
+  is_installing_samba = FALSE;
+
+  while (pages_waiting_for_samba)
+  {
+    PropertyPage *current = pages_waiting_for_samba->data;
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (current->checkbutton_share_folder), success);
+    property_page_check_sensitivity (current);
+    pages_waiting_for_samba = g_list_remove (pages_waiting_for_samba, current);
+  }
+
+  if (!success)
+    return;
+
+  /* if we're successful, then ask to restart to make libpam-smbpass create
+     NTLM password hash */
+  dialog_ask_restart = gtk_message_dialog_new (
+      NULL,
+      GTK_DIALOG_MODAL,
+      GTK_MESSAGE_WARNING,
+      GTK_BUTTONS_CLOSE,
+      _("Restart your session"));
+  gtk_message_dialog_format_secondary_markup (
+      GTK_MESSAGE_DIALOG (dialog_ask_restart),
+      _("You need to restart your session in order to enable sharing."));
+  gtk_dialog_add_button (GTK_DIALOG (dialog_ask_restart), _("Restart session"),
+      GTK_RESPONSE_OK);
+  response = gtk_dialog_run (GTK_DIALOG (dialog_ask_restart));
+  gtk_widget_destroy (dialog_ask_restart);
+
+  if (response == GTK_RESPONSE_OK) {
+    g_spawn_command_line_async ("gnome-session-save --logout", NULL);
+  }
+}
+
+static void
+set_environment (gpointer display)
+{
+  g_setenv ("DISPLAY", display, TRUE);
+}
+
+static gboolean
+spawn_synaptic (GtkWidget *window, const gchar *path, gint *child_pid)
+{
+  GError *error = NULL;
+  gboolean retval = TRUE;
+  gchar **argv;
+  gchar *display;
+
+  { /* generate argv */
+    gchar *synaptic_path = g_find_program_in_path ("synaptic");
+    gint i = 0;
+
+    argv = g_new0 (gchar*, 5);
+    argv[i++] = g_find_program_in_path ("gksu");
+    argv[i++] = g_strdup ("--desktop");
+    argv[i++] = g_strdup ("/usr/share/applications/synaptic.desktop");
+    argv[i++] = g_strdup_printf ("%s --hide-main-window "
+        "--set-selections-file %s "
+        "--non-interactive "
+        "--parent-window-id %d",
+        synaptic_path,
+        path,
+        GDK_WINDOW_XID (gtk_widget_get_window (GTK_WIDGET (window))));
+    argv[i++] = NULL;
+
+    g_free (synaptic_path);
+  }
+
+  display =
+    gdk_screen_make_display_name (gtk_window_get_screen (GTK_WINDOW (window)));
+
+  if (!g_spawn_async (NULL,     /* working directory */
+                      argv,
+                      NULL,     /* envp */
+                      G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
+                      set_environment, display, child_pid, &error))
+  {    fprintf (stderr, "synaptic spawn failed; %s", (error) ? error->message : "");
+    g_error_free (error);
+    retval = FALSE;
+  }
+
+  g_strfreev (argv);
+  g_free (display);
+
+  return retval;
+
+
+}
+
+static gboolean
+on_wait_timeout (gpointer data)
+{
+  gint pid, status;
+
+  pid = GPOINTER_TO_INT (data);
+
+  if (waitpid (pid, &status, WNOHANG) > 0)
+    {
+      gtk_main_quit ();
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+static gboolean
+wait_for_synaptic (GtkWindow *window, pid_t pid)
+{
+  gint timer;
+
+  /* set the cursor to a watch */
+  GdkCursor *cursor = gdk_cursor_new (GDK_WATCH);
+  gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (window)), cursor);
+  gtk_widget_set_sensitive (GTK_WIDGET (window), FALSE);
+
+  /* wait until synaptic is done */
+  timer = g_timeout_add (500, on_wait_timeout, GINT_TO_POINTER (pid));
+  gtk_main ();
+  g_source_remove (timer);
+
+  /* set the cursor to nothing */
+  gtk_widget_set_sensitive (GTK_WIDGET (window), FALSE);
+  gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (window)), NULL);
+
+  gdk_cursor_unref (cursor);
+
+  return check_samba_installed ();
+}
+
+static gchar*
+create_temp_file (const gchar *packages[])
+{
+  int fd;
+  gchar *path, *str;
+
+  path = g_strdup_printf ("/tmp/packages.XXXXXX");
+  fd = mkstemp (path);
+
+  while (*packages)
+    {
+      str = g_strdup_printf ("%s\ti\n", *packages);
+      write (fd, str, strlen (str));
+      g_free (str);
+      packages++;
+    }
+
+  close (fd);
+  return path;
+}
+
+static void
+run_synaptic (GtkWidget *window)
+{
+  gchar *path;
+  GtkWidget* dialog_ask_retry;
+  gboolean success = FALSE;
+
+  /* generate list of packages for installing */
+  {
+    const gchar *packages[] = {
+      "samba",
+      "libpam-smbpass",
+      NULL
+    };
+    path = create_temp_file (packages);
+  }
+
+  /* generate dialog_ask_retry */
+  dialog_ask_retry  = gtk_message_dialog_new (NULL,
+                        GTK_DIALOG_MODAL,
+                        GTK_MESSAGE_WARNING,
+                        GTK_BUTTONS_CLOSE,
+                        _("Sharing service installation failed"));
+  gtk_message_dialog_format_secondary_markup (
+      GTK_MESSAGE_DIALOG (dialog_ask_retry),
+      _("Sharing service installation has failed. Would you like to retry the "
+        "installation?"));
+  gtk_dialog_add_button (GTK_DIALOG (dialog_ask_retry),
+                         _("Retry"),
+                         GTK_RESPONSE_OK);
+
+  /* loop until either installed successfully, or user cancels */
+  for (;;) 
+  {
+    gint response; /* response from dialog */
+    pid_t pid; /* synaptic's pid */
+
+    if (spawn_synaptic (window, path, &pid))
+      if ((success = wait_for_synaptic (GTK_WINDOW (window), pid)))
+        break;
+    
+    response = gtk_dialog_run (GTK_DIALOG (dialog_ask_retry));
+    gtk_widget_hide (dialog_ask_retry);
+    if (response != GTK_RESPONSE_OK)
+    {
+      success = FALSE;
+      break;
+    }
+  }
+
+  /* clean up */
+  gtk_widget_destroy (dialog_ask_retry);
+  finish_samba_installation (success);
+}
+
+static void
+start_samba_installation ()
+{
+  gint response; /* response from dialog */
+  GtkWidget* dialog;
+
+  /* ask to install samba */
+  dialog = gtk_message_dialog_new (NULL,
+             GTK_DIALOG_MODAL,
+             GTK_MESSAGE_WARNING,
+             GTK_BUTTONS_CLOSE,
+             _("Sharing service is not installed"));
+  gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG (dialog),
+    _("You need to install the Windows networks "
+      "sharing service in order to share your folders."));
+  gtk_dialog_add_button (GTK_DIALOG (dialog), _("Install service"), GTK_RESPONSE_OK);
+  response = gtk_dialog_run (GTK_DIALOG (dialog));
+  gtk_widget_hide (dialog);
+  
+  if (response != GTK_RESPONSE_OK)
+    finish_samba_installation (FALSE);
+  else
+  {
+    is_installing_samba = TRUE;
+    run_synaptic (dialog);
+  }
+  gtk_widget_destroy (dialog);
+}
+
+static void
+wait_samba_installation (PropertyPage *page)
+{
+  /* if installed, do nothing */
+  if (check_samba_installed ())
+    return;
+
+  pages_waiting_for_samba = g_list_prepend (pages_waiting_for_samba, page);
+
+  /* start samba installation if not already started */
+  if (!is_installing_samba)
+    start_samba_installation ();
+}
+
+static void
+unwait_samba_installation (PropertyPage *page)
+{
+  pages_waiting_for_samba = g_list_remove (pages_waiting_for_samba, page);
+}
+/*---------------------end samba auto-install code--------------------------*/
 static void
 on_checkbutton_share_folder_toggled    (GtkToggleButton *togglebutton,
                                         gpointer         user_data)
@@ -589,7 +864,13 @@
 
   page = user_data;
 
-  property_page_check_sensitivity (page);
+  if (check_samba_installed ())
+    property_page_check_sensitivity (page);
+  else if (gtk_toggle_button_get_active (
+              GTK_TOGGLE_BUTTON (page->checkbutton_share_folder)))
+    wait_samba_installation (page);
+  else
+    unwait_samba_installation (page);
 }
 
 static void
@@ -625,6 +906,7 @@
 
   page = data;
 
+  unwait_samba_installation (page);
   g_free (page->path);
   g_object_unref (page->fileinfo);
   g_object_unref (page->xml);
