示例#1
0
 // =============================================================================
 // xtor
 // =============================================================================
 public CacheData(ZIMapApplication application)
     : base(application.Parent)
 {
     this.application = application;
     connection = application.Connection;
     server     = application.Server;
     factory    = connection.CommandLayer;
     progress   = connection.ProgressReporting;
     // At least deliver Info level messages ...
     MonitorLevel = application.MonitorLevel;
     if(MonitorLevel > ZIMapConnection.Monitor.Info)
         MonitorLevel = ZIMapConnection.Monitor.Info;
     Data = data = new DataRefImp(this);
 }
示例#2
0
            // Pretty formatting of monitor messages ...
            public override bool Monitor(ZIMapConnection connection, ZIMapConnection.Monitor level,
                                         string source, string message)
            {
                if(message == null || source == null) return true;

                // output messages ...
                string text = null;
                if(level <= ZIMapConnection.Monitor.Error)
                {   if(message.Length > 2 && message[0] == ':')
                        text = message.Substring(1);
                }
                if(text == null) text = source + ": " + message;

                switch(level)
                {   case ZIMapConnection.Monitor.Debug:     LineTool.Extra(text);
                                                            return true;
                    case ZIMapConnection.Monitor.Info:      LineTool.Info(text);
                                                            return true;
                    case ZIMapConnection.Monitor.Error:     ZIMapAdmin.ErrorCalled = true;
                                                            LineTool.Error(text);
                                                            return true;
                    default:                                return true;
                }
            }
示例#3
0
        // =====================================================================
        // The 'command loop' routine
        // =====================================================================
        /// <summary>The 'command loop' routine</summary>
        /// <param name="server">A name or URL to contact the server</param>
        /// <param name="prot">A protocol name like 'imap' or 'imaps'</param>
        /// <param name="mode">SSL handling, see 
        ///        <see cref="ZIMapConnection.TlsModeEnum"/></param>
        /// <param name="timeout">Timeout in [s]</param>
        /// <param name="account">The IMAP account (user) to be used</param>
        /// <param name="password">Password for the given account</param>
        /// <param name="debug">Turns debug output on</param>
        /// <returns><c>true</c> on success</returns>
        public static bool Run(string server, string prot, 
                               ZIMapConnection.TlsModeEnum mode, uint timeout,
                               string account, string password, bool debug)
        {
            ZIMapConnection connection;
            ZIMapProtocol protocol;
            ZIMapConnection.Callback = new IMapCallback();

            try {
                connection = ZIMapConnection.GetConnection(server,
                                ZIMapConnection.GetIMapPort(prot), mode, timeout);
                if(connection == null)
                {   LineTool.Error("Connect failed");
                    return false;
                }
                connection.MonitorLevel = debug ? ZIMapConnection.Monitor.Debug
                                                : ZIMapConnection.Monitor.Error;
                protocol = connection.ProtocolLayer;
                protocol.MonitorLevel = connection.MonitorLevel;
                connection.TransportLayer.MonitorLevel = connection.MonitorLevel;
                LineTool.Info(protocol.ServerGreeting);
            }
            catch(Exception e) {
                LineTool.Error("Connect failed with exception: {0}", e.Message);
                return false;
            }

            if(!string.IsNullOrEmpty(account))
            {   StringBuilder sb = new StringBuilder("LOGIN ");
                if(!ZIMapConverter.QuotedString(sb, account, false) ||
                   sb.Append(' ') == null ||
                   !ZIMapConverter.QuotedString(sb, password, false))
                {   LineTool.Error("Error: Can use only 7-bit data for '-account'");
                    return false;
                }
                LineTool.Info(sb.ToString());
                protocol.Send(sb.ToString());
                ZIMapProtocol.ReceiveData data;
                protocol.Receive(out data);
                if(!data.Succeeded)
                {   LineTool.Error("Error: {0}", data.Message);
                    return false;
                }
            }

            // The loop that does the real work
            string[] command;
            while((command = LineTool.Prompt("IMAP", 2)) != null) {
                try {
                    string message = command[0].ToUpper();
                    if(command.Length > 1) message += " " + command[1];
                    protocol.Send(message);
                    uint tag;
                    string status;
                    ZIMapProtocol.ReceiveState info;
                    do {
                        info = protocol.Receive(out tag, out status, out message);
                        LineTool.Message("{0} {1} {2}", tag, status, message);
                    }
                    while(info == ZIMapProtocol.ReceiveState.Info);

                    if(connection.IsTransportClosed) return false;
                }
                catch(Exception e) {
                    LineTool.Error("Command failed with exception: {0}", e.Message);
                }
            }
            return true;
        }
