Example #1
0
        string ParseString(ref int pos)
        {
            text.Clear();
            int  p   = pos;
            bool esc = false;

            for (;;)
            {
                if (p >= length - 1)
                {
                    throw ParserEx;
                }
                int b = this[++p];
                if (esc)
                {
                    text.Add(b == '"' ? '"' :
                             b == '\\' ? '\\' :
                             b == 'b' ? '\b' :
                             b == 'f' ? '\f' :
                             b == 'n' ? '\n' :
                             b == 'r' ? '\r' :
                             b == 't' ? '\t' : (char)0);
                    esc = !esc;
                }
                else
                {
                    if (b == '\\')
                    {
                        esc = !esc;
                    }
                    else if (b == '"')
                    {
                        pos = p;
                        return(text.ToString());
                    }
                    else
                    {
                        text.Accept(b);
                    }
                }
            }
        }
Example #2
0
        string ParseName(ref int pos)
        {
            text.Clear();
            int p = pos;

            for (;;)
            {
                if (p >= length)
                {
                    return(null);
                }
                int b = this[p++];
                if (b == '=')
                {
                    pos = p;
                    return(text.ToString());
                }
                else if (b == '+')
                {
                    text.Accept(' ');
                }
                else if (b == '%') // percent-encoding %xy
                {
                    if (p >= length)
                    {
                        throw ParserEx;
                    }
                    int x = this[p++];
                    if (p >= length)
                    {
                        throw ParserEx;
                    }
                    int y = this[p++];

                    text.Accept(Dv(x) << 4 | Dv(y));
                }
                else
                {
                    text.Accept(b);
                }
            }
        }
Example #3
0
        public Form Parse()
        {
            // locality for performance
            byte[] bound_  = this.bound;
            byte[] buffer_ = this.buffer;
            int    length_ = this.length;

            // UTF-8 header builder
            HeaderText hdr  = new HeaderText(128);
            Text       text = new Text(128);

            // keep local for speed
            int boundlen = bound_.Length;

            // shall init lately
            Form frm = null;
            int  p   = 0;

            // skip first bound line whatever
            for (;;)
            {
                if (buffer_[p++] == '\r' && buffer_[p++] == '\n')
                {
                    break;
                }
            }

            // parse parts
            for (;;)
            {
                string name     = null;
                string filename = null;
                string ctype    = null;

                // parse headers
                for (;;)
                {
                    hdr.Clear();

                    // parse a header line
                    for (;;)
                    {
                        if (p >= length_ - 2)
                        {
                            throw ParserEx;
                        }
                        byte b;
                        if ((b = buffer_[p++]) == '\r' && buffer_[p++] == '\n')
                        {
                            break;
                        }
                        hdr.Accept(b);  // lineup the byte
                    }
                    if (hdr.Count == 0) // if empty line then quit header section
                    {
                        break;
                    }
                    if (name == null && hdr.Check("Content-Disposition"))
                    {
                        name     = hdr.SeekParameter("name");
                        filename = hdr.SeekParameter("filename");
                    }
                    else if (ctype == null && hdr.Check("Content-Type"))
                    {
                        ctype = hdr.GetVvalue();
                    }
                }

                // get part's content
                text.Clear();
                bool plain = ctype == null || "text/plain".Equals(ctype);
                int  start = p; // mark down content start
                int  idx   = 0; // index on bound
                for (;;)
                {
                    byte b = buffer_[p++];
                    if (b == bound_[idx])
                    {
                        idx++;
                        if (idx >= boundlen) // fully matched the bound accumulatively
                        {
                            if (frm == null)
                            {
                                frm = new Form(true)
                                {
                                    Buffer = buffer_
                                }
                            }
                            ;
                            if (plain)
                            {
                                frm.Add(name, text.ToString());
                            }
                            else
                            {
                                frm.Add(name, filename, start, p - start - boundlen);
                            }
                            // goto the ending CRLF/-- check
                            break;
                        }
                    }
                    else if (idx > 0) // if fail-match
                    {
                        if (plain)    // re-add
                        {
                            for (int i = 0; i < idx; i++)
                            {
                                text.Accept(bound_[i]);
                            }
                        }
                        idx = 0; // reset
                    }
                    else
                    {
                        if (plain)
                        {
                            text.Accept(b);
                        }
                    }
                }

                // check if any more part
                if (buffer_[p++] == '\r' && buffer_[p++] == '\n')
                {
                    continue;
                }
                break;
            } // parts
            return(frm ?? Empty);
        }
    }
