⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 decode.cpp

📁 ASN.1样例工程代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	    }
        tobjp = pobjp->_ptr;
        }
    }
while (tobjp &&
    (tobjp->_tag == ASN_CHOICE || (tobjp->_flags & ASN_POINTER_FLAG)));
c[1] = 0;
return tobjp;
}

/* char_table masks  defined in asn.h
#define ASN_NUMERIC_MASK  1
#define ASN_PRINTABLE_MASK 4
#define ASN_T61_MASK       8
*/
static char char_table[] = "\
@@@@@@@@H@H@HHHH@@@@@@@@@HHH@H@@\
MHHHHHHHLLHHMMMMMMMMMMMMMMHHHHHH\
LNNNNNNNNNNNNNNNNNNNNNNNNNNHHH@H\
@LLLLLLLLLLLLLLLLLLLLLLLLLLHH@@@\
@@@@@@@@@@@HH@@@@@@@@@@@@@@H@@@@\
@HHHHHHHH@@H@@@@HHHHHHHHH@@HHHHH\
@HHHHHHHHHHHHHHH@@@@@@@@@@@H@@@@\
HHHHH@HHHHHHHHHHHHHHHHHHHHHHHHH@";

int AsnObj::write(const uchar *from, ulong lth)
{
/**
Procedure:
1. IF it's an object identifier (tables are only derived), call that write
   ELSE IF it's a bit string, call that write
   ELSE IF it's forbidden, return error
   ELSE return what _write returns
**/
AsnObjectIdentifier *objp;
AsnObj *tobjp = this;
int ansr;
if (!from) return asn_obj_err(ASN_NULL_PTR);
if ((_flags & ASN_DEFINED_FLAG) && !(tobjp = check_defined(tobjp)))
    return asn_obj_err(ASN_NO_DEF_ERR);
objp = (AsnObjectIdentifier *)tobjp;
if (tobjp->_type == ASN_OBJ_ID) ansr = objp->write((const char *)from, lth);
else if (tobjp->_type == ASN_BITSTRING)
    ansr = ((AsnBitString *)tobjp)->write(from, lth, 0);
else if (tobjp->_type == ASN_NONE) ansr = asn_obj_err(ASN_NONE_ERR);
else ansr = tobjp->_write(from, lth);
return ansr;
}

