Exemplo n.º 1
0
        /// <summary>
        /// Opens or creates specified text database.
        /// </summary>
        /// <param name="file">Text database file name with optional path.</param>
        public void OpenOrCreate(string file)
        {
            m_pDatabaseStream = OpenOrCreateDb(file);
            m_pReader         = new StreamLineReader(m_pDatabaseStream);

            m_Open = true;
        }
Exemplo n.º 2
0
        /// <summary>
        /// Does period handling.
        /// </summary>
        /// <param name="strm">Input stream.</param>
        /// <param name="add_Remove">If true add periods, else removes periods.</param>
        /// <param name="setStrmPosTo0">If true sets stream position to 0.</param>
        /// <returns></returns>
        public static MemoryStream DoPeriodHandling(Stream strm, bool add_Remove, bool setStrmPosTo0)
        {
            MemoryStream replyData = new MemoryStream();

            byte[] crlf = new byte[] { (byte)'\r', (byte)'\n' };

            if (setStrmPosTo0)
            {
                strm.Position = 0;
            }

            StreamLineReader r = new StreamLineReader(strm);

            byte[] line = r.ReadLine();

            // Loop through all lines
            while (line != null)
            {
                if (line.Length > 0)
                {
                    if (line[0] == (byte)'.')
                    {
                        /* Add period Rfc 2821 4.5.2
                         * -  Before sending a line of mail text, the SMTP client checks the
                         * first character of the line.  If it is a period, one additional
                         * period is inserted at the beginning of the line.
                         */
                        if (add_Remove)
                        {
                            replyData.WriteByte((byte)'.');
                            replyData.Write(line, 0, line.Length);
                        }

                        /* Remove period Rfc 2821 4.5.2
                         * If the first character is a period , the first characteris deleted.
                         */
                        else
                        {
                            replyData.Write(line, 1, line.Length - 1);
                        }
                    }
                    else
                    {
                        replyData.Write(line, 0, line.Length);
                    }
                }

                replyData.Write(crlf, 0, crlf.Length);

                // Read next line
                line = r.ReadLine();
            }

            replyData.Position = 0;

            return(replyData);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Opens specified text database.
        /// </summary>
        /// <param name="file">Text database file name with optional path.</param>
        public void Open(string file)
        {
            if(!File.Exists(file)){
                throw new Exception("Specified database file doesn't exist !");
            }

            m_pDatabaseStream = OpenOrCreateDb(file);
            m_pReader         = new StreamLineReader(m_pDatabaseStream);

            m_Open = true;
        }
        /// <summary>
        /// Deletes specified message from recycle bin.
        /// </summary>
        /// <param name="messageID">Message ID which to restore.</param>
        public static void DeleteRecycleBinMessage(string messageID)
        {
            using(FileStream fs = GetFile()){
                int              delRowCount = 0;
                StreamLineReader r           = new StreamLineReader(fs);
                long             pos         = fs.Position;
                string           line        = r.ReadLineString();
                while(line != null){
                    // Skip comment lines
                    if(!line.StartsWith("#")){
                        // Skip deleted row
                        if(line.StartsWith("\0")){
                            delRowCount++;
                        }
                        else{
                            string[] row = TextUtils.SplitQuotedString(line,' ');
                            // Delete row
                            if(row[0] == messageID){
                                string            user   = row[2];
                                string            folder = TextUtils.UnQuoteString(row[3]);

                                // Delete message
                                File.Delete(m_RecycleBinPath + messageID + ".eml");

                                // Delete row
                                byte[] linebytes = new byte[fs.Position - pos - 2];
                                fs.Position = pos;
                                fs.Write(linebytes,0,linebytes.Length);
                                fs.Position += 2; // CRLF
                                delRowCount++;
                                break;
                            }
                        }
                    }

                    pos  = fs.Position;
                    line = r.ReadLineString();
                }

                // There are many deleted rows, vacuum(remove deleted rows) flags database.
                if(delRowCount > 500){
                    Vacuum(fs);
                }
            }
        }
        /// <summary>
        /// Deletes specified user message flags on specified message.
        /// </summary>
        /// <param name="userID">User ID.</param>
        /// <param name="folder">Folder.</param>
        /// <param name="uid">Message UID.</param>
        public static void DeleteFlags(string userID,string folder,int uid)
        {
            using(FileStream fs = GetFlagsFile(userID,folder)){
                int              delRowCount = 0;
                StreamLineReader r           = new StreamLineReader(fs);
                long             pos         = fs.Position;
                string           line        = r.ReadLineString();
                while(line != null){
                    // Skip comment lines
                    if(!line.StartsWith("#")){
                        // Skip deleted row
                        if(line.StartsWith("\0")){
                            delRowCount++;
                        }
                        else{
                            string[] userID_uid_flags = line.Split(' ');
                            // Delete row
                            if(userID_uid_flags[1] == userID && Convert.ToInt32(userID_uid_flags[1]) == uid){
                                byte[] linebytes = new byte[fs.Position - pos - 2];
                                fs.Position = pos;
                                fs.Write(linebytes,0,linebytes.Length);
                                fs.Position += 2; // CRLF
                                delRowCount++;
                            }
                        }
                    }

                    pos  = fs.Position;
                    line = r.ReadLineString();
                }

                // There are many deleted rows, vacuum(remove deleted rows) flags database.
                if(delRowCount > 500){
                    Vacuum(fs);
                }
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="fs">Message file stream.</param>
        public _InternalHeader(FileStream fs)
        {
            m_pFile = fs;
            
            StreamLineReader r = new StreamLineReader(fs);
            string line = r.ReadLineString();
            if(line!= null && line.ToLower() == "<internalheader>"){                
                line = r.ReadLineString();
                while(line.ToLower() != "</internalheader>"){
                    if(line.ToLower().StartsWith("#-messageflags:")){                        
                        m_MessageFlags = (IMAP_MessageFlags)Enum.Parse(typeof(IMAP_MessageFlags),line.Substring(15).Trim());
                    }
                    else if(line.ToLower().StartsWith("#-envelope:")){
                        m_Envelope = line.Substring(11).Trim();
                    }
                    else if(line.ToLower().StartsWith("#-body:")){
                        m_Body = line.Substring(7).Trim();
                    }

                    line = r.ReadLineString();
                }

                // Remove internal header
                if(fs.CanWrite){
                    byte[] data = new byte[fs.Length - fs.Position];
                    fs.Read(data,0,data.Length);
                    fs.Position = 0;
                    fs.Write(data,0,data.Length);
                    fs.SetLength(data.Length);
                    fs.Position = 0;
                }
            }
            // Internal header doesn't exist
            else{
                fs.Position = 0;
            }
        }
Exemplo n.º 7
0
        /// <summary>
        /// Vacuums flags database, deletes deleted rows empty used space from file.
        /// </summary>
        /// <param name="fs">Database file stream.</param>
        private static void Vacuum(FileStream fs)
        {
            MemoryStream buffer = new MemoryStream();
            fs.Position = 0;

            StreamLineReader r    = new StreamLineReader(fs);
            string           line = r.ReadLineString();
            while(line != null){
                // Skip deleted rows
                if(!line.StartsWith("\0")){
                    byte[] lineBytes = System.Text.Encoding.ASCII.GetBytes(line + "\r\n");
                    buffer.Write(lineBytes,0,lineBytes.Length);
                }                

                line = r.ReadLineString();
            }

            fs.SetLength(buffer.Length);
            fs.Position = 0;
            buffer.WriteTo(fs);
        }
Exemplo n.º 8
0
        /// <summary>
        /// Restores specified message from recycle bin.
        /// </summary>
        /// <param name="messageID">Message ID which to restore.</param>
        /// <param name="api">Reference to API.</param>
        public static void RestoreFromRecycleBin(string messageID,IMailServerApi api)
        {
            using(FileStream fs = GetFile()){
                int              delRowCount = 0;
                StreamLineReader r           = new StreamLineReader(fs);
                long             pos         = fs.Position;
                string           line        = r.ReadLineString();
                while(line != null){
                    // Skip comment lines
                    if(!line.StartsWith("#")){
                        // Skip deleted row
                        if(line.StartsWith("\0")){
                            delRowCount++;
                        }
                        else{
                            string[] row = TextUtils.SplitQuotedString(line,' ');
                            // Delete row
                            if(row[0] == messageID){
                                string            user   = row[2];
                                string            folder = TextUtils.UnQuoteString(row[3]);

                                // Store message back to original user folder
                                using(FileStream stream = File.OpenRead(m_RecycleBinPath + messageID + ".eml")){
                                    // If folder doesn't exist, create it
                                    if(!api.FolderExists(user + "/" + folder)){
                                        api.CreateFolder("system",user,folder);
                                    }

                                    api.StoreMessage("system",user,folder,stream,DateTime.Now,new string[]{"Recent"});
                                }

                                // Delete row
                                byte[] linebytes = new byte[fs.Position - pos - 2];
                                fs.Position = pos;
                                fs.Write(linebytes,0,linebytes.Length);
                                fs.Position += 2; // CRLF
                                delRowCount++;

                                // Delete recycle bin message
                                File.Delete(m_RecycleBinPath + messageID + ".eml");
                                break;
                            }
                        }
                    }

                    pos  = fs.Position;
                    line = r.ReadLineString();
                }

                // There are many deleted rows, vacuum(remove deleted rows) flags database.
                if(delRowCount > 500){
                    Vacuum(fs);
                }
            }
        }
Exemplo n.º 9
0
        /// <summary>
        /// Gets recycle bin message stream. NOTE: This method caller must take care of closing stream.
        /// </summary>
        /// <param name="messageID">Message ID if of message what to get.</param>
        /// <returns></returns>
        public static Stream GetRecycleBinMessage(string messageID)
        {
            using(FileStream fs = GetFile()){
                int              delRowCount = 0;
                StreamLineReader r           = new StreamLineReader(fs);
                long             pos         = fs.Position;
                string           line        = r.ReadLineString();
                while(line != null){
                    // Skip comment lines
                    if(!line.StartsWith("#")){
                        // Skip deleted row
                        if(line.StartsWith("\0")){
                            delRowCount++;
                        }
                        else{
                            string[] row = TextUtils.SplitQuotedString(line,' ');
                            // Delete row
                            if(row[0] == messageID){
                                string            user   = row[2];
                                string            folder = TextUtils.UnQuoteString(row[3]);

                                // Store message back to original user folder
                                FileStream stream = File.OpenRead(m_RecycleBinPath + messageID + ".eml");
                                return stream;                                                                
                            }
                        }
                    }

                    pos  = fs.Position;
                    line = r.ReadLineString();
                }
            }

            throw new Exception("Specified message doesn't exist !");
        }
        /// <summary>
        /// Parses relay info from stream.
        /// </summary>
        /// <param name="relayMsgStrm"></param>
        private void ReadRelayInfo(Stream relayMsgStrm)
        {
            StreamLineReader reader = new StreamLineReader(relayMsgStrm);
            string relayHead = System.Text.Encoding.ASCII.GetString(reader.ReadLine());
            if(relayHead != null && relayHead.StartsWith("RelayInfo:")){
                relayHead = relayHead.Replace("RelayInfo:","");
                relayHead = relayHead.Trim();

                string[] param = relayHead.Split(new char[]{'\t'});
                if(param.Length == 4){
                    m_IsWSent = Convert.ToBoolean(Convert.ToInt32(param[0]));
                    m_To      = param[1];
                    m_From    = param[2];
                    m_MsgDate = DateTime.ParseExact(param[3],"r",System.Globalization.DateTimeFormatInfo.InvariantInfo);
                }

                m_MsgStartPos = (int)relayMsgStrm.Position;
            }
        }
        /// <summary>
        /// Does period handling.
        /// </summary>
        /// <param name="strm">Input stream.</param>
        /// <param name="add_Remove">If true add periods, else removes periods.</param>
        /// <param name="setStrmPosTo0">If true sets stream position to 0.</param>
        /// <returns></returns>
        public static MemoryStream DoPeriodHandling(Stream strm,bool add_Remove,bool setStrmPosTo0)
        {
            MemoryStream replyData = new MemoryStream();

            byte[] crlf = new byte[]{(byte)'\r',(byte)'\n'};

            if(setStrmPosTo0){
                strm.Position = 0;
            }

            StreamLineReader r = new StreamLineReader(strm);
            byte[] line = r.ReadLine();

            // Loop through all lines
            while(line != null){
                if(line.Length > 0){
                    if(line[0] == (byte)'.'){
                        /* Add period Rfc 281 4.5.2
                           -  Before sending a line of mail text, the SMTP client checks the
                           first character of the line.  If it is a period, one additional
                           period is inserted at the beginning of the line.
                        */
                        if(add_Remove){
                            replyData.WriteByte((byte)'.');
                            replyData.Write(line,0,line.Length);
                        }
                        /* Remove period Rfc 281 4.5.2
                         If the first character is a period , the first characteris deleted.
                        */
                        else{
                            replyData.Write(line,1,line.Length-1);
                        }
                    }
                    else{
                        replyData.Write(line,0,line.Length);
                    }
                }
                // write enc stuff here miceli
                replyData.Write(crlf,0,crlf.Length);

                // Read next line
                line = r.ReadLine();
            }

            replyData.Position = 0;

            return replyData;
        }
        /// <summary>
        /// Scans invalid CR or LF combination in stream. Returns true if contains invalid CR or LF combination.
        /// </summary>
        /// <param name="strm">Stream which to check.</param>
        /// <returns>Returns true if contains invalid CR or LF combination.</returns>
        public static bool ScanInvalid_CR_or_LF(Stream strm)
        {
            StreamLineReader lineReader = new StreamLineReader(strm);
            byte[] line = lineReader.ReadLine();
            while(line != null){
                foreach(byte b in line){
                    // Contains CR or LF. It cannot conatian such sumbols, because CR must be paired with LF
                    // and we currently reading lines with CRLF combination.
                    if(b == 10 || b == 13){
                        return true;
                    }
                }

                line = lineReader.ReadLine();
            }

            return false;
        }
        /// <summary>
        /// Sets specified message flags for specified user.
        /// </summary>
        /// <param name="userID">User ID.</param>
        /// <param name="folder">Folder.</param>
        /// <param name="uid">Message UID.</param>
        /// <param name="flags">Message flags.</param>
        public static void SetFlags(string userID,string folder,int uid,IMAP_MessageFlags flags)
        {
            using(FileStream fs = GetFlagsFile(userID,folder)){
                StreamLineReader r    = new StreamLineReader(fs);
                long             pos  = fs.Position;
                string           line = r.ReadLineString();
                while(line != null){
                    // Skip comment lines
                    if(!line.StartsWith("#")){
                        string[] userID_uid_flags = line.Split(' ');
                        // Update user message flags
                        if(userID_uid_flags[0] == userID && Convert.ToInt32(userID_uid_flags[1]) == uid){
                            fs.Position = pos;
                            byte[] record1 = System.Text.Encoding.ASCII.GetBytes(userID + " " + uid.ToString("d10") + " " + ((int)flags).ToString("d4") + "\r\n");
                            fs.Write(record1,0,record1.Length);
                            return;
                        }
                    }

                    pos  = fs.Position;
                    line = r.ReadLineString();
                }

                // If we reach here, then specified user has no flags for specified message, add new record.
                byte[] record = System.Text.Encoding.ASCII.GetBytes(userID + " " + uid.ToString("d10") + " " + ((int)flags).ToString("d4") + "\r\n");
                fs.Write(record,0,record.Length);
            }
        }
Exemplo n.º 14
0
        /// <summary>
        /// Adds column to db file.
        /// </summary>
        /// <param name="column"></param>
        internal void AddColumn(LDB_DataColumn column)
        {
            // Find free column data area

            // Set position over version, free data pages count and data page data area size
            m_pDbFile.Position = 68;

            long freeColumnPosition = -1;
            StreamLineReader r = new StreamLineReader(m_pDbFile);
            // Loop all columns data areas, see it there any free left
            for(int i=0;i<100;i++){
                byte[] columnInfo = r.ReadLine();
                if(columnInfo == null){
                    throw new Exception("Invalid columns data area length !");
                }

                // We found unused column data area
                if(columnInfo[0] == '\0'){
                    freeColumnPosition = m_pDbFile.Position;
                    break;
                }
            }
            m_FilePosition = m_pDbFile.Position;

            if(freeColumnPosition != -1){
                // TODO: If there is data ???

                // Move to row start
                SetFilePosition(GetFilePosition() - 102);

                // Store column
                byte[] columnData = column.ToColumnInfo();
                WriteToFile(columnData,0,columnData.Length);
            }
            else{
                throw new Exception("Couldn't find free column space ! ");
            }
        }
Exemplo n.º 15
0
        /// <summary>
        /// Opens specified data file.
        /// </summary>
        /// <param name="fileName">File name.</param>
        /// <param name="waitTime">If data base file is exclusively locked, then how many seconds to wait file to unlock before raising a error.</param>
        public void Open(string fileName,int waitTime)
        {
            DateTime lockExpireTime = DateTime.Now.AddSeconds(waitTime);
            while(true){
                try{
                    m_pDbFile = File.Open(fileName,FileMode.Open,FileAccess.ReadWrite,FileShare.ReadWrite);

                    break;
                }
                catch(IOException x){
                    // Make this because to get rid of "The variable 'x' is declared but never used"
                    string dummy = x.Message;

                    System.Threading.Thread.Sleep(15);

                    // Lock wait time timed out
                    if(DateTime.Now > lockExpireTime){
                        throw new Exception("Database file is locked and lock wait time expired !");
                    }
                }
            }

            /* Table structure:
                50    bytes         - version
                2     bytes         - CRLF
                8     bytes         - free datapages count
                2     bytes         - CRLF
                4     bytes         - datapage data area size
                2     bytes         - CRLF
                100 x 500 bytes     - 100 columns info store
                2     bytes         - CRLF
                ... data pages
            */

            m_DbFileName = fileName;
            StreamLineReader r = new StreamLineReader(m_pDbFile);

            // TODO: check if LDB file

            // Read version line (50 bytes + CRLF)
            byte[] version = r.ReadLine();

            // Skip free data pages count
            byte[] freeDataPagesCount = new byte[10];
            m_pDbFile.Read(freeDataPagesCount,0,freeDataPagesCount.Length);

            // 4 bytes datapage data area size + CRLF
            byte[] dataPageDataAreaSize = new byte[6];
            m_pDbFile.Read(dataPageDataAreaSize,0,dataPageDataAreaSize.Length);
            m_DataPageDataAreaSize = ldb_Utils.ByteToInt(dataPageDataAreaSize,0);

            // Read 100 column lines (500 + CRLF bytes each)
            for(int i=0;i<100;i++){
                byte[] columnInfo = r.ReadLine();
                if(columnInfo == null){
                    throw new Exception("Invalid columns data area length !");
                }

                if(columnInfo[0] != '\0'){
                    m_pColumns.Parse(columnInfo);
                }
            }

            // Header terminator \0
            m_pDbFile.Position++;

            // No we have rows start offset
            m_DatapagesStartOffset = m_pDbFile.Position;

            // Store file length and position
            m_FileLength = m_pDbFile.Length;
            m_FilePosition = m_pDbFile.Position;
        }