示例#4
0
 /// <summary>
 /// Output a top level error message via ZIMapConnection.
 /// </summary>
 /// <param name="message">
 /// Message to be displayed as an application error.
 /// </param>
 /// <param name="level">
 /// Severity or kind of the message.
 /// </param>
 /// <remarks>
 /// The ZIMapAdmin application uses an additional colon to filter
 /// top level error messages. Example: ":Top level error".
 /// </remarks>
 protected override void MonitorInvoke(ZIMapConnection.Monitor level, string message)
 {
     if(MonitorLevel <= level)
         ZIMapConnection.MonitorInvoke(connection, "Cache", level, ":" + message);
 }
示例#5
0
 // =====================================================================
 // Progress reporting
 // =====================================================================
 /// <summary>
 /// Update the progress display even before having a <see cref="ZIMapConnection"/>
 /// instance.
 /// </summary>
 /// <param name="connection">
 /// Should be the current connection but can also be <c>null</c> if no connection
 /// has been created until the time of the call.
 /// </param>
 /// <param name="percent">
 /// The progress value <see cref="ZIMapConnection.Progress.Update(uint)"/>.
 /// </param>
 /// <remarks>
 /// This wrapper is efficient and can be used by library routines as a standard
 /// call to update the progress display.  Another way for applications is to use
 /// the <see cref="ProgressReporting"/> protperty to obtain a reference to an
 /// instance of the <see cref="ZIMapConnection.Progress"/> class that offers more
 /// features.
 /// </remarks>
 public static void ProgressUpdate(ZIMapConnection connection, uint percent)
 {   if(connection == null)
     {   if(percent > 100) percent = 100;
         MonitorInvoke(null, "ZIMapConnection", Monitor.Progress, percent.ToString());
     }
     else if(connection.progress != null)
         connection.progress.Update(percent);
     else
         connection.ProgressReporting.Update(percent);
 }
示例#6
0
 public virtual bool Result(ZIMapConnection connection, object info)
 {   return false;   }
示例#7
0
 public virtual bool Closed(ZIMapConnection connection)
 {   return false;   }
示例#8
0
 public virtual bool Progress(ZIMapConnection connection, uint percent)
 {   return false;   }
 // =====================================================================
 // Debug stuff
 // =====================================================================
 public void SetMonitorLevel(ZIMapConnection.Monitor level, bool allLayers)
 {
     if(level > ZIMapConnection.Monitor.Error) return;
     monitorLevel = level;
     monitorAll = allLayers;
     if(factory == null) return;
     factory.MonitorLevel = level;
     factory.Connection.MonitorLevel = level;
     if(!allLayers && level != ZIMapConnection.Monitor.Error)
         level = ZIMapConnection.Monitor.Info;
     factory.Connection.TransportLayer.MonitorLevel = level;
     factory.Connection.ProtocolLayer.MonitorLevel = level;
 }
示例#10
0
        /// <summary>
        /// Pass exception object to ZIMapConnection.Callback, throw as error is not handled. 
        /// </summary>
        /// <param name="conn">
        /// The parent connection or <c>null</c> if unknown.
        /// </param>
        /// <param name="code">
        /// The error code <see cref="ZIMapException.ErrorCode"/>
        /// </param>
        /// <param name="arg1">
        /// <c>null</c> for no info, an Exception object as inner exception or any other
        /// object (ToString will be called).
        /// </param>
        public static void Throw(ZIMapConnection conn, Error code, object arg1)
        {
            ZIMapException err;
            if(arg1 == null)
               err = new ZIMapException(code);
            else if(arg1 is Exception)
               err = new ZIMapException(code, (Exception)arg1);
            else
               err = new ZIMapException(code, MessageFromCode(code) + ": " + arg1.ToString());

            if(ZIMapConnection.Callback.Error(conn, err))
                return;
            throw err;
        }