int AsnObj::_write(const uchar *from, ulong lth)
{
/**
Procedure:
1. IF it or any ancestor is the last member of a SET/SEQUENCE OF
        Return error
   IF it's a NULL or a NONE, report invalid type
   IF it's a choice or defined
	IF it's defined
    	    Search for the defined item
    	    IF none, return -1
        IF it's (still) a choice
    	    IF there's no mask in the first sub-object,  return -1
    	    Scan the input to find the type
    	    Scan the choices to find the best fit
1a. IF any higher object is a 'defined' but isn't defined yet, return -1
2. IF it's primitive OR it has no sub (an ANY)
        IF it's a BOOLEAN AND it's more than one octet, return -1
	IF there's a mask, check the contents of 'from'
	IF the size is out of range, return -1
	IF there's a table
	    Search the table for this string
	    IF none found, return -1
	    Save the index into the table
	IF this is an INTEGER, delete leading non-significant bytes
	IF this is an ENUMERATED OR an INTEGER with defined values
	    IF the value to be put in isn't defined
                Return -1 with undefined-value message
        IF it's an enumerated type
    	    IF parent is a bit string
		IF it's empty, make a big enough _valp (including leading byte)
		ELSE IF it's too small
		    Get a big enough buffer
		    Read the string into the buffer
		    Write it to the parent
                Put value into requested bit
    	    ELSE IF parent is an integer
                Return result of writing value of tag into parent
	ELSE
            IF there is already a valp, delete it
            Make a new valp
    	    Fill it
	IF it's a time AND its value is bad, return error
	Mark this filled
3.	Mark all higher objects filled in and clear non-chosen choices
	IF object is a time AND it is invalid, report error
4.      IF there's a table, mark the defined member chosen and clear any others
	Return the length written
5. FOR all objects in this chain
        Decode them, advancing the pointer
   Return count of what was written
**/
int i, table_index, map_num;
long tmp;
const uchar *c, *e = &from[lth];
AsnObj *objp = this, *subp, *superp, *tobjp;
AsnTableObj *ntablep;
							    /* step 1 */
if ((i = check_of(objp)) < 0) return i;
if (_type == ASN_NONE || (_type == ASN_NULL && lth > 0))
    return asn_obj_err((_type == ASN_NONE)? ASN_NONE_ERR: ASN_TYPE_ERR);
if (objp->_type == ASN_CHOICE)
    {
    if ((_flags & ASN_DEFINED_FLAG) && !(objp = check_defined(objp)))
	return asn_obj_err(ASN_NO_DEF_ERR);
    if (objp->_type == ASN_CHOICE)
        {
        if (!objp->_sub->_mask) return asn_obj_err(ASN_CHOICE_ERR);
        for (i = 0xFF, c = from; c < e; i &= (char_table[*c++]));
        for (tobjp = objp->_sub; tobjp && !(tobjp->_mask & i); tobjp =
            tobjp->_next);
        if (c < e || !tobjp)
	    {
	    asn_obj_err(ASN_NO_CHOICE_ERR);
            return -1;
	    }
	for (subp = objp->_sub; subp; subp->clear(), subp = subp->_next);
        objp = tobjp;
        }
    }
for(superp = objp->_supra; superp; superp = superp->_supra) /* step 1a */
    {
    if (superp->_type == ASN_CHOICE && (superp->_flags & ASN_DEFINED_FLAG) )
	{
        for (tobjp = superp->_sub; tobjp && !(tobjp->_flags & ASN_CHOSEN_FLAG);
    	    tobjp = tobjp->_next);
        if (!tobjp) return asn_obj_err(ASN_NO_DEF_ERR);
	}
    }
							    /* step 2 */
if (!(objp->_type & ASN_CONSTRUCTED) || !objp->_sub) // use _type, not _tag
    {                                           // in case of explicit tagging
    if (objp->_type == ASN_BOOLEAN && lth != 1)
        return asn_obj_err(ASN_BOUNDS_ERR);
    if (objp->_mask && (i = check_mask(objp, from, lth)) < 0)
	return i;
    if (objp->_max && (lth > objp->_max || lth < objp->_min))
        return asn_obj_err(ASN_BOUNDS_ERR);
    if ((objp->_flags & ASN_TABLE_FLAG))
	{
        for(table_index = 0, ntablep = (AsnTableObj *)objp->_sub;
            ntablep && compare(ntablep, from, (int)lth);
            ntablep = (AsnTableObj *)ntablep->_next, table_index++);
	if (!ntablep) return asn_obj_err(ASN_DEFINER_ERR);
	}
    if (objp->_type == ASN_INTEGER)
	{
	while (lth > 1 && ((!*from && !(from[1] & 0x80)) ||
            (*from == 0xFF && (from[1] & 0x80))))
	    {
	    from++;
	    lth--;
	    }
	}
    if (objp->_sub && (objp->_sub->_flags & ASN_ENUM_FLAG) &&
	(objp->_tag == ASN_INTEGER || objp->_tag == ASN_ENUMERATED))
	{
	long tmp;
	for (tmp = 0, i = lth, c = from; i--; tmp = (tmp << 8) + *c++);
	for (subp = objp->_sub; subp && subp->_tag != tmp; subp =
	    subp->_next);
	if (!subp) return asn_obj_err(ASN_UNDEF_VALUE);
	}
    if ((objp->_flags & ASN_ENUM_FLAG))
        {
	superp = objp->_supra;
        if (superp->_type == ASN_BITSTRING)
    	    {
	    int j, newsize = ((objp->_tag  + 8) >> 3) + 1;
	    if (!superp->_valp)
		superp->_valp = new UcharArray(newsize);
	    else if ((j = (*superp->_valp)[0]) ||
                newsize > superp->_valp->size())
		{
                uchar *tmpc;
		i = superp->size();
		tmpc = (uchar *)calloc(((newsize > i)? newsize: i), 1);
		i = ((AsnBitString *)superp)->read(tmpc, &j);
		((AsnBitString *)superp)->write((const uchar *)tmpc, (ulong)i, 0);
		free(tmpc);
		}
	    for (j = (objp->_tag & 7), i = 0x80; j--; i >>= 1);
	    j = 1 + (objp->_tag >> 3 );
	    if (*from) (*superp->_valp)[j] |= i;
            else (*superp->_valp)[j] &= ~i;
	    superp->_flags |= ASN_FILLED_FLAG;
    	    }
	else if (superp->_type == ASN_INTEGER ||
            superp->_type == ASN_ENUMERATED) return superp->write(objp->_tag);
        else return asn_obj_err(ASN_GEN_ERR);
        }
    else
	{
        if (objp->_valp)
	    {
            delete objp->_valp;
	    objp->_valp = (UcharArray *)0;
	    }
        objp->_valp = new UcharArray(from, lth);
	}
    objp->fill_upward(ASN_FILLED_FLAG);                         /* step 3 */
    if ((objp->_type == ASN_UTCTIME || objp->_type == ASN_GENTIME) &&
	objp->read(&tmp) < 0)
	{
	delete objp->_valp;
        objp->_valp = (UcharArray *)0;
        objp->_flags &= ~(ASN_FILLED_FLAG);
        return asn_obj_err(ASN_TIME_ERR);
	}
    subp = objp;                                                /* step 3 */
    if ((objp->_flags & ASN_TABLE_FLAG) &&                      /* step 4 */
	((AsnTableObj *)objp)->set_definees(table_index) < 0) return -1;
    return lth;
    }
							    /* step 5 */
int of = (objp->_flags & ASN_OF_FLAG);
objp->clear();
for(map_num = 0, c = from, subp = objp->_sub; (subp || of) && c < e; subp =
    subp->_next, map_num++)
    {
    i = subp->decode(c);
    if (!of)      /* in case decode skipped some empty optional items */
        for ( ; subp->_next && !(subp->_flags & ASN_FILLED_FLAG);
            subp = subp->_next, map_num++);
    else     /* because decode inserted the object ahead of subp */
        for (tobjp = subp, subp = objp->_sub, map_num = 0; subp != tobjp &&
            subp->_next != tobjp; subp = subp->_next, map_num++);
    if (i < 0)
        {
	stuff(map_num);
        return (i - (c - from));
	}
    c += i;
    }
return (c - from);
}

