/// <summary>
        /// Returns header field parameters as string.
        /// </summary>
        /// <param name="charset">Charset to use to encode 8-bit characters. Value null means parameters not encoded.</param>
        /// <returns>Returns header field parameters as string.</returns>
        public string ToString(Encoding charset)
        {
            /* RFC 2231.
             *      If parameter conatins 8-bit byte, we need to encode parameter value
             *      If parameter value length bigger than MIME maximum allowed line length,
             *      we need split value.
             */

            if (charset == null)
            {
                charset = Encoding.Default;
            }

            StringBuilder retVal = new StringBuilder();

            foreach (MIME_h_Parameter parameter in this.ToArray())
            {
                if (string.IsNullOrEmpty(parameter.Value))
                {
                    retVal.Append(";\r\n\t" + parameter.Name);
                }
                // We don't need to encode or split value.
                else if ((charset == null || Net_Utils.IsAscii(parameter.Value)) && parameter.Value.Length < 76)
                {
                    retVal.Append(";\r\n\t" + parameter.Name + "=" + TextUtils.QuoteString(parameter.Value));
                }
                // We need to encode/split value.
                else
                {
                    byte[] byteValue = charset.GetBytes(parameter.Value);

                    List <string> values = new List <string>();
                    // Do encoding/splitting.
                    int    offset    = 0;
                    char[] valueBuff = new char[50];
                    foreach (byte b in byteValue)
                    {
                        // We need split value as RFC 2231 says.
                        if (offset >= (50 - 3))
                        {
                            values.Add(new string(valueBuff, 0, offset));
                            offset = 0;
                        }

                        // Normal char, we don't need to encode.
                        if (MIME_Reader.IsAttributeChar((char)b))
                        {
                            valueBuff[offset++] = (char)b;
                        }
                        // We need to encode byte as %X2.
                        else
                        {
                            valueBuff[offset++] = '%';
                            valueBuff[offset++] = (b >> 4).ToString("X")[0];
                            valueBuff[offset++] = (b & 0xF).ToString("X")[0];
                        }
                    }
                    // Add pending buffer value.
                    if (offset > 0)
                    {
                        values.Add(new string(valueBuff, 0, offset));
                    }

                    for (int i = 0; i < values.Count; i++)
                    {
                        // Only fist value entry has charset and language info.
                        if (charset != null && i == 0)
                        {
                            retVal.Append(";\r\n\t" + parameter.Name + "*" + i.ToString() + "*=" + charset.WebName + "''" + values[i]);
                        }
                        else
                        {
                            retVal.Append(";\r\n\t" + parameter.Name + "*" + i.ToString() + "*=" + values[i]);
                        }
                    }
                }
            }

            return(retVal.ToString());
        }
        /// <summary>
        /// Parses parameters from the specified reader.
        /// </summary>
        /// <param name="reader">MIME reader.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>reader</b> is null reference.</exception>
        public void Parse(MIME_Reader reader)
        {
            if (reader == null)
            {
                throw new ArgumentNullException("reader");
            }

            /* RFC 2231.
             *  Asterisks ("*") are reused to provide the indicator that language and
             *  character set information is present and encoding is being used. A
             *  single quote ("'") is used to delimit the character set and language
             *  information at the beginning of the parameter value. Percent signs
             *  ("%") are used as the encoding flag, which agrees with RFC 2047.
             *
             *  Character set and language information may be combined with the
             *  parameter continuation mechanism. For example:
             *
             *  Content-Type: application/x-stuff
             *      title*0*=us-ascii'en'This%20is%20even%20more%20
             *      title*1*=%2A%2A%2Afun%2A%2A%2A%20
             *      title*2="isn't it!"
             *
             *  Note that:
             *
             *  (1) Language and character set information only appear at
             *      the beginning of a given parameter value.
             *
             *  (2) Continuations do not provide a facility for using more
             *      than one character set or language in the same
             *      parameter value.
             *
             *  (3) A value presented using multiple continuations may
             *      contain a mixture of encoded and unencoded segments.
             *
             *  (4) The first segment of a continuation MUST be encoded if
             *      language and character set information are given.
             *
             *  (5) If the first segment of a continued parameter value is
             *      encoded the language and character set field delimiters
             *      MUST be present even when the fields are left blank.
             */

            KeyValueCollection <string, _ParameterBuilder> parameters = new KeyValueCollection <string, _ParameterBuilder>();

            // Parse all parameter parts.
            string[] parameterParts = TextUtils.SplitQuotedString(reader.ToEnd(), ';');
            foreach (string part in parameterParts)
            {
                if (string.IsNullOrEmpty(part))
                {
                    continue;
                }

                string[] name_value = part.Trim().Split(new char[] { '=' }, 2);
                string   paramName  = name_value[0].Trim();
                string   paramValue = null;
                if (name_value.Length == 2)
                {
                    paramValue = TextUtils.UnQuoteString(name_value[1].Trim());
                }
                // Valueless parameter.
                //else{

                string[] nameParts = paramName.Split('*');
                int      index     = 0;
                bool     encoded   = nameParts.Length == 3;
                // Get multi value parameter index.
                if (nameParts.Length >= 2)
                {
                    try{
                        index = Convert.ToInt32(nameParts[1]);
                    }
                    catch {
                    }
                }

                // Single value parameter and we already have parameter with such name, skip it.
                if (nameParts.Length < 2 && parameters.ContainsKey(nameParts[0]))
                {
                    continue;
                }

                // Parameter builder doesn't exist for the specified parameter, create it.
                if (!parameters.ContainsKey(nameParts[0]))
                {
                    parameters.Add(nameParts[0], new _ParameterBuilder(nameParts[0]));
                }

                parameters[nameParts[0]].AddPart(index, encoded, paramValue);
            }

            // Build parameters from parts.
            foreach (_ParameterBuilder b in parameters)
            {
                m_pParameters.Add(b.Name, b.GetParamter());
            }

            m_IsModified = false;
        }