示例#11
0
 /// <summary>
 /// Hook for sending error and debug messages or to inform of 
 /// status changes.
 /// </summary>
 /// <param name="level">
 /// <see cref="ZIMapConnection.Monitor"/> indicates the importance of the message.
 /// </param>
 /// <param name="message">
 /// The payload.
 /// </param>
 /// <remarks>Implementing this in a derived class gives the implementor
 /// full control about the message output.  Usually the implementation
 /// will just call
 /// <see cref="ZIMapConnection.MonitorInvoke(ZIMapConnection.Monitor, string)"/>.
 /// <para />
 /// Messages will only be processed if <paramref name="level"/> is less
 /// or equal to <see cref="MonitorLevel"/>).
 /// </remarks>
 protected abstract void MonitorInvoke(ZIMapConnection.Monitor level, string message);
示例#12
0
 /// <summary>The one and only constructor.</summary>
 /// <param name="parent">
 /// The owning connection.
 /// </param>
 /// <remarks>
 /// The constructor is protected, use <see cref="ZIMapConnection.CommandLayer"/>
 /// to get an instance of a factory.
 /// </remarks>
 protected ZIMapFactory(ZIMapConnection parent)
     : base(parent)
 {
 }
示例#13
0
 // =============================================================================
 // Xtor
 // =============================================================================
 /// <summary>
 /// This is the one and only constructor.
 /// </summary>
 /// <param name="parent">
 /// Required reference to the connection.  Must not be <c>null</c>.
 /// </param>
 public ZIMapExport(ZIMapConnection parent)
     : base(parent)
 {
 }
示例#14
0
 // kill program on exception ...
 public override bool Error(ZIMapConnection connection, ZIMapException error)
 {
     if(Thread.CurrentThread.ThreadState == ThreadState.AbortRequested)
         return true;
     ZIMapAdmin.Error("Error [exception]: {0}", error.Message);
     if(!Executing)
     {   if(LineTool.LogWriter != null) LineTool.LogWriter.Close();
         ZIMapAdmin.Error("Terminating the program");
         System.Environment.Exit(2);
     }
     if(Debug == 0) LineTool.Info(
         "Ignoring the error. Use the 'debug 2' command to enable debug output.");
     return false;
 }
示例#15
0
 public override bool Progress(ZIMapConnection connection, uint percent)
 {
     if(ZIMapAdmin.Output < OutLevel.All) return true;
     if(ZIMapAdmin.Debug > 0)             return true;
     if(percent < 100) LineTool.Progress("Working [", percent,
                                         string.Format("] {0,2}%\r", percent));
     return true;
 }
示例#16
0
        public static void MonitorInvoke(ZIMapConnection origin, string name,
                                         Monitor level, string message)
        {   if(message == null) message = "<null>";
            if(level == Monitor.Progress)
            {   if(message == MonitorProgress) return;
                MonitorProgress = message;
            }
            else if(level != Monitor.Messages)
                MonitorProgress = null;

            if(name == null) name = "<null>";
            
            // must use locking to make this thread safe (see ZIMapTransport.Reader) ...
            try
            {   if(origin != null) System.Threading.Monitor.Enter(origin);
                
                if(level == Monitor.Progress)
                {   uint percent;
                    if(uint.TryParse(message, out percent) &&
                       ZIMapConnection.Callback.Progress(origin, percent))
                            return;
                    Console.Write("{0} {1}: {2}\r", name, level, message);
                }
                else if(level == Monitor.Messages)
                {   uint existing;
                    if(!uint.TryParse(message, out existing)) return;
                    ZIMapConnection.Callback.Message(origin, existing);
                }
                else
                {   if(ZIMapConnection.Callback.Monitor(origin, level, name, message))
                        return;
                    Console.WriteLine("{0} {1}: {2}", name, level, message);
                }
            }
            finally
            {   if(origin != null) System.Threading.Monitor.Exit(origin);
            }
        }