int AsnObj::write(long val)
{
/**
Procedure:
1. IF this is ANY DEFINED BY, find which one is defined
   IF current object is neither boolean NOR integer NOR enumerated NOR time
        return -1 with type error msg
2. IF it's either type of time
	Convert the val to a char string for GMT
   ELSE IF it's a boolean
	Set length to 1
        Put val into buf
   ELSE convert val into a string
   Return the length written
**/
int i;
AsnObj *objp = this;
char buf[20], *c;
                                                              /* step 1 */
if ((_flags & ASN_DEFINED_FLAG) && !(objp = check_defined(objp)))
    return asn_obj_err(ASN_NO_DEF_ERR);
if (!objp) return asn_obj_err(ASN_NO_DEF_ERR);
if (objp->_type != ASN_BOOLEAN && objp->_type != ASN_INTEGER &&
    objp->_type != ASN_ENUMERATED && objp->_type != ASN_UTCTIME &&
    objp->_type != ASN_GENTIME) return asn_obj_err(ASN_TYPE_ERR);
							/* step 2 */
if (objp->_type == ASN_UTCTIME || objp->_type == ASN_GENTIME)
    {
    if (val < 0) return asn_obj_err(ASN_TIME_ERR);
    c = (objp->_type == ASN_GENTIME)? &buf[2]: buf;
    i = put_asn_time(c, (ulong)val);
    if (c > buf)    /* make Gen time out of UTC time from put_asn_time() */
	{
	memcpy(buf, ((*c >= 7)? "19": "20"), 2);
	i += 2;
	}
    }
else if (objp->_type == ASN_BOOLEAN)
    {
    i = 1;
    *buf = (val != 0);
    }
else
    {
    long tmp = val;
    if (val < 0) for (i = 0; tmp != -1; tmp >>= 8, i++)
        {                        /* force 0x80 in MSbyte of integer*/
        if (tmp < -0x80 && tmp > -0x100) i++;
        }
    else for (i = 0; tmp; tmp >>= 8, i++)
	{                        /* prevent 0x80 in MSbyte of integer */
	if (tmp >= 0x80 && tmp < 0x100) i++;
	}
    if (!i) i++;
    for (c = &buf[i - 1]; c >= buf; *c-- = val & 0xFF, val >>= 8);
    }
return objp->_write((const uchar *)buf, i);   /* to do the table stuff etc. */
}

