void
screenshooter_job_image_uploaded (ScreenshooterJob *job, const gchar *file_name, const gchar *delete_hash)
{
  g_return_if_fail (SCREENSHOOTER_IS_JOB (job));

  TRACE ("Emit image-uploaded signal.");
  exo_job_emit (EXO_JOB (job), job_signals[IMAGE_UPLOADED], 0, file_name, delete_hash);
}
void screenshooter_job_ask_info (ScreenshooterJob *job,
                                 GtkListStore     *info,
                                 const gchar      *format,
                                 ...)
{
  va_list va_args;
  gchar *message;

  g_return_if_fail (SCREENSHOOTER_IS_JOB (job));
  g_return_if_fail (GTK_IS_LIST_STORE (info));
  g_return_if_fail (format != NULL);

  if (G_UNLIKELY (exo_job_is_cancelled (EXO_JOB (job))))
    return;

  va_start (va_args, format);
  message = g_strdup_vprintf (format, va_args);
  va_end (va_args);

  exo_job_emit (EXO_JOB (job), job_signals[ASK], 0, info, message);

  g_free (message);
}
void
cb_ask_for_information (ScreenshooterJob *job,
                        GtkListStore     *liststore,
                        const gchar      *message,
                        gpointer          unused)
{
  GtkWidget *dialog;
  GtkWidget *information_label;
  GtkWidget *vbox, *main_alignment;
  GtkWidget *table;
  GtkWidget *user_entry, *password_entry, *title_entry, *comment_entry;
  GtkWidget *user_label, *password_label, *title_label, *comment_label;

  GtkTreeIter iter;
  gint response;

  g_return_if_fail (SCREENSHOOTER_IS_JOB (job));
  g_return_if_fail (GTK_IS_LIST_STORE (liststore));
  g_return_if_fail (message != NULL);

  TRACE ("Create the dialog to ask for user information.");

  /* Create the information dialog */
  dialog =
    xfce_titled_dialog_new_with_buttons (_("Details about the screenshot for ZimageZ"),
                                         NULL,
                                         GTK_DIALOG_NO_SEPARATOR,
                                         GTK_STOCK_CANCEL,
                                         GTK_RESPONSE_CANCEL,
                                         GTK_STOCK_OK,
                                         GTK_RESPONSE_OK,
                                         NULL);

  gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
  gtk_box_set_spacing (GTK_BOX (GTK_DIALOG(dialog)->vbox), 12);

  gtk_window_set_icon_name (GTK_WINDOW (dialog), "gtk-info");
  gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);

  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);

  /* Create the main alignment for the dialog */
  main_alignment = gtk_alignment_new (0, 0, 1, 1);
  gtk_alignment_set_padding (GTK_ALIGNMENT (main_alignment), 6, 0, 12, 12);
  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), main_alignment, TRUE, TRUE, 0);

  /* Create the main box for the dialog */
  vbox = gtk_vbox_new (FALSE, 10);
  gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
  gtk_container_add (GTK_CONTAINER (main_alignment), vbox);

  /* Create the information label */
  information_label = gtk_label_new ("");
  gtk_label_set_markup (GTK_LABEL (information_label), message);
  gtk_misc_set_alignment (GTK_MISC (information_label), 0, 0);
  gtk_container_add (GTK_CONTAINER (vbox), information_label);

  /* Create the layout table */
  table = gtk_table_new (4, 2, FALSE);
  gtk_table_set_col_spacings (GTK_TABLE (table), 6);
  gtk_table_set_row_spacings (GTK_TABLE (table), 12);
  gtk_container_add (GTK_CONTAINER (vbox), table);

  /* Create the user label */
  user_label = gtk_label_new (_("User:"******"Your Zimagez user name, if you do not have one yet"
                                 " please create one on the Web page linked above"));
  gtk_entry_set_activates_default (GTK_ENTRY (user_entry), TRUE);
  gtk_table_attach_defaults (GTK_TABLE (table), user_entry, 1, 2, 0, 1);

  /* Create the password label */
  password_label = gtk_label_new (_("Password:"******"The password for the user above"));
  gtk_entry_set_visibility (GTK_ENTRY (password_entry), FALSE);
  gtk_entry_set_activates_default (GTK_ENTRY (password_entry), TRUE);
  gtk_table_attach_defaults (GTK_TABLE (table), password_entry, 1, 2, 1, 2);

  /* Create the title label */
  title_label = gtk_label_new (_("Title:"));
  gtk_misc_set_alignment (GTK_MISC (title_label), 0, 0.5);
  gtk_table_attach (GTK_TABLE (table), title_label,
                    0, 1,
                    2, 3,
                    GTK_FILL, GTK_FILL,
                    0, 0);
  /* Create the title entry */
  title_entry = gtk_entry_new ();
  gtk_widget_set_tooltip_text (title_entry,
                               _("The title of the screenshot, it will be used when"
                                 " displaying the screenshot on ZimageZ"));
  gtk_entry_set_activates_default (GTK_ENTRY (title_entry), TRUE);
  gtk_table_attach_defaults (GTK_TABLE (table), title_entry, 1, 2, 2, 3);

  /* Create the comment label */
  comment_label = gtk_label_new (_("Comment:"));
  gtk_misc_set_alignment (GTK_MISC (comment_label), 0, 0.5);
  gtk_table_attach (GTK_TABLE (table), comment_label,
                    0, 1,
                    3, 4,
                    GTK_FILL, GTK_FILL,
                    0, 0);

  /* Create the comment entry */
  comment_entry = gtk_entry_new ();
  gtk_widget_set_tooltip_text (comment_entry,
                               _("A comment on the screenshot, it will be used when"
                                 " displaying the screenshot on ZimageZ"));
  gtk_entry_set_activates_default (GTK_ENTRY (comment_entry), TRUE);
  gtk_table_attach_defaults (GTK_TABLE (table), comment_entry, 1, 2, 3, 4);

  /* Set the values */
  gtk_tree_model_get_iter_first (GTK_TREE_MODEL (liststore), &iter);

  do
    {
      gint field_index;
      gchar *field_value = NULL;

      gtk_tree_model_get (GTK_TREE_MODEL (liststore), &iter,
                          0, &field_index,
                          1, &field_value,
                          -1);
      switch (field_index)
        {
          case USER:
            gtk_entry_set_text (GTK_ENTRY (user_entry), field_value);
            break;
          case PASSWORD:
            gtk_entry_set_text (GTK_ENTRY (password_entry), field_value);
            break;
          case TITLE:
            gtk_entry_set_text (GTK_ENTRY (title_entry), field_value);
            break;
          case COMMENT:
            gtk_entry_set_text (GTK_ENTRY (comment_entry), field_value);
            break;
          default:
            break;
        }

      g_free (field_value);
    }
  while (gtk_tree_model_iter_next (GTK_TREE_MODEL (liststore), &iter));

  gtk_widget_show_all (GTK_DIALOG(dialog)->vbox);
  response = gtk_dialog_run (GTK_DIALOG (dialog));
  gtk_widget_hide (dialog);

  if (response == GTK_RESPONSE_CANCEL || response == GTK_RESPONSE_DELETE_EVENT)
    {
      exo_job_cancel (EXO_JOB (job));
    }
  else if (response == GTK_RESPONSE_OK)
    {
      gtk_tree_model_get_iter_first (GTK_TREE_MODEL (liststore), &iter);

      do
        {
          gint field_index;

          gtk_tree_model_get (GTK_TREE_MODEL (liststore), &iter,
                              0, &field_index, -1);

          switch (field_index)
            {
              case USER:
                gtk_list_store_set (liststore, &iter,
                                    1, gtk_entry_get_text (GTK_ENTRY (user_entry)),
                                    -1);
                break;
              case PASSWORD:
                gtk_list_store_set (liststore, &iter,
                                    1, gtk_entry_get_text (GTK_ENTRY (password_entry)),
                                    -1);
                break;
              case TITLE:
                gtk_list_store_set (liststore, &iter,
                                    1, gtk_entry_get_text (GTK_ENTRY (title_entry)),
                                    -1);
                break;
              case COMMENT:
                gtk_list_store_set (liststore, &iter,
                                    1, gtk_entry_get_text (GTK_ENTRY (comment_entry)),
                                    -1);
                break;
              default:
                break;
            }
        }
      while (gtk_tree_model_iter_next (GTK_TREE_MODEL (liststore), &iter));
    }

  gtk_widget_destroy (dialog);
}
GList *
thunar_io_scan_directory (ThunarJob          *job,
                          GFile              *file,
                          GFileQueryInfoFlags flags,
                          gboolean            recursively,
                          gboolean            unlinking,
                          GError            **error)
{
  GFileEnumerator *enumerator;
  GFileInfo       *info;
  GFileType        type;
  GError          *err = NULL;
  GFile           *child_file;
  GList           *child_files = NULL;
  GList           *files = NULL;
  
  _thunar_return_val_if_fail (THUNAR_IS_JOB (job), NULL);
  _thunar_return_val_if_fail (G_IS_FILE (file), NULL);
  _thunar_return_val_if_fail (error == NULL || *error == NULL, NULL);

  /* abort if the job was cancelled */
  if (exo_job_set_error_if_cancelled (EXO_JOB (job), error))
    return NULL;

  /* don't recurse when we are scanning prior to unlinking and the current 
   * file/dir is in the trash. In GVfs, only the top-level directories in 
   * the trash can be modified and deleted directly. See
   * http://bugzilla.xfce.org/show_bug.cgi?id=7147
   * for more information */
  if (unlinking
      && thunar_g_file_is_trashed (file)
      && !thunar_g_file_is_root (file))
    {
      return NULL;
    }

  /* query the file type */
  type = g_file_query_file_type (file, flags, exo_job_get_cancellable (EXO_JOB (job)));

  /* abort if the job was cancelled */
  if (exo_job_set_error_if_cancelled (EXO_JOB (job), error))
    return NULL;

  /* ignore non-directory nodes */
  if (type != G_FILE_TYPE_DIRECTORY)
    return NULL;

  /* try to read from the direectory */
  enumerator = g_file_enumerate_children (file,
                                          G_FILE_ATTRIBUTE_STANDARD_TYPE ","
                                          G_FILE_ATTRIBUTE_STANDARD_NAME,
                                          flags, exo_job_get_cancellable (EXO_JOB (job)),
                                          &err);

  /* abort if there was an error or the job was cancelled */
  if (err != NULL)
    {
      g_propagate_error (error, err);
      return NULL;
    }
        
  /* query info of the first child */
  info = g_file_enumerator_next_file (enumerator,
                                      exo_job_get_cancellable (EXO_JOB (job)), 
                                      &err);

  /* iterate over children one by one as long as there's no error */
  while (info != NULL && err == NULL && !exo_job_is_cancelled (EXO_JOB (job)))
    {
      /* create GFile for the child and prepend it to the file list */
      child_file = g_file_get_child (file, g_file_info_get_name (info));
      files = thunar_g_file_list_prepend (files, child_file);

      /* if the child is a directory and we need to recurse ... just do so */
      if (recursively && g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY)
        {
          child_files = thunar_io_scan_directory (job, child_file, flags, recursively, 
                                                  unlinking, &err);

          /* prepend children to the file list to make sure they're 
           * processed first (required for unlinking) */
          files = g_list_concat (child_files, files);
        }
      
      g_object_unref (child_file);
      g_object_unref (info);

      info = g_file_enumerator_next_file (enumerator, 
                                          exo_job_get_cancellable (EXO_JOB (job)), 
                                          &err);
    }

  /* release the enumerator */
  g_object_unref (enumerator);

  if (G_UNLIKELY (err != NULL))
    {
      g_propagate_error (error, err);
      thunar_g_file_list_free (files);
      return NULL;
    }
  else if (exo_job_set_error_if_cancelled (EXO_JOB (job), &err))
    {
      g_propagate_error (error, err);
      thunar_g_file_list_free (files);
      return NULL;
    }
  
  return files;
}
static gboolean
zimagez_upload_job (ScreenshooterJob *job, GArray *param_values, GError **error)
{
  const gchar *encoded_data;
  const gchar *image_path;
  const gchar *last_user;
  const gchar *proxy_uri;
  /* For translators: the first wildcard is the date, the second one the time,
   * e.g. "Taken on 12/31/99, at 23:13:48". */
  gchar *comment = screenshooter_get_datetime (_("Taken on %x, at %X"));
  gchar *data = NULL;
  gchar *encoded_password = NULL;
  gchar *file_name = NULL;
  gchar *login_response = NULL;
  gchar *online_file_name = NULL;
  gchar *password = g_strdup ("");
  gchar *title;
  gchar *user;

  gsize data_length;
  gboolean response = FALSE;

  const gchar *serverurl = "http://www.zimagez.com/apiXml.php";
  const gchar *method_login = "******";
  const gchar *method_logout = "apiXml.xmlrpcLogout";
  const gchar *method_upload = "apiXml.xmlrpcUpload";
  SoupSession *session;
  SoupURI *soup_proxy_uri;

  GError *tmp_error = NULL;
  GtkTreeIter iter;
  GtkListStore *liststore;
  GValue response_value;

  g_return_val_if_fail (SCREENSHOOTER_IS_JOB (job), FALSE);
  g_return_val_if_fail (param_values != NULL, FALSE);
  g_return_val_if_fail (param_values->len == 3, FALSE);
  g_return_val_if_fail (G_VALUE_HOLDS_STRING (&g_array_index (param_values, GValue, 0)), FALSE);
  g_return_val_if_fail (G_VALUE_HOLDS_STRING (&g_array_index (param_values, GValue, 1)), FALSE);
  g_return_val_if_fail (G_VALUE_HOLDS_STRING (&g_array_index (param_values, GValue, 2)), FALSE);
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);

  g_object_set_data (G_OBJECT (job), "jobtype", "zimagez");
  if (exo_job_set_error_if_cancelled (EXO_JOB (job), error))
    {
      g_free (comment);
      g_free (password);

      return FALSE;
    }

  /* Get the last user */
  last_user = g_value_get_string (&g_array_index (param_values, GValue, 1));
  user = g_strdup (last_user);

  if (user == NULL)
    user = g_strdup ("");

  if (!g_utf8_validate (user, -1, NULL))
    {
      g_free (user);
      user = g_strdup ("");
    }

  g_object_set_data_full (G_OBJECT (job), "user",
                          g_strdup (user), (GDestroyNotify) g_free);

  /* Get the default title */
  title = g_strdup (g_value_get_string (&g_array_index (param_values, GValue, 2)));
  if (title == NULL)
    title = g_strdup ("");

  if (!g_utf8_validate (title, -1, NULL))
    {
      g_free (title);
      title = g_strdup ("");
    }

  /* Get the path of the image that is to be uploaded */
  image_path = g_value_get_string (&g_array_index (param_values, GValue, 0));

  /* Start the user soup session */
  exo_job_info_message (EXO_JOB (job), _("Initialize the connection..."));
  session = soup_session_sync_new ();

  /* Set the proxy URI if any */
  proxy_uri = g_getenv ("http_proxy");

  if (proxy_uri != NULL)
    {
      soup_proxy_uri = soup_uri_new (proxy_uri);
      g_object_set (session, "proxy-uri", soup_proxy_uri, NULL);
      soup_uri_free (soup_proxy_uri);
    }

  TRACE ("Get the information liststore ready.");
  liststore = gtk_list_store_new (2, G_TYPE_INT, G_TYPE_STRING);

  TRACE ("Append the user");
  gtk_list_store_append (liststore, &iter);
  gtk_list_store_set (liststore, &iter,
                      0, USER,
                      1, user,
                      -1);

  TRACE ("Append the password");
  gtk_list_store_append (liststore, &iter);
  gtk_list_store_set (liststore, &iter,
                      0, PASSWORD,
                      1, password,
                      -1);

  TRACE ("Append the title");
  gtk_list_store_append (liststore, &iter);
  gtk_list_store_set (liststore, &iter,
                      0, TITLE,
                      1, title,
                      -1);

  TRACE ("Append the comment");
  gtk_list_store_append (liststore, &iter);
  gtk_list_store_set (liststore, &iter,
                      0, COMMENT,
                      1, comment,
                      -1);

  TRACE ("Ask the user to fill the information items.");
  screenshooter_job_ask_info (job, liststore,
                              _("Please fill the following fields with your "
                                "<a href=\"http://www.zimagez.com\">ZimageZ</a> \n"
                                "user name, passsword and details about the screenshot."));

  gtk_tree_model_get_iter_first (GTK_TREE_MODEL (liststore), &iter);

  do
    {
      gint field_index;
      gchar *field_value = NULL;

      gtk_tree_model_get (GTK_TREE_MODEL (liststore), &iter,
                          0, &field_index,
                          1, &field_value,
                          -1);

      switch (field_index)
        {
          case USER:
            user = g_strdup (field_value);
            break;
          case PASSWORD:
            password = g_strdup (field_value);
            break;
          case TITLE:
            title = g_strdup (field_value);
            break;
          case COMMENT:
            comment = g_strdup (field_value);
            break;
          default:
            break;
        }

      g_free (field_value);
    }
  while (gtk_tree_model_iter_next (GTK_TREE_MODEL (liststore), &iter));

  while (!response)
    {
      if (exo_job_set_error_if_cancelled (EXO_JOB (job), error))
        {
          soup_session_abort (session);
          g_object_unref (session);

          g_free (user);
          g_free (password);
          g_free (title);
          g_free (comment);
          if (encoded_password != NULL)
            g_free (encoded_password);

          TRACE ("The upload job was cancelled.");

          return FALSE;
        }

      exo_job_info_message (EXO_JOB (job), _("Check the user information..."));

      /* Test if one of the information fields is empty */
      if (has_empty_field (liststore))
        {
          TRACE ("One of the fields was empty, let the user file it.");
          screenshooter_job_ask_info (job, liststore,
                                      _("<span weight=\"bold\" foreground=\"darkred\" "
                                        "stretch=\"semiexpanded\">You must fill all the "
                                        "fields.</span>"));
          continue;
        }

      encoded_password = g_utf8_strreverse (rot13 (password), -1);

      TRACE ("User: %s", user);
      TRACE ("Encoded password: %s", encoded_password);

      /* Start the user session */
      TRACE ("Call the login method");

      exo_job_info_message (EXO_JOB (job), _("Login on ZimageZ..."));

      if (!do_xmlrpc (session, serverurl, method_login,
                      &tmp_error, &response_value,
                      G_TYPE_STRING, user,
                      G_TYPE_STRING, encoded_password,
                      G_TYPE_INVALID))
        {
          g_propagate_error (error, tmp_error);
          soup_session_abort (session);
          g_object_unref (session);

          g_free (password);
          g_free (title);
          g_free (comment);
          g_free (encoded_password);

          return FALSE;
        }

      TRACE ("Read the login response");

      /* If the response is a boolean, there was an error */
      if (G_VALUE_HOLDS_BOOLEAN (&response_value))
        {
          response = g_value_get_boolean (&response_value);
        }
      /* Else we read the string response to get the session ID */
      else if (G_VALUE_HOLDS_STRING (&response_value))
        {
          TRACE ("Read the session ID");
          login_response = g_strdup (g_value_get_string (&response_value));
          response = TRUE;
        }
      /* We received an unexpected reply */
      else
        {
          GError *tmp_err =
            g_error_new (SOUP_XMLRPC_FAULT,
                         SOUP_XMLRPC_FAULT_PARSE_ERROR_NOT_WELL_FORMED,
                         "%s", _("An unexpected reply from ZimageZ was received."
                                 " The upload of the screenshot failed."));
          soup_session_abort (session);
          g_object_unref (session);

          g_free (user);
          g_free (password);
          g_free (title);
          g_free (comment);
          g_free (encoded_password);

          g_propagate_error (error, tmp_err);

          return FALSE;
        }

      g_value_unset (&response_value);

      if (!response)
        {
          /* Login failed, erase the password and ask for the correct on to the
             user */
          gtk_tree_model_get_iter_first (GTK_TREE_MODEL (liststore), &iter);

          do
            {
              gint field_index;

              gtk_tree_model_get (GTK_TREE_MODEL (liststore), &iter, 0, &field_index, -1);

              if (field_index == PASSWORD)
                {
                  gtk_list_store_set (liststore, &iter, 1, g_strdup (""), -1);
                  break;
                }
            }
          while (gtk_tree_model_iter_next (GTK_TREE_MODEL (liststore), &iter));

          screenshooter_job_ask_info (job, liststore,
                                      _("<span weight=\"bold\" foreground=\"darkred\" "
                                        "stretch=\"semiexpanded\">The user and the "
                                        "password you entered do not match. "
                                        "Please retry.</span>"));

          gtk_tree_model_get_iter_first (GTK_TREE_MODEL (liststore), &iter);

          do
            {
              gint field_index;
              gchar *field_value = NULL;

              gtk_tree_model_get (GTK_TREE_MODEL (liststore), &iter,
                                  0, &field_index,
                                  1, &field_value,
                                  -1);

              switch (field_index)
                {
                  case USER:
                    user = g_strdup (field_value);
                    break;
                  case PASSWORD:
                    password = g_strdup (field_value);
                    break;
                  case TITLE:
                    title = g_strdup (field_value);
                    break;
                  case COMMENT:
                    comment = g_strdup (field_value);
                    break;
                  default:
                    break;
                }

              g_free (field_value);
            }
          while (gtk_tree_model_iter_next (GTK_TREE_MODEL (liststore), &iter));
        }
    }

  g_object_set_data_full (G_OBJECT (job), "user",
                          g_strdup (user), (GDestroyNotify) g_free);

  g_free (user);
  g_free (password);
  g_free (encoded_password);

  /* Get the contents of the image file and encode it to base64 */
  g_file_get_contents (image_path, &data, &data_length, NULL);

  encoded_data = g_base64_encode ((guchar*)data, data_length);

  g_free (data);

  /* Get the basename of the image path */
  file_name = g_path_get_basename (image_path);

  exo_job_info_message (EXO_JOB (job), _("Upload the screenshot..."));

  TRACE ("Call the upload method");
  do_xmlrpc (session, serverurl, method_upload,
             &tmp_error, &response_value,
             G_TYPE_STRING, encoded_data,
             G_TYPE_STRING, file_name,
             G_TYPE_STRING, title,
             G_TYPE_STRING, comment,
             G_TYPE_STRING, login_response,
             G_TYPE_INVALID);

  g_free (title);
  g_free (comment);
  g_free (file_name);

  if (tmp_error)
    {
      soup_session_abort (session);
      g_object_unref (session);

      g_propagate_error (error, tmp_error);

      return FALSE;
    }

  /* If the response is a boolean, there was an error */
  if (G_VALUE_HOLDS_BOOLEAN (&response_value))
    {
      if (!g_value_get_boolean (&response_value))
        {
          GError *tmp_err =
            g_error_new (G_IO_ERROR, G_IO_ERROR_FAILED,
                         _("An error occurred while uploading the screenshot."));

          soup_session_abort (session);
          g_object_unref (session);
          g_propagate_error (error, tmp_err);

          return FALSE;
        }
    }
  /* Else we get the file name */
  else if (G_VALUE_HOLDS_STRING (&response_value))
    {
      TRACE ("The screenshot has been uploaded, get the file name.");
      online_file_name = g_strdup (g_value_get_string (&response_value));
    }
  /* We received un unexpected reply */
  else
    {
      GError *tmp_err =
        g_error_new (SOUP_XMLRPC_FAULT,
                     SOUP_XMLRPC_FAULT_PARSE_ERROR_NOT_WELL_FORMED,
                     "%s", _("An unexpected reply from ZimageZ was received."
                       " The upload of the screenshot failed."));
      soup_session_abort (session);
      g_object_unref (session);
      g_propagate_error (error, tmp_err);

      return FALSE;
    }

  g_value_unset (&response_value);

  /* End the user session */
  exo_job_info_message (EXO_JOB (job), _("Close the session on ZimageZ..."));

  TRACE ("Closing the user session");

  do_xmlrpc (session, serverurl, method_logout,
             &tmp_error, &response_value,
             G_TYPE_STRING, login_response,
             G_TYPE_INVALID);

  if (G_IS_VALUE (&response_value))
    g_value_unset (&response_value);

  /* Clean the soup session */
  soup_session_abort (session);
  g_object_unref (session);
  g_free (login_response);

  screenshooter_job_image_uploaded (job, online_file_name);

  if (tmp_error)
    {
      g_propagate_error (error, tmp_error);

      return FALSE;
    }

  return TRUE;
}