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

📄 decode.cpp

📁 ASN.1样例工程代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*****************************************************************************
File:     decode.C
Contents: Functions to decode ans write ASN.1 objects.
System:   ASN development.
Created:
Author:   Charles W. Gardiner <gardiner@bbn.com>

Remarks:

COPYRIGHT 1995 BBN Systems and Technologies, A Division of Bolt Beranek and
    Newman Inc.
150 CambridgePark Drive
Cambridge, Ma. 02140
617-873-4000
*****************************************************************************/

#ifndef lint
const char decode_rcsid[]="$Header: /nfs/sub-rosa/u2/IOS_Project/ASN/Dev/rcs/lib/asn_obj/decode.C,v 1.38 1995/09/27 19:57:42 gardiner Exp $";
const char decode_sfcsid[] = "@(#)decode.C 285P";
#endif

#include "includes.h"
#include "asn_error.h"
#include "asn_obj.h"

extern ushort _mos[];

static int check_mask(AsnObj *, const uchar *, int),
    check_of(AsnObj *),
    compare(AsnObj *, const uchar *, int),
    find_lth(const uchar *),
    put_asn_time(char *, ulong);

static AsnObj *check_defined(AsnObj *),
    *tag_match(AsnObj *, ulong, char *),
    *tag_scan(AsnObj **, const uchar *, int, char *),
    *tag_search(ulong, AsnObj *, char *);

static void buf_stuff(char *);

int AsnObj::decode(const uchar *buf)
{
long lth = find_lth(buf);
if (lth < 0) return lth;
return decode(buf, lth);
}

int AsnObj::decode(const uchar *buf, long lth)
{
char map_buf[20];
AsnObj *objp = this, *tobjp;
if (!buf) return asn_obj_err(ASN_NULL_PTR);
*asn_map_string = 0;
*map_buf = '0';
map_buf[1] = 0;
clear();
if (!*buf && !buf[1]) return 0;
	    /* have to look for a match of the top tag */
if (!(tobjp = tag_scan(&objp, buf,
    ((_supra)? (_supra->_flags & ASN_OF_FLAG): 0), map_buf)))
    {
    buf_stuff(map_buf);
    return asn_obj_err(ASN_MATCH_ERR);
    }
return tobjp->match(buf, &buf[lth]);
}

int AsnObj::match(const uchar *sp, const uchar *endp)
{
/**
Name: int match(const uchar *sp, const uchar *endp)

Function: Matches the ASN.1 string pointed to by sp to the object defined
by 'this' and fills in the primitive items

Inputs:
	sp - pointer to an ASN.1 stream
	endp - pointer to char beyond last of stream
Outputs:
	IF no error, objbase is filled in
Returns:
	IF no error, number of bytes decoded
	ELSE negative of offset to place in the ASN.1 string that didn't match
	     NOTE: This might be zero.
Procedure:
1. Get this item's tag
   IF it doesn't match object, return error
2. IF item is definite length, note the end point
   ELSE IF item is primitive, return error
   ELSE note the end of an indefinite-length item
3. IF object is explicitly tagged OR it's a DEFINED BY but not ANY
	IF it's a DEFINED BY but not ANY
	    IF no sub-member has been chosen, return error
	    IF the sub-member is not ASN.1
		Write the stuff
		Return count
	Get the sub-tag
        IF (this isn't a CHOICE AND this tag doesn't match) OR
            (this is a CHOICE AND can't find a tag to match), error
	Get the sub-length
4. IF item is a constructed universal primitive
	Write the first subitem (to get initial special stuff for integers)
	FOR each other subitem with a matching tag, append it to this object
   ELSE IF item is primitive OR is a true ANY
	IF error writing the value into the object, return error
   ELSE
        WHILE not at the end of the item or the sub-objects
    	    Get the next tag
            IF this is an OF object
                Make a new object and link it in
            ELSE
                Scan through the sub-objs to find either a tag match OR a miss
            IF no tag match OR
                the count of sub-items in an OF chain is too great OR
                a call to the subordinate match returns a negative number
                Return error
    	    Advance the pointer
	    Return error
        IF it's an OF chain AND the number was below the minimum, return error
5. Return count of bytes processed in stream
**/
const uchar *bp, *cp = sp, *ep = (uchar *)0;
char map_buf[20], *mapp;
ulong tag;
int err = 0, indef, lth;
AsnObj *objp, *subp, *tobjp;
*(mapp = map_buf) = '0';
map_buf[1] = 0;
						            /* step 1 */
if ((tag = decode_asn_tag(&cp)) != _tag &&    /* cp now at length */
    (this->_tag != (tag & ~(ASN_CONSTRUCTED)) ||
    this->_type >= ASN_SEQUENCE)) return asn_obj_err(ASN_MATCH_ERR);
						            /* step 2 */
indef = lth = 0;
if (*cp != ASN_INDEF_LTH)
    {
    if (*cp > 0x84 || (lth = decode_asn_lth(&cp)) < 0 ||  /* cp at contents */
	&cp[lth] > endp) err = ASN_LENGTH_ERR;
    }
else if (!(tag & ASN_CONSTRUCTED)) err = ASN_CODING_ERR;
else
    {
    cp++;                        /* cp at contents */
    indef += 2;
    _flags |= ASN_INDEF_LTH_FLAG;
    }
						            /* step 3 */
objp = this;
if (!err && ((_flags & ASN_EXPLICIT_FLAG) || (_type == ASN_CHOICE &&
    _tag != _type && (_flags & ASN_DEFINED_FLAG))))
    {
    if (_type == ASN_CHOICE && _tag != _type && (_flags & ASN_DEFINED_FLAG))
	{
	for (subp = _sub; subp && !(subp->_flags & ASN_CHOSEN_FLAG);
	    subp = subp->_next);
	if (!subp) return asn_obj_err(ASN_NO_DEF_ERR);
	if (subp->_type == ASN_NOTASN1)
	    {
	    if ((lth = objp->_write(cp, lth)) < 0) return (sp - &cp[-lth]);
	    return (&cp[lth] - sp);
	    }
        if (_tag == ASN_BITSTRING) cp++;
	}
    tag = decode_asn_tag(&cp);    /* cp at length of sub-field */
    lth = 0;
    if ((_type != ASN_CHOICE && tag != _type) ||
	(_type == ASN_CHOICE && !(objp = tag_search(tag, this, &map_buf[-1]))))
    	{
	buf_stuff(map_buf);
	asn_obj_err(ASN_MATCH_ERR);
	return sp - cp;
	}
    if (objp != this)
        {
        while(*mapp) mapp++;
	*mapp = '0';
	mapp[1] = 0;
	}
    if (*cp != ASN_INDEF_LTH)
        {
        if (*cp > 0x84 || (lth = decode_asn_lth(&cp)) < 0 ||/* cp at contents */
	    &cp[lth] > endp) err = ASN_LENGTH_ERR;
        }
    else if (!(tag & ASN_CONSTRUCTED)) err = ASN_CODING_ERR;
    else
	{
        cp++;                         /* cp at contents */
	indef += 2;
	_flags |= ASN_SUB_INDEF_FLAG;
	}
    }
if (err)
    {
    asn_obj_err(err);
    return (sp - cp);
    }
if (!indef) ep = &cp[lth];
						            /* step 4 */
if ((tag & ASN_CONSTRUCTED) && objp->_type < ASN_SEQUENCE && objp->_type !=
    ASN_ANY)
    {
    for (bp = cp; !err && ((ep && cp < ep) || (!ep && *cp)); cp += lth)
	{
	if (*cp++ != objp->_type || *cp == ASN_INDEF_LTH) err = ASN_MATCH_ERR;
	else if (*cp > 0x84) err = ASN_LENGTH_ERR;
	else
	    {
    	    lth = decode_asn_lth(&cp);
    	    if ((cp == bp && (lth = objp->_write(cp, (ulong)lth)) < 0) ||
                (cp > bp && (lth = objp->_append(cp, (ulong)lth)) < 0))
                return (sp - &cp[-lth]);
    	    }
	}
    if (!err && objp->vsize() < objp->_min) err = ASN_BOUNDS_ERR;
    if (err)
	{
	asn_obj_err(err);
	return (sp - cp);
	}
    }
else if (!(tag & ASN_CONSTRUCTED) || !objp->_sub)
    {
    if ((lth = objp->_write(cp, lth)) < 0) return (sp - &cp[-lth]);
    cp += lth;
    }
else
    {
    int of = (objp->_flags & ASN_OF_FLAG);
    for (subp = objp->_sub; !err && subp && ((ep && cp < ep) || (!ep && *cp));
        subp = subp->_next)
	{
	tobjp = tag_scan(&subp, cp, of, mapp);
	lth = 0;
	if (!tobjp || !subp) err = ASN_MATCH_ERR;
        else if (of && objp->_max && *mapp >= objp->_max + '0')
            err = ASN_OF_BOUNDS_ERR;
        else if ((lth = tobjp->match(cp, endp)) < 0) err = ASN_MATCH_ERR;
	else
    	    {
            cp += lth;          /* now at next tag */
	    (*mapp)++;
	    mapp[1] = 0;
	    }
	}
    if (!err && !of)
	{
	if (objp->_type == ASN_SET)
	    {
	    map_buf[0] = '0';
	    map_buf[1] = 0;
            for (subp = objp->_sub; subp &&
                (subp->_flags & (ASN_FILLED_FLAG | ASN_OPTIONAL_FLAG));
    	        subp = subp->_next, (*map_buf)++);
	    }
        if (subp && !(subp->_flags & ASN_OPTIONAL_FLAG))
    	    {
            err = ASN_MANDATORY_ERR;
    	    lth = 0;
    	    }
	}
    if (of && *mapp < objp->_min + '0') err = ASN_OF_BOUNDS_ERR;
    if (err)
        {
        buf_stuff(map_buf);
        if (!lth) asn_obj_err(err);
	else if (lth < 0) cp -= lth;
        return (sp - cp);
        }
    cp += indef;
    }
return (cp - sp);
}

static void buf_stuff(char *map_buf)
{
char *c;
for (c = map_buf; *c; c++);
for (c--; c >= map_buf; stuff((int)(*c-- - '0')));
}

static int find_lth(const uchar *sp) /* sp points to start of tag field */
{
const uchar *c = sp;
int lth;
decode_asn_tag(&c);     /* c now points to length */
if (*c == ASN_INDEF_LTH) c++;
else
    {
    if (*c > 0x84)
	{
	asn_obj_err(ASN_LENGTH_ERR);
	return (sp - c);
	}
    lth = decode_asn_lth(&c); /* now c points to start of contents */
    return (&c[lth] - sp);
    }
if (!(*sp & ASN_CONSTRUCTED)) return -1;
for ( ; *c || c[1]; c += lth)
    {
    if ((lth = find_lth(c)) < 0) return (lth - (c - sp));
    }
return (&c[2] - sp);  /* length of tag + lth + contents + double null */
}

static AsnObj *tag_match(AsnObj *objp, ulong tag, char *map_buf)
{
/**
Function: Looks for a tag match, recursively, if necessary.  Called only by
tag_scan.
Inputs:
    Pointer to starting object
    Tag to match
Outputs:
    Pointer to object with matching tag, if found
	ELSE NULL
Procedure:
1. IF the object is a POINTER OR a CHOICE
        Return what tag_search returns
2. IF parent is a SET but not SET OF
	Scan through all the items to find a tag match
	IF none found, return NULL
	Add the address of the object at this level to the relink chain
	Set the return pointer to the address of the object found
3. ELSE IF this object has the ANY flag
	Make the tag match
        Return the pointer
4. ELSE IF tag doesn't match AND (it differs by more than the constructed bit
        OR the type is not a universal primitive), return NULL
   Return the pointer found (which may be the original)
**/
AsnObj *tobjp;
							    // step 1
if ((objp->_flags & ASN_POINTER_FLAG) || objp->_tag == ASN_CHOICE)
    return tag_search(tag, objp, map_buf);
							    // step 2
if (objp->_supra && objp->_supra->_tag == ASN_SET &&
    !(objp->_supra->_flags & ASN_OF_FLAG))
    {
    AsnLink *relinkp;
    for (objp = objp->_supra->_sub; objp; objp = objp->_next)
	{
	if ((objp->_flags & ASN_POINTER_FLAG) || objp->_tag == ASN_CHOICE)
	    {
            if (!(tobjp = tag_search(tag, objp, map_buf))) return tobjp;
	    }
	else tobjp = objp;
	if (tobjp->_tag == tag) break;
	}
       /* objp is at current level; tobjp may be 'down' one or more levels */
    if (!objp || !tobjp || (tobjp->_flags & ASN_FILLED_FLAG))
        return (AsnObj *)0;
    if (!(relinkp = ((AsnSet *)objp->_supra)->_relinksp))
        relinkp = ((AsnSet *)objp->_supra)->_relinksp = new AsnLink;
    else
        {
	while ( relinkp->_next) relinkp = relinkp->_next;
	relinkp->_next = new AsnLink;
	relinkp = relinkp->_next;
        }
    relinkp->objp = objp;
    objp = tobjp;
    }
							    // step 3
else if (objp->_type == ASN_ANY) objp->_tag = tag;
							    // step 4
else if (objp->_tag != tag && (objp->_tag != (tag & ~(ASN_CONSTRUCTED)) ||
    objp->_type >= ASN_SEQUENCE)) objp = (AsnObj *)0;
return objp;
}