int AsnBitString::write(const uchar *from, ulong lth, int shift)
{
short box;
int i;
if (!from) return asn_obj_err(ASN_NULL_PTR);
if ((i = check_of(this)) < 0) return i;
if (_valp)
    {
    delete _valp;
    _valp = (UcharArray *)0;
    }
_valp = new UcharArray(++lth);
(*_valp)[0] = shift;
if (!shift) for (i = 1; i < lth; (*_valp)[i++] = *from++);
else for (i = 1; i < lth; from++)
    {
    box = (short)*from;
    box <<= shift;
    (*_valp)[i++] |= (box >> 8);
    (*_valp)[i]    = (box & 0xFF);
    }
fill_upward(ASN_FILLED_FLAG);
return (lth - 1);
}

int AsnObjectIdentifier::write(const char *from, ulong lth)
{
/**
Procedure:
1. Form first field
   Find out how much space that requires
2. Find out how much space the remaining fields need
3. Convert the dot notation to binary
   Call _write to do the table stuff etc.
**/
const char *c = from, *e = &from[lth];
uchar *buf, *b, *a;
long val, tmp;
int siz, i;
AsnObj *objp = this;
							    /* step 1 */
if (!from) return asn_obj_err(ASN_NULL_PTR);
for (val = 0; c < e && *c != '.'; val = (val * 10) + *c++ - '0');
val *= 40;
for(c++, tmp = 0; c < e && *c != '.'; tmp = (tmp * 10) + *c++ - '0');
tmp += val;
for (val = tmp, siz = 0; tmp; siz++) tmp >>= 7;
							    /* step 2 */
for (c++; c < e && *c; c++)
    {
    for (tmp = 0; *c && c < e && *c != '.'; tmp = (tmp * 10) + *c++ - '0');
    if (!tmp) siz++;
    else for ( ; tmp; siz++) tmp >>= 7;
    }
for(c = from; c < e && *c && *c != '.'; c++);
for(c++; c < e && *c && *c != '.'; c++);          /* c at 2nd dot */
buf = (uchar *)calloc(siz, 1);
							    /* step 3 */
for (tmp = val, siz = 0; tmp; siz++) tmp >>= 7;       /* siz of first field */
					    /* put it into buf */
for (i = siz, tmp = val, b = &buf[siz]; siz--; val >>= 7)
    *(--b) = (uchar)(val & 0x7F) | ((tmp != val)? 0x80: 0);
for (c++; c < e && *c; c++)                       /* now do next fields */
    {
    for (val = 0; c < e && *c && *c != '.'; val = (val * 10) + *c++ - '0');
    if (!val) siz = 1;
    else for (tmp = val, siz = 0; tmp; siz++) tmp >>= 7;
    for(a = &buf[i], i += siz, tmp = val, b = &a[siz]; siz--; val >>= 7)
	*(--b) = (uchar)(val & 0x7F) | ((tmp != val)? 0x80: 0);
    }
lth = objp->_write(buf, i);
free(buf);
return lth;
}

