Files
microser/include/oss_sdk/aos_util.c

524 lines
13 KiB
C
Raw Normal View History

2025-01-16 16:17:01 +08:00
#include "aos_util.h"
#include "aos_log.h"
static const char *g_s_wday[] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
static const char *g_s_mon[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
static const char g_s_gmt_format[] = "%s, %.2d %s %.4d %.2d:%.2d:%.2d GMT";
int aos_parse_xml_body(aos_list_t *bc, mxml_node_t **root)
{
aos_buf_t *b;
size_t len;
*root = NULL;
len = (size_t)aos_buf_list_len(bc);
{
int nsize = 0;
char *buffer = (char*)malloc(sizeof(char)*(len+1));
memset(buffer, 0, len + 1);
aos_list_for_each_entry(aos_buf_t, b, bc, node) {
memcpy(buffer + nsize, (char *)b->pos, aos_buf_size(b));
nsize += aos_buf_size(b);
}
*root = mxmlLoadString(NULL, buffer, MXML_OPAQUE_CALLBACK);
free(buffer);
if (NULL == *root) {
return AOSE_INTERNAL_ERROR;
}
}
return AOSE_OK;
}
int aos_convert_to_gmt_time(char* date, const char* format, apr_time_exp_t *tm)
{
int size = apr_snprintf(date, AOS_MAX_GMT_TIME_LEN, format,
g_s_wday[tm->tm_wday], tm->tm_mday, g_s_mon[tm->tm_mon], 1900 + tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec);
if (size >= 0 && size < AOS_MAX_GMT_TIME_LEN) {
return AOSE_OK;
} else {
return AOSE_INTERNAL_ERROR;
}
}
int aos_get_gmt_str_time(char datestr[AOS_MAX_GMT_TIME_LEN])
{
int s;
apr_time_t now;
char buf[128];
apr_time_exp_t result;
now = apr_time_now();
if ((s = apr_time_exp_gmt(&result, now)) != APR_SUCCESS) {
aos_error_log("apr_time_exp_gmt fialure, code:%d %s.", s, apr_strerror(s, buf, sizeof(buf)));
return AOSE_INTERNAL_ERROR;
}
if ((s = aos_convert_to_gmt_time(datestr, g_s_gmt_format, &result))
!= AOSE_OK) {
aos_error_log("aos_convert_to_GMT failure, code:%d.", s);
}
return s;
}
int aos_url_encode(char *dest, const char *src, int maxSrcSize)
{
static const char *hex = "0123456789ABCDEF";
int len = 0;
unsigned char c;
while (*src) {
if (++len > maxSrcSize) {
*dest = 0;
return AOSE_INVALID_ARGUMENT;
}
c = *src;
if (isalnum(c) || (c == '-') || (c == '_') || (c == '.') || (c == '~')) {
*dest++ = c;
} else if (*src == ' ') {
*dest++ = '%';
*dest++ = '2';
*dest++ = '0';
} else {
*dest++ = '%';
*dest++ = hex[c >> 4];
*dest++ = hex[c & 15];
}
src++;
}
*dest = 0;
return AOSE_OK;
}
int aos_query_params_to_string(aos_pool_t *p, aos_table_t *query_params, aos_string_t *querystr)
{
int rs;
int pos;
int len;
char sep = '?';
char ebuf[AOS_MAX_QUERY_ARG_LEN*3+1];
char abuf[AOS_MAX_QUERY_ARG_LEN*6+128];
int max_len;
const aos_array_header_t *tarr;
const aos_table_entry_t *telts;
aos_buf_t *querybuf;
if (apr_is_empty_table(query_params)) {
return AOSE_OK;
}
max_len = sizeof(abuf)-1;
querybuf = aos_create_buf(p, 256);
aos_str_null(querystr);
tarr = aos_table_elts(query_params);
telts = (aos_table_entry_t*)tarr->elts;
for (pos = 0; pos < tarr->nelts; ++pos) {
if ((rs = aos_url_encode(ebuf, telts[pos].key, AOS_MAX_QUERY_ARG_LEN)) != AOSE_OK) {
aos_error_log("query params args too big, key:%s.", telts[pos].key);
return AOSE_INVALID_ARGUMENT;
}
len = apr_snprintf(abuf, max_len, "%c%s", sep, ebuf);
if (telts[pos].val != NULL && *telts[pos].val != '\0') {
if ((rs = aos_url_encode(ebuf, telts[pos].val, AOS_MAX_QUERY_ARG_LEN)) != AOSE_OK) {
aos_error_log("query params args too big, value:%s.", telts[pos].val);
return AOSE_INVALID_ARGUMENT;
}
len += apr_snprintf(abuf+len, max_len-len, "=%s", ebuf);
if (len >= AOS_MAX_QUERY_ARG_LEN) {
aos_error_log("query params args too big, %s.", abuf);
return AOSE_INVALID_ARGUMENT;
}
}
aos_buf_append_string(p, querybuf, abuf, len);
sep = '&';
}
// result
querystr->data = (char *)querybuf->pos;
querystr->len = aos_buf_size(querybuf);
return AOSE_OK;
}
void aos_gnome_sort(const char **headers, int size)
{
const char *tmp;
int i = 0, last_highest = 0;
while (i < size) {
if ((i == 0) || apr_strnatcasecmp(headers[i-1], headers[i]) < 0) {
i = ++last_highest;
} else {
tmp = headers[i];
headers[i] = headers[i - 1];
headers[--i] = tmp;
}
}
}
const char* aos_http_method_to_string(http_method_e method)
{
switch (method) {
case HTTP_GET:
return "GET";
case HTTP_HEAD:
return "HEAD";
case HTTP_PUT:
return "PUT";
case HTTP_POST:
return "POST";
case HTTP_DELETE:
return "DELETE";
default:
return "UNKNOWN";
}
}
int aos_base64_encode(const unsigned char *in, int inLen, char *out)
{
static const char *ENC =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
char *original_out = out;
while (inLen) {
// first 6 bits of char 1
*out++ = ENC[*in >> 2];
if (!--inLen) {
// last 2 bits of char 1, 4 bits of 0
*out++ = ENC[(*in & 0x3) << 4];
*out++ = '=';
*out++ = '=';
break;
}
// last 2 bits of char 1, first 4 bits of char 2
*out++ = ENC[((*in & 0x3) << 4) | (*(in + 1) >> 4)];
in++;
if (!--inLen) {
// last 4 bits of char 2, 2 bits of 0
*out++ = ENC[(*in & 0xF) << 2];
*out++ = '=';
break;
}
// last 4 bits of char 2, first 2 bits of char 3
*out++ = ENC[((*in & 0xF) << 2) | (*(in + 1) >> 6)];
in++;
// last 6 bits of char 3
*out++ = ENC[*in & 0x3F];
in++, inLen--;
}
return (out - original_out);
}
// HMAC-SHA-1:
//
// K - is key padded with zeros to 512 bits
// m - is message
// OPAD - 0x5c5c5c...
// IPAD - 0x363636...
//
// HMAC(K,m) = SHA1((K ^ OPAD) . SHA1((K ^ IPAD) . m))
void HMAC_SHA1(unsigned char hmac[20], const unsigned char *key, int key_len,
const unsigned char *message, int message_len)
{
unsigned char kopad[64], kipad[64];
int i;
unsigned char digest[APR_SHA1_DIGESTSIZE];
apr_sha1_ctx_t context;
if (key_len > 64) {
key_len = 64;
}
for (i = 0; i < key_len; i++) {
kopad[i] = key[i] ^ 0x5c;
kipad[i] = key[i] ^ 0x36;
}
for ( ; i < 64; i++) {
kopad[i] = 0 ^ 0x5c;
kipad[i] = 0 ^ 0x36;
}
apr_sha1_init(&context);
apr_sha1_update(&context, (const char *)kipad, 64);
apr_sha1_update(&context, (const char *)message, (unsigned int)message_len);
apr_sha1_final(digest, &context);
apr_sha1_init(&context);
apr_sha1_update(&context, (const char *)kopad, 64);
apr_sha1_update(&context, (const char *)digest, 20);
apr_sha1_final(hmac, &context);
}
unsigned char* aos_md5(aos_pool_t* pool, const char *in, apr_size_t in_len) {
unsigned char* out;
apr_md5_ctx_t context;
//APR_MD5_DIGESTSIZE: The MD5 digest size, value is 16
out = aos_palloc(pool, APR_MD5_DIGESTSIZE + 1);
if (!out) {
return NULL;
}
if (0 != apr_md5_init(&context)) {
return NULL;
}
if (0 != apr_md5_update(&context, in, in_len)) {
return NULL;
}
if (0 != apr_md5_final(out, &context)) {
return NULL;
}
out[APR_MD5_DIGESTSIZE] = '\0';
return out;
};
int aos_url_decode(const char *in, char *out)
{
static const char tbl[256] = {
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1,
-1,10,11,12,13,14,15,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,10,11,12,13,14,15,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1
};
char c, v1, v2;
if(in != NULL) {
while((c=*in++) != '\0') {
if(c == '%') {
if(!(v1=*in++) || (v1=tbl[(unsigned char)v1])<0 ||
!(v2=*in++) || (v2=tbl[(unsigned char)v2])<0) {
*out = '\0';
return -1;
}
c = (v1<<4)|v2;
} else if (c == '+') {
c = ' ';
}
*out++ = c;
}
}
*out = '\0';
return 0;
}
/*
* Convert a string to a long long integer.
*
* Ignores `locale' stuff. Assumes that the upper and lower case
* alphabets and digits are each contiguous.
*/
long long aos_strtoll(const char *nptr, char **endptr, int base)
{
const char *s;
/* LONGLONG */
long long int acc, cutoff;
int c;
int neg, any, cutlim;
/* endptr may be NULL */
#ifdef __GNUC__
/* This outrageous construct just to shut up a GCC warning. */
(void) &acc; (void) &cutoff;
#endif
/*
* Skip white space and pick up leading +/- sign if any.
* If base is 0, allow 0x for hex and 0 for octal, else
* assume decimal; if base is already 16, allow 0x.
*/
s = nptr;
do {
c = (unsigned char) *s++;
} while (isspace(c));
if (c == '-') {
neg = 1;
c = *s++;
} else {
neg = 0;
if (c == '+')
c = *s++;
}
if ((base == 0 || base == 16) &&
c == '0' && (*s == 'x' || *s == 'X')) {
c = s[1];
s += 2;
base = 16;
}
if (base == 0)
base = c == '0' ? 8 : 10;
/*
* Compute the cutoff value between legal numbers and illegal
* numbers. That is the largest legal value, divided by the
* base. An input number that is greater than this value, if
* followed by a legal input character, is too big. One that
* is equal to this value may be valid or not; the limit
* between valid and invalid numbers is then based on the last
* digit. For instance, if the range for long longs is
* [-9223372036854775808..9223372036854775807] and the input base
* is 10, cutoff will be set to 922337203685477580 and cutlim to
* either 7 (neg==0) or 8 (neg==1), meaning that if we have
* accumulated a value > 922337203685477580, or equal but the
* next digit is > 7 (or 8), the number is too big, and we will
* return a range error.
*
* Set any if any `digits' consumed; make it negative to indicate
* overflow.
*/
cutoff = neg ? LLONG_MIN : LLONG_MAX;
cutlim = (int)(cutoff % base);
cutoff /= base;
if (neg) {
if (cutlim > 0) {
cutlim -= base;
cutoff += 1;
}
cutlim = -cutlim;
}
for (acc = 0, any = 0;; c = (unsigned char) *s++) {
if (isdigit(c))
c -= '0';
else if (isalpha(c))
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
else
break;
if (c >= base)
break;
if (any < 0)
continue;
if (neg) {
if (acc < cutoff || (acc == cutoff && c > cutlim)) {
any = -1;
acc = LLONG_MIN;
errno = ERANGE;
} else {
any = 1;
acc *= base;
acc -= c;
}
} else {
if (acc > cutoff || (acc == cutoff && c > cutlim)) {
any = -1;
acc = LLONG_MAX;
errno = ERANGE;
} else {
any = 1;
acc *= base;
acc += c;
}
}
}
if (endptr != 0)
/* LINTED interface specification */
*endptr = (char *)(any ? s - 1 : nptr);
return (acc);
}
int64_t aos_atoi64(const char *nptr)
{
return aos_strtoull(nptr, NULL, 10);
}
unsigned long long aos_strtoull(const char *nptr, char **endptr, int base)
{
const char *s;
unsigned long long acc, cutoff;
int c;
int neg, any, cutlim;
/*
* See strtoq for comments as to the logic used.
*/
s = nptr;
do {
c = (unsigned char) *s++;
} while (isspace(c));
if (c == '-') {
neg = 1;
c = *s++;
} else {
neg = 0;
if (c == '+')
c = *s++;
}
if ((base == 0 || base == 16) &&
c == '0' && (*s == 'x' || *s == 'X')) {
c = s[1];
s += 2;
base = 16;
}
if (base == 0)
base = c == '0' ? 8 : 10;
cutoff = ULLONG_MAX / (unsigned long long)base;
cutlim = ULLONG_MAX % (unsigned long long)base;
for (acc = 0, any = 0;; c = (unsigned char) *s++) {
if (isdigit(c))
c -= '0';
else if (isalpha(c))
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
else
break;
if (c >= base)
break;
if (any < 0)
continue;
if (acc > cutoff || (acc == cutoff && c > cutlim)) {
any = -1;
acc = ULLONG_MAX;
errno = ERANGE;
} else {
any = 1;
acc *= (unsigned long long)base;
acc += c;
}
}
if (neg && any > 0)
#ifdef WIN32
#pragma warning(disable : 4146)
#endif
acc = -acc;
#ifdef WIN32
#pragma warning(default : 4146)
#endif
if (endptr != 0)
*endptr = (char *) (any ? s - 1 : nptr);
return (acc);
}
uint64_t aos_atoui64(const char *nptr)
{
return aos_strtoull(nptr, NULL, 10);
}