123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812 |
- /** @file
- This file is cloned from DMTF libredfish library tag v1.0.0 and maintained
- by EDKII.
- //----------------------------------------------------------------------------
- // Copyright Notice:
- // Copyright 2017 Distributed Management Task Force, Inc. All rights reserved.
- // License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libredfish/LICENSE.md
- //----------------------------------------------------------------------------
- Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
- (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include <redfishPayload.h>
- static redfishPayload *
- getOpResult (
- redfishPayload *payload,
- const char *propName,
- const char *op,
- const char *value,
- EFI_HTTP_STATUS_CODE **StatusCode
- );
- static redfishPayload *
- collectionEvalOp (
- redfishPayload *payload,
- const char *propName,
- const char *op,
- const char *value,
- EFI_HTTP_STATUS_CODE **StatusCode
- );
- static redfishPayload *
- arrayEvalOp (
- redfishPayload *payload,
- const char *propName,
- const char *op,
- const char *value,
- EFI_HTTP_STATUS_CODE **StatusCode
- );
- static redfishPayload *
- createCollection (
- redfishService *service,
- size_t count,
- redfishPayload **payloads
- );
- static json_t *
- json_object_get_by_index (
- json_t *json,
- size_t index
- );
- bool
- isPayloadCollection (
- redfishPayload *payload
- )
- {
- json_t *members;
- json_t *count;
- if (!payload || !json_is_object (payload->json)) {
- return false;
- }
- members = json_object_get (payload->json, "Members");
- count = json_object_get (payload->json, "Members@odata.count");
- return ((members != NULL) && (count != NULL));
- }
- size_t
- getCollectionSize (
- redfishPayload *payload
- )
- {
- json_t *members;
- json_t *count;
- if (!payload || !json_is_object (payload->json)) {
- return 0;
- }
- members = json_object_get (payload->json, "Members");
- count = json_object_get (payload->json, "Members@odata.count");
- if (!members || !count) {
- return 0;
- }
- return (size_t)json_integer_value (count);
- }
- bool
- isPayloadArray (
- redfishPayload *payload
- )
- {
- if (!payload || !json_is_array (payload->json)) {
- return false;
- }
- return true;
- }
- char *
- payloadToString (
- redfishPayload *payload,
- bool prettyPrint
- )
- {
- size_t flags = 0;
- if (!payload) {
- return NULL;
- }
- if (prettyPrint) {
- flags = JSON_INDENT (2);
- }
- return json_dumps (payload->json, flags);
- }
- redfishPayload *
- createRedfishPayload (
- json_t *value,
- redfishService *service
- )
- {
- redfishPayload *payload;
- payload = (redfishPayload *)malloc (sizeof (redfishPayload));
- if (payload != NULL) {
- payload->json = value;
- payload->service = service;
- }
- return payload;
- }
- redfishPayload *
- getPayloadByNodeName (
- redfishPayload *payload,
- const char *nodeName,
- EFI_HTTP_STATUS_CODE **StatusCode
- )
- {
- json_t *value;
- json_t *odataId;
- const char *uri;
- if (!payload || !nodeName || (StatusCode == NULL)) {
- return NULL;
- }
- *StatusCode = NULL;
- value = json_object_get (payload->json, nodeName);
- if (value == NULL) {
- return NULL;
- }
- json_incref (value);
- if (json_object_size (value) == 1) {
- odataId = json_object_get (value, "@odata.id");
- if (odataId != NULL) {
- json_incref (odataId);
- uri = json_string_value (odataId);
- json_decref (value);
- value = getUriFromService (payload->service, uri, StatusCode);
- json_decref (odataId);
- if ((value == NULL) || (*StatusCode == NULL)) {
- return NULL;
- }
- }
- }
- if ((*StatusCode == NULL) || ((**StatusCode >= HTTP_STATUS_200_OK) && (**StatusCode <= HTTP_STATUS_206_PARTIAL_CONTENT))) {
- if (json_is_string (value)) {
- odataId = json_object ();
- json_object_set (odataId, nodeName, value);
- json_decref (value);
- value = odataId;
- }
- }
- return createRedfishPayload (value, payload->service);
- }
- redfishPayload *
- getPayloadByIndex (
- redfishPayload *payload,
- size_t index,
- EFI_HTTP_STATUS_CODE **StatusCode
- )
- {
- json_t *value = NULL;
- json_t *odataId;
- const char *uri;
- BOOLEAN FromServerFlag = FALSE;
- if (!payload || (StatusCode == NULL)) {
- return NULL;
- }
- *StatusCode = NULL;
- if (isPayloadCollection (payload)) {
- redfishPayload *members = getPayloadByNodeName (payload, "Members", StatusCode);
- if (((*StatusCode == NULL) && (members == NULL)) ||
- ((*StatusCode != NULL) && ((**StatusCode < HTTP_STATUS_200_OK) || (**StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT))))
- {
- return members;
- }
- if (*StatusCode != NULL) {
- //
- // The Payload (members) are retrived from server.
- //
- FreePool (*StatusCode);
- *StatusCode = NULL;
- FromServerFlag = TRUE;
- }
- redfishPayload *ret = getPayloadByIndex (members, index, StatusCode);
- if ((*StatusCode == NULL) && (ret != NULL) && FromServerFlag) {
- //
- // In such a case, the Redfish resource is parsed from the input payload (members) directly.
- // Since the members are retrived from server, we still return HTTP_STATUS_200_OK.
- //
- *StatusCode = AllocateZeroPool (sizeof (EFI_HTTP_STATUS_CODE));
- if (*StatusCode == NULL) {
- ret = NULL;
- } else {
- **StatusCode = HTTP_STATUS_200_OK;
- }
- }
- cleanupPayload (members);
- return ret;
- }
- if (json_is_array (payload->json)) {
- //
- // The valid range for index is from 0 to the return value of json_array_size() minus 1
- //
- value = json_array_get (payload->json, index);
- } else if (json_is_object (payload->json)) {
- value = json_object_get_by_index (payload->json, index);
- }
- if (value == NULL) {
- return NULL;
- }
- json_incref (value);
- if (json_object_size (value) == 1) {
- odataId = json_object_get (value, "@odata.id");
- if (odataId != NULL) {
- uri = json_string_value (odataId);
- json_decref (value);
- value = getUriFromService (payload->service, uri, StatusCode);
- if (value == NULL) {
- return NULL;
- }
- }
- }
- return createRedfishPayload (value, payload->service);
- }
- redfishPayload *
- getPayloadForPath (
- redfishPayload *payload,
- redPathNode *redpath,
- EFI_HTTP_STATUS_CODE **StatusCode
- )
- {
- redfishPayload *ret = NULL;
- redfishPayload *tmp;
- if (!payload || !redpath || (StatusCode == NULL)) {
- return NULL;
- }
- *StatusCode = NULL;
- BOOLEAN FromServerFlag = FALSE;
- if (redpath->nodeName) {
- ret = getPayloadByNodeName (payload, redpath->nodeName, StatusCode);
- if (((*StatusCode == NULL) && (ret == NULL)) ||
- ((*StatusCode != NULL) && ((**StatusCode < HTTP_STATUS_200_OK) || (**StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT))))
- {
- //
- // Any error happen, return directly.
- //
- return ret;
- }
- } else if (redpath->isIndex) {
- ASSERT (redpath->index >= 1);
- ret = getPayloadByIndex (payload, redpath->index - 1, StatusCode);
- if (((*StatusCode == NULL) && (ret == NULL)) ||
- ((*StatusCode != NULL) && ((**StatusCode < HTTP_STATUS_200_OK) || (**StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT))))
- {
- //
- // Any error happen, return directly.
- //
- return ret;
- }
- } else if (redpath->op) {
- ret = getOpResult (payload, redpath->propName, redpath->op, redpath->value, StatusCode);
- if (((*StatusCode == NULL) && (ret == NULL)) ||
- ((*StatusCode != NULL) && ((**StatusCode < HTTP_STATUS_200_OK) || (**StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT))))
- {
- //
- // Any error happen, return directly.
- //
- return ret;
- }
- } else {
- return NULL;
- }
- if ((redpath->next == NULL) || (ret == NULL)) {
- return ret;
- } else {
- if (*StatusCode != NULL) {
- FreePool (*StatusCode);
- *StatusCode = NULL;
- FromServerFlag = TRUE;
- }
- tmp = getPayloadForPath (ret, redpath->next, StatusCode);
- if ((*StatusCode == NULL) && (tmp != NULL) && FromServerFlag) {
- //
- // In such a case, the Redfish resource is parsed from the input payload (ret) directly.
- // Since the ret are retrived from server, we still return HTTP_STATUS_200_OK.
- //
- *StatusCode = AllocateZeroPool (sizeof (EFI_HTTP_STATUS_CODE));
- if (*StatusCode == NULL) {
- tmp = NULL;
- } else {
- **StatusCode = HTTP_STATUS_200_OK;
- }
- }
- cleanupPayload (ret);
- return tmp;
- }
- }
- redfishPayload *
- getPayloadForPathString (
- redfishPayload *payload,
- const char *string,
- EFI_HTTP_STATUS_CODE **StatusCode
- )
- {
- redPathNode *redpath;
- redfishPayload *ret;
- if (!string || (StatusCode == NULL)) {
- return NULL;
- }
- *StatusCode = NULL;
- redpath = parseRedPath (string);
- if (redpath == NULL) {
- return NULL;
- }
- ret = getPayloadForPath (payload, redpath, StatusCode);
- cleanupRedPath (redpath);
- return ret;
- }
- redfishPayload *
- patchPayload (
- redfishPayload *target,
- redfishPayload *payload,
- EFI_HTTP_STATUS_CODE **StatusCode
- )
- {
- json_t *json;
- char *content;
- char *uri;
- if (!target || !payload || (StatusCode == NULL)) {
- return NULL;
- }
- *StatusCode = NULL;
- json = json_object_get (target->json, "@odata.id");
- if (json == NULL) {
- return NULL;
- }
- uri = strdup (json_string_value (json));
- content = json_dumps (payload->json, 0);
- json_decref (json);
- json = patchUriFromService (target->service, uri, content, StatusCode);
- free (uri);
- free (content);
- if (json == NULL) {
- return NULL;
- }
- return createRedfishPayload (json, target->service);
- }
- redfishPayload *
- postContentToPayload (
- redfishPayload *target,
- const char *data,
- size_t dataSize,
- const char *contentType,
- EFI_HTTP_STATUS_CODE **StatusCode
- )
- {
- json_t *json;
- char *uri;
- if (!target || !data || (StatusCode == NULL)) {
- return NULL;
- }
- *StatusCode = NULL;
- json = json_object_get (target->json, "@odata.id");
- if (json == NULL) {
- json = json_object_get (target->json, "target");
- if (json == NULL) {
- return NULL;
- }
- }
- uri = strdup (json_string_value (json));
- json = postUriFromService (target->service, uri, data, dataSize, contentType, StatusCode);
- free (uri);
- if (json == NULL) {
- return NULL;
- }
- return createRedfishPayload (json, target->service);
- }
- redfishPayload *
- postPayload (
- redfishPayload *target,
- redfishPayload *payload,
- EFI_HTTP_STATUS_CODE **StatusCode
- )
- {
- char *content;
- redfishPayload *ret;
- if (!target || !payload || (StatusCode == NULL)) {
- return NULL;
- }
- *StatusCode = NULL;
- if (!json_is_object (payload->json)) {
- return NULL;
- }
- content = payloadToString (payload, false);
- ret = postContentToPayload (target, content, strlen (content), NULL, StatusCode);
- free (content);
- return ret;
- }
- void
- cleanupPayload (
- redfishPayload *payload
- )
- {
- if (!payload) {
- return;
- }
- json_decref (payload->json);
- // Don't free payload->service, let the caller handle cleaning up the service
- free (payload);
- }
- static redfishPayload *
- getOpResult (
- redfishPayload *payload,
- const char *propName,
- const char *op,
- const char *value,
- EFI_HTTP_STATUS_CODE **StatusCode
- )
- {
- const char *propStr;
- json_t *stringProp;
- bool ret = false;
- redfishPayload *prop;
- long long intVal, intPropVal;
- json_type jsonType;
- if (isPayloadCollection (payload)) {
- return collectionEvalOp (payload, propName, op, value, StatusCode);
- }
- if (isPayloadArray (payload)) {
- return arrayEvalOp (payload, propName, op, value, StatusCode);
- }
- prop = getPayloadByNodeName (payload, propName, StatusCode);
- if (((*StatusCode == NULL) && (prop == NULL)) ||
- ((*StatusCode != NULL) && ((**StatusCode < HTTP_STATUS_200_OK) || (**StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT))))
- {
- return prop;
- }
- stringProp = prop->json;
- jsonType = prop->json->type;
- switch (jsonType) {
- case JSON_OBJECT:
- stringProp = json_object_get (prop->json, propName);
- case JSON_STRING:
- if (strcmp (op, "=") == 0) {
- propStr = json_string_value (stringProp);
- if (propStr == NULL) {
- cleanupPayload (prop);
- return NULL;
- }
- ret = (strcmp (propStr, value) == 0);
- } else if (strcmp (op, "~") == 0) {
- propStr = json_string_value (stringProp);
- if (propStr == NULL) {
- cleanupPayload (prop);
- return NULL;
- }
- ret = (strcasecmp (propStr, value) == 0);
- }
- break;
- case JSON_TRUE:
- if (strcmp (op, "=") == 0) {
- ret = (strcmp (value, "true") == 0);
- }
- break;
- case JSON_FALSE:
- if (strcmp (op, "=") == 0) {
- ret = (strcmp (value, "false") == 0);
- }
- break;
- case JSON_INTEGER:
- intPropVal = json_integer_value (prop->json);
- intVal = strtoll (value, NULL, 0);
- if (strcmp (op, "=") == 0) {
- ret = (intPropVal == intVal);
- } else if (strcmp (op, "<") == 0) {
- ret = (intPropVal < intVal);
- } else if (strcmp (op, ">") == 0) {
- ret = (intPropVal > intVal);
- } else if (strcmp (op, "<=") == 0) {
- ret = (intPropVal <= intVal);
- } else if (strcmp (op, ">=") == 0) {
- ret = (intPropVal >= intVal);
- }
- break;
- default:
- break;
- }
- cleanupPayload (prop);
- if (ret) {
- return payload;
- } else {
- return NULL;
- }
- }
- static redfishPayload *
- collectionEvalOp (
- redfishPayload *payload,
- const char *propName,
- const char *op,
- const char *value,
- EFI_HTTP_STATUS_CODE **StatusCode
- )
- {
- redfishPayload *ret;
- redfishPayload *tmp;
- redfishPayload *members;
- redfishPayload **valid;
- size_t validMax;
- size_t validCount = 0;
- size_t i;
- validMax = getCollectionSize (payload);
- if (validMax == 0) {
- return NULL;
- }
- valid = (redfishPayload **)calloc (validMax, sizeof (redfishPayload *));
- if (valid == NULL) {
- return NULL;
- }
- /*Technically getPayloadByIndex would do this, but this optimizes things*/
- members = getPayloadByNodeName (payload, "Members", StatusCode);
- if (((*StatusCode == NULL) && (members == NULL)) ||
- ((*StatusCode != NULL) && ((**StatusCode < HTTP_STATUS_200_OK) || (**StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT))))
- {
- return members;
- }
- for (i = 0; i < validMax; i++) {
- if (*StatusCode != NULL) {
- FreePool (*StatusCode);
- *StatusCode = NULL;
- }
- tmp = getPayloadByIndex (members, i, StatusCode);
- if (((*StatusCode == NULL) && (tmp == NULL)) ||
- ((*StatusCode != NULL) && ((**StatusCode < HTTP_STATUS_200_OK) || (**StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT))))
- {
- return tmp;
- }
- if (*StatusCode != NULL) {
- FreePool (*StatusCode);
- *StatusCode = NULL;
- }
- valid[validCount] = getOpResult (tmp, propName, op, value, StatusCode);
- /*
- if ((*StatusCode == NULL && valid[validCount] == NULL) ||
- (*StatusCode != NULL && (**StatusCode < HTTP_STATUS_200_OK || **StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT))) {
- return valid[validCount];
- }
- */
- if (valid[validCount] != NULL) {
- validCount++;
- } else {
- cleanupPayload (tmp);
- }
- }
- cleanupPayload (members);
- if (validCount == 0) {
- free (valid);
- return NULL;
- }
- if (validCount == 1) {
- ret = valid[0];
- free (valid);
- return ret;
- } else {
- ret = createCollection (payload->service, validCount, valid);
- free (valid);
- return ret;
- }
- }
- static redfishPayload *
- arrayEvalOp (
- redfishPayload *payload,
- const char *propName,
- const char *op,
- const char *value,
- EFI_HTTP_STATUS_CODE **StatusCode
- )
- {
- redfishPayload *ret;
- redfishPayload *tmp;
- redfishPayload **valid;
- size_t validMax;
- size_t validCount = 0;
- size_t i;
- validMax = json_array_size (payload->json);
- if (validMax == 0) {
- return NULL;
- }
- valid = (redfishPayload **)calloc (validMax, sizeof (redfishPayload *));
- if (valid == NULL) {
- return NULL;
- }
- for (i = 0; i < validMax; i++) {
- if (*StatusCode != NULL) {
- FreePool (*StatusCode);
- *StatusCode = NULL;
- }
- tmp = getPayloadByIndex (payload, i, StatusCode);
- if (((*StatusCode == NULL) && (tmp == NULL)) ||
- ((*StatusCode != NULL) && ((**StatusCode < HTTP_STATUS_200_OK) || (**StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT))))
- {
- return tmp;
- }
- if (*StatusCode != NULL) {
- FreePool (*StatusCode);
- *StatusCode = NULL;
- }
- valid[validCount] = getOpResult (tmp, propName, op, value, StatusCode);
- /*
- if ((*StatusCode == NULL && valid[validCount] == NULL) ||
- (*StatusCode != NULL && (**StatusCode < HTTP_STATUS_200_OK || **StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT))) {
- return valid[validCount];
- }
- */
- if (valid[validCount] != NULL) {
- validCount++;
- } else {
- cleanupPayload (tmp);
- }
- }
- if (validCount == 0) {
- free (valid);
- return NULL;
- }
- if (validCount == 1) {
- ret = valid[0];
- free (valid);
- return ret;
- } else {
- ret = createCollection (payload->service, validCount, valid);
- free (valid);
- return ret;
- }
- }
- static redfishPayload *
- createCollection (
- redfishService *service,
- size_t count,
- redfishPayload **payloads
- )
- {
- redfishPayload *ret;
- json_t *collectionJson = json_object ();
- json_t *jcount = json_integer ((json_int_t)count);
- json_t *members = json_array ();
- size_t i;
- if (!collectionJson) {
- return NULL;
- }
- if (!members) {
- json_decref (collectionJson);
- return NULL;
- }
- json_object_set (collectionJson, "Members@odata.count", jcount);
- json_decref (jcount);
- for (i = 0; i < count; i++) {
- json_array_append (members, payloads[i]->json);
- cleanupPayload (payloads[i]);
- }
- json_object_set (collectionJson, "Members", members);
- json_decref (members);
- ret = createRedfishPayload (collectionJson, service);
- return ret;
- }
- static json_t *
- json_object_get_by_index (
- json_t *json,
- size_t index
- )
- {
- void *iter;
- size_t i;
- iter = json_object_iter (json);
- for (i = 0; i < index; i++) {
- iter = json_object_iter_next (json, iter);
- if (iter == NULL) {
- break;
- }
- }
- if (iter == NULL) {
- return NULL;
- }
- return json_object_iter_value (iter);
- }
- /* vim: set tabstop=4 shiftwidth=4 expandtab: */
|