int AsnObj::_append(const uchar *from, ulong lth)
{
int i;
if (_max && vsize() + lth > _max) return asn_obj_err(ASN_BOUNDS_ERR);
if (_mask && (i = check_mask(this, from, lth)) < 0) return i;
_valp->append(from, lth);
return lth;
}

static AsnObj *check_defined(AsnObj *objp)
{
AsnObj *subp;
for (subp = objp->_sub; subp && !(subp->_flags & ASN_CHOSEN_FLAG);
    subp = subp->_next);
return subp;
}

static int check_mask(AsnObj *objp, const uchar *from, int lth)
{
const uchar *c;
for(c = from; lth-- && (char_table[*c] & objp->_mask); c++);
if (lth >= 0)
    {
    asn_obj_err(ASN_MASK_ERR);
    return (from - c);
    }
return 1;
}

static int check_of(AsnObj *objp)
{
for( ; objp; objp = objp->_supra)
    {
    if (objp->_supra && (objp->_supra->_flags & ASN_OF_FLAG) &&
    	!objp->_next) return asn_obj_err(ASN_OF_BOUNDS_ERR);
    }
return 1;
}

static int compare(AsnObj *objp, const uchar *from, int lth)
{
uchar *c = &(*objp->_valp)[0], *e;
if (objp->_valp->size() == 2 && c[0] == 0xFF && c[1] == 0xFF) return 0;
if (lth != objp->_valp->size()) return -1;
for (e = &c[lth]; c < e && *c == *from++; c++);
if (c < e) return -1;
return 0;
}

static ulong put_num (char *to, ulong val, int lth)
{
char *c;
for (c = &to[lth]; c > to; )
    {
    *(--c) = (val % 10) + '0';
    val /= 10;
    }
return val;
}

static int put_asn_time(char *to, ulong time)
{
ushort *mop;
long da, min, sec;
char *c = to;
sec = (time % 60);
time /= 60;
min = (time % 60);
time /= 60;
da = (time % 24);
put_num (&c[UTCSE],(ulong)sec,UTCSESIZ);
put_num (&c[UTCMI],(ulong)min,UTCMISIZ);
put_num (&c[UTCHR],(ulong)da,UTCHRSIZ);
time /= 24;             /* day number */
time += (((UTCBASE - 1) % 4) * 365); /* days since leap year before base year */
da = time  % 1461; /* da # in quadrenniad */
time /= 1461;                        /* quadrenniads since prior leap yr */
sec = ((time * 4) + ((da == 1460)? 3 : (da / 365)) - ((UTCBASE - 1) % 4));
                                /* yrs since base yr */
if (da == 1460) da = 365;
else da %= 365;
for (mop = _mos; da >= *mop; mop++);
if (mop > &_mos[12]) mop--;
if ((sec % 4) == (UTCBASE % 4))  /* leap year */
    {
    if (da == 59) mop--;  /* Feb 29  */
    else if (da > 59 && (da -= 1) < mop[-1]) mop--;
    }
put_num (&c[UTCDA],(ulong)(da + 1 - mop[-1]),UTCDASIZ);
put_num (&c[UTCMO],(ulong)(mop - _mos),UTCMOSIZ);
put_num (&c[UTCYR],(ulong)(sec + UTCBASE),UTCYRSIZ);
c += UTCSE + UTCSESIZ;
*c++ = 'Z';
return (c - to);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -