Пример #1
0
        //  Simple recursive parser for ASN1 BER.
        private MHParseNode DoParse()
        {
            byte ch;
            // Tag class
            int tagClass = Universal;
            // Byte count of end of this item.  Set to INDEFINITE_LENGTH if the length is Indefinite.
            int endOfItem;
            int tagNumber = 0;

            // Read the first character.
            ch = GetNextChar();

            // ASN1 Coding rules: Top two bits (0 and 1) indicate the tag class.
            // 0x00 - Universal,  0x40 - Application, 0x80 - Context-specific, 0xC0 - Private
            // We only use Universal and Context.
            switch (ch & 0xC0)
            {
            case 0x00: // Universal
                tagClass = Universal;
                break;

            case 0x80:
                tagClass = Context;
                break;

            default:
                throw new MHEGException("Invalid tag class = " + ch);
            }
            // Bit 2 indicates whether it is a simple or compound type.  Not used.
            // Lower bits are the tag number.
            tagNumber = ch & 0x1f;
            if (tagNumber == 0x1f)   // Except that if it is 0x1F then the tag is encoded in the following bytes.
            {
                tagNumber = 0;
                do
                {
                    ch        = GetNextChar();
                    tagNumber = (tagNumber << 7) | (ch & 0x7f);
                } while ((ch & 0x80) != 0); // Top bit set means there's more to come.
            }

            // Next byte is the length.  If it is less than 128 it is the actual length, otherwise it
            // gives the number of bytes containing the length, except that if this is zero the item
            // has an "indefinite" length and is terminated by two zero bytes.
            ch = GetNextChar();
            if ((ch & 0x80) != 0)
            {
                int lengthOfLength = ch & 0x7f;
                if (lengthOfLength == 0)
                {
                    endOfItem = INDEFINITE_LENGTH;
                }
                else
                {
                    endOfItem = 0;
                    while ((lengthOfLength--) != 0)
                    {
                        ch        = GetNextChar();
                        endOfItem = (endOfItem << 8) | ch;
                    }
                    endOfItem += m_p;
                }
            }
            else
            {
                endOfItem = ch + m_p;
            }

            if (tagClass == Context)
            {
                MHPTagged pNode = new MHPTagged(tagNumber);
                // The argument here depends on the particular tag we're processing.
                switch (tagNumber)
                {
                case ASN1Codes.C_MULTIPLE_SELECTION:
                case ASN1Codes.C_OBSCURED_INPUT:
                case ASN1Codes.C_INITIALLY_AVAILABLE:
                case ASN1Codes.C_WRAP_AROUND:
                case ASN1Codes.C_TEXT_WRAPPING:
                case ASN1Codes.C_INITIALLY_ACTIVE:
                case ASN1Codes.C_MOVING_CURSOR:
                case ASN1Codes.C_SHARED:
                case ASN1Codes.C_ENGINE_RESP:
                case ASN1Codes.C_TILING:
                case ASN1Codes.C_BORDERED_BOUNDING_BOX:
                {     // BOOL
                    // If there is no argument we need to indicate that so that it gets
                    // the correct default value.
                    if (m_p != endOfItem)
                    {
                        int intVal = ParseInt(endOfItem);     // May raise an exception
                        pNode.AddArg(new MHPBool(intVal != 0));
                    }
                    break;
                }

                case ASN1Codes.C_INPUT_TYPE:
                case ASN1Codes.C_SLIDER_STYLE:
                case ASN1Codes.C_TERMINATION:
                case ASN1Codes.C_ORIENTATION:
                case ASN1Codes.C_HORIZONTAL_JUSTIFICATION:
                case ASN1Codes.C_BUTTON_STYLE:
                case ASN1Codes.C_START_CORNER:
                case ASN1Codes.C_LINE_ORIENTATION:
                case ASN1Codes.C_VERTICAL_JUSTIFICATION:
                case ASN1Codes.C_STORAGE:
                {     // ENUM
                    if (m_p != endOfItem)
                    {
                        int intVal = ParseInt(endOfItem);     // May raise an exception
                        pNode.AddArg(new MHPEnum(intVal));
                    }
                    break;
                }

                case ASN1Codes.C_INITIAL_PORTION:
                case ASN1Codes.C_STEP_SIZE:
                case ASN1Codes.C_INPUT_EVENT_REGISTER:
                case ASN1Codes.C_INITIAL_VALUE:
                case ASN1Codes.C_IP_CONTENT_HOOK:
                case ASN1Codes.C_MAX_VALUE:
                case ASN1Codes.C_MIN_VALUE:
                case ASN1Codes.C_LINE_ART_CONTENT_HOOK:
                case ASN1Codes.C_BITMAP_CONTENT_HOOK:
                case ASN1Codes.C_TEXT_CONTENT_HOOK:
                case ASN1Codes.C_STREAM_CONTENT_HOOK:
                case ASN1Codes.C_MAX_LENGTH:
                case ASN1Codes.C_CHARACTER_SET:
                case ASN1Codes.C_ORIGINAL_TRANSPARENCY:
                case ASN1Codes.C_ORIGINAL_GC_PRIORITY:
                case ASN1Codes.C_LOOPING:
                case ASN1Codes.C_ORIGINAL_LINE_STYLE:
                case ASN1Codes.C_STANDARD_VERSION:
                case ASN1Codes.C_ORIGINAL_LINE_WIDTH:
                case ASN1Codes.C_CONTENT_HOOK:
                case ASN1Codes.C_CONTENT_CACHE_PRIORITY:
                case ASN1Codes.C_COMPONENT_TAG:
                case ASN1Codes.C_ORIGINAL_VOLUME:
                case ASN1Codes.C_PROGRAM_CONNECTION_TAG:
                case ASN1Codes.C_CONTENT_SIZE:
                {     // INT
                    if (m_p != endOfItem)
                    {
                        int intVal = ParseInt(endOfItem);     // May raise an exception
                        pNode.AddArg(new MHPInt(intVal));
                    }
                    break;
                }

                case ASN1Codes.C_OBJECT_INFORMATION:
                case ASN1Codes.C_CONTENT_REFERENCE:
                case ASN1Codes.C_FONT_ATTRIBUTES:
                case ASN1Codes.C_CHAR_LIST:
                case ASN1Codes.C_NAME:
                case ASN1Codes.C_ORIGINAL_LABEL:
                {     // STRING
                    // Unlike INT, BOOL and ENUM we can't distinguish an empty string
                    // from a missing string.
                    MHOctetString str = new MHOctetString();
                    ParseString(endOfItem, str);
                    pNode.AddArg(new MHPString(str));
                    break;
                }

                default:
                {
                    // Everything else has either no argument or is self-describing
                    // TODO: Handle indefinite length.
                    Logging.Assert(endOfItem != INDEFINITE_LENGTH);     // For the moment.
                    while (m_p < endOfItem)
                    {
                        pNode.AddArg(DoParse());
                    }
                    break;
                }
                }
                return(pNode);
            }
            else   // Universal - i.e. a primitive type.
                   // Tag values

            {
                switch (tagNumber)
                {
                case ASN1Codes.U_BOOL: // Boolean
                {
                    int intVal = ParseInt(endOfItem);
                    return(new MHPBool(intVal != 0));
                }

                case ASN1Codes.U_INT: // Integer
                {
                    int intVal = ParseInt(endOfItem);
                    return(new MHPInt(intVal));
                }

                case ASN1Codes.U_ENUM: // ENUM
                {
                    int intVal = ParseInt(endOfItem);
                    return(new MHPEnum(intVal));
                }

                case ASN1Codes.U_STRING: // String
                {
                    MHOctetString str = new MHOctetString();
                    ParseString(endOfItem, str);
                    return(new MHPString(str));
                }

                case ASN1Codes.U_NULL: // ASN1 NULL
                {
                    return(new MHPNull());
                }

                case ASN1Codes.U_SEQUENCE: // Sequence
                {
                    MHParseSequence pNode = new MHParseSequence();
                    Logging.Assert(endOfItem != INDEFINITE_LENGTH);     // TODO: Implement this.
                    while (m_p < endOfItem)
                    {
                        pNode.Append(DoParse());
                    }
                    Logging.Assert(m_p == endOfItem);
                    return(pNode);
                }

                default:
                    Logging.Assert(false);
                    throw new MHEGException("Unknown universal");
                }
            }
        }
