1
0
mirror of https://github.com/SoftEtherVPN/SoftEtherVPN.git synced 2025-04-03 18:00:08 +03:00
SoftEtherVPN/src/Mayaqua/Pack.c
Davide Beatrici 233e28f38c Refactor Base64 functions, encode/decode using OpenSSL's EVP interface
Our own implementation works fine, however we should use OpenSSL's one since we already link to the library.

Base64Decode() and Base64Encode() return the required buffer size when "dst" is NULL.

This allows to efficiently allocate a buffer, without wasting memory or risking an overflow.

Base64FromBin() and Base64ToBin() perform all steps, returning a heap-allocated buffer with the data in it.
2021-07-02 09:24:41 +02:00

2467 lines
45 KiB
C

// SoftEther VPN Source Code - Developer Edition Master Branch
// Mayaqua Kernel
// Pack.c
// Data package code
#include "Pack.h"
#include "Encrypt.h"
#include "Internat.h"
#include "Mayaqua.h"
#include "Memory.h"
#include "Network.h"
#include "Str.h"
// Get a list of the element names in the PACK
TOKEN_LIST *GetPackElementNames(PACK *p)
{
TOKEN_LIST *ret;
UINT i;
// Validate arguments
if (p == NULL)
{
return NULL;
}
ret = ZeroMalloc(sizeof(TOKEN_LIST));
ret->NumTokens = LIST_NUM(p->elements);
ret->Token = ZeroMalloc(sizeof(char *) * ret->NumTokens);
for (i = 0;i < ret->NumTokens;i++)
{
ELEMENT *e = LIST_DATA(p->elements, i);
ret->Token[i] = CopyStr(e->name);
}
return ret;
}
// Convert the BUF to a PACK
PACK *BufToPack(BUF *b)
{
PACK *p;
// Validate arguments
if (b == NULL)
{
return NULL;
}
p = NewPack();
if (ReadPack(b, p) == false)
{
FreePack(p);
return NULL;
}
return p;
}
// Convert the PACK to the BUF
BUF *PackToBuf(PACK *p)
{
BUF *b;
// Validate arguments
if (p == NULL)
{
return NULL;
}
b = NewBuf();
WritePack(b, p);
return b;
}
// Read the PACK
bool ReadPack(BUF *b, PACK *p)
{
UINT i, num;
// Validate arguments
if (b == NULL || p == NULL)
{
return false;
}
// The number of ELEMENTs
num = ReadBufInt(b);
if (num > MAX_ELEMENT_NUM)
{
// Number exceeds
return false;
}
// Read the ELEMENT
for (i = 0;i < num;i++)
{
ELEMENT *e;
e = ReadElement(b);
if (AddElement(p, e) == false)
{
// Adding error
return false;
}
}
return true;
}
// Write down the PACK
void WritePack(BUF *b, PACK *p)
{
UINT i;
// Validate arguments
if (b == NULL || p == NULL)
{
return;
}
// The number of ELEMENTs
WriteBufInt(b, LIST_NUM(p->elements));
// Write the ELEMENT
for (i = 0;i < LIST_NUM(p->elements);i++)
{
ELEMENT *e = LIST_DATA(p->elements, i);
WriteElement(b, e);
}
}
// Read the ELEMENT
ELEMENT *ReadElement(BUF *b)
{
UINT i;
char name[MAX_ELEMENT_NAME_LEN + 1];
UINT type, num_value;
VALUE **values;
ELEMENT *e;
// Validate arguments
if (b == NULL)
{
return NULL;
}
// Name
if (ReadBufStr(b, name, sizeof(name)) == false)
{
return NULL;
}
// Type of item
type = ReadBufInt(b);
// Number of items
num_value = ReadBufInt(b);
if (num_value > MAX_VALUE_NUM)
{
// Number exceeds
return NULL;
}
// VALUE
values = (VALUE **)Malloc(sizeof(VALUE *) * num_value);
for (i = 0;i < num_value;i++)
{
values[i] = ReadValue(b, type);
}
// Create a ELEMENT
e = NewElement(name, type, num_value, values);
Free(values);
return e;
}
// Write the ELEMENT
void WriteElement(BUF *b, ELEMENT *e)
{
UINT i;
// Validate arguments
if (b == NULL || e == NULL)
{
return;
}
// Name
WriteBufStr(b, e->name);
// Type of item
WriteBufInt(b, e->type);
// Number of items
WriteBufInt(b, e->num_value);
// VALUE
for (i = 0;i < e->num_value;i++)
{
VALUE *v = e->values[i];
WriteValue(b, v, e->type);
}
}
// Read the VALUE
VALUE *ReadValue(BUF *b, UINT type)
{
UINT len;
BYTE *u;
void *data;
char *str;
wchar_t *unistr;
UINT unistr_size;
UINT size;
UINT u_size;
VALUE *v = NULL;
// Validate arguments
if (b == NULL)
{
return NULL;
}
// Data item
switch (type)
{
case VALUE_INT: // Integer
v = NewIntValue(ReadBufInt(b));
break;
case VALUE_INT64:
v = NewInt64Value(ReadBufInt64(b));
break;
case VALUE_DATA: // Data
size = ReadBufInt(b);
if (size > MAX_VALUE_SIZE)
{
// Size over
break;
}
data = Malloc(size);
if (ReadBuf(b, data, size) != size)
{
// Read failure
Free(data);
break;
}
v = NewDataValue(data, size);
Free(data);
break;
case VALUE_STR: // ANSI string
len = ReadBufInt(b);
if (len > (MAX_VALUE_SIZE - 1))
{
// Size over
break;
}
str = Malloc(len + 1);
// String body
if (ReadBuf(b, str, len) != len)
{
// Read failure
Free(str);
break;
}
str[len] = 0;
v = NewStrValue(str);
Free(str);
break;
case VALUE_UNISTR: // Unicode string
u_size = ReadBufInt(b);
if (u_size > MAX_VALUE_SIZE)
{
// Size over
break;
}
// Reading an UTF-8 string
u = ZeroMalloc(u_size + 1);
if (ReadBuf(b, u, u_size) != u_size)
{
// Read failure
Free(u);
break;
}
// Convert to a Unicode string
unistr_size = CalcUtf8ToUni(u, u_size);
if (unistr_size == 0)
{
Free(u);
break;
}
unistr = Malloc(unistr_size);
Utf8ToUni(unistr, unistr_size, u, u_size);
Free(u);
v = NewUniStrValue(unistr);
Free(unistr);
break;
}
return v;
}
// Write the VALUE
void WriteValue(BUF *b, VALUE *v, UINT type)
{
UINT len;
BYTE *u;
UINT u_size;
// Validate arguments
if (b == NULL || v == NULL)
{
return;
}
// Data item
switch (type)
{
case VALUE_INT: // Integer
WriteBufInt(b, v->IntValue);
break;
case VALUE_INT64: // 64 bit integer
WriteBufInt64(b, v->Int64Value);
break;
case VALUE_DATA: // Data
// Size
WriteBufInt(b, v->Size);
// Body
WriteBuf(b, v->Data, v->Size);
break;
case VALUE_STR: // ANSI string
len = StrLen(v->Str);
// Length
WriteBufInt(b, len);
// String body
WriteBuf(b, v->Str, len);
break;
case VALUE_UNISTR: // Unicode string
// Convert to UTF-8
u_size = CalcUniToUtf8(v->UniStr) + 1;
u = ZeroMalloc(u_size);
UniToUtf8(u, u_size, v->UniStr);
// Size
WriteBufInt(b, u_size);
// UTF-8 string body
WriteBuf(b, u, u_size);
Free(u);
break;
}
}
// Get data size
UINT GetDataValueSize(ELEMENT *e, UINT index)
{
// Validate arguments
if (e == NULL)
{
return 0;
}
if (e->values == NULL)
{
return 0;
}
if (index >= e->num_value)
{
return 0;
}
if (e->values[index] == NULL)
{
return 0;
}
return e->values[index]->Size;
}
// Get the data
void *GetDataValue(ELEMENT *e, UINT index)
{
// Validate arguments
if (e == NULL)
{
return NULL;
}
if (e->values == NULL)
{
return NULL;
}
if (index >= e->num_value)
{
return NULL;
}
if (e->values[index] == NULL)
{
return NULL;
}
return e->values[index]->Data;
}
// Get the Unicode string type
wchar_t *GetUniStrValue(ELEMENT *e, UINT index)
{
// Validate arguments
if (e == NULL)
{
return 0;
}
if (index >= e->num_value)
{
return 0;
}
if (e->values[index] == NULL)
{
return NULL;
}
return e->values[index]->UniStr;
}
// Get the ANSI string type
char *GetStrValue(ELEMENT *e, UINT index)
{
// Validate arguments
if (e == NULL)
{
return 0;
}
if (index >= e->num_value)
{
return 0;
}
if (e->values[index] == NULL)
{
return NULL;
}
return e->values[index]->Str;
}
// Get the 64 bit integer value
UINT64 GetInt64Value(ELEMENT *e, UINT index)
{
// Validate arguments
if (e == NULL)
{
return 0;
}
if (index >= e->num_value)
{
return 0;
}
if (e->values[index] == NULL)
{
return 0;
}
return e->values[index]->Int64Value;
}
// Get the integer value
UINT GetIntValue(ELEMENT *e, UINT index)
{
// Validate arguments
if (e == NULL)
{
return 0;
}
if (index >= e->num_value)
{
return 0;
}
if (e->values[index] == NULL)
{
return 0;
}
return e->values[index]->IntValue;
}
// Function of sort for PACK
int ComparePackName(void *p1, void *p2)
{
ELEMENT *o1, *o2;
if (p1 == NULL || p2 == NULL)
{
return 0;
}
o1 = *(ELEMENT **)p1;
o2 = *(ELEMENT **)p2;
if (o1 == NULL || o2 == NULL)
{
return 0;
}
return StrCmpi(o1->name, o2->name);
}
// Delete the VALUE
void FreeValue(VALUE *v, UINT type)
{
// Validate arguments
if (v == NULL)
{
return;
}
switch (type)
{
case VALUE_INT:
case VALUE_INT64:
break;
case VALUE_DATA:
Free(v->Data);
break;
case VALUE_STR:
Free(v->Str);
break;
case VALUE_UNISTR:
Free(v->UniStr);
break;
}
// Memory release
Free(v);
}
// Create a VALUE of Unicode String type
VALUE *NewUniStrValue(wchar_t *str)
{
VALUE *v;
// Validate arguments
if (str == NULL)
{
return NULL;
}
// Memory allocation
v = Malloc(sizeof(VALUE));
// String copy
v->Size = UniStrSize(str);
v->UniStr = Malloc(v->Size);
UniStrCpy(v->UniStr, v->Size, str);
UniTrim(v->UniStr);
return v;
}
// Creation of the VALUE of ANSI string type
VALUE *NewStrValue(char *str)
{
VALUE *v;
// Validate arguments
if (str == NULL)
{
return NULL;
}
// Memory allocation
v = Malloc(sizeof(VALUE));
// String copy
v->Size = StrLen(str) + 1;
v->Str = Malloc(v->Size);
StrCpy(v->Str, v->Size, str);
Trim(v->Str);
return v;
}
// Create the VALUE of the data type
VALUE *NewDataValue(void *data, UINT size)
{
VALUE *v;
// Validate arguments
if (data == NULL)
{
return NULL;
}
// Memory allocation
v = Malloc(sizeof(VALUE));
// Data copy
v->Size = size;
v->Data = Malloc(v->Size);
Copy(v->Data, data, size);
return v;
}
// Create the VALUE of 64 bit integer type
VALUE *NewInt64Value(UINT64 i)
{
VALUE *v;
v = Malloc(sizeof(VALUE));
v->Int64Value = i;
v->Size = sizeof(UINT64);
return v;
}
// Create the VALUE of integer type
VALUE *NewIntValue(UINT i)
{
VALUE *v;
// Memory allocation
v = Malloc(sizeof(VALUE));
v->IntValue = i;
v->Size = sizeof(UINT);
return v;
}
// Delete the ELEMENT
void FreeElement(ELEMENT *e)
{
UINT i;
// Validate arguments
if (e == NULL)
{
return;
}
for (i = 0;i < e->num_value;i++)
{
FreeValue(e->values[i], e->type);
}
Free(e->values);
Free(e);
}
// Create a ELEMENT
ELEMENT *NewElement(char *name, UINT type, UINT num_value, VALUE **values)
{
ELEMENT *e;
UINT i;
// Validate arguments
if (name == NULL || num_value == 0 || values == NULL)
{
return NULL;
}
// Memory allocation
e = ZeroMalloc(sizeof(ELEMENT));
StrCpy(e->name, sizeof(e->name), name);
e->num_value = num_value;
e->type = type;
// Copy of the pointer list to the element
e->values = (VALUE **)ZeroMalloc(sizeof(VALUE *) * num_value);
for (i = 0;i < e->num_value;i++)
{
e->values[i] = values[i];
}
return e;
}
// Search and retrieve a ELEMENT from the PACK
ELEMENT *GetElement(PACK *p, char *name, UINT type)
{
ELEMENT t;
ELEMENT *e;
// Validate arguments
if (p == NULL || name == NULL)
{
return NULL;
}
// Search
StrCpy(t.name, sizeof(t.name), name);
e = Search(p->elements, &t);
if (e == NULL)
{
return NULL;
}
// Type checking
if (type != INFINITE)
{
if (e->type != type)
{
return NULL;
}
}
return e;
}
// Check whether the specified element exists
bool IsElement(PACK *p, char *name)
{
ELEMENT t;
ELEMENT *e;
// Validate arguments
if (p == NULL || name == NULL)
{
return false;
}
// Search
StrCpy(t.name, sizeof(t.name), name);
e = Search(p->elements, &t);
if (e == NULL)
{
return false;
}
return true;
}
// Remove the ELEMENT from the PACK
void DelElement(PACK *p, char *name)
{
ELEMENT *e;
// Validate arguments
if (p == NULL || name == NULL)
{
return;
}
e = GetElement(p, name, INFINITE);
if (e != NULL)
{
Delete(p->elements, e);
FreeElement(e);
}
}
// Add an ELEMENT to the PACK
bool AddElement(PACK *p, ELEMENT *e)
{
// Validate arguments
if (p == NULL || e == NULL)
{
return false;
}
// Size Check
if (LIST_NUM(p->elements) >= MAX_ELEMENT_NUM)
{
// Can not add any more
FreeElement(e);
return false;
}
// Check whether there is another item which have same name
if (GetElement(p, e->name, INFINITE))
{
// Exists
FreeElement(e);
return false;
}
if (e->num_value == 0)
{
// VALUE without any items can not be added
FreeElement(e);
return false;
}
// Set JsonHint_GroupName
StrCpy(e->JsonHint_GroupName, sizeof(e->JsonHint_GroupName), p->CurrentJsonHint_GroupName);
// Adding
Add(p->elements, e);
return true;
}
// Release of the PACK object
void FreePack(PACK *p)
{
UINT i;
ELEMENT **elements;
// Validate arguments
if (p == NULL)
{
return;
}
elements = ToArray(p->elements);
for (i = 0;i < LIST_NUM(p->elements);i++)
{
FreeElement(elements[i]);
}
Free(elements);
if (p->json_subitem_names != NULL)
{
FreeStrList(p->json_subitem_names);
}
ReleaseList(p->elements);
Free(p);
}
// Create a PACK object
PACK *NewPack()
{
PACK *p;
// Memory allocation
p = ZeroMallocEx(sizeof(PACK), true);
// Creating a List
p->elements = NewListFast(ComparePackName);
return p;
}
// Get the K from the PACK
K *PackGetK(PACK *p, char *name)
{
K *k;
BUF *b;
// Validate arguments
if (p == NULL || name == NULL)
{
return NULL;
}
b = PackGetBuf(p, name);
if (b == NULL)
{
return NULL;
}
k = BufToK(b, true, false, NULL);
if (k == NULL)
{
k = BufToK(b, true, true, NULL);
}
FreeBuf(b);
return k;
}
// Get the X from the PACK
X *PackGetX(PACK *p, char *name)
{
X *x;
BUF *b;
// Validate arguments
if (p == NULL || name == NULL)
{
return NULL;
}
b = PackGetBuf(p, name);
if (b == NULL)
{
return NULL;
}
x = BufToX(b, false);
if (x == NULL)
{
x = BufToX(b, true);
}
FreeBuf(b);
return x;
}
// Add the K to the PACK
ELEMENT *PackAddK(PACK *p, char *name, K *k)
{
BUF *b;
ELEMENT *e = NULL;
// Validate arguments
if (p == NULL || name == NULL || k == NULL)
{
return NULL;
}
b = KToBuf(k, false, NULL);
if (b == NULL)
{
return NULL;
}
e = PackAddBuf(p, name, b);
FreeBuf(b);
return e;
}
// Add an X into the PACK
ELEMENT *PackAddX(PACK *p, char *name, X *x)
{
BUF *b;
ELEMENT *e = NULL;
// Validate arguments
if (p == NULL || name == NULL || x == NULL)
{
return NULL;
}
b = XToBuf(x, false);
if (b == NULL)
{
return NULL;
}
e = PackAddBuf(p, name, b);
FreeBuf(b);
return e;
}
// Get a buffer from the PACK
BUF *PackGetBuf(PACK *p, char *name)
{
return PackGetBufEx(p, name, 0);
}
BUF *PackGetBufEx(PACK *p, char *name, UINT index)
{
UINT size;
void *tmp;
BUF *b;
// Validate arguments
if (p == NULL || name == NULL)
{
return NULL;
}
size = PackGetDataSizeEx(p, name, index);
tmp = MallocEx(size, true);
if (PackGetDataEx(p, name, tmp, index) == false)
{
Free(tmp);
return NULL;
}
b = NewBuf();
WriteBuf(b, tmp, size);
SeekBuf(b, 0, 0);
Free(tmp);
return b;
}
// Get the data from the PACK
bool PackGetData(PACK *p, char *name, void *data)
{
return PackGetDataEx(p, name, data, 0);
}
bool PackGetDataEx(PACK *p, char *name, void *data, UINT index)
{
ELEMENT *e;
// Validate arguments
if (p == NULL || name == NULL)
{
return false;
}
e = GetElement(p, name, VALUE_DATA);
if (e == NULL)
{
return false;
}
Copy(data, GetDataValue(e, index), GetDataValueSize(e, index));
return true;
}
bool PackGetData2(PACK *p, char *name, void *data, UINT size)
{
return PackGetDataEx2(p, name, data, size, 0);
}
bool PackGetDataEx2(PACK *p, char *name, void *data, UINT size, UINT index)
{
ELEMENT *e;
// Validate arguments
if (p == NULL || name == NULL)
{
return false;
}
e = GetElement(p, name, VALUE_DATA);
if (e == NULL)
{
return false;
}
if (GetDataValueSize(e, index) != size)
{
return false;
}
Copy(data, GetDataValue(e, index), GetDataValueSize(e, index));
return true;
}
// Get the data size from the PACK
UINT PackGetDataSize(PACK *p, char *name)
{
return PackGetDataSizeEx(p, name, 0);
}
UINT PackGetDataSizeEx(PACK *p, char *name, UINT index)
{
ELEMENT *e;
// Validate arguments
if (p == NULL || name == NULL)
{
return 0;
}
e = GetElement(p, name, VALUE_DATA);
if (e == NULL)
{
return 0;
}
return GetDataValueSize(e, index);
}
// Get an integer from the PACK
UINT64 PackGetInt64(PACK *p, char *name)
{
return PackGetInt64Ex(p, name, 0);
}
UINT64 PackGetInt64Ex(PACK *p, char *name, UINT index)
{
ELEMENT *e;
// Validate arguments
if (p == NULL || name == NULL)
{
return 0;
}
e = GetElement(p, name, VALUE_INT64);
if (e == NULL)
{
return 0;
}
return GetInt64Value(e, index);
}
// Get the index number from the PACK
UINT PackGetIndexCount(PACK *p, char *name)
{
ELEMENT *e;
// Validate arguments
if (p == NULL || name == NULL)
{
return 0;
}
e = GetElement(p, name, INFINITE);
if (e == NULL)
{
return 0;
}
return e->num_value;
}
// Get the number from the PACK
UINT PackGetNum(PACK *p, char *name)
{
return MIN(PackGetInt(p, name), 65536);
}
// Get a bool type from the PACK
bool PackGetBool(PACK *p, char *name)
{
return PackGetInt(p, name) == 0 ? false : true;
}
bool PackGetBoolEx(PACK *p, char *name, UINT index)
{
return PackGetIntEx(p, name, index) == 0 ? false : true;
}
// Set CurrentJsonHint_GroupName to PACK
void PackSetCurrentJsonGroupName(PACK *p, char *json_group_name)
{
if (p == NULL)
{
return;
}
if (json_group_name == NULL)
{
ClearStr(p->CurrentJsonHint_GroupName, sizeof(p->CurrentJsonHint_GroupName));
}
else
{
StrCpy(p->CurrentJsonHint_GroupName, sizeof(p->CurrentJsonHint_GroupName), json_group_name);
if (p->json_subitem_names == NULL)
{
p->json_subitem_names = NewStrList();
}
AddStrToStrListDistinct(p->json_subitem_names, json_group_name);
}
}
// Add a bool type into the PACK
ELEMENT *PackAddBool(PACK *p, char *name, bool b)
{
ELEMENT *e = PackAddInt(p, name, b ? 1 : 0);
if (e != NULL)
{
e->JsonHint_IsBool = true;
}
return e;
}
ELEMENT *PackAddBoolEx(PACK *p, char *name, bool b, UINT index, UINT total)
{
ELEMENT *e = PackAddIntEx(p, name, b ? 1 : 0, index, total);
if (e != NULL)
{
e->JsonHint_IsBool = true;
}
return e;
}
// Add the IPV6_ADDR to the PACK
ELEMENT *PackAddIp6AddrEx(PACK *p, char *name, IPV6_ADDR *addr, UINT index, UINT total)
{
// Validate arguments
if (p == NULL || name == NULL || addr == NULL)
{
return NULL;
}
return PackAddDataEx(p, name, addr, sizeof(IPV6_ADDR), index, total);
}
ELEMENT *PackAddIp6Addr(PACK *p, char *name, IPV6_ADDR *addr)
{
return PackAddIp6AddrEx(p, name, addr, 0, 1);
}
// Get an IPV6_ADDR from the PACK
bool PackGetIp6AddrEx(PACK *p, char *name, IPV6_ADDR *addr, UINT index)
{
// Validate arguments
if (p == NULL || name == NULL || addr == NULL)
{
Zero(addr, sizeof(IPV6_ADDR));
return false;
}
return PackGetDataEx2(p, name, addr, sizeof(IPV6_ADDR), index);
}
bool PackGetIp6Addr(PACK *p, char *name, IPV6_ADDR *addr)
{
return PackGetIp6AddrEx(p, name, addr, 0);
}
// Add the IP to the PACK
void PackAddIp32Ex(PACK *p, char *name, UINT ip32, UINT index, UINT total)
{
PackAddIp32Ex2(p, name, ip32, index, total, false);
}
void PackAddIp32Ex2(PACK *p, char *name, UINT ip32, UINT index, UINT total, bool is_single)
{
IP ip;
// Validate arguments
if (p == NULL || name == NULL)
{
return;
}
UINTToIP(&ip, ip32);
PackAddIpEx2(p, name, &ip, index, total, is_single);
}
void PackAddIp32(PACK *p, char *name, UINT ip32)
{
PackAddIp32Ex2(p, name, ip32, 0, 1, true);
}
void PackAddIpEx(PACK *p, char *name, IP *ip, UINT index, UINT total)
{
PackAddIpEx2(p, name, ip, index, total, false);
}
void PackAddIpEx2(PACK *p, char *name, IP *ip, UINT index, UINT total, bool is_single)
{
UINT i;
char tmp[MAX_PATH];
ELEMENT *e;
// Validate arguments
if (p == NULL || name == NULL || ip == NULL)
{
return;
}
if (total >= 2)
{
is_single = false;
}
Format(tmp, sizeof(tmp), "%s@ipv6_bool", name);
e = PackAddBoolEx(p, tmp, IsIP6(ip), index, total);
if (e != NULL && is_single) e->JsonHint_IsArray = false;
if (e != NULL) e->JsonHint_IsIP = true;
Format(tmp, sizeof(tmp), "%s@ipv6_array", name);
e = PackAddDataEx(p, tmp, ip->address, sizeof(ip->address), index, total);
if (e != NULL && is_single) e->JsonHint_IsArray = false;
if (e != NULL) e->JsonHint_IsIP = true;
Format(tmp, sizeof(tmp), "%s@ipv6_scope_id", name);
e = PackAddIntEx(p, tmp, ip->ipv6_scope_id, index, total);
if (e != NULL && is_single) e->JsonHint_IsArray = false;
if (e != NULL) e->JsonHint_IsIP = true;
i = IPToUINT(ip);
if (IsBigEndian())
{
i = Swap32(i);
}
e = PackAddIntEx(p, name, i, index, total);
if (e != NULL && is_single) e->JsonHint_IsArray = false;
if (e != NULL) e->JsonHint_IsIP = true;
}
void PackAddIp(PACK *p, char *name, IP *ip)
{
PackAddIpEx2(p, name, ip, 0, 1, true);
}
// Get an IP from the PACK
UINT PackGetIp32Ex(PACK *p, char *name, UINT index)
{
IP ip;
// Validate arguments
if (p == NULL || name == NULL)
{
return 0;
}
if (PackGetIpEx(p, name, &ip, index) == false)
{
return 0;
}
return IPToUINT(&ip);
}
UINT PackGetIp32(PACK *p, char *name)
{
return PackGetIp32Ex(p, name, 0);
}
bool PackGetIpEx(PACK *p, char *name, IP *ip, UINT index)
{
UINT i;
char tmp[MAX_PATH];
// Validate arguments
if (p == NULL || ip == NULL || name == NULL)
{
return false;
}
Format(tmp, sizeof(tmp), "%s@ipv6_bool", name);
if (PackGetBoolEx(p, tmp, index))
{
UCHAR data[16];
UINT scope_id;
Zero(data, sizeof(data));
Format(tmp, sizeof(tmp), "%s@ipv6_array", name);
PackGetDataEx2(p, tmp, data, sizeof(data), index);
Format(tmp, sizeof(tmp), "%s@ipv6_scope_id", name);
scope_id = PackGetIntEx(p, tmp, index);
SetIP6(ip, data);
ip->ipv6_scope_id = scope_id;
}
else
{
if (GetElement(p, name, VALUE_INT) == NULL)
{
Zero(ip, sizeof(IP));
return false;
}
i = PackGetIntEx(p, name, index);
if (IsBigEndian())
{
i = Swap32(i);
}
UINTToIP(ip, i);
}
return true;
}
bool PackGetIp(PACK *p, char *name, IP *ip)
{
return PackGetIpEx(p, name, ip, 0);
}
// Check whether the specified value is existing on the Pack
bool PackIsValueExists(PACK *p, char *name)
{
// Validate arguments
if (p == NULL || name == NULL)
{
return false;
}
return IsElement(p, name);
}
// Get an integer from the PACK
UINT PackGetInt(PACK *p, char *name)
{
return PackGetIntEx(p, name, 0);
}
UINT PackGetIntEx(PACK *p, char *name, UINT index)
{
ELEMENT *e;
// Validate arguments
if (p == NULL || name == NULL)
{
return 0;
}
e = GetElement(p, name, VALUE_INT);
if (e == NULL)
{
return 0;
}
return GetIntValue(e, index);
}
// Get an Unicode string from the PACK
bool PackGetUniStr(PACK *p, char *name, wchar_t *unistr, UINT size)
{
return PackGetUniStrEx(p, name, unistr, size, 0);
}
bool PackGetUniStrEx(PACK *p, char *name, wchar_t *unistr, UINT size, UINT index)
{
ELEMENT *e;
// Validate arguments
if (p == NULL || name == NULL || unistr == NULL || size == 0)
{
return false;
}
unistr[0] = 0;
e = GetElement(p, name, VALUE_UNISTR);
if (e == NULL)
{
return false;
}
UniStrCpy(unistr, size, GetUniStrValue(e, index));
return true;
}
// Compare strings in the PACK
bool PackCmpStr(PACK *p, char *name, char *str)
{
char tmp[MAX_SIZE];
if (PackGetStr(p, name, tmp, sizeof(tmp)) == false)
{
return false;
}
if (StrCmpi(tmp, str) == 0)
{
return true;
}
return false;
}
// Get a string from the PACK
bool PackGetStr(PACK *p, char *name, char *str, UINT size)
{
return PackGetStrEx(p, name, str, size, 0);
}
bool PackGetStrEx(PACK *p, char *name, char *str, UINT size, UINT index)
{
ELEMENT *e;
// Validate arguments
if (p == NULL || name == NULL || str == NULL || size == 0)
{
return false;
}
str[0] = 0;
e = GetElement(p, name, VALUE_STR);
if (e == NULL)
{
return false;
}
StrCpy(str, size, GetStrValue(e, index));
return true;
}
// Get the string size from the PACK
UINT PackGetStrSize(PACK *p, char *name)
{
return PackGetStrSizeEx(p, name, 0);
}
UINT PackGetStrSizeEx(PACK *p, char *name, UINT index)
{
ELEMENT *e;
// Validate arguments
if (p == NULL || name == NULL)
{
return 0;
}
e = GetElement(p, name, VALUE_STR);
if (e == NULL)
{
return 0;
}
return GetDataValueSize(e, index);
}
// Add the buffer to the PACK (array)
ELEMENT *PackAddBufEx(PACK *p, char *name, BUF *b, UINT index, UINT total)
{
// Validate arguments
if (p == NULL || name == NULL || b == NULL || total == 0)
{
return NULL;
}
return PackAddDataEx(p, name, b->Buf, b->Size, index, total);
}
// Add the data to the PACK (array)
ELEMENT *PackAddDataEx(PACK *p, char *name, void *data, UINT size, UINT index, UINT total)
{
VALUE *v;
ELEMENT *e;
// Validate arguments
if (p == NULL || data == NULL || name == NULL || total == 0)
{
return NULL;
}
v = NewDataValue(data, size);
e = GetElement(p, name, VALUE_DATA);
if (e != NULL)
{
if (e->num_value >= total)
{
FreeValue(e->values[index], VALUE_DATA);
e->values[index] = v;
}
else
{
FreeValue(v, VALUE_DATA);
}
}
else
{
e = ZeroMallocEx(sizeof(ELEMENT), true);
StrCpy(e->name, sizeof(e->name), name);
e->num_value = total;
e->type = VALUE_DATA;
e->values = ZeroMallocEx(sizeof(VALUE *) * total, true);
e->values[index] = v;
if (AddElement(p, e) == false)
{
return NULL;
}
}
e->JsonHint_IsArray = true;
return e;
}
// Add the buffer to the PACK
ELEMENT *PackAddBuf(PACK *p, char *name, BUF *b)
{
// Validate arguments
if (p == NULL || name == NULL || b == NULL)
{
return NULL;
}
return PackAddData(p, name, b->Buf, b->Size);
}
// Add the data to the PACK
ELEMENT *PackAddData(PACK *p, char *name, void *data, UINT size)
{
VALUE *v;
ELEMENT *e;
// Validate arguments
if (p == NULL || data == NULL || name == NULL)
{
return NULL;
}
v = NewDataValue(data, size);
e = NewElement(name, VALUE_DATA, 1, &v);
if (AddElement(p, e) == false)
{
return NULL;
}
return e;
}
// Add a 64 bit integer (array) to the PACK
ELEMENT *PackAddInt64Ex(PACK *p, char *name, UINT64 i, UINT index, UINT total)
{
VALUE *v;
ELEMENT *e;
// Validate arguments
if (p == NULL || name == NULL || total == 0)
{
return NULL;
}
v = NewInt64Value(i);
e = GetElement(p, name, VALUE_INT64);
if (e != NULL)
{
if (e->num_value >= total)
{
FreeValue(e->values[index], VALUE_INT64);
e->values[index] = v;
}
else
{
FreeValue(v, VALUE_INT64);
}
}
else
{
e = ZeroMallocEx(sizeof(ELEMENT), true);
StrCpy(e->name, sizeof(e->name), name);
e->num_value = total;
e->type = VALUE_INT64;
e->values = ZeroMallocEx(sizeof(VALUE *) * total, true);
e->values[index] = v;
if (AddElement(p, e) == false)
{
return NULL;
}
}
e->JsonHint_IsArray = true;
return e;
}
// Add an integer to the PACK (array)
ELEMENT *PackAddIntEx(PACK *p, char *name, UINT i, UINT index, UINT total)
{
VALUE *v;
ELEMENT *e;
// Validate arguments
if (p == NULL || name == NULL || total == 0)
{
return NULL;
}
v = NewIntValue(i);
e = GetElement(p, name, VALUE_INT);
if (e != NULL)
{
if (e->num_value >= total)
{
FreeValue(e->values[index], VALUE_INT);
e->values[index] = v;
}
else
{
FreeValue(v, VALUE_INT);
}
}
else
{
e = ZeroMallocEx(sizeof(ELEMENT), true);
StrCpy(e->name, sizeof(e->name), name);
e->num_value = total;
e->type = VALUE_INT;
e->values = ZeroMallocEx(sizeof(VALUE *) * total, true);
e->values[index] = v;
if (AddElement(p, e) == false)
{
return NULL;
}
}
e->JsonHint_IsArray = true;
return e;
}
// Add 64 bit integer time value to the PACK
ELEMENT *PackAddTime64(PACK *p, char *name, UINT64 i)
{
ELEMENT *e = PackAddInt64(p, name, i);
if (e != NULL)
{
e->JsonHint_IsDateTime = true;
}
return e;
}
ELEMENT *PackAddTime64Ex(PACK *p, char *name, UINT64 i, UINT index, UINT total)
{
ELEMENT *e = PackAddInt64Ex(p, name, i, index, total);
if (e != NULL)
{
e->JsonHint_IsDateTime = true;
}
return e;
}
// Add a 64 bit integer to the PACK
ELEMENT *PackAddInt64(PACK *p, char *name, UINT64 i)
{
VALUE *v;
ELEMENT *e;
// Validate arguments
if (p == NULL || name == NULL)
{
return NULL;
}
v = NewInt64Value(i);
e = NewElement(name, VALUE_INT64, 1, &v);
if (AddElement(p, e) == false)
{
return NULL;
}
return e;
}
// Add the number of items to the PACK
ELEMENT *PackAddNum(PACK *p, char *name, UINT num)
{
return PackAddInt(p, name, num);
}
// Add an integer to the PACK
ELEMENT *PackAddInt(PACK *p, char *name, UINT i)
{
VALUE *v;
ELEMENT *e = NULL;
// Validate arguments
if (p == NULL || name == NULL)
{
return NULL;
}
v = NewIntValue(i);
e = NewElement(name, VALUE_INT, 1, &v);
if (AddElement(p, e) == false)
{
return NULL;
}
return e;
}
// Add a Unicode string (array) to the PACK
ELEMENT *PackAddUniStrEx(PACK *p, char *name, wchar_t *unistr, UINT index, UINT total)
{
VALUE *v;
ELEMENT *e;
// Validate arguments
if (p == NULL || name == NULL || unistr == NULL || total == 0)
{
return NULL;
}
v = NewUniStrValue(unistr);
e = GetElement(p, name, VALUE_UNISTR);
if (e != NULL)
{
if (e->num_value >= total)
{
FreeValue(e->values[index], VALUE_UNISTR);
e->values[index] = v;
}
else
{
FreeValue(v, VALUE_UNISTR);
}
}
else
{
e = ZeroMallocEx(sizeof(ELEMENT), true);
StrCpy(e->name, sizeof(e->name), name);
e->num_value = total;
e->type = VALUE_UNISTR;
e->values = ZeroMallocEx(sizeof(VALUE *) * total, true);
e->values[index] = v;
if (AddElement(p, e) == false)
{
return NULL;
}
}
e->JsonHint_IsArray = true;
return e;
}
// Add a Unicode string to the PACK
ELEMENT *PackAddUniStr(PACK *p, char *name, wchar_t *unistr)
{
VALUE *v;
ELEMENT *e = NULL;
// Validate arguments
if (p == NULL || name == NULL || unistr == NULL)
{
return NULL;
}
v = NewUniStrValue(unistr);
e = NewElement(name, VALUE_UNISTR, 1, &v);
if (AddElement(p, e) == false)
{
return NULL;
}
return e;
}
// Add a string to the PACK (array)
ELEMENT *PackAddStrEx(PACK *p, char *name, char *str, UINT index, UINT total)
{
VALUE *v;
ELEMENT *e;
// Validate arguments
if (p == NULL || name == NULL || str == NULL || total == 0)
{
return NULL;
}
v = NewStrValue(str);
e = GetElement(p, name, VALUE_STR);
if (e != NULL)
{
if (e->num_value >= total)
{
FreeValue(e->values[index], VALUE_STR);
e->values[index] = v;
}
else
{
FreeValue(v, VALUE_STR);
}
}
else
{
e = ZeroMallocEx(sizeof(ELEMENT), true);
StrCpy(e->name, sizeof(e->name), name);
e->num_value = total;
e->type = VALUE_STR;
e->values = ZeroMallocEx(sizeof(VALUE *) * total, true);
e->values[index] = v;
if (AddElement(p, e) == false)
{
return NULL;
}
}
e->JsonHint_IsArray = true;
return e;
}
// Add a string to the PACK
ELEMENT *PackAddStr(PACK *p, char *name, char *str)
{
VALUE *v;
ELEMENT *e = NULL;
// Validate arguments
if (p == NULL || name == NULL || str == NULL)
{
return NULL;
}
v = NewStrValue(str);
e = NewElement(name, VALUE_STR, 1, &v);
if (AddElement(p, e) == false)
{
return NULL;
}
return e;
}
// Add an element of PACK array to JSON Array
void PackArrayElementToJsonArray(JSON_ARRAY *ja, PACK *p, ELEMENT *e, UINT index)
{
if (ja == NULL || p == NULL || e == NULL || index >= e->num_value)
{
return;
}
switch (e->type)
{
case VALUE_INT:
if (e->JsonHint_IsIP)
{
if (InStr(e->name, "@") == false)
{
IP ip;
if (PackGetIpEx(p, e->name, &ip, index))
{
char ip_str[64];
IPToStr(ip_str, sizeof(ip_str), &ip);
JsonArrayAddStr(ja, ip_str);
}
}
}
else if (e->JsonHint_IsBool)
{
JsonArrayAddBool(ja, PackGetBoolEx(p, e->name, index));
}
else
{
JsonArrayAddNumber(ja, PackGetIntEx(p, e->name, index));
}
break;
case VALUE_INT64:
if (e->JsonHint_IsIP == false)
{
if (e->JsonHint_IsDateTime == false)
{
JsonArrayAddNumber(ja, PackGetInt64Ex(p, e->name, index));
}
else
{
char dtstr[64];
SystemTime64ToJsonStr(dtstr, sizeof(dtstr), PackGetInt64Ex(p, e->name, index));
JsonArrayAddStr(ja, dtstr);
}
}
break;
case VALUE_DATA:
if (e->JsonHint_IsIP == false)
{
BUF *buf = PackGetBufEx(p, e->name, index);
if (buf != NULL)
{
JsonArrayAddData(ja, buf->Buf, buf->Size);
FreeBuf(buf);
}
else
{
UCHAR zero = 0;
JsonArrayAddData(ja, &zero, 0);
}
}
break;
case VALUE_STR:
if (e->JsonHint_IsIP == false)
{
if (e->values[index] != NULL)
{
JsonArrayAddStr(ja, e->values[index]->Str);
}
else
{
JsonArrayAddStr(ja, "");
}
}
break;
case VALUE_UNISTR:
if (e->JsonHint_IsIP == false)
{
if (e->values[index] != NULL)
{
JsonArrayAddUniStr(ja, e->values[index]->UniStr);
}
else
{
JsonArrayAddUniStr(ja, L"");
}
}
break;
}
}
// Add an element of PACK to JSON Object
void PackElementToJsonObject(JSON_OBJECT *o, PACK *p, ELEMENT *e, UINT index)
{
char *suffix;
char name[MAX_PATH];
if (o == NULL || p == NULL || e == NULL)
{
return;
}
suffix = DetermineJsonSuffixForPackElement(e);
if (suffix == NULL)
{
return;
}
StrCpy(name, sizeof(name), e->name);
StrCat(name, sizeof(name), suffix);
switch (e->type)
{
case VALUE_INT:
if (e->JsonHint_IsIP)
{
if (InStr(e->name, "@") == false)
{
IP ip;
if (PackGetIpEx(p, e->name, &ip, index))
{
char ip_str[64];
IPToStr(ip_str, sizeof(ip_str), &ip);
JsonSetStr(o, name, ip_str);
}
}
}
else if (e->JsonHint_IsBool)
{
JsonSetBool(o, name, PackGetBoolEx(p, e->name, index));
}
else
{
JsonSetNumber(o, name, PackGetIntEx(p, e->name, index));
}
break;
case VALUE_INT64:
if (e->JsonHint_IsIP == false)
{
if (e->JsonHint_IsDateTime == false)
{
JsonSetNumber(o, name, PackGetInt64Ex(p, e->name, index));
}
else
{
char dtstr[64];
SystemTime64ToJsonStr(dtstr, sizeof(dtstr), PackGetInt64Ex(p, e->name, index));
JsonSetStr(o, name, dtstr);
}
}
break;
case VALUE_DATA:
if (e->JsonHint_IsIP == false)
{
BUF *buf = PackGetBufEx(p, e->name, index);
if (buf != NULL)
{
JsonSetData(o, name, buf->Buf, buf->Size);
FreeBuf(buf);
}
else
{
UCHAR zero = 0;
JsonSetData(o, name, &zero, 0);
}
}
break;
case VALUE_STR:
if (e->JsonHint_IsIP == false)
{
if (e->values[index] != NULL)
{
JsonSetStr(o, name, e->values[index]->Str);
}
else
{
JsonSetStr(o, name, "");
}
}
break;
case VALUE_UNISTR:
if (e->JsonHint_IsIP == false)
{
if (e->values[index] != NULL)
{
JsonSetUniStr(o, name, e->values[index]->UniStr);
}
else
{
JsonSetUniStr(o, name, L"");
}
}
break;
}
}
// Determine JSON element suffix for PACK element
char *DetermineJsonSuffixForPackElement(ELEMENT *e)
{
switch (e->type)
{
case VALUE_INT:
if (e->JsonHint_IsIP)
{
if (InStr(e->name, "@") == false)
{
return "_ip";
}
}
else if (e->JsonHint_IsBool)
{
return "_bool";
}
else
{
return "_u32";
}
break;
case VALUE_INT64:
if (e->JsonHint_IsIP == false)
{
if (e->JsonHint_IsDateTime == false)
{
return "_u64";
}
else
{
return "_dt";
}
}
break;
case VALUE_DATA:
if (e->JsonHint_IsIP == false)
{
return "_bin";
}
break;
case VALUE_STR:
if (e->JsonHint_IsIP == false)
{
return "_str";
}
break;
case VALUE_UNISTR:
if (e->JsonHint_IsIP == false)
{
return "_utf";
}
break;
}
return NULL;
}
// Convert JSON to PACK
PACK *JsonToPack(JSON_VALUE *v)
{
PACK *p = NULL;
JSON_OBJECT *jo;
if (v == NULL)
{
return NULL;
}
p = NewPack();
jo = JsonValueGetObject(v);
if (jo != NULL)
{
UINT i;
for (i = 0;i < jo->count;i++)
{
char *name = jo->names[i];
JSON_VALUE *value = jo->values[i];
if (value->type == JSON_TYPE_ARRAY)
{
UINT j;
JSON_ARRAY *ja = value->value.array;
for (j = 0;j < ja->count;j++)
{
if (ja->items[j]->type != JSON_TYPE_OBJECT)
{
JsonTryParseValueAddToPack(p, ja->items[j], name, j, ja->count, false);
}
else
{
JSON_VALUE *v = ja->items[j];
JSON_OBJECT *o = v->value.object;
UINT k;
for (k = 0;k < o->count;k++)
{
char *name2 = o->names[k];
JSON_VALUE *value2 = o->values[k];
PackSetCurrentJsonGroupName(p, name);
JsonTryParseValueAddToPack(p, value2, name2, j, ja->count, false);
PackSetCurrentJsonGroupName(p, NULL);
}
}
}
}
else
{
JsonTryParseValueAddToPack(p, value, name, 0, 1, true);
}
}
}
return p;
}
ELEMENT *ElementNullSafe(ELEMENT *p)
{
static ELEMENT dummy;
if (p == NULL)
{
Zero(&dummy, sizeof(dummy));
return &dummy;
}
return p;
}
bool JsonTryParseValueAddToPack(PACK *p, JSON_VALUE *v, char *v_name, UINT index, UINT total, bool is_single)
{
char name[MAX_PATH];
bool ok = true;
if (p == NULL || v == NULL)
{
return false;
}
if (TrimEndWith(name, sizeof(name), v_name, "_bool"))
{
if (v->type == JSON_TYPE_BOOL)
{
ElementNullSafe(PackAddBoolEx(p, name, MAKEBOOL(v->value.boolean), index, total))->JsonHint_IsArray = !is_single;
ok = true;
}
else if (v->type == JSON_TYPE_NUMBER)
{
ElementNullSafe(PackAddBoolEx(p, name, MAKEBOOL(v->value.number), index, total))->JsonHint_IsArray = !is_single;
ok = true;
}
else if (v->type == JSON_TYPE_STRING)
{
ElementNullSafe(PackAddBoolEx(p, name, ToBool(v->value.string), index, total))->JsonHint_IsArray = !is_single;
ok = true;
}
}
else if (TrimEndWith(name, sizeof(name), v_name, "_u32"))
{
if (v->type == JSON_TYPE_BOOL)
{
ElementNullSafe(PackAddIntEx(p, name, MAKEBOOL(v->value.boolean), index, total))->JsonHint_IsArray = !is_single;
ok = true;
}
else if (v->type == JSON_TYPE_NUMBER)
{
ElementNullSafe(PackAddIntEx(p, name, (UINT)v->value.number, index, total))->JsonHint_IsArray = !is_single;
ok = true;
}
else if (v->type == JSON_TYPE_STRING)
{
ElementNullSafe(PackAddIntEx(p, name, ToInt(v->value.string), index, total))->JsonHint_IsArray = !is_single;
ok = true;
}
}
else if (TrimEndWith(name, sizeof(name), v_name, "_u64"))
{
if (v->type == JSON_TYPE_BOOL)
{
ElementNullSafe(PackAddInt64Ex(p, name, MAKEBOOL(v->value.boolean), index, total))->JsonHint_IsArray = !is_single;
ok = true;
}
else if (v->type == JSON_TYPE_NUMBER)
{
ElementNullSafe(PackAddInt64Ex(p, name, v->value.number, index, total))->JsonHint_IsArray = !is_single;
ok = true;
}
else if (v->type == JSON_TYPE_STRING)
{
ElementNullSafe(PackAddInt64Ex(p, name, ToInt64(v->value.string), index, total))->JsonHint_IsArray = !is_single;
ok = true;
}
}
else if (TrimEndWith(name, sizeof(name), v_name, "_str"))
{
if (v->type == JSON_TYPE_BOOL)
{
ElementNullSafe(PackAddStrEx(p, name, MAKEBOOL(v->value.boolean) ? "true" : "false", index, total))->JsonHint_IsArray = !is_single;
ok = true;
}
else if (v->type == JSON_TYPE_NUMBER)
{
char tmp[64];
ToStr64(tmp, v->value.number);
ElementNullSafe(PackAddStrEx(p, name, tmp, index, total))->JsonHint_IsArray = !is_single;
ok = true;
}
else if (v->type == JSON_TYPE_STRING)
{
ElementNullSafe(PackAddStrEx(p, name, v->value.string, index, total))->JsonHint_IsArray = !is_single;
ok = true;
}
}
else if (TrimEndWith(name, sizeof(name), v_name, "_utf"))
{
if (v->type == JSON_TYPE_BOOL)
{
ElementNullSafe(PackAddUniStrEx(p, name, MAKEBOOL(v->value.boolean) ? L"true" : L"false", index, total))->JsonHint_IsArray = !is_single;
ok = true;
}
else if (v->type == JSON_TYPE_NUMBER)
{
char tmp[64];
wchar_t tmp2[64];
ToStr64(tmp, v->value.number);
StrToUni(tmp2, sizeof(tmp2), tmp);
ElementNullSafe(PackAddUniStrEx(p, name, tmp2, index, total))->JsonHint_IsArray = !is_single;
ok = true;
}
else if (v->type == JSON_TYPE_STRING)
{
wchar_t *uni = CopyUtfToUni(v->value.string);
ElementNullSafe(PackAddUniStrEx(p, name, uni, index, total))->JsonHint_IsArray = !is_single;
Free(uni);
ok = true;
}
}
else if (TrimEndWith(name, sizeof(name), v_name, "_bin"))
{
if (v->type == JSON_TYPE_STRING)
{
UINT data_size;
void *data = Base64ToBin(&data_size, v->value.string, StrLen(v->value.string));
ElementNullSafe(PackAddDataEx(p, name, data, data_size, index, total))->JsonHint_IsArray = !is_single;
Free(data);
ok = true;
}
}
else if (TrimEndWith(name, sizeof(name), v_name, "_dt"))
{
if (v->type == JSON_TYPE_NUMBER)
{
ElementNullSafe(PackAddInt64Ex(p, name, v->value.number, index, total))->JsonHint_IsArray = !is_single;
ok = true;
}
else if (v->type == JSON_TYPE_STRING)
{
UINT64 time = DateTimeStrRFC3339ToSystemTime64(v->value.string);
ELEMENT *e = PackAddInt64Ex(p, name, time, index, total);
if (e != NULL)
{
e->JsonHint_IsArray = !is_single;
e->JsonHint_IsDateTime = true;
}
ok = true;
}
}
else if (TrimEndWith(name, sizeof(name), v_name, "_ip"))
{
if (v->type == JSON_TYPE_STRING)
{
IP ip;
if (StrToIP(&ip, v->value.string))
{
PackAddIpEx2(p, name, &ip, index, total, is_single);
ok = true;
}
}
}
return ok;
}
// Convert JSON string to PACK
PACK *JsonStrToPack(char *str)
{
JSON_VALUE *v = StrToJson(str);
PACK *ret;
if (v == NULL)
{
return NULL;
}
ret = JsonToPack(v);
JsonFree(v);
return ret;
}
// Convert PACK to JSON string
char *PackToJsonStr(PACK *p)
{
char *ret;
JSON_VALUE *json = PackToJson(p);
ret = JsonToStr(json);
JsonFree(json);
return ret;
}
// Convert PACK to JSON
JSON_VALUE *PackToJson(PACK *p)
{
JSON_VALUE *v;
JSON_OBJECT *o;
UINT i, j, k;
LIST *json_group_id_list;
if (p == NULL)
{
return JsonNewObject();
}
json_group_id_list = NewStrList();
for (i = 0;i < LIST_NUM(p->elements);i++)
{
ELEMENT *e = LIST_DATA(p->elements, i);
if (e->num_value >= 2 || e->JsonHint_IsArray)
{
if (IsEmptyStr(e->JsonHint_GroupName) == false)
{
AddStrToStrListDistinct(json_group_id_list, e->JsonHint_GroupName);
}
}
}
for (i = 0;i < LIST_NUM(p->json_subitem_names);i++)
{
char *group_name = LIST_DATA(p->json_subitem_names, i);
if (IsEmptyStr(group_name) == false)
{
AddStrToStrListDistinct(json_group_id_list, group_name);
}
}
v = JsonNewObject();
o = JsonValueGetObject(v);
for (k = 0;k < LIST_NUM(json_group_id_list);k++)
{
char *group_name = LIST_DATA(json_group_id_list, k);
UINT array_count = INFINITE;
bool ok = true;
for (i = 0;i < LIST_NUM(p->elements);i++)
{
ELEMENT *e = LIST_DATA(p->elements, i);
if (e->num_value >= 2 || e->JsonHint_IsArray)
{
if (StrCmpi(e->JsonHint_GroupName, group_name) == 0)
{
if (array_count == INFINITE)
{
array_count = e->num_value;
}
else
{
if (array_count != e->num_value)
{
ok = false;
}
}
}
}
}
if (array_count == INFINITE)
{
array_count = 0;
}
if (ok)
{
JSON_VALUE **json_objects = ZeroMalloc(sizeof(void *) * array_count);
JSON_VALUE *jav = JsonNewArray();
JSON_ARRAY *ja = JsonArray(jav);
JsonSet(o, group_name, jav);
for (j = 0;j < array_count;j++)
{
json_objects[j] = JsonNewObject();
JsonArrayAdd(ja, json_objects[j]);
}
for (i = 0;i < LIST_NUM(p->elements);i++)
{
ELEMENT *e = LIST_DATA(p->elements, i);
if (e->num_value >= 2 || e->JsonHint_IsArray)
{
if (StrCmpi(e->JsonHint_GroupName, group_name) == 0)
{
for (j = 0;j < e->num_value;j++)
{
PackElementToJsonObject(JsonValueGetObject(json_objects[j]),
p, e, j);
}
}
}
}
Free(json_objects);
}
}
for (i = 0;i < LIST_NUM(p->elements);i++)
{
ELEMENT *e = LIST_DATA(p->elements, i);
if (e->num_value >= 2 || e->JsonHint_IsArray)
{
if (IsEmptyStr(e->JsonHint_GroupName))
{
char *suffix = DetermineJsonSuffixForPackElement(e);
if (suffix != NULL)
{
JSON_VALUE *jav = JsonNewArray();
JSON_ARRAY *ja = JsonArray(jav);
char name[MAX_PATH];
for (j = 0;j < e->num_value;j++)
{
PackArrayElementToJsonArray(ja, p, e, j);
}
StrCpy(name, sizeof(name), e->name);
StrCat(name, sizeof(name), suffix);
JsonSet(o, name, jav);
}
}
}
else if (e->num_value == 1)
{
PackElementToJsonObject(o, p, e, 0);
}
}
ReleaseStrList(json_group_id_list);
return v;
}