Example #4
0
        XElem ParseElem(ref int pos, int startchar)
        {
            int p = pos;
            int b;

            // parse element tag name
            text.Clear();
            text.Accept(startchar);
            while (IsNameChar(b = this[++p]))
            {
                text.Accept(b); // to comprise start tag
            }
            string tag  = text.ToString();
            XElem  elem = new XElem(tag);

            // optionally parse attributes
            while (IsWs(b))
            {
                while (IsWs(b = this[++p]))
                {
                } // skip ws

                if (IsNameStartChar(b))
                {
                    // attribute name
                    text.Clear();
                    text.Accept(b);
                    while ((b = this[++p]) != '=')
                    {
                        text.Accept(b);
                    }
                    string name = text.ToString();

                    // attribute value
                    if (this[++p] != '"')
                    {
                        throw ParserEx;                   // left quote
                    }
                    text.Clear();
                    while ((b = this[++p]) != '"') // till right quote
                    {
                        if (b == '&')              // escape &lt; &gt; &amp; &quot;
                        {
                            int b1 = this[p + 1];
                            int b2 = this[p + 2];
                            int b3 = this[p + 3];
                            if (b1 == 'l' && b2 == 't' && b3 == ';')
                            {
                                b  = '<';
                                p += 3;
                            }
                            else if (b1 == 'g' && b2 == 't' && b3 == ';')
                            {
                                b  = '>';
                                p += 3;
                            }
                            else if (b1 == 'a' && b2 == 'm' && b3 == 'p' && this[p + 4] == ';')
                            {
                                b  = '&';
                                p += 4;
                            }
                            else if (b1 == 'q' && b2 == 'u' && b3 == 'o' && this[p + 4] == 't' && this[p + 5] == ';')
                            {
                                b  = '"';
                                p += 5;
                            }
                        }
                        text.Accept(b);
                    }
                    string value = text.ToString();

                    elem.AddAttr(name, value);

                    b = this[++p]; // step
                }
            } // end of attributes

            if (b == '>')                       // a start tag just finished, expecting the ending-tag
            {
                for (;;)                        // child nodes iteration
                {
                    while (IsWs(b = this[++p])) // skip ws
                    {
                    }

                    if (b == '<')
                    {
                        b = this[++p];
                        if (b == '/') // the ending tag
                        {
                            // consume
                            text.Clear();
                            while ((b = this[++p]) != '>')
                            {
                                text.Accept(b);
                            }
                            if (!text.Equals(tag))
                            {
                                throw ParserEx;
                            }

                            pos = p; // adjust current position
                            return(elem);
                        }
                        else if (b == '!') // CDATA section
                        {
                            if (this[p + 1] == '[' && this[p + 2] == 'C' && this[p + 3] == 'D' && this[p + 4] == 'A' && this[p + 5] == 'T' && this[p + 6] == 'A' && this[p + 7] == '[')
                            {
                                text.Clear();
                                p += 7;
                                while ((b = this[++p]) != ']' || this[p + 1] != ']' || this[p + 2] != '>')
                                {
                                    text.Accept(b);
                                }
                                elem.Text = text.ToString();
                                p        += 2; // skip ]>
                            }
                        }
                        else if (IsNameStartChar(b))
                        {
                            XElem child = ParseElem(ref p, b);
                            elem.Add(child);
                        }
                    }
                    else // text node
                    {
                        text.Clear();
                        while ((b = this[p]) != '<') // NOTE from the first char
                        {
                            if (b == '&')            // escape &lt; &gt; &amp; &quot;
                            {
                                int b1 = this[p + 1];
                                int b2 = this[p + 2];
                                int b3 = this[p + 3];
                                if (b1 == 'l' && b2 == 't' && b3 == ';')
                                {
                                    b  = '<';
                                    p += 3;
                                }
                                else if (b1 == 'g' && b2 == 't' && b3 == ';')
                                {
                                    b  = '>';
                                    p += 3;
                                }
                                else if (b1 == 'a' && b2 == 'm' && b3 == 'p' && this[p + 4] == ';')
                                {
                                    b  = '&';
                                    p += 4;
                                }
                                else if (b1 == 'q' && b2 == 'u' && b3 == 'o' && this[p + 4] == 't' && this[p + 5] == ';')
                                {
                                    b  = '"';
                                    p += 5;
                                }
                            }
                            text.Accept(b);
                            ++p;
                        }
                        if (text.Count > 0)
                        {
                            elem.Text = text.ToString();
                        }
                        // NOTE decrease in position to behave as other child nodes
                        --p;
                    }
                } // child nodes iteration
            }
            if (b == '/' && this[++p] == '>') // empty-element
            {
                pos = p; // adjust current position
                return(elem);
            }
            throw ParserEx;
        }