commit
92c45f3390
@ -0,0 +1,158 @@
|
||||
/*-
|
||||
* Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include <asn_internal.h>
|
||||
#include <ANY.h>
|
||||
#include <errno.h>
|
||||
|
||||
static asn_OCTET_STRING_specifics_t asn_DEF_ANY_specs = {
|
||||
sizeof(ANY_t),
|
||||
offsetof(ANY_t, _asn_ctx),
|
||||
2 /* Special indicator that this is an ANY type */
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_ANY = {
|
||||
"ANY",
|
||||
"ANY",
|
||||
OCTET_STRING_free,
|
||||
OCTET_STRING_print,
|
||||
asn_generic_no_constraint,
|
||||
OCTET_STRING_decode_ber,
|
||||
OCTET_STRING_encode_der,
|
||||
OCTET_STRING_decode_xer_hex,
|
||||
ANY_encode_xer,
|
||||
0, 0,
|
||||
0, /* Use generic outmost tag fetcher */
|
||||
0, 0, 0, 0,
|
||||
0, /* No PER visible constraints */
|
||||
0, 0, /* No members */
|
||||
&asn_DEF_ANY_specs,
|
||||
};
|
||||
|
||||
|
||||
asn_enc_rval_t
|
||||
ANY_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
|
||||
int ilevel, enum xer_encoder_flags_e flags,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
|
||||
if(flags & XER_F_CANONICAL) {
|
||||
/*
|
||||
* Canonical XER-encoding of ANY type is not supported.
|
||||
*/
|
||||
_ASN_ENCODE_FAILED;
|
||||
}
|
||||
|
||||
/* Dump as binary */
|
||||
return OCTET_STRING_encode_xer(td, sptr, ilevel, flags, cb, app_key);
|
||||
}
|
||||
|
||||
struct _callback_arg {
|
||||
uint8_t *buffer;
|
||||
size_t offset;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
static int ANY__consume_bytes(const void *buffer, size_t size, void *key);
|
||||
|
||||
int
|
||||
ANY_fromType(ANY_t *st, asn_TYPE_descriptor_t *td, void *sptr) {
|
||||
struct _callback_arg arg;
|
||||
asn_enc_rval_t erval;
|
||||
|
||||
if(!st || !td) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!sptr) {
|
||||
if(st->buf) FREEMEM(st->buf);
|
||||
st->size = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
arg.offset = arg.size = 0;
|
||||
arg.buffer = 0;
|
||||
|
||||
erval = der_encode(td, sptr, ANY__consume_bytes, &arg);
|
||||
if(erval.encoded == -1) {
|
||||
if(arg.buffer) FREEMEM(arg.buffer);
|
||||
return -1;
|
||||
}
|
||||
assert((size_t)erval.encoded == arg.offset);
|
||||
|
||||
if(st->buf) FREEMEM(st->buf);
|
||||
st->buf = arg.buffer;
|
||||
st->size = arg.offset;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ANY_t *
|
||||
ANY_new_fromType(asn_TYPE_descriptor_t *td, void *sptr) {
|
||||
ANY_t tmp;
|
||||
ANY_t *st;
|
||||
|
||||
if(!td || !sptr) {
|
||||
errno = EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(&tmp, 0, sizeof(tmp));
|
||||
|
||||
if(ANY_fromType(&tmp, td, sptr)) return 0;
|
||||
|
||||
st = (ANY_t *)CALLOC(1, sizeof(ANY_t));
|
||||
if(st) {
|
||||
*st = tmp;
|
||||
return st;
|
||||
} else {
|
||||
FREEMEM(tmp.buf);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ANY_to_type(ANY_t *st, asn_TYPE_descriptor_t *td, void **struct_ptr) {
|
||||
asn_dec_rval_t rval;
|
||||
void *newst = 0;
|
||||
|
||||
if(!st || !td || !struct_ptr) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(st->buf == 0) {
|
||||
/* Nothing to convert, make it empty. */
|
||||
*struct_ptr = (void *)0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
rval = ber_decode(0, td, (void **)&newst, st->buf, st->size);
|
||||
if(rval.code == RC_OK) {
|
||||
*struct_ptr = newst;
|
||||
return 0;
|
||||
} else {
|
||||
/* Remove possibly partially decoded data. */
|
||||
ASN_STRUCT_FREE(*td, newst);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int ANY__consume_bytes(const void *buffer, size_t size, void *key) {
|
||||
struct _callback_arg *arg = (struct _callback_arg *)key;
|
||||
|
||||
if((arg->offset + size) >= arg->size) {
|
||||
size_t nsize = (arg->size ? arg->size << 2 : 16) + size;
|
||||
void *p = REALLOC(arg->buffer, nsize);
|
||||
if(!p) return -1;
|
||||
arg->buffer = (uint8_t *)p;
|
||||
arg->size = nsize;
|
||||
}
|
||||
|
||||
memcpy(arg->buffer + arg->offset, buffer, size);
|
||||
arg->offset += size;
|
||||
assert(arg->offset < arg->size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -0,0 +1,48 @@
|
||||
/*-
|
||||
* Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#ifndef ASN_TYPE_ANY_H
|
||||
#define ASN_TYPE_ANY_H
|
||||
|
||||
#include <OCTET_STRING.h> /* Implemented via OCTET STRING type */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct ANY {
|
||||
uint8_t *buf; /* BER-encoded ANY contents */
|
||||
int size; /* Size of the above buffer */
|
||||
|
||||
asn_struct_ctx_t _asn_ctx; /* Parsing across buffer boundaries */
|
||||
} ANY_t;
|
||||
|
||||
extern asn_TYPE_descriptor_t asn_DEF_ANY;
|
||||
|
||||
asn_struct_free_f ANY_free;
|
||||
asn_struct_print_f ANY_print;
|
||||
ber_type_decoder_f ANY_decode_ber;
|
||||
der_type_encoder_f ANY_encode_der;
|
||||
xer_type_encoder_f ANY_encode_xer;
|
||||
|
||||
/******************************
|
||||
* Handy conversion routines. *
|
||||
******************************/
|
||||
|
||||
/* Convert another ASN.1 type into the ANY. This implies DER encoding. */
|
||||
int ANY_fromType(ANY_t *, asn_TYPE_descriptor_t *td, void *struct_ptr);
|
||||
ANY_t *ANY_new_fromType(asn_TYPE_descriptor_t *td, void *struct_ptr);
|
||||
|
||||
/* Convert the contents of the ANY type into the specified type. */
|
||||
int ANY_to_type(ANY_t *, asn_TYPE_descriptor_t *td, void **struct_ptr);
|
||||
|
||||
#define ANY_fromBuf(s, buf, size) OCTET_STRING_fromBuf((s), (buf), (size))
|
||||
#define ANY_new_fromBuf(buf, size) OCTET_STRING_new_fromBuf( \
|
||||
&asn_DEF_ANY, (buf), (size))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ASN_TYPE_ANY_H */
|
@ -0,0 +1,188 @@
|
||||
/*-
|
||||
* Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include <asn_internal.h>
|
||||
#include <BIT_STRING.h>
|
||||
#include <asn_internal.h>
|
||||
|
||||
/*
|
||||
* BIT STRING basic type description.
|
||||
*/
|
||||
static ber_tlv_tag_t asn_DEF_BIT_STRING_tags[] = {
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (3 << 2))
|
||||
};
|
||||
static asn_OCTET_STRING_specifics_t asn_DEF_BIT_STRING_specs = {
|
||||
sizeof(BIT_STRING_t),
|
||||
offsetof(BIT_STRING_t, _asn_ctx),
|
||||
1, /* Special indicator that this is a BIT STRING type */
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_BIT_STRING = {
|
||||
"BIT STRING",
|
||||
"BIT_STRING",
|
||||
OCTET_STRING_free, /* Implemented in terms of OCTET STRING */
|
||||
BIT_STRING_print,
|
||||
BIT_STRING_constraint,
|
||||
OCTET_STRING_decode_ber, /* Implemented in terms of OCTET STRING */
|
||||
OCTET_STRING_encode_der, /* Implemented in terms of OCTET STRING */
|
||||
OCTET_STRING_decode_xer_binary,
|
||||
BIT_STRING_encode_xer,
|
||||
OCTET_STRING_decode_uper, /* Unaligned PER decoder */
|
||||
OCTET_STRING_encode_uper, /* Unaligned PER encoder */
|
||||
0, /* Use generic outmost tag fetcher */
|
||||
asn_DEF_BIT_STRING_tags,
|
||||
sizeof(asn_DEF_BIT_STRING_tags)
|
||||
/ sizeof(asn_DEF_BIT_STRING_tags[0]),
|
||||
asn_DEF_BIT_STRING_tags, /* Same as above */
|
||||
sizeof(asn_DEF_BIT_STRING_tags)
|
||||
/ sizeof(asn_DEF_BIT_STRING_tags[0]),
|
||||
0, /* No PER visible constraints */
|
||||
0, 0, /* No members */
|
||||
&asn_DEF_BIT_STRING_specs
|
||||
};
|
||||
|
||||
/*
|
||||
* BIT STRING generic constraint.
|
||||
*/
|
||||
int
|
||||
BIT_STRING_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
|
||||
asn_app_constraint_failed_f *ctfailcb, void *app_key) {
|
||||
const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
|
||||
|
||||
if(st && st->buf) {
|
||||
if(st->size == 1 && st->bits_unused) {
|
||||
_ASN_CTFAIL(app_key, td,
|
||||
"%s: invalid padding byte (%s:%d)",
|
||||
td->name, __FILE__, __LINE__);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
_ASN_CTFAIL(app_key, td,
|
||||
"%s: value not given (%s:%d)",
|
||||
td->name, __FILE__, __LINE__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *_bit_pattern[16] = {
|
||||
"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111",
|
||||
"1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"
|
||||
};
|
||||
|
||||
asn_enc_rval_t
|
||||
BIT_STRING_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
|
||||
int ilevel, enum xer_encoder_flags_e flags,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
asn_enc_rval_t er;
|
||||
char scratch[128];
|
||||
char *p = scratch;
|
||||
char *scend = scratch + (sizeof(scratch) - 10);
|
||||
const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
|
||||
int xcan = (flags & XER_F_CANONICAL);
|
||||
uint8_t *buf;
|
||||
uint8_t *end;
|
||||
|
||||
if(!st || !st->buf)
|
||||
_ASN_ENCODE_FAILED;
|
||||
|
||||
er.encoded = 0;
|
||||
|
||||
buf = st->buf;
|
||||
end = buf + st->size - 1; /* Last byte is special */
|
||||
|
||||
/*
|
||||
* Binary dump
|
||||
*/
|
||||
for(; buf < end; buf++) {
|
||||
int v = *buf;
|
||||
int nline = xcan?0:(((buf - st->buf) % 8) == 0);
|
||||
if(p >= scend || nline) {
|
||||
er.encoded += p - scratch;
|
||||
_ASN_CALLBACK(scratch, p - scratch);
|
||||
p = scratch;
|
||||
if(nline) _i_ASN_TEXT_INDENT(1, ilevel);
|
||||
}
|
||||
memcpy(p + 0, _bit_pattern[v >> 4], 4);
|
||||
memcpy(p + 4, _bit_pattern[v & 0x0f], 4);
|
||||
p += 8;
|
||||
}
|
||||
|
||||
if(!xcan && ((buf - st->buf) % 8) == 0)
|
||||
_i_ASN_TEXT_INDENT(1, ilevel);
|
||||
er.encoded += p - scratch;
|
||||
_ASN_CALLBACK(scratch, p - scratch);
|
||||
p = scratch;
|
||||
|
||||
if(buf == end) {
|
||||
int v = *buf;
|
||||
int ubits = st->bits_unused;
|
||||
int i;
|
||||
for(i = 7; i >= ubits; i--)
|
||||
*p++ = (v & (1 << i)) ? 0x31 : 0x30;
|
||||
er.encoded += p - scratch;
|
||||
_ASN_CALLBACK(scratch, p - scratch);
|
||||
}
|
||||
|
||||
if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel - 1);
|
||||
|
||||
_ASN_ENCODED_OK(er);
|
||||
cb_failed:
|
||||
_ASN_ENCODE_FAILED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* BIT STRING specific contents printer.
|
||||
*/
|
||||
int
|
||||
BIT_STRING_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
static const char *h2c = "0123456789ABCDEF";
|
||||
char scratch[64];
|
||||
const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
|
||||
uint8_t *buf;
|
||||
uint8_t *end;
|
||||
char *p = scratch;
|
||||
|
||||
(void)td; /* Unused argument */
|
||||
|
||||
if(!st || !st->buf)
|
||||
return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
|
||||
|
||||
ilevel++;
|
||||
buf = st->buf;
|
||||
end = buf + st->size;
|
||||
|
||||
/*
|
||||
* Hexadecimal dump.
|
||||
*/
|
||||
for(; buf < end; buf++) {
|
||||
if((buf - st->buf) % 16 == 0 && (st->size > 16)
|
||||
&& buf != st->buf) {
|
||||
_i_INDENT(1);
|
||||
/* Dump the string */
|
||||
if(cb(scratch, p - scratch, app_key) < 0) return -1;
|
||||
p = scratch;
|
||||
}
|
||||
*p++ = h2c[*buf >> 4];
|
||||
*p++ = h2c[*buf & 0x0F];
|
||||
*p++ = 0x20;
|
||||
}
|
||||
|
||||
if(p > scratch) {
|
||||
p--; /* Eat the tailing space */
|
||||
|
||||
if((st->size > 16)) {
|
||||
_i_INDENT(1);
|
||||
}
|
||||
|
||||
/* Dump the incomplete 16-bytes row */
|
||||
if(cb(scratch, p - scratch, app_key) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -0,0 +1,33 @@
|
||||
/*-
|
||||
* Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#ifndef _BIT_STRING_H_
|
||||
#define _BIT_STRING_H_
|
||||
|
||||
#include <OCTET_STRING.h> /* Some help from OCTET STRING */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct BIT_STRING_s {
|
||||
uint8_t *buf; /* BIT STRING body */
|
||||
int size; /* Size of the above buffer */
|
||||
|
||||
int bits_unused;/* Unused trailing bits in the last octet (0..7) */
|
||||
|
||||
asn_struct_ctx_t _asn_ctx; /* Parsing across buffer boundaries */
|
||||
} BIT_STRING_t;
|
||||
|
||||
extern asn_TYPE_descriptor_t asn_DEF_BIT_STRING;
|
||||
|
||||
asn_struct_print_f BIT_STRING_print; /* Human-readable output */
|
||||
asn_constr_check_f BIT_STRING_constraint;
|
||||
xer_type_encoder_f BIT_STRING_encode_xer;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BIT_STRING_H_ */
|
@ -0,0 +1,181 @@
|
||||
/*-
|
||||
* Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include <asn_internal.h>
|
||||
#include <BMPString.h>
|
||||
#include <UTF8String.h>
|
||||
|
||||
/*
|
||||
* BMPString basic type description.
|
||||
*/
|
||||
static ber_tlv_tag_t asn_DEF_BMPString_tags[] = {
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (30 << 2)), /* [UNIVERSAL 30] IMPLICIT ...*/
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_BMPString = {
|
||||
"BMPString",
|
||||
"BMPString",
|
||||
OCTET_STRING_free, /* Implemented in terms of OCTET STRING */
|
||||
BMPString_print,
|
||||
asn_generic_no_constraint, /* No constraint by default */
|
||||
OCTET_STRING_decode_ber,
|
||||
OCTET_STRING_encode_der,
|
||||
BMPString_decode_xer, /* Convert from UTF-8 */
|
||||
BMPString_encode_xer, /* Convert to UTF-8 */
|
||||
0, 0,
|
||||
0, /* Use generic outmost tag fetcher */
|
||||
asn_DEF_BMPString_tags,
|
||||
sizeof(asn_DEF_BMPString_tags)
|
||||
/ sizeof(asn_DEF_BMPString_tags[0]) - 1,
|
||||
asn_DEF_BMPString_tags,
|
||||
sizeof(asn_DEF_BMPString_tags)
|
||||
/ sizeof(asn_DEF_BMPString_tags[0]),
|
||||
0, /* No PER visible constraints */
|
||||
0, 0, /* No members */
|
||||
0 /* No specifics */
|
||||
};
|
||||
|
||||
/*
|
||||
* BMPString specific contents printer.
|
||||
*/
|
||||
static ssize_t
|
||||
BMPString__dump(const BMPString_t *st,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
char scratch[128]; /* Scratchpad buffer */
|
||||
char *p = scratch;
|
||||
ssize_t wrote = 0;
|
||||
uint8_t *ch;
|
||||
uint8_t *end;
|
||||
|
||||
ch = st->buf;
|
||||
end = (st->buf + st->size);
|
||||
for(end--; ch < end; ch += 2) {
|
||||
uint16_t wc = (ch[0] << 8) | ch[1]; /* 2 bytes */
|
||||
if(sizeof(scratch) - (p - scratch) < 3) {
|
||||
wrote += p - scratch;
|
||||
if(cb(scratch, p - scratch, app_key) < 0)
|
||||
return -1;
|
||||
p = scratch;
|
||||
}
|
||||
if(wc < 0x80) {
|
||||
*p++ = (char)wc;
|
||||
} else if(wc < 0x800) {
|
||||
*p++ = 0xc0 | ((wc >> 6));
|
||||
*p++ = 0x80 | ((wc & 0x3f));
|
||||
} else {
|
||||
*p++ = 0xe0 | ((wc >> 12));
|
||||
*p++ = 0x80 | ((wc >> 6) & 0x3f);
|
||||
*p++ = 0x80 | ((wc & 0x3f));
|
||||
}
|
||||
}
|
||||
|
||||
wrote += p - scratch;
|
||||
if(cb(scratch, p - scratch, app_key) < 0)
|
||||
return -1;
|
||||
|
||||
return wrote;
|
||||
}
|
||||
|
||||
asn_dec_rval_t
|
||||
BMPString_decode_xer(asn_codec_ctx_t *opt_codec_ctx,
|
||||
asn_TYPE_descriptor_t *td, void **sptr,
|
||||
const char *opt_mname, const void *buf_ptr, size_t size) {
|
||||
asn_dec_rval_t rc;
|
||||
|
||||
rc = OCTET_STRING_decode_xer_utf8(opt_codec_ctx, td, sptr, opt_mname,
|
||||
buf_ptr, size);
|
||||
if(rc.code == RC_OK) {
|
||||
/*
|
||||
* Now we have a whole string in UTF-8 format.
|
||||
* Convert it into UCS-2.
|
||||
*/
|
||||
uint32_t *wcs;
|
||||
size_t wcs_len;
|
||||
UTF8String_t *st;
|
||||
|
||||
assert(*sptr);
|
||||
st = (UTF8String_t *)*sptr;
|
||||
assert(st->buf);
|
||||
wcs_len = UTF8String_to_wcs(st, 0, 0);
|
||||
|
||||
wcs = (uint32_t *)MALLOC(4 * (wcs_len + 1));
|
||||
if(wcs == 0 || UTF8String_to_wcs(st, wcs, wcs_len) != wcs_len) {
|
||||
rc.code = RC_FAIL;
|
||||
rc.consumed = 0;
|
||||
return rc;
|
||||
} else {
|
||||
wcs[wcs_len] = 0; /* nul-terminate */
|
||||
}
|
||||
|
||||
if(1) {
|
||||
/* Swap byte order and trim encoding to 2 bytes */
|
||||
uint32_t *wc = wcs;
|
||||
uint32_t *wc_end = wcs + wcs_len;
|
||||
uint16_t *dstwc = (uint16_t *)wcs;
|
||||
for(; wc < wc_end; wc++, dstwc++) {
|
||||
uint32_t wch = *wc;
|
||||
if(wch > 0xffff) {
|
||||
FREEMEM(wcs);
|
||||
rc.code = RC_FAIL;
|
||||
rc.consumed = 0;
|
||||
return rc;
|
||||
}
|
||||
*((uint8_t *)dstwc + 0) = wch >> 8;
|
||||
*((uint8_t *)dstwc + 1) = wch;
|
||||
}
|
||||
dstwc = (uint16_t *)REALLOC(wcs, 2 * (wcs_len + 1));
|
||||
if(!dstwc) {
|
||||
FREEMEM(wcs);
|
||||
rc.code = RC_FAIL;
|
||||
rc.consumed = 0;
|
||||
return rc;
|
||||
} else {
|
||||
dstwc[2 * wcs_len] = 0;
|
||||
wcs = (uint32_t *)dstwc;
|
||||
}
|
||||
}
|
||||
|
||||
FREEMEM(st->buf);
|
||||
st->buf = (uint8_t *)wcs;
|
||||
st->size = 2 * wcs_len;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
BMPString_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
|
||||
int ilevel, enum xer_encoder_flags_e flags,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
const BMPString_t *st = (const BMPString_t *)sptr;
|
||||
asn_enc_rval_t er;
|
||||
|
||||
(void)ilevel;
|
||||
(void)flags;
|
||||
|
||||
if(!st || !st->buf)
|
||||
_ASN_ENCODE_FAILED;
|
||||
|
||||
er.encoded = BMPString__dump(st, cb, app_key);
|
||||
if(er.encoded < 0) _ASN_ENCODE_FAILED;
|
||||
|
||||
_ASN_ENCODED_OK(er);
|
||||
}
|
||||
|
||||
int
|
||||
BMPString_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
const BMPString_t *st = (const BMPString_t *)sptr;
|
||||
|
||||
(void)td; /* Unused argument */
|
||||
(void)ilevel; /* Unused argument */
|
||||
|
||||
if(!st || !st->buf)
|
||||
return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
|
||||
|
||||
if(BMPString__dump(st, cb, app_key) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -0,0 +1,26 @@
|
||||
/*-
|
||||
* Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#ifndef _BMPString_H_
|
||||
#define _BMPString_H_
|
||||
|
||||
#include <OCTET_STRING.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef OCTET_STRING_t BMPString_t; /* Implemented via OCTET STRING */
|
||||
|
||||
extern asn_TYPE_descriptor_t asn_DEF_BMPString;
|
||||
|
||||
asn_struct_print_f BMPString_print; /* Human-readable output */
|
||||
xer_type_decoder_f BMPString_decode_xer;
|
||||
xer_type_encoder_f BMPString_encode_xer;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BMPString_H_ */
|
@ -0,0 +1,284 @@
|
||||
/*-
|
||||
* Copyright (c) 2003, 2005 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include <asn_internal.h>
|
||||
#include <asn_codecs_prim.h>
|
||||
#include <BOOLEAN.h>
|
||||
|
||||
/*
|
||||
* BOOLEAN basic type description.
|
||||
*/
|
||||
static ber_tlv_tag_t asn_DEF_BOOLEAN_tags[] = {
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (1 << 2))
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_BOOLEAN = {
|
||||
"BOOLEAN",
|
||||
"BOOLEAN",
|
||||
BOOLEAN_free,
|
||||
BOOLEAN_print,
|
||||
asn_generic_no_constraint,
|
||||
BOOLEAN_decode_ber,
|
||||
BOOLEAN_encode_der,
|
||||
BOOLEAN_decode_xer,
|
||||
BOOLEAN_encode_xer,
|
||||
BOOLEAN_decode_uper, /* Unaligned PER decoder */
|
||||
BOOLEAN_encode_uper, /* Unaligned PER encoder */
|
||||
0, /* Use generic outmost tag fetcher */
|
||||
asn_DEF_BOOLEAN_tags,
|
||||
sizeof(asn_DEF_BOOLEAN_tags) / sizeof(asn_DEF_BOOLEAN_tags[0]),
|
||||
asn_DEF_BOOLEAN_tags, /* Same as above */
|
||||
sizeof(asn_DEF_BOOLEAN_tags) / sizeof(asn_DEF_BOOLEAN_tags[0]),
|
||||
0, /* No PER visible constraints */
|
||||
0, 0, /* No members */
|
||||
0 /* No specifics */
|
||||
};
|
||||
|
||||
/*
|
||||
* Decode BOOLEAN type.
|
||||
*/
|
||||
asn_dec_rval_t
|
||||
BOOLEAN_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
|
||||
asn_TYPE_descriptor_t *td,
|
||||
void **bool_value, const void *buf_ptr, size_t size,
|
||||
int tag_mode) {
|
||||
BOOLEAN_t *st = (BOOLEAN_t *)*bool_value;
|
||||
asn_dec_rval_t rval;
|
||||
ber_tlv_len_t length;
|
||||
ber_tlv_len_t lidx;
|
||||
|
||||
if(st == NULL) {
|
||||
st = (BOOLEAN_t *)(*bool_value = CALLOC(1, sizeof(*st)));
|
||||
if(st == NULL) {
|
||||
rval.code = RC_FAIL;
|
||||
rval.consumed = 0;
|
||||
return rval;
|
||||
}
|
||||
}
|
||||
|
||||
ASN_DEBUG("Decoding %s as BOOLEAN (tm=%d)",
|
||||
td->name, tag_mode);
|
||||
|
||||
/*
|
||||
* Check tags.
|
||||
*/
|
||||
rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size,
|
||||
tag_mode, 0, &length, 0);
|
||||
if(rval.code != RC_OK)
|
||||
return rval;
|
||||
|
||||
ASN_DEBUG("Boolean length is %d bytes", (int)length);
|
||||
|
||||
buf_ptr = ((const char *)buf_ptr) + rval.consumed;
|
||||
size -= rval.consumed;
|
||||
if(length > (ber_tlv_len_t)size) {
|
||||
rval.code = RC_WMORE;
|
||||
rval.consumed = 0;
|
||||
return rval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute boolean value.
|
||||
*/
|
||||
for(*st = 0, lidx = 0;
|
||||
(lidx < length) && *st == 0; lidx++) {
|
||||
/*
|
||||
* Very simple approach: read bytes until the end or
|
||||
* value is already TRUE.
|
||||
* BOOLEAN is not supposed to contain meaningful data anyway.
|
||||
*/
|
||||
*st |= ((const uint8_t *)buf_ptr)[lidx];
|
||||
}
|
||||
|
||||
rval.code = RC_OK;
|
||||
rval.consumed += length;
|
||||
|
||||
ASN_DEBUG("Took %ld/%ld bytes to encode %s, value=%d",
|
||||
(long)rval.consumed, (long)length,
|
||||
td->name, *st);
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
BOOLEAN_encode_der(asn_TYPE_descriptor_t *td, void *sptr,
|
||||
int tag_mode, ber_tlv_tag_t tag,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
asn_enc_rval_t erval;
|
||||
BOOLEAN_t *st = (BOOLEAN_t *)sptr;
|
||||
|
||||
erval.encoded = der_write_tags(td, 1, tag_mode, 0, tag, cb, app_key);
|
||||
if(erval.encoded == -1) {
|
||||
erval.failed_type = td;
|
||||
erval.structure_ptr = sptr;
|
||||
return erval;
|
||||
}
|
||||
|
||||
if(cb) {
|
||||
uint8_t bool_value;
|
||||
|
||||
bool_value = *st ? 0xff : 0; /* 0xff mandated by DER */
|
||||
|
||||
if(cb(&bool_value, 1, app_key) < 0) {
|
||||
erval.encoded = -1;
|
||||
erval.failed_type = td;
|
||||
erval.structure_ptr = sptr;
|
||||
return erval;
|
||||
}
|
||||
}
|
||||
|
||||
erval.encoded += 1;
|
||||
|
||||
_ASN_ENCODED_OK(erval);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Decode the chunk of XML text encoding INTEGER.
|
||||
*/
|
||||
static enum xer_pbd_rval
|
||||
BOOLEAN__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chunk_buf, size_t chunk_size) {
|
||||
BOOLEAN_t *st = (BOOLEAN_t *)sptr;
|
||||
const char *p = (const char *)chunk_buf;
|
||||
|
||||
(void)td;
|
||||
|
||||
if(chunk_size && p[0] == 0x3c /* '<' */) {
|
||||
switch(xer_check_tag(chunk_buf, chunk_size, "false")) {
|
||||
case XCT_BOTH:
|
||||
/* "<false/>" */
|
||||
*st = 0;
|
||||
break;
|
||||
case XCT_UNKNOWN_BO:
|
||||
if(xer_check_tag(chunk_buf, chunk_size, "true")
|
||||
!= XCT_BOTH)
|
||||
return XPBD_BROKEN_ENCODING;
|
||||
/* "<true/>" */
|
||||
*st = 1; /* Or 0xff as in DER?.. */
|
||||
break;
|
||||
default:
|
||||
return XPBD_BROKEN_ENCODING;
|
||||
}
|
||||
return XPBD_BODY_CONSUMED;
|
||||
} else {
|
||||
if(xer_is_whitespace(chunk_buf, chunk_size))
|
||||
return XPBD_NOT_BODY_IGNORE;
|
||||
else
|
||||
return XPBD_BROKEN_ENCODING;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
asn_dec_rval_t
|
||||
BOOLEAN_decode_xer(asn_codec_ctx_t *opt_codec_ctx,
|
||||
asn_TYPE_descriptor_t *td, void **sptr, const char *opt_mname,
|
||||
const void *buf_ptr, size_t size) {
|
||||
|
||||
return xer_decode_primitive(opt_codec_ctx, td,
|
||||
sptr, sizeof(BOOLEAN_t), opt_mname, buf_ptr, size,
|
||||
BOOLEAN__xer_body_decode);
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
BOOLEAN_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
|
||||
int ilevel, enum xer_encoder_flags_e flags,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
const BOOLEAN_t *st = (const BOOLEAN_t *)sptr;
|
||||
asn_enc_rval_t er;
|
||||
|
||||
(void)ilevel;
|
||||
(void)flags;
|
||||
|
||||
if(!st) _ASN_ENCODE_FAILED;
|
||||
|
||||
if(*st) {
|
||||
_ASN_CALLBACK("<true/>", 7);
|
||||
er.encoded = 7;
|
||||
} else {
|
||||
_ASN_CALLBACK("<false/>", 8);
|
||||
er.encoded = 8;
|
||||
}
|
||||
|
||||
_ASN_ENCODED_OK(er);
|
||||
cb_failed:
|
||||
_ASN_ENCODE_FAILED;
|
||||
}
|
||||
|
||||
int
|
||||
BOOLEAN_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
const BOOLEAN_t *st = (const BOOLEAN_t *)sptr;
|
||||
const char *buf;
|
||||
size_t buflen;
|
||||
|
||||
(void)td; /* Unused argument */
|
||||
(void)ilevel; /* Unused argument */
|
||||
|
||||
if(st) {
|
||||
if(*st) {
|
||||
buf = "TRUE";
|
||||
buflen = 4;
|
||||
} else {
|
||||
buf = "FALSE";
|
||||
buflen = 5;
|
||||
}
|
||||
} else {
|
||||
buf = "<absent>";
|
||||
buflen = 8;
|
||||
}
|
||||
|
||||
return (cb(buf, buflen, app_key) < 0) ? -1 : 0;
|
||||
}
|
||||
|
||||
void
|
||||
BOOLEAN_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) {
|
||||
if(td && ptr && !contents_only) {
|
||||
FREEMEM(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
asn_dec_rval_t
|
||||
BOOLEAN_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
|
||||
asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
|
||||
asn_dec_rval_t rv;
|
||||
BOOLEAN_t *st = (BOOLEAN_t *)*sptr;
|
||||
|
||||
(void)opt_codec_ctx;
|
||||
(void)constraints;
|
||||
|
||||
if(!st) {
|
||||
st = (BOOLEAN_t *)(*sptr = MALLOC(sizeof(*st)));
|
||||
if(!st) _ASN_DECODE_FAILED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract a single bit
|
||||
*/
|
||||
switch(per_get_few_bits(pd, 1)) {
|
||||
case 1: *st = 1; break;
|
||||
case 0: *st = 0; break;
|
||||
case -1: default: _ASN_DECODE_FAILED;
|
||||
}
|
||||
|
||||
ASN_DEBUG("%s decoded as %s", td->name, *st ? "TRUE" : "FALSE");
|
||||
|
||||
rv.code = RC_OK;
|
||||
rv.consumed = 1;
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
asn_enc_rval_t
|
||||
BOOLEAN_encode_uper(asn_TYPE_descriptor_t *td,
|
||||
asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
|
||||
const BOOLEAN_t *st = (const BOOLEAN_t *)sptr;
|
||||
asn_enc_rval_t er;
|
||||
|
||||
(void)constraints;
|
||||
|
||||
if(!st) _ASN_ENCODE_FAILED;
|
||||
|
||||
per_put_few_bits(po, *st ? 1 : 0, 1);
|
||||
|
||||
_ASN_ENCODED_OK(er);
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/*-
|
||||
* Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#ifndef _BOOLEAN_H_
|
||||
#define _BOOLEAN_H_
|
||||
|
||||
#include <asn_application.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The underlying integer may contain various values, but everything
|
||||
* non-zero is capped to 0xff by the DER encoder. The BER decoder may
|
||||
* yield non-zero values different from 1, beware.
|
||||
*/
|
||||
typedef int BOOLEAN_t;
|
||||
|
||||
extern asn_TYPE_descriptor_t asn_DEF_BOOLEAN;
|
||||
|
||||
asn_struct_free_f BOOLEAN_free;
|
||||
asn_struct_print_f BOOLEAN_print;
|
||||
ber_type_decoder_f BOOLEAN_decode_ber;
|
||||
der_type_encoder_f BOOLEAN_encode_der;
|
||||
xer_type_decoder_f BOOLEAN_decode_xer;
|
||||
xer_type_encoder_f BOOLEAN_encode_xer;
|
||||
per_type_decoder_f BOOLEAN_decode_uper;
|
||||
per_type_encoder_f BOOLEAN_encode_uper;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BOOLEAN_H_ */
|
@ -0,0 +1,71 @@
|
||||
/*-
|
||||
* Copyright (c) 2003, 2005, 2006 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include <asn_internal.h>
|
||||
#include <ENUMERATED.h>
|
||||
#include <NativeEnumerated.h>
|
||||
#include <asn_codecs_prim.h> /* Encoder and decoder of a primitive type */
|
||||
|
||||
/*
|
||||
* ENUMERATED basic type description.
|
||||
*/
|
||||
static ber_tlv_tag_t asn_DEF_ENUMERATED_tags[] = {
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (10 << 2))
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_ENUMERATED = {
|
||||
"ENUMERATED",
|
||||
"ENUMERATED",
|
||||
ASN__PRIMITIVE_TYPE_free,
|
||||
INTEGER_print, /* Implemented in terms of INTEGER */
|
||||
asn_generic_no_constraint,
|
||||
ber_decode_primitive,
|
||||
INTEGER_encode_der, /* Implemented in terms of INTEGER */
|
||||
INTEGER_decode_xer, /* This is temporary! */
|
||||
INTEGER_encode_xer,
|
||||
ENUMERATED_decode_uper, /* Unaligned PER decoder */
|
||||
ENUMERATED_encode_uper, /* Unaligned PER encoder */
|
||||
0, /* Use generic outmost tag fetcher */
|
||||
asn_DEF_ENUMERATED_tags,
|
||||
sizeof(asn_DEF_ENUMERATED_tags) / sizeof(asn_DEF_ENUMERATED_tags[0]),
|
||||
asn_DEF_ENUMERATED_tags, /* Same as above */
|
||||
sizeof(asn_DEF_ENUMERATED_tags) / sizeof(asn_DEF_ENUMERATED_tags[0]),
|
||||
0, /* No PER visible constraints */
|
||||
0, 0, /* No members */
|
||||
0 /* No specifics */
|
||||
};
|
||||
|
||||
asn_dec_rval_t
|
||||
ENUMERATED_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
|
||||
asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
|
||||
asn_dec_rval_t rval;
|
||||
ENUMERATED_t *st = (ENUMERATED_t *)*sptr;
|
||||
long value;
|
||||
void *vptr = &value;
|
||||
|
||||
if(!st) {
|
||||
st = (ENUMERATED_t *)(*sptr = CALLOC(1, sizeof(*st)));
|
||||
if(!st) _ASN_DECODE_FAILED;
|
||||
}
|
||||
|
||||
rval = NativeEnumerated_decode_uper(opt_codec_ctx, td, constraints,
|
||||
(void **)&vptr, pd);
|
||||
if(rval.code == RC_OK)
|
||||
if(asn_long2INTEGER(st, value))
|
||||
rval.code = RC_FAIL;
|
||||
return rval;
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
ENUMERATED_encode_uper(asn_TYPE_descriptor_t *td,
|
||||
asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
|
||||
ENUMERATED_t *st = (ENUMERATED_t *)sptr;
|
||||
long value;
|
||||
|
||||
if(asn_INTEGER2long(st, &value))
|
||||
_ASN_ENCODE_FAILED;
|
||||
|
||||
return NativeEnumerated_encode_uper(td, constraints, &value, po);
|
||||
}
|
||||
|
@ -0,0 +1,25 @@
|
||||
/*-
|
||||
* Copyright (c) 2003, 2005 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#ifndef _ENUMERATED_H_
|
||||
#define _ENUMERATED_H_
|
||||
|
||||
#include <INTEGER.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef INTEGER_t ENUMERATED_t; /* Implemented via INTEGER */
|
||||
|
||||
extern asn_TYPE_descriptor_t asn_DEF_ENUMERATED;
|
||||
|
||||
per_type_decoder_f ENUMERATED_decode_uper;
|
||||
per_type_encoder_f ENUMERATED_encode_uper;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ENUMERATED_H_ */
|
@ -0,0 +1,37 @@
|
||||
/*-
|
||||
* Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include <asn_internal.h>
|
||||
#include <GeneralString.h>
|
||||
|
||||
/*
|
||||
* GeneralString basic type description.
|
||||
*/
|
||||
static ber_tlv_tag_t asn_DEF_GeneralString_tags[] = {
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (27 << 2)), /* [UNIVERSAL 27] IMPLICIT ...*/
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_GeneralString = {
|
||||
"GeneralString",
|
||||
"GeneralString",
|
||||
OCTET_STRING_free,
|
||||
OCTET_STRING_print, /* non-ascii string */
|
||||
asn_generic_unknown_constraint,
|
||||
OCTET_STRING_decode_ber, /* Implemented in terms of OCTET STRING */
|
||||
OCTET_STRING_encode_der,
|
||||
OCTET_STRING_decode_xer_hex,
|
||||
OCTET_STRING_encode_xer,
|
||||
0, 0,
|
||||
0, /* Use generic outmost tag fetcher */
|
||||
asn_DEF_GeneralString_tags,
|
||||
sizeof(asn_DEF_GeneralString_tags)
|
||||
/ sizeof(asn_DEF_GeneralString_tags[0]) - 1,
|
||||
asn_DEF_GeneralString_tags,
|
||||
sizeof(asn_DEF_GeneralString_tags)
|
||||
/ sizeof(asn_DEF_GeneralString_tags[0]),
|
||||
0, /* No PER visible constraints */
|
||||
0, 0, /* No members */
|
||||
0 /* No specifics */
|
||||
};
|
||||
|
@ -0,0 +1,22 @@
|
||||
/*-
|
||||
* Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#ifndef _GeneralString_H_
|
||||
#define _GeneralString_H_
|
||||
|
||||
#include <OCTET_STRING.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef OCTET_STRING_t GeneralString_t; /* Implemented via OCTET STRING */
|
||||
|
||||
extern asn_TYPE_descriptor_t asn_DEF_GeneralString;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _GeneralString_H_ */
|
@ -0,0 +1,683 @@
|
||||
/*-
|
||||
* Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#define _POSIX_PTHREAD_SEMANTICS /* for Sun */
|
||||
#define _REENTRANT /* for Sun */
|
||||
#include <asn_internal.h>
|
||||
#include <GeneralizedTime.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
#include "/usr/include/time.h"
|
||||
#else
|
||||
#include <time.h>
|
||||
#endif /* __CYGWIN__ */
|
||||
|
||||
#if defined(WIN32)
|
||||
#pragma message( "PLEASE STOP AND READ!")
|
||||
#pragma message( " localtime_r is implemented via localtime(), which may be not thread-safe.")
|
||||
#pragma message( " gmtime_r is implemented via gmtime(), which may be not thread-safe.")
|
||||
#pragma message( " ")
|
||||
#pragma message( " You must fix the code by inserting appropriate locking")
|
||||
#pragma message( " if you want to use asn_GT2time() or asn_UT2time().")
|
||||
#pragma message( "PLEASE STOP AND READ!")
|
||||
|
||||
static struct tm *localtime_r(const time_t *tloc, struct tm *result) {
|
||||
struct tm *tm;
|
||||
if((tm = localtime(tloc)))
|
||||
return memcpy(result, tm, sizeof(struct tm));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct tm *gmtime_r(const time_t *tloc, struct tm *result) {
|
||||
struct tm *tm;
|
||||
if((tm = gmtime(tloc)))
|
||||
return memcpy(result, tm, sizeof(struct tm));
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define tzset() _tzset()
|
||||
#define putenv(c) _putenv(c)
|
||||
#define _EMULATE_TIMEGM
|
||||
|
||||
#endif /* WIN32 */
|
||||
|
||||
#if defined(sun) || defined(_sun_) || defined(__solaris__)
|
||||
#define _EMULATE_TIMEGM
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Where to look for offset from GMT, Phase I.
|
||||
* Several platforms are known.
|
||||
*/
|
||||
#if defined(__FreeBSD__) \
|
||||
|| (defined(__GNUC__) && defined(__APPLE_CC__)) \
|
||||
|| (defined __GLIBC__ && __GLIBC__ >= 2)
|
||||
#undef HAVE_TM_GMTOFF
|
||||
#define HAVE_TM_GMTOFF
|
||||
#endif /* BSDs and newer glibc */
|
||||
|
||||
/*
|
||||
* Where to look for offset from GMT, Phase II.
|
||||
*/
|
||||
#ifdef HAVE_TM_GMTOFF
|
||||
#define GMTOFF(tm) ((tm).tm_gmtoff)
|
||||
#else /* HAVE_TM_GMTOFF */
|
||||
#define GMTOFF(tm) (-timezone)
|
||||
#endif /* HAVE_TM_GMTOFF */
|
||||
|
||||
#if (defined(_EMULATE_TIMEGM) || !defined(HAVE_TM_GMTOFF))
|
||||
#warning "PLEASE STOP AND READ!"
|
||||
#warning " timegm() is implemented via getenv(\"TZ\")/setenv(\"TZ\"), which may be not thread-safe."
|
||||
#warning " "
|
||||
#warning " You must fix the code by inserting appropriate locking"
|
||||
#warning " if you want to use asn_GT2time() or asn_UT2time()."
|
||||
#warning "PLEASE STOP AND READ!"
|
||||
#endif /* _EMULATE_TIMEGM */
|
||||
|
||||
/*
|
||||
* Override our GMTOFF decision for other known platforms.
|
||||
*/
|
||||
#ifdef __CYGWIN__
|
||||
#undef GMTOFF
|
||||
static long GMTOFF(struct tm a){
|
||||
struct tm *lt;
|
||||
time_t local_time, gmt_time;
|
||||
long zone;
|
||||
|
||||
tzset();
|
||||
gmt_time = time (NULL);
|
||||
|
||||
lt = gmtime(&gmt_time);
|
||||
|
||||
local_time = mktime(lt);
|
||||
return (gmt_time - local_time);
|
||||
}
|
||||
#define _EMULATE_TIMEGM
|
||||
|
||||
#endif /* __CYGWIN__ */
|
||||
|
||||
#define ATZVARS do { \
|
||||
char tzoldbuf[64]; \
|
||||
char *tzold
|
||||
#define ATZSAVETZ do { \
|
||||
tzold = getenv("TZ"); \
|
||||
if(tzold) { \
|
||||
size_t tzlen = strlen(tzold); \
|
||||
if(tzlen < sizeof(tzoldbuf)) \
|
||||
tzold = memcpy(tzoldbuf, tzold, tzlen + 1); \
|
||||
else \
|
||||
tzold = strdup(tzold); /* Ignore error */ \
|
||||
setenv("TZ", "UTC", 1); \
|
||||
} \
|
||||
tzset(); \
|
||||
} while(0)
|
||||
#define ATZOLDTZ do { \
|
||||
if (tzold) { \
|
||||
setenv("TZ", tzold, 1); \
|
||||
*tzoldbuf = 0; \
|
||||
if(tzold != tzoldbuf) \
|
||||
FREEMEM(tzold); \
|
||||
} else { \
|
||||
unsetenv("TZ"); \
|
||||
} \
|
||||
tzset(); \
|
||||
} while(0); } while(0);
|
||||
|
||||
#ifdef _EMULATE_TIMEGM
|
||||
static time_t timegm(struct tm *tm) {
|
||||
time_t tloc;
|
||||
ATZVARS;
|
||||
ATZSAVETZ;
|
||||
tloc = mktime(tm);
|
||||
ATZOLDTZ;
|
||||
return tloc;
|
||||
}
|
||||
#endif /* _EMULATE_TIMEGM */
|
||||
|
||||
|
||||
#ifndef __ASN_INTERNAL_TEST_MODE__
|
||||
|
||||
/*
|
||||
* GeneralizedTime basic type description.
|
||||
*/
|
||||
static ber_tlv_tag_t asn_DEF_GeneralizedTime_tags[] = {
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (24 << 2)), /* [UNIVERSAL 24] IMPLICIT ...*/
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (26 << 2)), /* [UNIVERSAL 26] IMPLICIT ...*/
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_GeneralizedTime = {
|
||||
"GeneralizedTime",
|
||||
"GeneralizedTime",
|
||||
OCTET_STRING_free,
|
||||
GeneralizedTime_print,
|
||||
GeneralizedTime_constraint, /* Check validity of time */
|
||||
OCTET_STRING_decode_ber, /* Implemented in terms of OCTET STRING */
|
||||
GeneralizedTime_encode_der,
|
||||
OCTET_STRING_decode_xer_utf8,
|
||||
GeneralizedTime_encode_xer,
|
||||
0, 0,
|
||||
0, /* Use generic outmost tag fetcher */
|
||||
asn_DEF_GeneralizedTime_tags,
|
||||
sizeof(asn_DEF_GeneralizedTime_tags)
|
||||
/ sizeof(asn_DEF_GeneralizedTime_tags[0]) - 2,
|
||||
asn_DEF_GeneralizedTime_tags,
|
||||
sizeof(asn_DEF_GeneralizedTime_tags)
|
||||
/ sizeof(asn_DEF_GeneralizedTime_tags[0]),
|
||||
0, /* No PER visible constraints */
|
||||
0, 0, /* No members */
|
||||
0 /* No specifics */
|
||||
};
|
||||
|
||||
#endif /* __ASN_INTERNAL_TEST_MODE__ */
|
||||
|
||||
/*
|
||||
* Check that the time looks like the time.
|
||||
*/
|
||||
int
|
||||
GeneralizedTime_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
|
||||
asn_app_constraint_failed_f *ctfailcb, void *app_key) {
|
||||
const GeneralizedTime_t *st = (const GeneralizedTime_t *)sptr;
|
||||
time_t tloc;
|
||||
|
||||
errno = EPERM; /* Just an unlikely error code */
|
||||
tloc = asn_GT2time(st, 0, 0);
|
||||
if(tloc == -1 && errno != EPERM) {
|
||||
_ASN_CTFAIL(app_key, td,
|
||||
"%s: Invalid time format: %s (%s:%d)",
|
||||
td->name, strerror(errno), __FILE__, __LINE__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
GeneralizedTime_encode_der(asn_TYPE_descriptor_t *td, void *sptr,
|
||||
int tag_mode, ber_tlv_tag_t tag,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
GeneralizedTime_t *st = (GeneralizedTime_t *)sptr;
|
||||
asn_enc_rval_t erval;
|
||||
int fv, fd; /* seconds fraction value and number of digits */
|
||||
struct tm tm;
|
||||
time_t tloc;
|
||||
|
||||
/*
|
||||
* Encode as a canonical DER.
|
||||
*/
|
||||
errno = EPERM;
|
||||
tloc = asn_GT2time_frac(st, &fv, &fd, &tm, 1); /* Recognize time */
|
||||
if(tloc == -1 && errno != EPERM)
|
||||
/* Failed to recognize time. Fail completely. */
|
||||
_ASN_ENCODE_FAILED;
|
||||
|
||||
st = asn_time2GT_frac(0, &tm, fv, fd, 1); /* Save time canonically */
|
||||
if(!st) _ASN_ENCODE_FAILED; /* Memory allocation failure. */
|
||||
|
||||
erval = OCTET_STRING_encode_der(td, st, tag_mode, tag, cb, app_key);
|
||||
|
||||
FREEMEM(st->buf);
|
||||
FREEMEM(st);
|
||||
|
||||
return erval;
|
||||
}
|
||||
|
||||
#ifndef __ASN_INTERNAL_TEST_MODE__
|
||||
|
||||
asn_enc_rval_t
|
||||
GeneralizedTime_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
|
||||
int ilevel, enum xer_encoder_flags_e flags,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
|
||||
if(flags & XER_F_CANONICAL) {
|
||||
GeneralizedTime_t *gt;
|
||||
asn_enc_rval_t rv;
|
||||
int fv, fd; /* fractional parts */
|
||||
struct tm tm;
|
||||
|
||||
errno = EPERM;
|
||||
if(asn_GT2time_frac((GeneralizedTime_t *)sptr,
|
||||
&fv, &fd, &tm, 1) == -1
|
||||
&& errno != EPERM)
|
||||
_ASN_ENCODE_FAILED;
|
||||
|
||||
gt = asn_time2GT_frac(0, &tm, fv, fd, 1);
|
||||
if(!gt) _ASN_ENCODE_FAILED;
|
||||
|
||||
rv = OCTET_STRING_encode_xer_utf8(td, sptr, ilevel, flags,
|
||||
cb, app_key);
|
||||
ASN_STRUCT_FREE(asn_DEF_GeneralizedTime, gt);
|
||||
return rv;
|
||||
} else {
|
||||
return OCTET_STRING_encode_xer_utf8(td, sptr, ilevel, flags,
|
||||
cb, app_key);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* __ASN_INTERNAL_TEST_MODE__ */
|
||||
|
||||
int
|
||||
GeneralizedTime_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
const GeneralizedTime_t *st = (const GeneralizedTime_t *)sptr;
|
||||
|
||||
(void)td; /* Unused argument */
|
||||
(void)ilevel; /* Unused argument */
|
||||
|
||||
if(st && st->buf) {
|
||||
char buf[32];
|
||||
struct tm tm;
|
||||
int ret;
|
||||
|
||||
errno = EPERM;
|
||||
if(asn_GT2time(st, &tm, 1) == -1 && errno != EPERM)
|
||||
return (cb("<bad-value>", 11, app_key) < 0) ? -1 : 0;
|
||||
|
||||
ret = snprintf(buf, sizeof(buf),
|
||||
"%04d-%02d-%02d %02d:%02d:%02d (GMT)",
|
||||
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
|
||||
tm.tm_hour, tm.tm_min, tm.tm_sec);
|
||||
assert(ret > 0 && ret < (int)sizeof(buf));
|
||||
return (cb(buf, ret, app_key) < 0) ? -1 : 0;
|
||||
} else {
|
||||
return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
time_t
|
||||
asn_GT2time(const GeneralizedTime_t *st, struct tm *ret_tm, int as_gmt) {
|
||||
return asn_GT2time_frac(st, 0, 0, ret_tm, as_gmt);
|
||||
}
|
||||
|
||||
time_t
|
||||
asn_GT2time_prec(const GeneralizedTime_t *st, int *frac_value, int frac_digits, struct tm *ret_tm, int as_gmt) {
|
||||
time_t tloc;
|
||||
int fv, fd = 0;
|
||||
|
||||
if(frac_value)
|
||||
tloc = asn_GT2time_frac(st, &fv, &fd, ret_tm, as_gmt);
|
||||
else
|
||||
return asn_GT2time_frac(st, 0, 0, ret_tm, as_gmt);
|
||||
if(fd == 0 || frac_digits <= 0) {
|
||||
*frac_value = 0;
|
||||
} else {
|
||||
while(fd > frac_digits)
|
||||
fv /= 10, fd--;
|
||||
while(fd < frac_digits) {
|
||||
int new_fv = fv * 10;
|
||||
if(new_fv / 10 != fv) {
|
||||
/* Too long precision request */
|
||||
fv = 0;
|
||||
break;
|
||||
}
|
||||
fv = new_fv, fd++;
|
||||
}
|
||||
|
||||
*frac_value = fv;
|
||||
}
|
||||
|
||||
return tloc;
|
||||
}
|
||||
|
||||
time_t
|
||||
asn_GT2time_frac(const GeneralizedTime_t *st, int *frac_value, int *frac_digits, struct tm *ret_tm, int as_gmt) {
|
||||
struct tm tm_s;
|
||||
uint8_t *buf;
|
||||
uint8_t *end;
|
||||
int gmtoff_h = 0;
|
||||
int gmtoff_m = 0;
|
||||
int gmtoff = 0; /* h + m */
|
||||
int offset_specified = 0;
|
||||
int fvalue = 0;
|
||||
int fdigits = 0;
|
||||
time_t tloc;
|
||||
|
||||
if(!st || !st->buf) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
} else {
|
||||
buf = st->buf;
|
||||
end = buf + st->size;
|
||||
}
|
||||
|
||||
if(st->size < 10) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode first 10 bytes: "AAAAMMJJhh"
|
||||
*/
|
||||
memset(&tm_s, 0, sizeof(tm_s));
|
||||
#undef B2F
|
||||
#undef B2T
|
||||
#define B2F(var) do { \
|
||||
unsigned ch = *buf; \
|
||||
if(ch < 0x30 || ch > 0x39) { \
|
||||
errno = EINVAL; \
|
||||
return -1; \
|
||||
} else { \
|
||||
var = var * 10 + (ch - 0x30); \
|
||||
buf++; \
|
||||
} \
|
||||
} while(0)
|
||||
#define B2T(var) B2F(tm_s.var)
|
||||
|
||||
B2T(tm_year); /* 1: A */
|
||||
B2T(tm_year); /* 2: A */
|
||||
B2T(tm_year); /* 3: A */
|
||||
B2T(tm_year); /* 4: A */
|
||||
B2T(tm_mon); /* 5: M */
|
||||
B2T(tm_mon); /* 6: M */
|
||||
B2T(tm_mday); /* 7: J */
|
||||
B2T(tm_mday); /* 8: J */
|
||||
B2T(tm_hour); /* 9: h */
|
||||
B2T(tm_hour); /* 0: h */
|
||||
|
||||
if(buf == end) goto local_finish;
|
||||
|
||||
/*
|
||||