Example #1
0
MHParseNode *MHParseText::DoParse()
{
    MHParseNode *pRes = NULL;
    try {
        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 C_ITEMS:
                case C_LINK_EFFECT:
                case C_ACTIVATE:
                case C_ADD:
                case C_ADD_ITEM:
                case C_APPEND:
                case C_BRING_TO_FRONT:
                case C_CALL:
                case C_CALL_ACTION_SLOT:
                case C_CLEAR:
                case C_CLONE:
                case C_CLOSE_CONNECTION:
                case C_DEACTIVATE:
                case C_DEL_ITEM:
                case C_DESELECT:
                case C_DESELECT_ITEM:
                case C_DIVIDE:
                case C_DRAW_ARC:
                case C_DRAW_LINE:
                case C_DRAW_OVAL:
                case C_DRAW_POLYGON:
                case C_DRAW_POLYLINE:
                case C_DRAW_RECTANGLE:
                case C_DRAW_SECTOR:
                case C_FORK:
                case C_GET_AVAILABILITY_STATUS:
                case C_GET_BOX_SIZE:
                case C_GET_CELL_ITEM:
                case C_GET_CURSOR_POSITION:
                case C_GET_ENGINE_SUPPORT:
                case C_GET_ENTRY_POINT:
                case C_GET_FILL_COLOUR:
                case C_GET_FIRST_ITEM:
                case C_GET_HIGHLIGHT_STATUS:
                case C_GET_INTERACTION_STATUS:
                case C_GET_ITEM_STATUS:
                case C_GET_LABEL:
                case C_GET_LAST_ANCHOR_FIRED:
                case C_GET_LINE_COLOUR:
                case C_GET_LINE_STYLE:
                case C_GET_LINE_WIDTH:
                case C_GET_LIST_ITEM:
                case C_GET_LIST_SIZE:
                case C_GET_OVERWRITE_MODE:
                case C_GET_PORTION:
                case C_GET_POSITION:
                case C_GET_RUNNING_STATUS:
                case C_GET_SELECTION_STATUS:
                case C_GET_SLIDER_VALUE:
                case C_GET_TEXT_CONTENT:
                case C_GET_TEXT_DATA:
                case C_GET_TOKEN_POSITION:
                case C_GET_VOLUME:
                case C_LAUNCH:
                case C_LOCK_SCREEN:
                case C_MODULO:
                case C_MOVE:
                case C_MOVE_TO:
                case C_MULTIPLY:
                case C_OPEN_CONNECTION:
                case C_PRELOAD:
                case C_PUT_BEFORE:
                case C_PUT_BEHIND:
                case C_QUIT:
                case C_READ_PERSISTENT:
                case C_RUN:
                case C_SCALE_BITMAP:
                case C_SCALE_VIDEO:
                case C_SCROLL_ITEMS:
                case C_SELECT:
                case C_SELECT_ITEM:
                case C_SEND_EVENT:
                case C_SEND_TO_BACK:
                case C_SET_BOX_SIZE:
                case C_SET_CACHE_PRIORITY:
                case C_SET_COUNTER_END_POSITION:
                case C_SET_COUNTER_POSITION:
                case C_SET_COUNTER_TRIGGER:
                case C_SET_CURSOR_POSITION:
                case C_SET_CURSOR_SHAPE:
                case C_SET_DATA:
                case C_SET_ENTRY_POINT:
                case C_SET_FILL_COLOUR:
                case C_SET_FIRST_ITEM:
                case C_SET_FONT_REF:
                case C_SET_HIGHLIGHT_STATUS:
                case C_SET_INTERACTION_STATUS:
                case C_SET_LABEL:
                case C_SET_LINE_COLOUR:
                case C_SET_LINE_STYLE:
                case C_SET_LINE_WIDTH:
                case C_SET_OVERWRITE_MODE:
                case C_SET_PALETTE_REF:
                case C_SET_PORTION:
                case C_SET_POSITION:
                case C_SET_SLIDER_VALUE:
                case C_SET_SPEED:
                case C_SET_TIMER:
                case C_SET_TRANSPARENCY:
                case C_SET_VARIABLE:
                case C_SET_VOLUME:
                case C_SPAWN:
                case C_STEP:
                case C_STOP:
                case C_STORE_PERSISTENT:
                case C_SUBTRACT:
                case C_TEST_VARIABLE:
                case C_TOGGLE:
                case C_TOGGLE_ITEM:
                case C_TRANSITION_TO:
                case C_UNLOAD:
                case C_UNLOCK_SCREEN:
                case C_CONTENT_REFERENCE:
                case C_TOKEN_GROUP_ITEMS:
                case C_POSITIONS:
                case 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 C_ORIGINAL_CONTENT:
                case C_NEW_GENERIC_BOOLEAN:
                case C_NEW_GENERIC_INTEGER:
                case C_NEW_GENERIC_OCTETSTRING:
                case C_NEW_GENERIC_OBJECT_REF:
                case C_NEW_GENERIC_CONTENT_REF:
                case C_ORIGINAL_VALUE:
                    // 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;
            }

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

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

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

        case PTEnum:
            {
                pRes = new MHPEnum(m_nInt);
                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");
        }
        return pRes;
    }
    catch (...) {
        delete(pRes);
        throw;
    }
}
Example #2
0
//  Simple recursive parser for ASN1 BER.
MHParseNode *MHParseBinary::DoParse()
{
    unsigned char ch;
    // Tag class
    enum { Universal, Context/*, Pseudo*/ } tagClass = Universal;
    // Byte count of end of this item.  Set to INDEFINITE_LENGTH if the length is Indefinite.
    int endOfItem;
    unsigned 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:
            MHERROR(QString("Invalid tag class = %1").arg(ch, 0, 16));
    }

    // 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);   // 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)
    {
        int lengthOfLength = ch & 0x7f;

        if (lengthOfLength == 0)
        {
            endOfItem = INDEFINITE_LENGTH;
        }
        else
        {
            endOfItem = 0;

            while (lengthOfLength--)
            {
                ch = GetNextChar();
                endOfItem = (endOfItem << 8) | ch;
            }

            endOfItem += m_p;
        }
    }
    else
    {
        endOfItem = ch + m_p;
    }

    if (tagClass == Context)
    {
        MHPTagged *pNode = new MHPTagged(tagNumber);

        try
        {
            // The argument here depends on the particular tag we're processing.
            switch (tagNumber)
            {
                case C_MULTIPLE_SELECTION:
                case C_OBSCURED_INPUT:
                case C_INITIALLY_AVAILABLE:
                case C_WRAP_AROUND:
                case C_TEXT_WRAPPING:
                case C_INITIALLY_ACTIVE:
                case C_MOVING_CURSOR:
                case C_SHARED:
                case C_ENGINE_RESP:
                case C_TILING:
                case 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 C_INPUT_TYPE:
                case C_SLIDER_STYLE:
                case C_TERMINATION:
                case C_ORIENTATION:
                case C_HORIZONTAL_JUSTIFICATION:
                case C_BUTTON_STYLE:
                case C_START_CORNER:
                case C_LINE_ORIENTATION:
                case C_VERTICAL_JUSTIFICATION:
                case C_STORAGE:
                {
                    // ENUM
                    if (m_p != endOfItem)
                    {
                        int intVal = ParseInt(endOfItem); // May raise an exception
                        pNode->AddArg(new MHPEnum(intVal));
                    }

                    break;
                }

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

                    break;
                }

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

                default:
                {
                    // Everything else has either no argument or is self-describing
                    // TODO: Handle indefinite length.
                    if (endOfItem == INDEFINITE_LENGTH)
                    {
                        MHERROR("Indefinite length arguments are not implemented");
                    }

                    while (m_p < endOfItem)
                    {
                        pNode->AddArg(DoParse());
                    }
                }
            }
        }
        catch (...)
        {
            // Memory clean-up
            delete pNode;
            throw;
        }

        return pNode;
    }
    else   // Universal - i.e. a primitive type.
    {
        // Tag values

        switch (tagNumber)
        {
            case U_BOOL: // Boolean
            {
                int intVal = ParseInt(endOfItem);
                return new MHPBool(intVal != 0);
            }
            case U_INT: // Integer
            {
                int intVal = ParseInt(endOfItem);
                return new MHPInt(intVal);
            }
            case U_ENUM: // ENUM
            {
                int intVal = ParseInt(endOfItem);
                return new MHPEnum(intVal);
            }
            case U_STRING: // String
            {
                MHOctetString str;
                ParseString(endOfItem, str);
                return new MHPString(str);
            }
            case U_NULL: // ASN1 NULL
            {
                return new MHPNull;
            }
            case U_SEQUENCE: // Sequence
            {
                MHParseSequence *pNode = new MHParseSequence();

                if (endOfItem == INDEFINITE_LENGTH)
                {
                    MHERROR("Indefinite length sequences are not implemented");
                }

                try
                {
                    while (m_p < endOfItem)
                    {
                        pNode->Append(DoParse());
                    }
                }
                catch (...)
                {
                    // Memory clean-up if error.
                    delete pNode;
                    throw;
                }

                return pNode;
            }
            default:
                MHERROR(QString("Unknown universal %1").arg(tagNumber));
        }
    }
}