<commit_before>/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
 *
 * Copyright (C) 2017-2018 <NAME> <<EMAIL>>
 *
 * SPDX-License-Identifier: LGPL-2.1+
 */

#include "config.h"

#include <json-glib/json-glib.h>
#include <libsoup/soup.h>
#include <string.h>

#include "fwupd-error.h"
#include "fwupd-enums.h"

#include "fu-device.h"

#include "fu-redfish-client.h"
#include "fu-redfish-common.h"

struct _FuRedfishClient
{
	GObject			 parent_instance;
	SoupSession		*session;
	gchar			*hostname;
	guint			 port;
	gchar			*username;
	gchar			*password;
	gchar			*update_uri_path;
	gboolean		 auth_created;
	GPtrArray		*devices;
};

G_DEFINE_TYPE (FuRedfishClient, fu_redfish_client, G_TYPE_OBJECT)

static GBytes *
fu_redfish_client_fetch_data (FuRedfishClient *self, const gchar *uri_path, GError **error)
{
	guint status_code;
	g_autoptr(SoupMessage) msg = NULL;
	g_autoptr(SoupURI) uri = NULL;

	/* create URI */
	uri = soup_uri_new (NULL);
	soup_uri_set_scheme (uri, g_strcmp0 (self->hostname, "localhost") == 0 ?
				  "http" : "https");
	soup_uri_set_path (uri, uri_path);
	soup_uri_set_host (uri, self->hostname);
	soup_uri_set_port (uri, self->port);
	msg = soup_message_new_from_uri (SOUP_METHOD_GET, uri);
	if (msg == NULL) {
		g_autofree gchar *tmp = soup_uri_to_string (uri, FALSE);
		g_set_error (error,
			     FWUPD_ERROR,
			     FWUPD_ERROR_INVALID_FILE,
			     "failed to create message for URI %s", tmp);
		return NULL;
	}
	if ((self->username != NULL && self->password != NULL) &&
	    self->auth_created == FALSE) {
		/*
		 * Some redfish implementations miss WWW-Authenticate
		 * header for a 401 response, and SoupAuthManager couldn't
		 * generate SoupAuth accordingly. Since DSP0266 makes
		 * Basic Authorization a requirement for redfish it shall be
		 * safe to use Basic Auth for all redfish implementations.
		 */
		SoupAuthManager *manager;
		g_autoptr(SoupAuth) auth = NULL;

		manager = SOUP_AUTH_MANAGER (soup_session_get_feature (self->session, SOUP_TYPE_AUTH_MANAGER));
		auth = soup_auth_new (SOUP_TYPE_AUTH_BASIC, msg, "Basic");
		soup_auth_authenticate (auth, self->username, self->password);
		soup_auth_manager_use_auth (manager, uri, auth);
		self->auth_created = TRUE;
	}
	status_code = soup_session_send_message (self->session, msg);
	if (status_code != SOUP_STATUS_OK) {
		g_autofree gchar *tmp = soup_uri_to_string (uri, FALSE);
		g_set_error (error,
			     FWUPD_ERROR,
			     FWUPD_ERROR_INVALID_FILE,
			     "failed to download %s: %s",
			     tmp, soup_status_get_phrase (status_code));
		return NULL;
	}
	return g_bytes_new (msg->response_body->data, msg->response_body->length);
}