示例#17
0
 {   public virtual bool Monitor(ZIMapConnection connection, ZIMapConnection.Monitor level,
                                 string source, string message)
     {   return false;   }
示例#18
0
 // must implement, abstract in base ...
 protected override void MonitorInvoke(ZIMapConnection.Monitor level, string message)
 {
     if(MonitorLevel <= level)
         ZIMapConnection.MonitorInvoke(connection, "ZIMapFactory", level, message);
 }
示例#19
0
 public virtual bool Message(ZIMapConnection connection, uint existing)
 {   return false;   }
示例#20
0
        /// <summary>
        /// Connect to the IMap server and optionally login.
        /// </summary>
        /// <param name="user">
        /// An IMap account name or <c>null</c> for no login.
        /// </param>
        /// <param name="password">
        /// The password for the given account.
        /// </param>
        /// <param name="tlsMode">
        /// Controls TLS (tranport layer security).
        /// </param>
        /// <returns>
        /// On success <c>true</c> is returned.
        /// </returns>
        /// <remarks>This function calls <see cref="ZIMapConnection.GetConnection(string)"/>
        /// and uses <see cref="ZIMapCommand.Login"/> for login.
        /// <para />
        /// If this method is called while having an open connection <c>Disconnect</c> 
        /// gets called first.
        /// </remarks>
        public bool Connect(string user, string password, ZIMapConnection.TlsModeEnum tlsMode)
        {
            // step 1: Open a new connection and get factory ...
            ZIMapConnection.ProgressUpdate(null, 0);
            if(connection != null) Disconnect();

            connection = ZIMapConnection.GetConnection(ServerName, ServerPort,
                                                       tlsMode, timeout);
            if(connection != null)
            {   connection.MonitorLevel = MonitorLevel;
                progress = connection.ProgressReporting;
                progress.Update(20);
                factory = connection.CommandLayer;
            }
            if(factory == null)
            {   connection = null;
                MonitorError("Connect: failed to open connection");
                return false;
            }

            // defaults for logging ...
            SetMonitorLevel(monitorLevel, monitorAll);

            // step 2: login
            string greeting = connection.ProtocolLayer.ServerGreeting;
            MonitorInfo("Connect: server greeting: " + greeting);
            progress.Update(40);

            ZIMapCommand.Login cmd = new ZIMapCommand.Login(factory);
            cmd.Queue(user, password);
            if(!cmd.CheckSuccess())
            {   MonitorError("Connect: login failed");
                return false;
            }
            username = user;
            progress.Update(60);

            // set 3: get server configuration

            bool bIMap = true;
            CheckCapability("IMAP4rev1", false, ref bIMap);
            CheckCapability("NAMESPACE", bIMap, ref enableNamespaces);
            CheckCapability("QUOTA",     false, ref enableQuota);
            CheckCapability("ACL",       false, ref enableRights);
            CheckCapability("UIDPLUS",   bIMap, ref enableUid);
            progress.Update(80);

            // step4: get Namespace info
            if(enableNamespaces)
            {   if(Server.NamespaceDataPersonal.Valid)
                    MonitorInfo("Connect: NAMESPACE enabled");
                else
                {   MonitorInfo("Connect: NAMESPACE disabled (not supported)");
                    enableNamespaces = false;
                }
                factory.HierarchyDelimiter = server.DefaultDelimiter;
            }
            progress.Done();
            return true;
        }
示例#21
0
 public virtual bool Request(ZIMapConnection connection, uint tag, string command)
 {   return false;   }
示例#22
0
        /// <summary>
        /// Logout and close the IMap connection.
        /// </summary>
        /// <remarks>
        /// If a user is logged in this command sends an IMap LOGOUT command.  If also
        /// closes the connection if it is open.  The <see cref="ZIMapFactory"/>
        /// object gets released.  After a call to this method a connection can be
        /// reestablished by calling <see cref="Connect(string, string)"/>. 
        /// </remarks>
        public void Disconnect()
        {
            if(factory != null && IsLoggedIn)
            {   ZIMapCommand.Logout cmd = new ZIMapCommand.Logout(factory);
                cmd.Execute(true);
                cmd.Dispose();
            }
            if(connection != null)
            {   connection.Close();
                MonitorInfo("Disconnect: done");
            }

            connection = null;
            factory = null;
            username = null;
            mailboxName = null;
        }
示例#23
0
 public virtual bool Error(ZIMapConnection connection, ZIMapException error)
 {   return false;   }
示例#24
0
        /// <summary>
        /// Creates a connection instance and opens an IMap connection.
        /// </summary>
        /// <param name="server">
        /// The server URL or IP Address.
        /// </param>
        /// <param name="port">
        /// The port number to be used, see <see cref="GetIMapPort(string)"/>.
        /// </param>
        /// <param name="tlsMode">
        /// Controls TLS (tranport layer security), see <see cref="TlsModeEnum"/>.
        /// </param>
        /// <param name="timeout">
        /// Connection timeout, use <c>0</c> for no timeout.
        /// </param>
        /// <returns>
        /// A new instance of <c>ZIMapConnection</c> that is connected to the
        /// specified IMap server.
        /// </returns>
        /// <remarks>
        /// The method raises an error of type <see cref="ZIMapException.Error.CannotConnect"/>
        /// if no connection can be established.
        /// </remarks>
        public static ZIMapConnection GetConnection(string server, uint port, 
                                                    TlsModeEnum tlsMode, uint timeout)
        {   ZIMapConnection conn = new ZIMapConnection();
            conn.tlsmode = tlsMode;
            conn.timeout = timeout;
            try
            {   conn.socket = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, 
                                                              System.Net.Sockets.SocketType.Stream, 
                                                              System.Net.Sockets.ProtocolType.IP);
                // The socket timeouts will be reset by the transport layer!
                if(timeout > 0)
                {   conn.socket.ReceiveTimeout = (int)timeout * 1000;
                    conn.socket.SendTimeout = (int)timeout * 1000;
                }
                conn.socket.NoDelay = true;             // nagle causes more windows trouble
                
                conn.server = server;
                conn.socket.Connect(server, (int)port);

                conn.stream = new System.Net.Sockets.NetworkStream(conn.socket);
            }
            catch(Exception inner)
            {   if(inner is System.Net.Sockets.SocketException)
                    conn.MonitorError("GetConnection: " + inner.Message);
                else
                    conn.RaiseError(ZIMapException.Error.CannotConnect, inner.Message);
                return null;
            }

            // init transport level and start async receive ...
            if(port == 993 && !conn.StartTls(0))
                return null;                                // after Throw()
            conn.transport = new Transport(conn);
            
            // start async receive and init protocol layer ...
            conn.transport.Poll(0);
            conn.protocol = new Protocol(conn, conn.transport);
            return conn;
        }
