Beispiel #1
0
        /// <summary>
        /// Parse body part information
        /// </summary>
        /// <param name="partInfo">
        /// A list that contains at least 7 tokens (not checked - DANGER)
        /// </param>
        /// <param name="level">
        /// The nesting level.
        /// </param>
        private static BodyPart ParseBodyInfo(ZIMapParser.Token partInfo, uint level)
        {
            ZIMapParser.Token[] list = partInfo.List;
            BodyPart part = new BodyPart();
            part.Part    = partInfo.Text;
            part.Level   = level;

            // 0 := Type
            part.Type    = list[0].QuotedText;
            // 1 := Subtype
            part.Subtype = list[1].QuotedText;

            // 2 := body parameter list (value pairs) ...
            if(list[2].Type == ZIMapParser.TokenType.List)
            {   ZIMapParser.Token[] pars = list[2].List;
                for(int ipar=0; ipar+1 < pars.Length; ipar+=2)
                    if(pars[ipar].Text.ToUpper() == "CHARSET")
                        part.Charset = pars[ipar+1].Text;
                    else
                        part.Filename = pars[ipar+1].Text;
            }
            // 3 := id
            part.ID = list[3].QuotedText;
            // 4 := desciption
            part.Description = list[4].QuotedText;
            // 5 := encoding
            part.Encoding = list[5].QuotedText;

            // 6 := size
            if(list[6].Type == ZIMapParser.TokenType.Number)
                part.Size = list[6].Number;
            return part;
        }
Beispiel #2
0
        public static BodyInfo ParseBodyInfo(string partList)
        {
            if(string.IsNullOrEmpty(partList)) return null;
            ZIMapParser parser = new ZIMapParser(partList);
            if(parser.Length <= 0 || parser[0].Type != ZIMapParser.TokenType.List) return null;

            BodyInfo info = new BodyInfo();
            info.Info = partList;
            List<BodyPart> plis = new List<BodyPart>();
            List<string> pother = new List<string>();
            ParseBodyInfo(plis, pother, parser[0], 0);
            if(plis.Count   > 0) info.Parts = plis.ToArray();
            if(pother.Count > 0) info.Other = pother.ToArray();
            return info;
        }
