コード例 #1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="data">The byte array in which to search for boundaries</param>
        /// <param name="boundary">The boundary string, from the Content-Type header</param>
        /// <param name="startIndex">The 0-based index to begin the search at (default is 0)</param>
        /// <returns>Index of the start of the next boundary line, or -1 if no such line exists</returns>
        public static MimePart[] findParts(byte[] data, String boundary, int startIndex = 0)
        {
            List <MimePart> parts     = new List <MimePart>();
            MimePart        part      = null;
            int             lineStart = startIndex - 1;
            int             start     = -1;

            // First, we have to find the start boundary.
            // Scan the body for lines long enough to contain the boundary marker.
            while (lineStart < (data.Length - boundary.Length))
            {
                // Find the next line
                int lineEnd = Array.IndexOf <byte>(data, (byte)'\n', ++lineStart);
                if (-1 == lineEnd)
                {
                    // We found the end (instead of a newline); treat the whole thing as a line.
                    lineEnd = data.Length;
                }
                // Make sure the line is long enough to hold the boundary
                if ((lineEnd - lineStart) >= boundary.Length)
                {
                    // Found a long-enough line; Stringify it and check.
                    String line = Encoding.UTF8.GetString(
                        data,
                        lineStart,
                        (lineEnd - lineStart - 1));
                    if (line.Contains(boundary))
                    {
                        // Check if this is the first boundary or a subsequent one.
                        if (-1 == start)
                        {
                            // OK, we found the first boundary! Remember it and find the next.
                            start = lineEnd + 1;
                        }
                        else
                        {
                            // We found a full MIME part! Parse it.
                            part        = new MimePart();
                            part.offset = start;
                            part.length = lineStart - start;

                            // Locate the headers (\r\n\r\n), searching from end of boundary line.
                            for (start -= 2; start < (lineStart - 3); start++)
                            {
                                // Find the end of the headers
                                if (Utility.CR == data[start] &&
                                    Utility.CR == data[start + 2] &&
                                    Utility.LF == data[start + 1] &&
                                    Utility.LF == data[start + 3])
                                {
                                    // End of the headers found
                                    String head = Encoding.UTF8.GetString(
                                        data,
                                        part.offset,
                                        start - part.offset);
                                    String[] lines = head.Split(new String[] { "\r\n" },
                                                                StringSplitOptions.RemoveEmptyEntries);
                                    // Parse the headers for this part.
                                    part.parseHeaders(lines);
                                    // End of headers reached, skip over the blank line
                                    start    += 4;
                                    part.body = new byte[lineStart - start];
                                    Array.Copy(data, start, part.body, 0, lineStart - start);
                                    // Done with headers
                                    break;
                                }
                            }
                            if (null == part.headers)
                            {
                                // We never found the end of the headers. It's all body?
                                part.body = new byte[part.length];
                                Array.Copy(data, part.offset, part.body, 0, part.length);
                            }
                            // All right, headers are parsed. Let's get the body now...
                            else if (part.headers.ContainsKey("Content-Type"))
                            {
                                String ct = part.headers["Content-Type"];
                                // Find the offset of the value part of the character set.
                                int cso = ct.IndexOf("charset");
                                if (-1 != cso)
                                {
                                    // The charset field is present; get the body as a string.
                                    cso = ct.IndexOf('=', cso);
                                    String   cs  = ct.Substring(cso + 1).Trim();
                                    Encoding enc = Encoding.GetEncoding(cs);
                                    part.bodyText = enc.GetString(part.body, 0, part.body.Length);
                                }
                                else if (!String.IsNullOrEmpty(part.multipartboundry))
                                {
                                    part.bodyParts = findParts(part.body, part.multipartboundry);
                                }
                            }
                            else
                            {
                                // There are headers, but no Content-Type.
                                // Probably an ordinary value; try to encode it as a string.
                                try
                                {
                                    part.bodyText = Encoding.UTF8.GetString(
                                        part.body,
                                        0,
                                        part.body.Length);
                                }
                                catch (Exception)
                                { }
                            }
                            // Part fully parsed
                            parts.Add(part);
                            // Keep going; there may be more parts.
                            start = lineEnd + 1;
                        }
                    }
                }
                // Maybe the line wasn't long enough or it didn't have the boundary.
                // Or maybe it did, and it was the first boundary, so we have to find another.
                // Or maybe we even found a whole part, parsed it, and are now looking for more.
                lineStart = lineEnd;
            }
            // We didn't find an expected boundary so there's no (more) part(s).
            return(parts.Count > 0 ? parts.ToArray() : null);
        }
