static void
send_login_html (CockpitWebResponse *response,
                 CockpitHandlerData *ws)
{
  GHashTable *headers = NULL;
  GList *l, *output = NULL;
  gchar *login_html;
  GMappedFile *file;
  GError *error = NULL;
  GBytes *body = NULL;
  gsize length;

  login_html = g_build_filename (ws->static_roots[0], "login.html", NULL);
  file = g_mapped_file_new (login_html, FALSE, &error);
  if (file == NULL)
    {
      g_warning ("%s: %s", login_html, error->message);
      cockpit_web_response_error (response, 500, NULL, NULL);
      g_clear_error (&error);
      goto out;
    }

  body = g_mapped_file_get_bytes (file);
  output = cockpit_template_expand (body, substitute_environment, ws->os_release);

  length = 0;
  for (l = output; l != NULL; l = g_list_next (l))
    length += g_bytes_get_size (l->data);

  headers = cockpit_web_server_new_table ();
  g_hash_table_insert (headers, g_strdup ("Content-Type"), g_strdup ("text/html; charset=utf8"));

  cockpit_web_response_headers_full (response, 200, "OK", length, headers);

  for (l = output; l != NULL; l = g_list_next (l))
    {
      if (!cockpit_web_response_queue (response, l->data))
        break;
    }
  if (l == NULL)
    cockpit_web_response_complete (response);

out:
  g_list_free_full (output, (GDestroyNotify)g_bytes_unref);
  if (headers)
    g_hash_table_unref (headers);
  g_free (login_html);
  if (body)
    g_bytes_unref (body);
  if (file)
    g_mapped_file_unref (file);
}
Exemple #2
0
void
cockpit_package_expand (GHashTable *listing,
                        const gchar *host,
                        GBytes *input,
                        GQueue *output)
{
  ExpandInfo expand = { listing, host };
  GList *blocks;
  GList *l;
  gsize size;
  gsize length;
  gsize offset;

  if (is_binary_data (input))
    {
      /* If binary data, no variable expansion takes place */
      blocks = g_list_prepend (NULL, g_bytes_ref (input));
    }
  else
    {
      /* Expand all variables */
      blocks = cockpit_template_expand (input, expand_variables, &expand);
    }

  /* Also break data into blocks */
  for (l = blocks; l != NULL; l = g_list_next (l))
    {
      size = g_bytes_get_size (l->data);
      if (size < 8192)
        {
          g_queue_push_tail (output, l->data);
        }
      else
        {
          for (offset = 0; offset < size; offset += 4096)
            {
              length = MIN (4096, size - offset);
              g_queue_push_tail (output, g_bytes_new_from_bytes (l->data, offset, length));
            }
          g_bytes_unref (l->data);
        }
    }

  g_list_free (blocks);
}
static void
add_dynamic_args_to_array (gchar ***key,
                           gchar **config_args,
                           JsonObject *options)
{
  GPtrArray *arr = NULL;
  gint length;
  gint i;

  g_assert (config_args != NULL);
  g_assert (key != NULL);

  arr = g_ptr_array_new ();
  length = g_strv_length (config_args);
  for (i = 0; i < length; i++)
    {
      GString *s = g_string_new ("");
      GBytes *input = g_bytes_new_static (config_args[i], strlen(config_args[i]) + 1);
      GList *output = cockpit_template_expand (input, substitute_json_string,
                                               "${", "}", options);
      GList *l;
      for (l = output; l != NULL; l = g_list_next (l))
        {
          gsize size;
          gconstpointer data = g_bytes_get_data (l->data, &size);
          g_string_append_len (s, data, size);
        }

      g_ptr_array_add (arr, g_string_free (s, FALSE));
      g_bytes_unref (input);
      g_list_free_full (output, (GDestroyNotify) g_bytes_unref);
    }

  g_ptr_array_add (arr, NULL);
  *key = (gchar **)g_ptr_array_free (arr, FALSE);
}
/**
 * cockpit_web_response_error:
 * @self: the response
 * @status: the HTTP status code
 * @headers: headers to include or NULL
 * @format: printf format of error message
 *
 * Send an error message with a basic HTML page containing
 * the error.
 */