Beispiel #3
0
        private static void ParseBodyInfo(List<BodyPart> plis, List<string> pother,
                                          ZIMapParser.Token list, uint level)
        {
            if(list.Type != ZIMapParser.TokenType.List)
            {   string text = list.Text.ToUpper();
                if(text == "ALTERNATIVE")
                {   for(int irun=0; irun < plis.Count; irun++)
                        if(plis[irun].Level != level) continue;
                        else plis[irun].Alternative = true;
                }
                if(text == "RELATED")
                {   for(int irun=0; irun < plis.Count; irun++)
                        if(plis[irun].Level != level) continue;
                        else plis[irun].Related = true;
                }
                else
                {   //Console.WriteLine("{0} Final: {1}", level, list.Text);
                    pother.Add(list.Text);
                }
                return;
            }

            uint ulen = (uint)list.List.Length;
            if(ulen >= 7 && list.List[2].Type == ZIMapParser.TokenType.List)
            {   plis.Add(ParseBodyInfo(list, level));
                return;
            }

            foreach(ZIMapParser.Token tok in list.List)
                ParseBodyInfo(plis, pother, tok, level+1);
        }
            protected override bool Parse(bool reset)
            {
                if(reset)
                {   items  = null;
                    return true;
                }

                ZIMapProtocol.ReceiveData data = Result;
                if(data.Infos == null) return false;
                items = new Item[data.Infos.Length];
                int ilit=0;                                 // literal index
                for(int irun=0; irun < items.Length; irun++)
                {   uint sequ;
                    if(!uint.TryParse(data.Infos[irun].Status, out sequ))
                        continue;                           // status not a number
                    items[irun].Index = sequ;

                    ZIMapParser parser = new ZIMapParser(data.Infos[irun].Message);
                    if(parser.Length < 2 || parser[0].Text != command)
                        continue;                           // not for "FETCH"
                    if(parser[1].Type != ZIMapParser.TokenType.List)
                        continue;                           // server error

                    ZIMapParser.Token[] tokens = parser[1].List;
                    List<string> parts = null;
                    uint ulit = 0;

                    for(int itok=0; itok < tokens.Length; itok++)
                    {   ZIMapParser.Token token = tokens[itok];

                        if(token.Type == ZIMapParser.TokenType.Literal)
                        {   if(ulit == 0)                   // count literals
                            {   for(int icnt=itok+1; icnt < tokens.Length; icnt++)
                                    if(tokens[icnt].Type == ZIMapParser.TokenType.Literal) ulit++;
                                if(ulit > 0)
                                {   items[irun].Data = new byte[ulit+1][];
                                    ulit = 1;
                                }
                                else ulit = uint.MaxValue;
                            }
                            if(data.Literals == null || ilit >= data.Literals.Length)
                                MonitorError("Fetch: literal missing: " + ilit);
                            else
                            {   if(data.Literals[ilit].Length == token.Number)
                                {   if(ulit == uint.MaxValue)
                                        items[irun].Data = Result.Literals[ilit];
                                    else
                                    {   ((byte[][])items[irun].Data)[ulit-1] = Result.Literals[ilit];
                                        ulit++;
                                    }
                                }
                                else
                                    MonitorError("Fetch: literal invalid: " + ilit);
                                ilit++;
                            }
                        }
                        else if(token.Text == "UID")
                        {   if(itok+1 >= tokens.Length) continue;   // server bug
                            token = tokens[itok+1];                 // should be a number
                            if(token.Type == ZIMapParser.TokenType.Number)
                            {   items[irun].UID = token.Number;
                                itok++;
                            }
                        }
                        else if(token.Text == "FLAGS")
                        {   if(itok+1 >= tokens.Length) continue;   // server bug
                            token = tokens[itok+1];                 // should be a list
                            if(token.Type == ZIMapParser.TokenType.List)
                            {   string[] flis = ZIMapConverter.StringArray(token.List.Length);
                                items[irun].Flags = flis;
                                int isub=0;
                                foreach(ZIMapParser.Token flag in token.List)
                                    flis[isub++] = flag.Text;
                                itok++;
                            }
                        }
                        else if(token.Text == "RFC822.SIZE")
                        {   if(itok+1 >= tokens.Length) continue;   // server bug
                            token = tokens[itok+1];                 // should be a number
                            if(token.Type == ZIMapParser.TokenType.Number)
                            {   items[irun].Size = token.Number;
                                itok++;
                            }
                        }
                        else
                        {   if(parts == null) parts = new List<string>();
                            parts.Add(token.ToString());
                        }
                    }
                    if(parts != null)
                       items[irun].Parts = parts.ToArray();
                }
                return true;
            }
            protected override bool Parse(bool reset)
            {
                if(reset)
                {   roots = null;
                    return base.Parse(reset);
                }

                ZIMapProtocol.ReceiveData data = Result;
                if(data.Infos == null) return false;

                List<Item> list = new List<Item>();
                foreach(ZIMapProtocol.ReceiveInfo info in data.Infos)
                {   ZIMapParser parser = new ZIMapParser(info.Message);
                    if(parser.Length < 1) continue;         // server bug

                    if(info.Status == "QUOTAROOT")          // not for us
                    {   int icnt = parser.Length;
                        roots = new string[icnt];
                        for(int irun=0; irun < icnt; irun++)
                            roots[irun] = parser[irun].Text;
                    }
                    if(info.Status != "QUOTA") continue;    // not for us...

                    if(parser.Length < 2 ||
                       parser[1].Type != ZIMapParser.TokenType.List)
                        continue;                           // ignore this
                    ZIMapParser.Token[] triplet = parser[1].List;
                    for(int irun=0; irun < triplet.Length; irun += 3)
                    {   if(triplet.Length - irun < 3 ||
                           triplet[irun+1].Type != ZIMapParser.TokenType.Number ||
                           triplet[irun+2].Type != ZIMapParser.TokenType.Number)
                        {   MonitorError("Invalid data: " + info);
                            break;
                        }

                        Item item = new Item();
                        item.RootName = parser[0].Text;
                        item.Resource = triplet[irun].Text;
                        item.Usage = triplet[irun+1].Number;
                        item.Limit = triplet[irun+2].Number;
                        list.Add(item);
                    }
                }
                if(roots == null) return false;             // got no QUOTAROOT
                quota = list.ToArray();
                return true;
            }
            protected override bool Parse(bool reset)
            {
                base.Parse(reset);
                if(reset)
                {   messages = recent = unseen = 0;
                    args = null;
                    return true;
                }

                ZIMapProtocol.ReceiveData data = Result;
                if(data.Infos == null) return false;
                if(!IsReady) return false;

                // get flags. exists and recent are special...
                foreach(ZIMapProtocol.ReceiveInfo i in data.Infos)
                {   if(i.Status == "FLAGS")
                        flags = i.Message;
                    else if(i.Message == "EXISTS")
                        uint.TryParse(i.Status, out messages);
                    else if(i.Message == "RECENT")
                        uint.TryParse(i.Status, out recent);
                }

                // search for unseen ...
                foreach(ZIMapProtocol.ReceiveInfo i in data.Infos)
                {   if(i.Status != "OK") continue;
                    ZIMapParser parser = new ZIMapParser(i.Message);
                    if(parser.Length < 1) continue;
                    if(parser[0].Type != ZIMapParser.TokenType.Bracketed) continue;

                    parser = new ZIMapParser(parser[0].Text);
                    if(parser.Length < 2) continue;
                    if(parser[0].Text == "UNSEEN")
                    {   unseen = parser[1].Number;
                        break;
                    }
                }

                // get the readonly flag
                ZIMapParser.Token access = data.Parser[0];
                if(access.Type == ZIMapParser.TokenType.Bracketed)
                {   if(access.Text == "READ-ONLY")
                        readOnly = true;
                    else if(access.Text == "READ-WRITE")
                        readOnly = false;
                }
                data.Parser = null;
                return true;
            }
            protected override bool Parse(bool reset)
            {
                if(reset)
                {   items  = null;
                    return true;
                }

                ZIMapProtocol.ReceiveData data = Result;
                if(data.Infos == null) return false;
                items = new Item[data.Infos.Length];
                for(int irun=0; irun < items.Length; irun++)
                {   uint sequ;
                    if(!uint.TryParse(data.Infos[irun].Status, out sequ))
                        continue;                           // status not a number
                    ZIMapParser parser = new ZIMapParser(data.Infos[irun].Message);
                    if(parser.Length < 2 || parser[0].Text != "FETCH")
                        continue;                           // not for "FETCH"
                    if(parser[1].Type != ZIMapParser.TokenType.List)
                        continue;                           // server error

                    ZIMapParser.Token[] tokens = parser[1].List;
                    List<string> parts = null;

                    for(int itok=0; itok < tokens.Length; itok++)
                    {   ZIMapParser.Token token = tokens[itok];

                        if(token.Text == "UID")
                        {   if(itok+1 >= tokens.Length) continue;   // server bug
                            token = tokens[itok+1];                 // should be a number
                            if(token.Type == ZIMapParser.TokenType.Number)
                            {   items[irun].UID = token.Number;
                                itok++;
                            }
                        }
                        else if(token.Text == "FLAGS")
                        {   if(itok+1 >= tokens.Length) continue;   // server bug
                            token = tokens[itok+1];                 // should be a list
                            if(token.Type == ZIMapParser.TokenType.List)
                            {   string[] flis = ZIMapConverter.StringArray(token.List.Length);
                                items[irun].Flags = flis;
                                int isub=0;
                                foreach(ZIMapParser.Token flag in token.List)
                                    flis[isub++] = flag.Text;
                                itok++;
                            }
                        }
                        else
                        {   if(parts == null) parts = new List<string>();
                            parts.Add(token.ToString());
                        }
                    }
                    if(parts != null)
                       items[irun].Parts = parts.ToArray();
                }
                return true;
            }
