123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523 |
- #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);
- }
|