void
cockpit_web_response_error (CockpitWebResponse *self,
                            guint code,
                            GHashTable *headers,
                            const gchar *format,
                            ...)
{
  va_list var_args;
  gchar *reason = NULL;
  const gchar *message;
  GBytes *input = NULL;
  GList *output, *l;
  GError *error = NULL;

  g_return_if_fail (COCKPIT_IS_WEB_RESPONSE (self));

  if (format)
    {
      va_start (var_args, format);
      reason = g_strdup_vprintf (format, var_args);
      va_end (var_args);
      message = reason;
    }
  else
    {
      switch (code)
        {
        case 400:
          message = "Bad request";
          break;
        case 401:
          message = "Not Authorized";
          break;
        case 403:
          message = "Forbidden";
          break;
        case 404:
          message = "Not Found";
          break;
        case 405:
          message = "Method Not Allowed";
          break;
        case 413:
          message = "Request Entity Too Large";
          break;
        case 502:
          message = "Remote Page is Unavailable";
          break;
        case 500:
          message = "Internal Server Error";
          break;
        default:
          if (code < 100)
            reason = g_strdup_printf ("%u Continue", code);
          else if (code < 200)
            reason = g_strdup_printf ("%u OK", code);
          else if (code < 300)
            reason = g_strdup_printf ("%u Moved", code);
          else
            reason = g_strdup_printf ("%u Failed", code);
          message = reason;
          break;
        }
    }

  g_debug ("%s: returning error: %u %s", self->logname, code, message);

  if (cockpit_web_failure_resource)
    {
      input = g_resources_lookup_data (cockpit_web_failure_resource, G_RESOURCE_LOOKUP_FLAGS_NONE, &error);
      if (input == NULL)
        {
          g_critical ("couldn't load: %s: %s", cockpit_web_failure_resource, error->message);
          g_error_free (error);
        }
    }

  if (!input)
    input = g_bytes_new_static (default_failure_template, strlen (default_failure_template));

  if (headers)
    {
      if (!g_hash_table_lookup (headers, "Content-Type"))
        g_hash_table_replace (headers, g_strdup ("Content-Type"), g_strdup ("text/html; charset=utf8"));
      cockpit_web_response_headers_full (self, code, message, -1, headers);
    }
  else
    {
      cockpit_web_response_headers (self, code, message, -1, "Content-Type", "text/html; charset=utf8", NULL);
    }

  output = cockpit_template_expand (input, substitute_message, (gpointer)message);
  g_bytes_unref (input);

  for (l = output; l != NULL; l = g_list_next (l))
    {
      if (!cockpit_web_response_queue (self, l->data))
        break;
    }
  if (l == NULL)
    cockpit_web_response_complete (self);
  g_list_free_full (output, (GDestroyNotify)g_bytes_unref);

  g_free (reason);
}
Exemple #5
0
static gboolean
package_checksum_file (GChecksum *checksum,
                       GHashTable *depends,
                       const gchar *root,
                       const gchar *filename)
{
  gchar *path = NULL;
  const gchar *string;
  GError *error = NULL;
  GChecksum *inner = NULL;
  GMappedFile *mapped = NULL;
  gboolean ret = FALSE;
  GList *output = NULL;
  GBytes *bytes;
  GList *l;

  if (!validate_path (filename))
    {
      g_warning ("package has an invalid path name: %s", filename);
      goto out;
    }

  path = g_build_filename (root, filename, NULL);
  if (g_file_test (path, G_FILE_TEST_IS_DIR))
    {
      ret = package_checksum_directory (checksum, depends, root, filename);
      goto out;
    }

  mapped = g_mapped_file_new (path, FALSE, &error);
  if (error)
    {
      g_warning ("couldn't open file: %s: %s", path, error->message);
      g_error_free (error);
      goto out;
    }

  bytes = g_mapped_file_get_bytes (mapped);
  output = cockpit_template_expand (bytes, gather_depends, depends);
  g_bytes_unref (bytes);

  inner = g_checksum_new (G_CHECKSUM_SHA1);

  for (l = output; l != NULL; l = g_list_next (l))
    {
      g_checksum_update (inner,
                         g_bytes_get_data (l->data, NULL),
                         g_bytes_get_size (l->data));
    }

  string = g_checksum_get_string (inner);

  /*
   * Place file name and hex checksum into checksum,
   * include the null terminators so these values
   * cannot be accidentally have a boundary discrepancy.
   */
  g_checksum_update (checksum, (const guchar *)filename,
                     strlen (filename) + 1);
  g_checksum_update (checksum, (const guchar *)string,
                     strlen (string) + 1);
  ret = TRUE;

out:
  g_list_free_full (output, (GDestroyNotify)g_bytes_unref);
  g_checksum_free (inner);
  if (mapped)
    g_mapped_file_unref (mapped);
  g_free (path);
  return ret;
}