示例#25
0
 public Progress(ZIMapConnection parent)
 {   connection = parent;
     min = 0; max = 100;
 }
示例#26
0
 // base has no def xtor ...
 public Transport(ZIMapConnection parent) : base(parent) 
 {   name = "ZIMapTransport";
     Setup(parent.socket, parent.stream, parent.timeout);
 }
示例#27
0
 // base has no def xtor ...
 public Factory(ZIMapConnection parent) : base(parent) 
 {   name = "ZIMapFactory";
 }
示例#28
0
 // must implement, abstract in base ...
 protected override void MonitorInvoke(ZIMapConnection.Monitor level, string message)
 {   if(MonitorLevel <= level)
         ZIMapConnection.MonitorInvoke(Parent, name, level, message); 
 }
示例#29
0
            public override bool Monitor(ZIMapConnection connection, ZIMapConnection.Monitor level, 
	                                     string origin, string message)
            {
                if(origin == null || message == null) return true;
                switch(level)
                {   case ZIMapConnection.Monitor.Debug:
                            LineTool.Extra("{0}: {1}", origin, message); return true;
                    case ZIMapConnection.Monitor.Info:
                            LineTool.Info("{0}: {1}", origin, message); return true;
                    case ZIMapConnection.Monitor.Error:
                            LineTool.Error("{0}: {1}", origin, message); return true;
                }
                return true;
            }
示例#30
0
 public ZIMapProtocol(ZIMapBase parent, ZIMapTransport transport)
     : base(parent)
 {
     this.transport = transport;
     this.connection = parent as ZIMapConnection;
 }