Beispiel #8
0
        /// <summary>
        /// Return information from the parsed reply of the NAMESPACE command.
        /// </summary>
        /// <param name="nsIndex">
        /// Selects the returned <see cref="Namespace"/> information<para/>
        /// <list type="table"><listheader>
        ///    <term>nsIndex Value</term>
        ///    <description>Selected Namespace</description>
        /// </listheader><item>
        ///    <term>Personal (0)</term>
        ///    <description>The current user's namepace (INBOX)</description>
        /// </item><item>
        ///    <term>Others (1)</term>
        ///    <description>Other users</description>
        /// </item><item>
        ///    <term>Shared (2)</term>
        ///    <description>Shared folders</description>
        /// </item><item>
        ///    <term>Search (3)</term>
        ///    <description>Pseudo-Namespace for search results</description>
        /// </item><item>
        ///    <term>Nothing (uint.MaxValue)</term>
        ///    <description>Invalid, returns <c>null</c></description>
        /// </item></list>
        /// </param>
        /// <returns>
        /// A <see cref="Namespace"/> item that contains parsed data.
        /// The server may have sent items that get ignored by this
        /// parser (multiple entries for a namespace and annotations).
        /// <para/>
        /// When the <paramref name="nsIndex"/> argument is invalid, the method
        /// returns <c>null</c>.
        /// </returns>
        public virtual Namespace NamespaceData(uint nsIndex)
        {
            if(nsIndex > Search) return null;
            if(namespdata == null) namespdata = new Namespace[Search+1];
            if(namespdata[nsIndex] != null) return namespdata[nsIndex];

            // Preinit: namespace not valid
            namespdata[nsIndex] = new Namespace();
            namespdata[nsIndex].Prefix = "";
            namespdata[nsIndex].Qualifier = "";
            namespdata[nsIndex].Index = nsIndex;

            // Get namespace info if namespaces are enabled ...
            if(namespaceOK)
            {   string list = NamespaceList(nsIndex);
                if(list != null)
                {   ZIMapParser parser = new ZIMapParser(list);
                    if(parser.Length > 0 && parser[0].Type == ZIMapParser.TokenType.List)
                    {   ZIMapParser.Token[] toks = parser[0].List;
                        if(toks.Length > 0)
                            namespdata[nsIndex].Prefix = toks[0].Text;
                        if(toks.Length > 1)
                        {   string del = toks[1].Text;
                            if(!string.IsNullOrEmpty(del))
                            {   namespdata[nsIndex].Delimiter = del[0];
                                namespdata[nsIndex].Valid = true;
                            }
                        }
                    }
                }
            }

            // Postinit: fix-up
            if(!namespdata[nsIndex].Valid)
                namespdata[nsIndex].Delimiter = factory.HierarchyDelimiter;
            string pref = namespdata[nsIndex].Prefix;
            int plen = pref.Length;
            if(plen > 0 && pref[plen-1] == namespdata[nsIndex].Delimiter)
                namespdata[nsIndex].Qualifier = pref.Substring(0, plen - 1);
            else
                namespdata[nsIndex].Qualifier = pref;

            return namespdata[nsIndex];
        }
