/// <summary>
        /// Converts the notification information into a packet of data to be sent
        /// to the Growl receiving application.
        /// </summary>
        /// <returns>byte array</returns>
        private byte[] PrepareData()
        {
            ByteBuilder nb    = new ByteBuilder();
            ByteBuilder db    = new ByteBuilder();
            int         index = 0;
            int         notificationTypeCount        = 0;
            int         notificationTypeEnabledCount = 0;

            foreach (NotificationType notificationType in this.notificationTypes)
            {
                nb.Append(notificationType.Name.Length);
                nb.Append(notificationType.Name);

                notificationTypeCount++;
                if (notificationType.Enabled)
                {
                    notificationTypeEnabledCount++;
                    db.Append((byte)index);
                }
                index++;
            }

            ByteBuilder bb = new ByteBuilder();

            bb.Append((byte)this.protocolVersion);
            bb.Append((byte)this.packetType);
            bb.Append(ByteBuilder.GetStringLengthAsShort(this.applicationName));
            bb.Append((byte)notificationTypeCount);
            bb.Append((byte)notificationTypeEnabledCount);
            bb.Append(this.applicationName);
            bb.Append(nb.GetBytes());
            bb.Append(db.GetBytes());

            // handle the password
            ByteBuilder pb = new ByteBuilder();

            pb.Append(this.password);
            ByteBuilder bpb = new ByteBuilder();

            bpb.Append(bb.GetBytes());
            bpb.Append(pb.GetBytes());

            byte[]      checksum = Cryptography.ComputeHash(bpb.GetBytes(), Cryptography.HashAlgorithmType.MD5);
            ByteBuilder fb       = new ByteBuilder();

            fb.Append(bb.GetBytes());
            fb.Append(checksum);
            byte[] data = fb.GetBytes();

            return(data);
        }
        /// <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);
        }
        /// <summary>
        /// Converts the notification information into a packet of data to be sent
        /// to the Growl receiving application.
        /// </summary>
        /// <returns>byte array</returns>
        private byte[] PrepareData()
        {
            int flags = ConvertPriorityToFlag(this.priority);

            if (this.sticky)
            {
                flags = flags | 1;
            }

            ByteBuilder bb = new ByteBuilder();

            bb.Append((byte)this.protocolVersion);
            bb.Append((byte)this.packetType);
            bb.Append((short)flags);
            bb.Append(ByteBuilder.GetStringLengthAsShort(this.notificationType.Name));
            bb.Append(ByteBuilder.GetStringLengthAsShort(this.title));
            bb.Append(ByteBuilder.GetStringLengthAsShort(this.description));
            bb.Append(ByteBuilder.GetStringLengthAsShort(this.applicationName));
            bb.Append(this.notificationType.Name);
            bb.Append(this.title);
            bb.Append(this.description);
            bb.Append(this.applicationName);

            // handle the password
            ByteBuilder pb = new ByteBuilder();

            pb.Append(this.password);
            ByteBuilder bpb = new ByteBuilder();

            bpb.Append(bb.GetBytes());
            bpb.Append(pb.GetBytes());

            byte[]      checksum = Cryptography.ComputeHash(bpb.GetBytes(), Cryptography.HashAlgorithmType.MD5);
            ByteBuilder fb       = new ByteBuilder();

            fb.Append(bb.GetBytes());
            fb.Append(checksum);
            byte[] data = fb.GetBytes();

            return(data);
        }