static AsnObj *tag_scan(AsnObj **objpp, const uchar *cp, int of, char *map_buf)
{
ulong tag = decode_asn_tag(&cp);
int index;
AsnObj *tobjp = *objpp;
if (!of)
    {
    for ( ; *objpp && !(tobjp = tag_match(*objpp, tag, map_buf)) &&
        ((*objpp)->_flags & ASN_OPTIONAL_FLAG); *objpp = (*objpp)->_next,
        map_buf[0]++);
    if (!tobjp)
	{
	if (*map_buf > '0') map_buf[0]--;
	}
    else if (tobjp->_type == ASN_ANY) tobjp->_tag = tag;
    if (tobjp && tobjp->_tag != tag &&
        (tobjp->_tag != (tag & ~(ASN_CONSTRUCTED)) ||
        tobjp->_type >= ASN_SEQUENCE)) return (AsnObj *)0;
    }
else if (!tobjp->_next || (tobjp->_flags & ASN_FILLED_FLAG))
    {    /* insert if not empty or at end */
    if ((index = ((AsnArray *)tobjp)->insert()) < 0) tobjp = (AsnObj *)0;
    else
        {
        AsnArray *arrayp = (AsnArray *)tobjp->_supra->_sub;
        *objpp = tobjp = &(*arrayp)[index];
    	    /* have to set *objpp because we have "backed up" in the chain */
	if (tobjp->_type == ASN_CHOICE) tobjp = tag_search(tag, tobjp, map_buf);
	}
    }
return tobjp;
}

static AsnObj *tag_search(ulong tag, AsnObj *objp, char *map_buf)
{
/**
Function: Searches through pointers and CHOICEs to find first tag match.
This function is recursive.  NOTE: It is only called if objp points to a
pointer or a CHOICE or a DEFINED_BY.
Returns: IF match found, pointer to object with matching tag
	 ELSE NULL pointer
Procedure:
1. Set temp pointer to starting pointer
   DO
	Set starting pointer to temp pointer (for later times around loop)
2.	IF starting object is not a pointer
            IF the object is DEFINED, scan through its subordinates to find
	        the chosen one
            IF at the starting object OR the object is a true CHOICE
                Scan through its subordinate to find a tag match
    		    IF at a CHOICE OR a pointer AND tag_search returns a
		        non-null
			Set temp pointer to that
			Break out of scan
3.	ELSE
    	    IF it doesn't yet point to anything, make it point to an instance
	    IF the tag doesn't match
	        Delete the duplicate and clear pointer to it
                IF the original object is OPTIONAL, continue in FOR
	        Clear original object pointer
	    ELSE Set temp object to pointed-to object
   WHILE temp object is a pointer OR a true CHOICE
   Return temp pointer
**/
AsnObj *tobjp, *subp;
char *c = &map_buf[1];
tobjp = objp;                                           /* step 1 */
do
    {
    objp = tobjp;
    if (!(objp->_flags & ASN_POINTER_FLAG))             // step 2
        {
        if ((objp->_flags & ASN_DEFINED_FLAG))
            {
            for(tobjp = objp->_sub, *c = '0', c[1] = 0;
                tobjp && !(tobjp->_flags & ASN_CHOSEN_FLAG);
                tobjp = tobjp->_next, (*c)++);
	    c++;
            }
        if (tobjp == objp || tobjp->_tag == ASN_CHOICE)
            {
            for (tobjp = tobjp->_sub, *c = '0', c[1] = 0; tobjp &&
                tobjp->_tag != tag; tobjp = tobjp->_next, (*c)++)
		{
		if ((tobjp->_type == ASN_CHOICE ||
                    (objp->_flags & ASN_POINTER_FLAG)) &&
		    (subp == tag_search(tag, tobjp, c)))
		    {
		    tobjp = subp;
		    break;
		    }
		}
		c++;
            }
        }
    else  /* pointer object */
        {
        AsnPtr *pobjp = (AsnPtr *)objp;   /* just a cast */
        if (tag == objp->_tag)
            {
            if (!pobjp->_ptr) pobjp->_point();
    	    else pobjp->_ptr->clear();
    	    pobjp->_ptr->_tag = tobjp->_tag;
	    }
        else if (pobjp->_ptr)
	    {
            delete(pobjp->_ptr);
            pobjp->_ptr = (AsnObj *)0;

⌨️ 快捷键说明

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