Beispiel #9
0
        // helper used for lists
        private void Parse(string message, ref int start)
        {
            TokenType state = TokenType.Void;
            bool skip = false;
            StringBuilder sb = new StringBuilder();

            int len = message.Length;               // dummy space at the end
            int idx = start;
            for(; idx <= len; idx++)
            {   char curr = (idx >= len) ? ' ' : message[idx];

                switch(state)
                {   case TokenType.Void:
                            if(curr == ' ')
                                continue;
                            skip = false; sb.Length = 0;
                            if(curr == '"')
                                state = TokenType.Quoted;
                            else if(curr >= '0' && curr <= '9')
                            {   state = TokenType.Number;
                                sb.Append(curr);
                            }
                            else if(curr == '(')
                            {   idx++;
                                List<Token> list = new ZIMapParser(message, ref idx).tokens;
                                tokens.Add(new Token(list.ToArray(), TokenType.List));
                                idx--;                          // should be ')'
                                continue;
                            }
                            else if(curr == ')' && start > 0)
                            {   len=0; break;
                            }
                            else if(curr == '{')
                                state = TokenType.Literal;
                            else if(curr == '[')
                                state = TokenType.Bracketed;
                            else
                            {   state = TokenType.Text;
                                sb.Append(curr);
                            }
                            break;

                    case  TokenType.Bracketed:
                            if(curr == ']')
                            {   tokens.Add(new Token(sb.ToString(), state));
                                state = TokenType.Void;
                                continue;
                            }
                            sb.Append(curr);
                            break;

                    case  TokenType.Literal:
                            if(curr == '}')
                            {   tokens.Add(new Token(sb.ToString(), state));
                                state = TokenType.Void;
                                continue;
                            }
                            if(curr < '0' || curr > '9')
                                state = TokenType.Text;
                            sb.Append(curr);
                            break;

                    case  TokenType.Number:
                            if(curr == ')' || curr == ']')
                            {   curr  = ' '; idx--;
                            }
                            if(curr == ' ' || curr == '[')
                            {   tokens.Add(new Token(sb.ToString(), state));
                                state = TokenType.Void;
                                if(curr == '[') idx--;
                                continue;
                            }
                            if(curr < '0' || curr > '9')
                                state = TokenType.Text;
                            sb.Append(curr);
                            break;

                    case  TokenType.Quoted:
                            if(skip)
                                skip = false;
                            else if(curr == '\\')
                                skip = true;
                            else if(curr == '"')
                            {   tokens.Add(new Token(sb.ToString(), state));
                                state = TokenType.Void;
                            }
                            else
                                sb.Append(curr);
                            break;

                    default:                                // text
                            if(curr == ')' || curr == ']')
                            {   curr  = ' '; idx--;
                            }
                            if(curr == ' ' || curr == '[')
                            {   tokens.Add(new Token(sb.ToString(), state));
                                state = TokenType.Void;
                                if(curr == '[') idx--;
                                continue;
                            }
                            sb.Append(curr);
                            break;
                }
            }
            start = idx;
        }