static gboolean
fu_redfish_client_coldplug_member (FuRedfishClient *self,
				   JsonObject *member,
				   GError **error)
{
	g_autoptr(FuDevice) dev = fu_device_new ();

	fu_device_set_name (dev, json_object_get_string_member (member, "Name"));
	fu_device_set_summary (dev, "Redfish device");
	fu_device_set_version (dev, json_object_get_string_member (member, "Version"));
	if (json_object_has_member (member, "LowestSupportedVersion"))
		fu_device_set_version_lowest (dev, json_object_get_string_member (member, "LowestSupportedVersion"));
	if (json_object_has_member (member, "Description"))
		fu_device_set_description (dev, json_object_get_string_member (member, "Description"));
	if (json_object_has_member (member, "Updateable")) {
		if (json_object_get_boolean_member (member, "Updateable"))
			fu_device_add_flag (dev, FWUPD_DEVICE_FLAG_UPDATABLE);
	}
	if (json_object_has_member (member, "SoftwareId")) {
		fu_device_add_guid (dev, json_object_get_string_member (member, "SoftwareId"));
	} else if (json_object_has_member (member, "Oem")) {
		JsonObject *oem = json_object_get_object_member (member, "Oem");
		if (json_object_has_member (oem, "Hpe")) {
			JsonObject *hpe = json_object_get_object_member (oem, "Hpe");
			const gchar *dev_class = json_object_get_string_member (hpe, "DeviceClass");
			if (dev_class != NULL)
				fu_device_add_guid (dev, dev_class);
		}<commit_msg>redfish: Generate IDs for redfish devices<commit_after>/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
 *
 * Copyright (C) 2017-2018 <NAME> <<EMAIL>>
 *
 * SPDX-License-Identifier: LGPL-2.1+
 */

#include "config.h"

#include <json-glib/json-glib.h>
#include <libsoup/soup.h>
#include <string.h>

#include "fwupd-error.h"
#include "fwupd-enums.h"

#include "fu-device.h"

#include "fu-redfish-client.h"
#include "fu-redfish-common.h"

struct _FuRedfishClient
{
	GObject			 parent_instance;
	SoupSession		*session;
	gchar			*hostname;
	guint			 port;
	gchar			*username;
	gchar			*password;
	gchar			*update_uri_path;
	gboolean		 auth_created;
	GPtrArray		*devices;
};

G_DEFINE_TYPE (FuRedfishClient, fu_redfish_client, G_TYPE_OBJECT)

static GBytes *
fu_redfish_client_fetch_data (FuRedfishClient *self, const gchar *uri_path, GError **error)
{
	guint status_code;
	g_autoptr(SoupMessage) msg = NULL;
	g_autoptr(SoupURI) uri = NULL;

	/* create URI */
	uri = soup_uri_new (NULL);
	soup_uri_set_scheme (uri, g_strcmp0 (self->hostname, "localhost") == 0 ?
				  "http" : "https");
	soup_uri_set_path (uri, uri_path);
	soup_uri_set_host (uri, self->hostname);
	soup_uri_set_port (uri, self->port);
	msg = soup_message_new_from_uri (SOUP_METHOD_GET, uri);
	if (msg == NULL) {
		g_autofree gchar *tmp = soup_uri_to_string (uri, FALSE);
		g_set_error (error,
			     FWUPD_ERROR,
			     FWUPD_ERROR_INVALID_FILE,
			     "failed to create message for URI %s", tmp);
		return NULL;
	}
	if ((self->username != NULL && self->password != NULL) &&
	    self->auth_created == FALSE) {
		/*
		 * Some redfish implementations miss WWW-Authenticate
		 * header for a 401 response, and SoupAuthManager couldn't
		 * generate SoupAuth accordingly. Since DSP0266 makes
		 * Basic Authorization a requirement for redfish it shall be
		 * safe to use Basic Auth for all redfish implementations.
		 */
		SoupAuthManager *manager;
		g_autoptr(SoupAuth) auth = NULL;

		manager = SOUP_AUTH_MANAGER (soup_session_get_feature (self->session, SOUP_TYPE_AUTH_MANAGER));
		auth = soup_auth_new (SOUP_TYPE_AUTH_BASIC, msg, "Basic");
		soup_auth_authenticate (auth, self->username, self->password);
		soup_auth_manager_use_auth (manager, uri, auth);
		self->auth_created = TRUE;
	}
	status_code = soup_session_send_message (self->session, msg);
	if (status_code != SOUP_STATUS_OK) {
		g_autofree gchar *tmp = soup_uri_to_string (uri, FALSE);
		g_set_error (error,
			     FWUPD_ERROR,
			     FWUPD_ERROR_INVALID_FILE,
			     "failed to download %s: %s",
			     tmp, soup_status_get_phrase (status_code));
		return NULL;
	}
	return g_bytes_new (msg->response_body->data, msg->response_body->length);
}

static gboolean
fu_redfish_client_coldplug_member (FuRedfishClient *self,
				   JsonObject *member,
				   GError **error)
{
	g_autoptr(FuDevice) dev = NULL;
	const gchar *guid = NULL;
	g_autofree gchar *id = NULL;

	if (json_object_has_member (member, "SoftwareId")) {
		guid = json_object_get_string_member (member, "SoftwareId");
	} else if (json_object_has_member (member, "Oem")) {
		JsonObject *oem = json_object_get_object_member (member, "Oem");
		if (json_object_has_member (oem, "Hpe")) {
			JsonObject *hpe = json_object_get_object_member (oem, "Hpe");
			if (json_object_has_member (hpe, "DeviceClass"))
				guid = json_object_get_string_member (hpe, "DeviceClass");
		}
	}

	/* skip the devices without guid */
	if (guid == NULL)
		return TRUE;

	dev = fu_device_new ();

	id = g_strdup_printf ("Redfish-Inventory-%s",
			      json_object_get_string_member (member, "Id"));
	fu_device_set_id (dev, id);

	fu_device_add_guid (dev, guid);
	fu_device_set_name (dev, json_object_get_string_member (member, "Name"));
	fu_device_set_summary (dev, "Redfish device");
	fu_device_set_version (dev, json_object_get_string_member (member, "Version"));
	if (json_object_has_member (member, "LowestSupportedVersion"))
		fu_device_set_version_lowest (dev, json_object_get_string_member (member, "LowestSupportedVersion"));
	if (json_object_has_member (member, "Description"))
		fu_device_set_description (dev, json_object_get_string_member (member, "Description"));
	if (json_object_has_member (member, "Updateable")) {
		if (json_object_get_boolean_member (member, "Updateable"))
			fu_device_add_flag (dev, FWUPD_DEVICE_FLAG_UPDATABLE);
{'fraction_non_alphanumeric': 0.12019058963668851, 'fraction_numerical': 0.005002977963073258, 'mean_word_length': 4.997142857142857, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5090323', 'n_tokens_mistral': 3323, 'n_tokens_neox': 3070, 'n_words': 672}