Beispiel #3
0
        /// <summary>
        /// Parses RFC 2822 date-time from the specified value.
        /// </summary>
        /// <param name="value">RFC 2822 date-time string value.</param>
        /// <returns>Returns parsed datetime value.</returns>
        /// <exception cref="ArgumentNullException">Is raised when <b>value</b> is null.</exception>
        /// <exception cref="ArgumentException">Is raised when any of the arguments has invalid value.</exception>
        public static DateTime ParseRfc2822DateTime(string value)
        {
            if (value == null)
            {
                throw new ArgumentNullException(value);
            }

            /* RFC 2822 3.
             *      date-time       =       [ day-of-week "," ] date FWS time [CFWS]
             *      day-of-week     =       ([FWS] day-name) / obs-day-of-week
             *      day-name        =       "Mon" / "Tue" / "Wed" / "Thu" / "Fri" / "Sat" / "Sun"
             *      date            =       day month year
             *      year            =       4*DIGIT / obs-year
             *      month           =       (FWS month-name FWS) / obs-month
             *      month-name      =       "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" / "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec"
             *      day             =       ([FWS] 1*2DIGIT) / obs-day
             *      time            =       time-of-day FWS zone
             *      time-of-day     =       hour ":" minute [ ":" second ]
             *      hour            =       2DIGIT / obs-hour
             *      minute          =       2DIGIT / obs-minute
             *      second          =       2DIGIT / obs-second
             *      zone            =       (( "+" / "-" ) 4DIGIT) / obs-zone
             *
             *      The date and time-of-day SHOULD express local time.
             */

            try{
                MIME_Reader r = new MIME_Reader(value);
                string      v = r.Atom();
                // Skip optional [ day-of-week "," ] and read "day".
                if (v.Length == 3)
                {
                    r.Char(true);
                    v = r.Atom();
                }
                int day = Convert.ToInt32(v);
                v = r.Atom().ToLower();
                int month = 1;
                if (v == "jan")
                {
                    month = 1;
                }
                else if (v == "feb")
                {
                    month = 2;
                }
                else if (v == "mar")
                {
                    month = 3;
                }
                else if (v == "apr")
                {
                    month = 4;
                }
                else if (v == "may")
                {
                    month = 5;
                }
                else if (v == "jun")
                {
                    month = 6;
                }
                else if (v == "jul")
                {
                    month = 7;
                }
                else if (v == "aug")
                {
                    month = 8;
                }
                else if (v == "sep")
                {
                    month = 9;
                }
                else if (v == "oct")
                {
                    month = 10;
                }
                else if (v == "nov")
                {
                    month = 11;
                }
                else if (v == "dec")
                {
                    month = 12;
                }
                else
                {
                    throw new ArgumentException("Invalid month-name value '" + value + "'.");
                }
                int year = Convert.ToInt32(r.Atom());
                int hour = Convert.ToInt32(r.Atom());
                r.Char(true);
                int minute = Convert.ToInt32(r.Atom());
                int second = 0;
                // We have optional "second".
                if (r.Peek(true) == ':')
                {
                    r.Char(true);
                    second = Convert.ToInt32(r.Atom());
                }
                int timeZoneMinutes = 0;
                v = r.Atom();
                // Time zone missing. Not RFC syntax, but some servers will send such dates.
                if (v == null)
                {
                    // Just consider time zone as 0(GMT).
                }
                // We have RFC 2822 date. For example: +2000.
                else if (v[0] == '+' || v[0] == '-')
                {
                    if (v[0] == '+')
                    {
                        timeZoneMinutes = (Convert.ToInt32(v.Substring(1, 2)) * 60 + Convert.ToInt32(v.Substring(3, 2)));
                    }
                    else
                    {
                        timeZoneMinutes = -(Convert.ToInt32(v.Substring(1, 2)) * 60 + Convert.ToInt32(v.Substring(3, 2)));
                    }
                }
                // We have RFC 822 date with abbrevated time zone name. For example: GMT.
                else
                {
                    v = v.ToUpper();

                    #region time zones

                    // Alpha Time Zone (military).
                    if (v == "A")
                    {
                        timeZoneMinutes = ((01 * 60) + 00);
                    }
                    // Australian Central Daylight Time.
                    else if (v == "ACDT")
                    {
                        timeZoneMinutes = ((10 * 60) + 30);
                    }
                    // Australian Central Standard Time.
                    else if (v == "ACST")
                    {
                        timeZoneMinutes = ((09 * 60) + 30);
                    }
                    // Atlantic Daylight Time.
                    else if (v == "ADT")
                    {
                        timeZoneMinutes = -((03 * 60) + 00);
                    }
                    // Australian Eastern Daylight Time.
                    else if (v == "AEDT")
                    {
                        timeZoneMinutes = ((11 * 60) + 00);
                    }
                    // Australian Eastern Standard Time.
                    else if (v == "AEST")
                    {
                        timeZoneMinutes = ((10 * 60) + 00);
                    }
                    // Alaska Daylight Time.
                    else if (v == "AKDT")
                    {
                        timeZoneMinutes = -((08 * 60) + 00);
                    }
                    // Alaska Standard Time.
                    else if (v == "AKST")
                    {
                        timeZoneMinutes = -((09 * 60) + 00);
                    }
                    // Atlantic Standard Time.
                    else if (v == "AST")
                    {
                        timeZoneMinutes = -((04 * 60) + 00);
                    }
                    // Australian Western Daylight Time.
                    else if (v == "AWDT")
                    {
                        timeZoneMinutes = ((09 * 60) + 00);
                    }
                    // Australian Western Standard Time.
                    else if (v == "AWST")
                    {
                        timeZoneMinutes = ((08 * 60) + 00);
                    }
                    // Bravo Time Zone (millitary).
                    else if (v == "B")
                    {
                        timeZoneMinutes = ((02 * 60) + 00);
                    }
                    // British Summer Time.
                    else if (v == "BST")
                    {
                        timeZoneMinutes = ((01 * 60) + 00);
                    }
                    // Charlie Time Zone (millitary).
                    else if (v == "C")
                    {
                        timeZoneMinutes = ((03 * 60) + 00);
                    }
                    // Central Daylight Time.
                    else if (v == "CDT")
                    {
                        timeZoneMinutes = -((05 * 60) + 00);
                    }
                    // Central European Daylight Time.
                    else if (v == "CEDT")
                    {
                        timeZoneMinutes = ((02 * 60) + 00);
                    }
                    // Central European Summer Time.
                    else if (v == "CEST")
                    {
                        timeZoneMinutes = ((02 * 60) + 00);
                    }
                    // Central European Time.
                    else if (v == "CET")
                    {
                        timeZoneMinutes = ((01 * 60) + 00);
                    }
                    // Central Standard Time.
                    else if (v == "CST")
                    {
                        timeZoneMinutes = -((06 * 60) + 00);
                    }
                    // Christmas Island Time.
                    else if (v == "CXT")
                    {
                        timeZoneMinutes = ((01 * 60) + 00);
                    }
                    // Delta Time Zone (military).
                    else if (v == "D")
                    {
                        timeZoneMinutes = ((04 * 60) + 00);
                    }
                    // Echo Time Zone (military).
                    else if (v == "E")
                    {
                        timeZoneMinutes = ((05 * 60) + 00);
                    }
                    // Eastern Daylight Time.
                    else if (v == "EDT")
                    {
                        timeZoneMinutes = -((04 * 60) + 00);
                    }
                    // Eastern European Daylight Time.
                    else if (v == "EEDT")
                    {
                        timeZoneMinutes = ((03 * 60) + 00);
                    }
                    // Eastern European Summer Time.
                    else if (v == "EEST")
                    {
                        timeZoneMinutes = ((03 * 60) + 00);
                    }
                    // Eastern European Time.
                    else if (v == "EET")
                    {
                        timeZoneMinutes = ((02 * 60) + 00);
                    }
                    // Eastern Standard Time.
                    else if (v == "EST")
                    {
                        timeZoneMinutes = -((05 * 60) + 00);
                    }
                    // Foxtrot Time Zone (military).
                    else if (v == "F")
                    {
                        timeZoneMinutes = (06 * 60 + 00);
                    }
                    // Golf Time Zone (military).
                    else if (v == "G")
                    {
                        timeZoneMinutes = ((07 * 60) + 00);
                    }
                    // Greenwich Mean Time.
                    else if (v == "GMT")
                    {
                        timeZoneMinutes = 0000;
                    }
                    // Hotel Time Zone (military).
                    else if (v == "H")
                    {
                        timeZoneMinutes = ((08 * 60) + 00);
                    }
                    // India Time Zone (military).
                    else if (v == "I")
                    {
                        timeZoneMinutes = ((09 * 60) + 00);
                    }
                    // Irish Summer Time.
                    else if (v == "IST")
                    {
                        timeZoneMinutes = ((01 * 60) + 00);
                    }
                    // Kilo Time Zone (millitary).
                    else if (v == "K")
                    {
                        timeZoneMinutes = ((10 * 60) + 00);
                    }
                    // Lima Time Zone (millitary).
                    else if (v == "L")
                    {
                        timeZoneMinutes = ((11 * 60) + 00);
                    }
                    // Mike Time Zone (millitary).
                    else if (v == "M")
                    {
                        timeZoneMinutes = ((12 * 60) + 00);
                    }
                    // Mountain Daylight Time.
                    else if (v == "MDT")
                    {
                        timeZoneMinutes = -((06 * 60) + 00);
                    }
                    // Mountain Standard Time.
                    else if (v == "MST")
                    {
                        timeZoneMinutes = -((07 * 60) + 00);
                    }
                    // November Time Zone (military).
                    else if (v == "N")
                    {
                        timeZoneMinutes = -((01 * 60) + 00);
                    }
                    // Newfoundland Daylight Time.
                    else if (v == "NDT")
                    {
                        timeZoneMinutes = -((02 * 60) + 30);
                    }
                    // Norfolk (Island) Time.
                    else if (v == "NFT")
                    {
                        timeZoneMinutes = ((11 * 60) + 30);
                    }
                    // Newfoundland Standard Time.
                    else if (v == "NST")
                    {
                        timeZoneMinutes = -((03 * 60) + 30);
                    }
                    // Oscar Time Zone (military).
                    else if (v == "O")
                    {
                        timeZoneMinutes = -((02 * 60) + 00);
                    }
                    // Papa Time Zone (military).
                    else if (v == "P")
                    {
                        timeZoneMinutes = -((03 * 60) + 00);
                    }
                    // Pacific Daylight Time.
                    else if (v == "PDT")
                    {
                        timeZoneMinutes = -((07 * 60) + 00);
                    }
                    // Pacific Standard Time.
                    else if (v == "PST")
                    {
                        timeZoneMinutes = -((08 * 60) + 00);
                    }
                    // Quebec Time Zone (military).
                    else if (v == "Q")
                    {
                        timeZoneMinutes = -((04 * 60) + 00);
                    }
                    // Romeo Time Zone (military).
                    else if (v == "R")
                    {
                        timeZoneMinutes = -((05 * 60) + 00);
                    }
                    // Sierra Time Zone (military).
                    else if (v == "S")
                    {
                        timeZoneMinutes = -((06 * 60) + 00);
                    }
                    // Tango Time Zone (military).
                    else if (v == "T")
                    {
                        timeZoneMinutes = -((07 * 60) + 00);
                    }
                    // Uniform Time Zone (military).
                    else if (v == "")
                    {
                        timeZoneMinutes = -((08 * 60) + 00);
                    }
                    // Coordinated Universal Time.
                    else if (v == "UTC")
                    {
                        timeZoneMinutes = 0000;
                    }
                    // Victor Time Zone (militray).
                    else if (v == "V")
                    {
                        timeZoneMinutes = -((09 * 60) + 00);
                    }
                    // Whiskey Time Zone (military).
                    else if (v == "W")
                    {
                        timeZoneMinutes = -((10 * 60) + 00);
                    }
                    // Western European Daylight Time.
                    else if (v == "WEDT")
                    {
                        timeZoneMinutes = ((01 * 60) + 00);
                    }
                    // Western European Summer Time.
                    else if (v == "WEST")
                    {
                        timeZoneMinutes = ((01 * 60) + 00);
                    }
                    // Western European Time.
                    else if (v == "WET")
                    {
                        timeZoneMinutes = 0000;
                    }
                    // Western Standard Time.
                    else if (v == "WST")
                    {
                        timeZoneMinutes = ((08 * 60) + 00);
                    }
                    // X-ray Time Zone (military).
                    else if (v == "X")
                    {
                        timeZoneMinutes = -((11 * 60) + 00);
                    }
                    // Yankee Time Zone (military).
                    else if (v == "Y")
                    {
                        timeZoneMinutes = -((12 * 60) + 00);
                    }
                    // Zulu Time Zone (military).
                    else if (v == "Z")
                    {
                        timeZoneMinutes = 0000;
                    }

                    #endregion
                }

                // Convert time to UTC and then back to local.
                DateTime timeUTC = new DateTime(year, month, day, hour, minute, second).AddMinutes(-(timeZoneMinutes));
                return(new DateTime(timeUTC.Year, timeUTC.Month, timeUTC.Day, timeUTC.Hour, timeUTC.Minute, timeUTC.Second, DateTimeKind.Utc).ToLocalTime());
            }
            catch (Exception x) {
                string dymmy = x.Message;
                throw new ArgumentException("Argumnet 'value' value '" + value + "' is not valid RFC 822/2822 date-time string.");
            }
        }