/// <summary>
        /// Initializes a new instance of the <see cref="GNTPWebSocketReader"/> class.
        /// </summary>
        /// <param name="socket">The <see cref="AsyncSocket"/></param>
        /// <param name="passwordManager">The <see cref="PasswordManager"/> containing a list of allowed passwords</param>
        /// <param name="passwordRequired">Indicates if a password is required</param>
        /// <param name="allowNetworkNotifications">Indicates if network requests are allowed</param>
        /// <param name="allowBrowserConnections">Indicates if browser requests are allowed</param>
        /// <param name="allowSubscriptions">Indicates if SUBSCRIPTION requests are allowed</param>
        /// <param name="requestInfo">The <see cref="RequestInfo"/> associated with this request</param>
        public GNTPWebSocketReader(AsyncSocket socket, PasswordManager passwordManager, bool passwordRequired, bool allowNetworkNotifications, bool allowBrowserConnections, bool allowSubscriptions, RequestInfo requestInfo)
            : base(socket, passwordManager, passwordRequired, allowNetworkNotifications, allowBrowserConnections, allowSubscriptions, requestInfo)
        {
            this.allowed = allowBrowserConnections;

            parser = new GNTPParser2(passwordManager, passwordRequired, allowNetworkNotifications, allowBrowserConnections, allowSubscriptions, requestInfo);
            parser.MessageParsed += new GNTPParser2.GNTPParserMessageParsedEventHandler(parser_MessageParsed);
            parser.Error += new GNTPParser2.GNTPParserErrorEventHandler(parser_Error);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="GNTPSocketReader"/> class.
        /// </summary>
        /// <param name="socket">The <see cref="AsyncSocket"/></param>
        /// <param name="passwordManager">The <see cref="PasswordManager"/> containing a list of allowed passwords</param>
        /// <param name="passwordRequired">Indicates if a password is required</param>
        /// <param name="allowNetworkNotifications">Indicates if network requests are allowed</param>
        /// <param name="allowBrowserConnections">Indicates if browser requests are allowed</param>
        /// <param name="allowSubscriptions">Indicates if SUBSCRIPTION requests are allowed</param>
        /// <param name="requestInfo">The <see cref="RequestInfo"/> associated with this request</param>
        public GNTPSocketReader(AsyncSocket socket, PasswordManager passwordManager, bool passwordRequired, bool allowNetworkNotifications, bool allowBrowserConnections, bool allowSubscriptions, RequestInfo requestInfo)
        {
            this.parser = new GNTPParser(passwordManager, passwordRequired, allowNetworkNotifications, allowBrowserConnections, allowSubscriptions, requestInfo);
            parser.Error += new GNTPParser.GNTPParserErrorEventHandler(parser_Error);
            parser.MessageParsed += new GNTPParser.GNTPParserMessageParsedEventHandler(parser_MessageParsed);

            this.socket = socket;
            this.socket.Tag = parser;
        }
        /// <summary>
        /// Given the raw packet data, converts the data back into a <see cref="RegistrationPacket"/>
        /// </summary>
        /// <param name="bytes">The raw packet data</param>
        /// <param name="passwordManager">The list of client passwords</param>
        /// <param name="passwordRequired">Indicates if the request must supply a valid password</param>
        /// <returns><see cref="RegistrationPacket"/></returns>
        /// <remarks>
        /// If the client password does not match the password used to validate the sent notification,
        /// or if the packet is malformed in any way, a <c>null</c> object will be returned.
        /// </remarks>
        public static RegistrationPacket FromPacket(byte[] bytes, PasswordManager passwordManager, bool passwordRequired)
        {
            RegistrationPacket rp = null;

            // parse the packet
            if (bytes != null && bytes.Length > 18)
            {
                // check md5 hash first
                string password = null;
                bool valid = BasePacket.IsPasswordValid(bytes, passwordManager, passwordRequired, out password);
                if (!valid)
                    return rp;

                int protocolVersion = (int)bytes[0];
                PacketType packetType = (PacketType)bytes[1];

                if (packetType == PacketType.Registration)
                {
                    int index = 6;
                    List<NotificationType> notificationTypes = new List<NotificationType>();
                    short applicationNameLength = BitConverter.ToInt16(new byte[] { bytes[3], bytes[2] }, 0);
                    int notificationCount = (int)bytes[4];
                    int defaultNotificationCount = (int)bytes[5];
                    string applicationName = Encoding.UTF8.GetString(bytes, index, applicationNameLength);
                    index += applicationNameLength;
                    for (int n = 0; n < notificationCount; n++ )
                    {
                        short notificationNameLength = BitConverter.ToInt16(new byte[] { bytes[index + 1], bytes[index] }, 0);
                        string notificationName = Encoding.UTF8.GetString(bytes, index + 2, notificationNameLength);
                        index += 2 + notificationNameLength;
                        NotificationType nt = new NotificationType(notificationName, false);
                        notificationTypes.Add(nt);
                    }
                    for (int d = 0; d < defaultNotificationCount; d++)
                    {
                        int notificationIndex = (int) bytes[index++];
                        notificationTypes[notificationIndex].Enabled = true;
                    }

                    rp = new RegistrationPacket(protocolVersion, applicationName, password, notificationTypes);
                }
            }

            return rp;
        }
Example #4
0
        private void button3_Click(object sender, EventArgs e)
        {
            if (this.isRunning)
            {
                this.server.Stop();
                this.isRunning    = false;
                this.button3.Text = "start server";
                Write("server stopped");

                //this.pollClient.Stop();
                //this.pollServer.Stop();
            }
            else
            {
                string historyFolder = System.Windows.Forms.Application.UserAppDataPath + @"\history";

                Growl.Connector.PasswordManager pm = new Growl.Connector.PasswordManager();
                //pm.Add(password);
                pm.Add(altPassword, true);
                this.server = new Growl.Daemon.GrowlServer(24000, pm, historyFolder);
                //this.server = new Growl.Daemon.GrowlServer(Growl.Connector.GrowlConnector.TCP_PORT, pm, historyFolder);
                this.server.RegisterReceived  += new Growl.Daemon.GrowlServer.RegisterReceivedEventHandler(server_RegisterReceived);
                this.server.NotifyReceived    += new Growl.Daemon.GrowlServer.NotifyReceivedEventHandler(server_NotifyReceived);
                this.server.SubscribeReceived += new Growl.Daemon.GrowlServer.SubscribeReceivedEventHandler(server_SubscribeReceived);

                this.server.ServerMessage += new Growl.Daemon.GrowlServer.ServerMessageEventHandler(server_ServerMessage);

                this.server.Start();
                this.isRunning     = true;
                this.button3.Text  = "stop server";
                this.textBox1.Text = "";
                Write("server is listening");

                //this.pollServer = new Growl.Polling.PollServer(7777, keyHex);
                //this.pollServer.Start();

                //this.pollClient = new Growl.Polling.PollClient(keyHex, "*****@*****.**", "localhost", 7777, 10, "localhost", Growl.Connector.GrowlConnector.TCP_PORT);
                //this.pollClient.Start();
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="GNTPParser"/> class.
        /// </summary>
        /// <param name="passwordManager">The <see cref="PasswordManager"/> containing a list of allowed passwords</param>
        /// <param name="passwordRequired">Indicates if a password is required</param>
        /// <param name="allowNetworkNotifications">Indicates if network requests are allowed</param>
        /// <param name="allowBrowserConnections">Indicates if browser requests are allowed</param>
        /// <param name="allowSubscriptions">Indicates if SUBSCRIPTION requests are allowed</param>
        /// <param name="requestInfo">The <see cref="RequestInfo"/> associated with this request</param>
        public GNTPParser2(PasswordManager passwordManager, bool passwordRequired, bool allowNetworkNotifications, bool allowBrowserConnections, bool allowSubscriptions, RequestInfo requestInfo)
        {
            this.passwordManager = passwordManager;
            this.passwordRequired = passwordRequired;
            this.allowNetworkNotifications = allowNetworkNotifications;
            this.allowBrowserConnections = allowBrowserConnections;
            this.allowSubscriptions = allowSubscriptions;
            this.requestInfo = requestInfo;

            this.alreadyReceived = new StringBuilder();
            this.headers = new HeaderCollection();
            this.notificationsToBeRegistered = new List<HeaderCollection>();
            this.pointers = new List<Pointer>();
            this.callbackInfo = new CallbackInfo();

            ms = new MemoryStream();
            gntpReader = new GNTPStreamReader(ms);
            buffer = new List<byte>();
            nextIndicator = AsyncSocket.CRLFData;
            tag = GNTP_IDENTIFIER_TAG;
        }
Example #6
0
        /// <summary>
        /// Creates a new instance of the Growl server.
        /// </summary>
        /// <param name="port">The port to listen on. The standard GNTP port is <see cref="ConnectorBase.TCP_PORT"/>.</param>
        /// <param name="passwordManager">The <see cref="PasswordManager"/> containing the list of allowed passwords.</param>
        /// <param name="userFolder">The full path to the user folder where logs, resource cache, and other files will be stored.</param>
        public GrowlServer(int port, PasswordManager passwordManager, string userFolder)
        {
            // this will set the server name and version properly
            ServerName = serverName;

            this.port = (ushort) port;

            this.passwordManager = passwordManager;

            this.userFolder = userFolder;

            this.logFolder = PathUtility.Combine(userFolder, @"Log\");
            PathUtility.EnsureDirectoryExists(this.logFolder);

            this.resourceFolder = PathUtility.Combine(userFolder, @"Resources\");
            PathUtility.EnsureDirectoryExists(this.resourceFolder);

            this.listenSocket = new AsyncSocket();
            this.listenSocket.AllowMultithreadedCallbacks = true; // VERY IMPORTANT: if we dont set this, async socket events will silently be swallowed by the AsyncSocket class
            listenSocket.DidAccept += new AsyncSocket.SocketDidAccept(listenSocket_DidAccept);
            //listenSocket.DidClose += new AsyncSocket.SocketDidClose(listenSocket_DidClose);
 
            // Initialize list to hold connected sockets
            // We support multiple concurrent connections
            connectedSockets = new ConnectedSocketCollection();
            connectedHandlers = new Dictionary<AsyncSocket, MessageHandler>();
            socketCleanupTimer = new System.Timers.Timer(30 * 1000);
            socketCleanupTimer.Elapsed += new System.Timers.ElapsedEventHandler(socketCleanupTimer_Elapsed);

            ResourceCache.ResourceFolder = this.resourceFolder;
            ResourceCache.Enabled = true;

            this.bonjour = new BonjourService(BonjourServiceName, BONJOUR_SERVICE_TYPE);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="MessageHandler"/> class.
        /// </summary>
        /// <param name="serverName">Name of the server</param>
        /// <param name="passwordManager">A list of valid passwords</param>
        /// <param name="passwordRequired">Indicates if the request must contain a password</param>
        /// <param name="logFolder">The path to the folder where log files are written</param>
        /// <param name="loggingEnabled">Indicates if logging is enabled or not</param>
        /// <param name="allowNetworkNotifications">Indicates if notifications from remote machines are allowed</param>
        /// <param name="allowBrowserConnections">Indicates if notifications from browsers are allowed</param>
        /// <param name="allowSubscriptions">Indicates if clients are allowed to subscribe to notifications from this server</param>
        public MessageHandler(string serverName, PasswordManager passwordManager, bool passwordRequired, string logFolder, bool loggingEnabled, bool allowNetworkNotifications, bool allowBrowserConnections, bool allowSubscriptions)
        {
            this.serverName = serverName;
            this.passwordManager = passwordManager;
            this.passwordRequired = passwordRequired;
            this.logFolder = logFolder;
            this.loggingEnabled = loggingEnabled;
            this.allowNetworkNotifications = allowNetworkNotifications;
            this.allowBrowserConnections = allowBrowserConnections;
            this.allowSubscriptions = allowSubscriptions;

            this.serverName = serverName;
            this.callbackInfo = new CallbackInfo();
            this.requestInfo = new RequestInfo();
        }
Example #8
0
        /// <summary>
        /// Initializes a new instance of the <see cref="GNTPParser"/> class.
        /// </summary>
        /// <param name="passwordManager">The <see cref="PasswordManager"/> containing a list of allowed passwords</param>
        /// <param name="passwordRequired">Indicates if a password is required</param>
        /// <param name="allowNetworkNotifications">Indicates if network requests are allowed</param>
        /// <param name="allowBrowserConnections">Indicates if browser requests are allowed</param>
        /// <param name="allowSubscriptions">Indicates if SUBSCRIPTION requests are allowed</param>
        /// <param name="requestInfo">The <see cref="RequestInfo"/> associated with this request</param>
        public GNTPParser(PasswordManager passwordManager, bool passwordRequired, bool allowNetworkNotifications, bool allowBrowserConnections, bool allowSubscriptions, RequestInfo requestInfo)
        {
            this.passwordManager = passwordManager;
            this.passwordRequired = passwordRequired;
            this.allowNetworkNotifications = allowNetworkNotifications;
            this.allowBrowserConnections = allowBrowserConnections;
            this.allowSubscriptions = allowSubscriptions;
            this.requestInfo = requestInfo;

            this.alreadyReceived = new StringBuilder();
            this.headers = new HeaderCollection();
            this.notificationsToBeRegistered = new List<HeaderCollection>();
            this.pointers = new List<Pointer>();
            this.callbackInfo = new CallbackInfo();
        }
        /// <summary>
        /// Checks to see if a given packets data matches a password
        /// provided by the receiving client and returns the matching password if found.
        /// </summary>
        /// <param name="bytes">The packets data</param>
        /// <param name="passwordManager">The receiving client's list of passwords</param>
        /// <param name="passwordRequired">Indicates if the request must supply a valid password</param>
        /// <param name="password">Returns the matching password if found; null otherwise</param>
        /// <returns><c>true</c> if the password matches, <c>false</c> otherwise</returns>
        protected static bool IsPasswordValid(byte[] bytes, PasswordManager passwordManager, bool passwordRequired, out string password)
        {
            password = null;

            byte[] packetWithoutPassword = new byte[bytes.Length - 16];
            Array.Copy(bytes, 0, packetWithoutPassword, 0, packetWithoutPassword.Length);
            byte[] thatChecksum = new byte[16];
            Array.Copy(bytes, bytes.Length - 16, thatChecksum, 0, 16);
            string thatChecksumString = Encoding.UTF8.GetString(thatChecksum);

            ByteBuilder bpb = new ByteBuilder();
            bpb.Append(packetWithoutPassword);

            Queue<string> validPasswords = new Queue<string>();
            foreach (KeyValuePair<string, Password> item in passwordManager.Passwords)
            {
                validPasswords.Enqueue(item.Key);
            }
            // if the request does not require a password, then
            // we can also try no (blank) password
            if (!passwordRequired) validPasswords.Enqueue(String.Empty);

            while(validPasswords.Count > 0)
            {
                string p = validPasswords.Dequeue();
                ByteBuilder pb = new ByteBuilder();
                pb.Append(bpb.GetBytes());
                pb.Append(p);
                byte[] thisChecksum = Cryptography.ComputeHash(pb.GetBytes(), Cryptography.HashAlgorithmType.MD5);
                string thisChecksumString = Encoding.UTF8.GetString(thisChecksum);

                if (thisChecksumString == thatChecksumString)
                {
                    password = p;
                    return true;
                }
            }

            return false;
        }
Example #10
0
        private void button3_Click(object sender, EventArgs e)
        {
            if (this.isRunning)
            {
                this.server.Stop();
                this.isRunning = false;
                this.button3.Text = "start server";
                Write("server stopped");

                //this.pollClient.Stop();
                //this.pollServer.Stop();
            }
            else
            {
                string historyFolder = System.Windows.Forms.Application.UserAppDataPath + @"\history";

                Growl.Connector.PasswordManager pm = new Growl.Connector.PasswordManager();
                //pm.Add(password);
                pm.Add(altPassword, true);
                this.server = new Growl.Daemon.GrowlServer(24000, pm, historyFolder);
                //this.server = new Growl.Daemon.GrowlServer(Growl.Connector.GrowlConnector.TCP_PORT, pm, historyFolder);
                this.server.RegisterReceived += new Growl.Daemon.GrowlServer.RegisterReceivedEventHandler(server_RegisterReceived);
                this.server.NotifyReceived += new Growl.Daemon.GrowlServer.NotifyReceivedEventHandler(server_NotifyReceived);
                this.server.SubscribeReceived += new Growl.Daemon.GrowlServer.SubscribeReceivedEventHandler(server_SubscribeReceived);

                this.server.ServerMessage += new Growl.Daemon.GrowlServer.ServerMessageEventHandler(server_ServerMessage);

                this.server.Start();
                this.isRunning = true;
                this.button3.Text = "stop server";
                this.textBox1.Text = "";
                Write("server is listening");

                //this.pollServer = new Growl.Polling.PollServer(7777, keyHex);
                //this.pollServer.Start();

                //this.pollClient = new Growl.Polling.PollClient(keyHex, "*****@*****.**", "localhost", 7777, 10, "localhost", Growl.Connector.GrowlConnector.TCP_PORT);
                //this.pollClient.Start();
            }
        }
        /// <summary>
        /// Given the raw packet data, converts the data back into a <see cref="NotificationPacket"/>
        /// </summary>
        /// <param name="bytes">The raw packet data</param>
        /// <param name="passwordManager">The list of client passwords</param>
        /// <param name="passwordRequired">Indicates if the request must supply a valid password</param>
        /// <returns><see cref="NotificationPacket"/></returns>
        /// <remarks>
        /// If the client password does not match the password used to validate the sent notification,
        /// or if the packet is malformed in any way, a <c>null</c> object will be returned.
        /// </remarks>
        public static NotificationPacket FromPacket(byte[] bytes, PasswordManager passwordManager, bool passwordRequired)
        {
            NotificationPacket np = null;

            // parse the packet
            if (bytes != null && bytes.Length > 18)
            {
                // check md5 hash first
                string password = null;
                bool valid = BasePacket.IsPasswordValid(bytes, passwordManager, passwordRequired, out password);
                if (!valid)
                    return np;

                int protocolVersion = (int)bytes[0];
                PacketType packetType = (PacketType)bytes[1];

                if (packetType == PacketType.Notification)
                {
                    short flags = BitConverter.ToInt16(new byte[] { bytes[3], bytes[2] }, 0);
                    bool sticky = ((flags & 1) == 1 ? true : false);
                    Priority priority = ConvertFlagToPriority(flags);

                    short notificationNameLength = BitConverter.ToInt16(new byte[] { bytes[5], bytes[4] }, 0);
                    short titleLength = BitConverter.ToInt16(new byte[] { bytes[7], bytes[6] }, 0);
                    short descriptionLength = BitConverter.ToInt16(new byte[] { bytes[9], bytes[8] }, 0);
                    short applicationNameLength = BitConverter.ToInt16(new byte[] { bytes[11], bytes[10] }, 0);

                    int index = 12;
                    string notificationName = Encoding.UTF8.GetString(bytes, index, notificationNameLength);
                    index += notificationNameLength;
                    string title = Encoding.UTF8.GetString(bytes, index, titleLength);
                    index += titleLength;
                    string description = Encoding.UTF8.GetString(bytes, index, descriptionLength);
                    index += descriptionLength;
                    string applicationName = Encoding.UTF8.GetString(bytes, index, applicationNameLength);

                    NotificationType nt = NotificationType.GetByName(notificationName); //TODO:
                    np = new NotificationPacket(protocolVersion, applicationName, password, nt, title, description, priority, sticky);
                }
            }

            return np;
        }
 /// <summary>
 /// Default constructor.
 /// </summary>
 public MessageReceiver(int port, PasswordManager passwordManager, bool loggingEnabled, string logFolder)
 {
     this.port = port;
     this.passwordManager = passwordManager;
     this.loggingEnabled = loggingEnabled;
     this.logFolder = logFolder;
 }