Beispiel #10
0
 /// <summary>
 /// Search a string array of partially parserd data for an item.
 /// </summary>
 /// <param name="parts">
 /// The string array to be searched.
 /// </param>
 /// <param name="item">
 /// The item to be searched for.
 /// </param>
 /// <param name="text">
 /// Returns the text from array element that follows the item on success.
 /// Will return an empty string on error. Should never return <c>null</c>.
 /// </param>
 /// <returns>
 /// On success a value of <c>true</c> is returned.
 /// </returns>
 /// <remarks>
 /// The commands FETCH and STORE can return data that is only partially parsed in
 /// their Item arrays.  This function is provided to help searching such data.
 /// The following example tries to retrieve 'INTERNALDATE' from a FETCH:<para />
 /// <example><code lang="C#">
 ///     DateTime date;
 ///     string sdat;
 ///     if (ZIMapFactory.FindInParts(item.Parts, "INTERNALDATE", out sdat))
 ///         date = ZIMapConverter.DecodeIMapTime(sdat, true);
 ///     else
 ///         date = msg.DateBinary;
 /// </code></example>
 /// </remarks>
 public static bool FindInParts(string[] parts, string item, out string text)
 {
     text = "";
     int idx = FindInStrings(parts, 0, item, false);
     if(idx < 0) return false;                           // item not found
     if(++idx >= parts.Length) return false;             // no value
     text = parts[idx];
     if(text.Length > 0 && text[0] == '"')               // must unquote
     {   ZIMapParser parser = new ZIMapParser(text);
         text = parser[0].Text;
     }
     return true;
 }
Beispiel #11
0
        // =============================================================================
        // Command execution
        // =============================================================================
        /// <summary>
        /// A simple overload for <see cref="Execute(string, string[], string[])"/>
        /// </summary>
        /// <param name="cmd">
        /// Comand string to be executed.
        /// </param>
        /// <returns>
        /// <c>true</c> on success.
        /// </returns>
        public static bool Execute(string cmd)
        {
            UnparsedCommand = cmd;

            // Debug stuff
            #if DEBUG
            if(cmd == "xxx")
            {    ZIMapFactory.Bulk bulk = new ZIMapFactory.Bulk(App.Factory, "Examine", 8, false);
                uint urub = 0;
                uint urdy = 0;
                uint umax = 5000;
                ZIMapCommand.Generic cmdb = null;
                while(urdy < umax)
                {   if(bulk.NextCommand(ref cmdb))
                    {   cmdb.CheckSuccess(); urdy++;
                        ProgressReporting.Update(urdy, umax);
                        cmdb.Reset();
                    }
                    if(urub++ < umax)
                    {   //cmdb.AddLiteral("unfug");
                        cmdb.AddString("unfug");
                        cmdb.AddString("unfugxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
                        cmdb.Queue();
                    }
                }
                bulk.Dispose();
                return true;
            }
            #endif
            List<string> opts = new List<string>();
            List<string> args = new List<string>();
            if(!string.IsNullOrEmpty(cmd))
            {   ZIMapParser parser = new ZIMapParser(cmd);
                cmd = parser[0].ToString();

                bool bimap = cmd == "imap";
                for(int irun=1; irun < parser.Length; irun++)
                {   ZIMapParser.Token token = parser[irun];
                    if(!bimap && token.Type == ZIMapParser.TokenType.Quoted)
                        args.Add(token.Text);
                    else if(token.Type != ZIMapParser.TokenType.Text ||
                            token.Text.Length <= 1 ||
                            !(token.Text[0] == '-' || token.Text[0] == '/'))
                        args.Add(token.ToString());
                    else
                        opts.Add(token.Text.Substring(1));
                }
            }

            ErrorCalled = false;
            bool bok = Execute(ref cmd, opts.ToArray(), args.ToArray());
            UnparsedCommand = null;
            if(bok) return true;
            if(!ErrorCalled) Error("Command failed: {0}", cmd);
            return false;
        }
Beispiel #12
0
 /// <summary>
 /// Resets the structure to it's initial state
 /// </summary>
 /// <remarks>
 /// Call this method to release resources (mostly the parser). 
 /// </remarks>
 public void Reset()
 {
     Status = Message = null;
     parser = null;
 }