コード例 #2
0
 private byte[] parseRequest(byte[] request, int length, bool resume)
 {
     if (length > request.Length || length < 0)
     {
         throw new ArgumentOutOfRangeException("length", length, "The length must be between zero and request.Length, inclusive!");
     }
     if (!resume)
     {
         // Start the search from the beginning
         current   = 0;
         body      = null;
         bodytext  = null;
         bodyIndex = -1;
     }
     if (bodyIndex <= 0)
     {
         // Haven't found the end of the headers yet.
         for (; current < (length - 3); current++)
         {
             // Find the end of the headers
             if (Utility.CR == request[current] && Utility.CR == request[current + 2] &&
                 Utility.LF == request[current + 1] && Utility.LF == request[current + 3])
             {
                 // End of the headers found
                 String   head  = Encoding.UTF8.GetString(request, 0, (int)current);
                 String[] lines = head.Split(new String[] { "\r\n" }, StringSplitOptions.None);
                 // Parse the first line
                 parseFirstLine(lines[0]);
                 // Parse the headers. This version doesn't mess up current
                 parseHeaders(lines, 1);
                 // End of headers reached, skip over the blank line
                 current  += 4;
                 bodyIndex = current;
                 break;
             }
         }
     }
     // Check whether the request is done
     if (-1 != bodyIndex && -1 == contentlength)
     {                   // We'd know if there's a body, and there isn't; we're done
         current = -1;
         if (length > bodyIndex)
         {
             // There may be another request past this one
             byte[] remainder = new byte[length - bodyIndex];
             Array.Copy(request, (int)bodyIndex, remainder, 0, remainder.Length);
             return(remainder);
         }
         else
         {
             // No remainder in this particular packet
             return(null);
         }
     }
     else if ((contentlength > 0) && ((length - bodyIndex) >= contentlength))
     {
         // We have the entire body already
         body = new byte[contentlength];
         Array.Copy(request, bodyIndex, body, 0, (int)contentlength);
         if (headers.ContainsKey("Content-Type"))
         {
             String ct  = headers["Content-Type"];
             int    csi = ct.IndexOf("charset");
             if (-1 != csi)
             {
                 // There is a character set for the body
                 String cs = ct.Substring(ct.IndexOf('=', csi) + 1).Trim();
                 if (cs.Contains(';'))
                 {
                     cs = cs.Substring(0, cs.IndexOf(';')).Trim();
                 }
                 Encoding enc = Encoding.GetEncoding(cs);
                 bodytext = enc.GetString(body, 0, (int)contentlength);
             }
             else if (ct.Contains("text"))
             {
                 // Text without specified charset. Oookay then, let's try autodetection.
                 bodytext = new System.IO.StreamReader(new System.IO.MemoryStream(body)).ReadToEnd();
             }
             else if (multipartboundry != null)
             {
                 // Get the collection of parts.
                 bodyparts = MimePart.findParts(body, multipartboundry);
             }
         }
         // Since we have the whole body...
         current = -1;
         long totallen = (contentlength > 0) ? bodyIndex + contentlength : bodyIndex;
         if (length > totallen)
         {
             // There may be another request past this one
             byte[] remainder = new byte[length - totallen];
             Array.Copy(request, (int)totallen, remainder, 0, remainder.Length);
             return(remainder);
         }
         else
         {
             // No remainder in this particular packet
             return(null);
         }
     }
     else
     {
         // We don't have the full body yet
         return(request);
     }
 }