Пример #2
0
 // Add an argument to the argument sequence.
 public void AddArg(MHParseNode node)
 {
     m_Args.Append(node);
 }
Пример #3
0
        private MHParseNode DoParse()
        {
            MHParseNode pRes = null;

            switch (m_nType)
            {
            case PTStartSection: // Open curly bracket
            {
                NextSym();
                // Should be followed by a tag.
                if (m_nType != PTTag)
                {
                    Error("Expected ':' after '{'");
                }
                MHPTagged pTag = new MHPTagged(m_nTag);
                pRes = pTag;
                NextSym();
                while (m_nType != PTEndSection)
                {
                    pTag.AddArg(DoParse());
                }
                NextSym();     // Remove the close curly bracket.
                break;
            }

            case PTTag: // Tag on its own.
            {
                int       nTag = m_nTag;
                MHPTagged pTag = new MHPTagged(nTag);
                pRes = pTag;
                NextSym();
                switch (nTag)
                {
                case ASN1Codes.C_ITEMS:
                case ASN1Codes.C_LINK_EFFECT:
                case ASN1Codes.C_ACTIVATE:
                case ASN1Codes.C_ADD:
                case ASN1Codes.C_ADD_ITEM:
                case ASN1Codes.C_APPEND:
                case ASN1Codes.C_BRING_TO_FRONT:
                case ASN1Codes.C_CALL:
                case ASN1Codes.C_CALL_ACTION_SLOT:
                case ASN1Codes.C_CLEAR:
                case ASN1Codes.C_CLONE:
                case ASN1Codes.C_CLOSE_CONNECTION:
                case ASN1Codes.C_DEACTIVATE:
                case ASN1Codes.C_DEL_ITEM:
                case ASN1Codes.C_DESELECT:
                case ASN1Codes.C_DESELECT_ITEM:
                case ASN1Codes.C_DIVIDE:
                case ASN1Codes.C_DRAW_ARC:
                case ASN1Codes.C_DRAW_LINE:
                case ASN1Codes.C_DRAW_OVAL:
                case ASN1Codes.C_DRAW_POLYGON:
                case ASN1Codes.C_DRAW_POLYLINE:
                case ASN1Codes.C_DRAW_RECTANGLE:
                case ASN1Codes.C_DRAW_SECTOR:
                case ASN1Codes.C_FORK:
                case ASN1Codes.C_GET_AVAILABILITY_STATUS:
                case ASN1Codes.C_GET_BOX_SIZE:
                case ASN1Codes.C_GET_CELL_ITEM:
                case ASN1Codes.C_GET_CURSOR_POSITION:
                case ASN1Codes.C_GET_ENGINE_SUPPORT:
                case ASN1Codes.C_GET_ENTRY_POINT:
                case ASN1Codes.C_GET_FILL_COLOUR:
                case ASN1Codes.C_GET_FIRST_ITEM:
                case ASN1Codes.C_GET_HIGHLIGHT_STATUS:
                case ASN1Codes.C_GET_INTERACTION_STATUS:
                case ASN1Codes.C_GET_ITEM_STATUS:
                case ASN1Codes.C_GET_LABEL:
                case ASN1Codes.C_GET_LAST_ANCHOR_FIRED:
                case ASN1Codes.C_GET_LINE_COLOUR:
                case ASN1Codes.C_GET_LINE_STYLE:
                case ASN1Codes.C_GET_LINE_WIDTH:
                case ASN1Codes.C_GET_LIST_ITEM:
                case ASN1Codes.C_GET_LIST_SIZE:
                case ASN1Codes.C_GET_OVERWRITE_MODE:
                case ASN1Codes.C_GET_PORTION:
                case ASN1Codes.C_GET_POSITION:
                case ASN1Codes.C_GET_RUNNING_STATUS:
                case ASN1Codes.C_GET_SELECTION_STATUS:
                case ASN1Codes.C_GET_SLIDER_VALUE:
                case ASN1Codes.C_GET_TEXT_CONTENT:
                case ASN1Codes.C_GET_TEXT_DATA:
                case ASN1Codes.C_GET_TOKEN_POSITION:
                case ASN1Codes.C_GET_VOLUME:
                case ASN1Codes.C_LAUNCH:
                case ASN1Codes.C_LOCK_SCREEN:
                case ASN1Codes.C_MODULO:
                case ASN1Codes.C_MOVE:
                case ASN1Codes.C_MOVE_TO:
                case ASN1Codes.C_MULTIPLY:
                case ASN1Codes.C_OPEN_CONNECTION:
                case ASN1Codes.C_PRELOAD:
                case ASN1Codes.C_PUT_BEFORE:
                case ASN1Codes.C_PUT_BEHIND:
                case ASN1Codes.C_QUIT:
                case ASN1Codes.C_READ_PERSISTENT:
                case ASN1Codes.C_RUN:
                case ASN1Codes.C_SCALE_BITMAP:
                case ASN1Codes.C_SCALE_VIDEO:
                case ASN1Codes.C_SCROLL_ITEMS:
                case ASN1Codes.C_SELECT:
                case ASN1Codes.C_SELECT_ITEM:
                case ASN1Codes.C_SEND_EVENT:
                case ASN1Codes.C_SEND_TO_BACK:
                case ASN1Codes.C_SET_BOX_SIZE:
                case ASN1Codes.C_SET_CACHE_PRIORITY:
                case ASN1Codes.C_SET_COUNTER_END_POSITION:
                case ASN1Codes.C_SET_COUNTER_POSITION:
                case ASN1Codes.C_SET_COUNTER_TRIGGER:
                case ASN1Codes.C_SET_CURSOR_POSITION:
                case ASN1Codes.C_SET_CURSOR_SHAPE:
                case ASN1Codes.C_SET_DATA:
                case ASN1Codes.C_SET_ENTRY_POINT:
                case ASN1Codes.C_SET_FILL_COLOUR:
                case ASN1Codes.C_SET_FIRST_ITEM:
                case ASN1Codes.C_SET_FONT_REF:
                case ASN1Codes.C_SET_HIGHLIGHT_STATUS:
                case ASN1Codes.C_SET_INTERACTION_STATUS:
                case ASN1Codes.C_SET_LABEL:
                case ASN1Codes.C_SET_LINE_COLOUR:
                case ASN1Codes.C_SET_LINE_STYLE:
                case ASN1Codes.C_SET_LINE_WIDTH:
                case ASN1Codes.C_SET_OVERWRITE_MODE:
                case ASN1Codes.C_SET_PALETTE_REF:
                case ASN1Codes.C_SET_PORTION:
                case ASN1Codes.C_SET_POSITION:
                case ASN1Codes.C_SET_SLIDER_VALUE:
                case ASN1Codes.C_SET_SPEED:
                case ASN1Codes.C_SET_TIMER:
                case ASN1Codes.C_SET_TRANSPARENCY:
                case ASN1Codes.C_SET_VARIABLE:
                case ASN1Codes.C_SET_VOLUME:
                case ASN1Codes.C_SPAWN:
                case ASN1Codes.C_STEP:
                case ASN1Codes.C_STOP:
                case ASN1Codes.C_STORE_PERSISTENT:
                case ASN1Codes.C_SUBTRACT:
                case ASN1Codes.C_TEST_VARIABLE:
                case ASN1Codes.C_TOGGLE:
                case ASN1Codes.C_TOGGLE_ITEM:
                case ASN1Codes.C_TRANSITION_TO:
                case ASN1Codes.C_UNLOAD:
                case ASN1Codes.C_UNLOCK_SCREEN:
                case ASN1Codes.C_CONTENT_REFERENCE:
                case ASN1Codes.C_TOKEN_GROUP_ITEMS:
                case ASN1Codes.C_POSITIONS:
                case ASN1Codes.C_MULTIPLEX:
                {           // These are parenthesised in the text form.  We have to remove the
                            // parentheses otherwise we will return a sequence which will not be
                            // be compatible with the binary form.
                    if (m_nType != PTStartSeq)
                    {
                        Error("Expected '('");
                    }
                    NextSym();
                    while (m_nType != PTEndSeq)
                    {
                        pTag.AddArg(DoParse());
                    }
                    NextSym();         // Remove the close parenthesis.
                    break;
                }

                case ASN1Codes.C_ORIGINAL_CONTENT:
                case ASN1Codes.C_NEW_GENERIC_BOOLEAN:
                case ASN1Codes.C_NEW_GENERIC_INTEGER:
                case ASN1Codes.C_NEW_GENERIC_OCTETSTRING:
                case ASN1Codes.C_NEW_GENERIC_OBJECT_REF:
                case ASN1Codes.C_NEW_GENERIC_CONTENT_REF:
                case ASN1Codes.C_ORIGINAL_VALUE:
                case ASN1Codes.C_INDIRECTREFERENCE:
                    // These always have an argument which may be a tagged item.
                {
                    // Is it always the case that there is at least one argument so if we haven't
                    // had any arguments yet we should always process a tag as an argument?
                    pTag.AddArg(DoParse());
                    break;
                }

                default:
                    // This can be followed by an int, etc but a new tag is dealt with by the caller.
                    while (m_nType == PTBool || m_nType == PTInt || m_nType == PTString || m_nType == PTEnum || m_nType == PTStartSeq)
                    {
                        pTag.AddArg(DoParse());
                    }
                    break;
                }
                break;
            }

            case PTInt:
            {
                pRes = new MHPInt(m_nInt);
                NextSym();
                break;
            }

            case PTBool:
            {
                pRes = new MHPBool(m_fBool);
                NextSym();
                break;
            }

            case PTString:
            {
                MHOctetString str = new MHOctetString();
//                    str.Copy(MHOctetString((const char *)m_String, m_nStringLength));
                str.Copy(m_String);
                pRes = new MHPString(str);
                NextSym();
                break;
            }

            case PTEnum:
            {
                pRes = new MHPEnum(m_nInt);
//                    ASSERT(m_nInt > 0);
                NextSym();
                break;
            }

            case PTNull:
            {
                pRes = new MHPNull();
                NextSym();
                break;
            }

            case PTStartSeq: // Open parenthesis.
            {
                MHParseSequence pSeq = new MHParseSequence();
                pRes = pSeq;
                NextSym();
                while (m_nType != PTEndSeq)
                {
                    pSeq.Append(DoParse());
                }
                NextSym();     // Remove the close parenthesis.
                break;
            }

            default:
                Error("Unexpected symbol");
                break;
            }
            return(pRes);
        }