コード例 #1
0
        /// <summary>
        /// Checks a single file and handles changes if
        /// any occured (modification, creation).
        /// </summary>
        /// <param name="file">Path to the file.</param>
        private void HandleFile(string file)
        {
            // Without this, used files would be treated as deleted.
            if (FileHelper.FileInUse(file))
            {
                filesChecked.Add(file);
                return;
            }

            if (!System.IO.File.Exists(file) || FileHelper.FileInUse(file) ||
                file.EndsWith(".tmp") || filesChecked.Contains(file) || Ignored(file))
            {
                return;
            }
            filesChecked.Add(file);

            DB.File tmp   = null;
            var     files = db.GetFiles();
            var     date  = System.IO.File.GetLastWriteTime(file);

            if (!files.TryGet(file, out tmp) && canCreateFiles)
            {
                var f = new DB.File();
                f.Name         = file;
                f.DateModified = date;
                f.Access       = null;
                files.Add(f);
                filesCreated.Add(file);
            }
            else if (tmp != null && tmp.OlderThan(date))
            {
                tmp.Update(date);
                filesChanged.Add(file);
            }
        }
コード例 #2
0
        /// <summary>
        /// Updates a file based on data sent by a client.
        /// </summary>
        /// <param name="file">Path to the file.</param>
        /// <param name="operation">Type of operation to be done with the file.</param>
        /// <param name="reader">StreamReader used as a source for the new file data.</param>
        /// <returns>True if the file was successfully updated, false otherwise.</returns>
        private bool WriteContentsToFile(DB.File file, Protocol operation, StreamReader reader)
        {
            lock (file)
            {
                if (operation == Protocol.FILE_CHANGED)
                {
                    BackupFile(file.Name);
                }
                string tmpFile = file.Name + ".tmp";
                try
                {
                    string line;
                    using (var stream = System.IO.File.OpenWrite(tmpFile))
                        using (var fileWriter = new StreamWriter(stream, encoding))
                        {
                            while ((line = reader.ReadLine()) != null && line != "TRANSMISSION_END")
                            {
                                fileWriter.WriteLine(line);
                            }
                            fileWriter.BaseStream.SetLength(fileWriter.BaseStream.Position);
                        }

                    if (line != "TRANSMISSION_END")
                    {
                        FileHelper.Delete(tmpFile);
                        Console.WriteLine("[ERROR] Wrong file transmission end token.");
                        return(false);
                    }
                    else
                    {
                        FileHelper.Move(tmpFile, file.Name);
                    }
                }
                catch (IOException e)
                {                 // Most probably time out.
                    try
                    {
                        Console.WriteLine("[ERROR] Cannot write to file: {0}", e.Message);
                        FileHelper.Delete(tmpFile);
                    }
                    catch (IOException)
                    { /* Just in case Delete throws, which should not propagate. */ }

                    return(false);
                }
            }
            return(true);
        }
コード例 #3
0
        /// <summary>
        /// Requests (and reads if authorized) contents of a given file from
        /// the server.
        /// </summary>
        /// <param name="reader">StreamReader used to read authorization result and the contents of the file.</param>
        /// <param name="writer">StreamWriter used to send the request.</param>
        /// <param name="file">Path to the file.</param>
        private void RequestFileContents(StreamReader reader, StreamWriter writer, string file)
        {
            writer.WriteLine(Protocol.REQUEST_FILE_CONTENTS);
            writer.WriteLine(subTreePrefix + file);
            string line    = reader.ReadLine();
            string tmpFile = file + ".tmp";

            if (ProtocolHelper.ExtractProtocol(line) == Protocol.SUCCESS)
            {
                DB.File tmp = null;
                if (!db.GetFiles().TryGet(file, out tmp))
                {
                    tmp = new DB.File(file);
                    db.GetFiles().Add(tmp);
                }

                try
                {
                    reader.ReadLine();                     // File name resent, here we can discard it.
                    writer.WriteLine(Protocol.SUCCESS);

                    Directory.CreateDirectory(Path.GetDirectoryName(file));

                    using (var stream = System.IO.File.OpenWrite(tmpFile))
                        using (var fileWriter = new StreamWriter(stream, encoding))
                        {
                            while ((line = reader.ReadLine()) != null && line != "TRANSMISSION_END" && line != "FAIL")
                            {
                                fileWriter.WriteLine(line);
                            }
                        }

                    FileHelper.Move(tmpFile, file);
                    tmp.DateModified = System.IO.File.GetLastWriteTime(file);
                }
                catch (SocketException)
                {                 // This should be connection interruption or time out.
                    FileHelper.Delete(tmpFile);
                }
                catch (IOException)
                {                 // Target file in use or nonexistent.
                    FileHelper.Delete(tmpFile);
                }
            }
        }
コード例 #4
0
        /// <summary>
        /// Updates a file based on the information sent by the user, this includes
        /// changing contents, creating new files and deleting existing files.
        /// </summary>
        /// <param name="socket">Socket used for the communication.</param>
        /// <param name="reader">StreamReader used to read data from the client.</param>
        /// <param name="writer">StreamWriter used to write data to the client.</param>
        /// <param name="operation">Type of operation to be done with the file.</param>
        /// <param name="user">Database entry of the user (used for authorization).</param>
        private void HandleFileUpdate(Socket socket, StreamReader reader, StreamWriter writer, Protocol operation, User user)
        {
            Group group;
            var   groups = db.GetGroups();

            if (user == null || !groups.TryGet(user.Group, out group))
            {
                return;
            }

            string fileName = reader.ReadLine();

            if (fileName == null)
            {
                return;
            }
            var files = db.GetFiles();

            DB.File file = null;

            if (!AuthorizeFileAccess(fileName, out file, operation, group))
            {
                writer.WriteLine(Protocol.FAIL);
                return;
            }
            else
            {
                writer.WriteLine(Protocol.SUCCESS);
            }
            fileName = null;

            if (operation == Protocol.FILE_DELETED)
            {
                DeleteFile(file);
            }
            else if (!WriteContentsToFile(file, operation, reader))
            {
                return;
            }

            InformAll(user, operation, file.Name);
            file.DateModified = DateTime.Now;             // So the clients don't all refresh the file contents.
            return;
        }
コード例 #5
0
 /// <summary>
 /// Backs up and deletes a file (both from the database
 /// and the directory tree).
 /// </summary>
 /// <param name="file">Path to the file.</param>
 /// <returns>True if the file was deleted, false otherwise.</returns>
 private bool DeleteFile(DB.File file)
 {
     lock (file)
     {
         try
         {
             BackupFile(file.Name);
             System.IO.File.Delete(file.Name);
             if (db.GetFiles().Contains(file.Name))
             {
                 db.GetFiles().Remove(file);
             }
             return(true);
         }
         catch (IOException)
         {
             return(false);
         }
     }
 }
コード例 #6
0
        /// <summary>
        /// Checks if the user is allowed to perform a given operation on a given file.
        /// </summary>
        /// <param name="name">Path to the file.</param>
        /// <param name="file">Database entry of the file which will be assigned to.</param>
        /// <param name="type">Type of operation to be done with the file.</param>
        /// <param name="group">Group the user belongs to.</param>
        /// <returns></returns>
        private bool AuthorizeFileAccess(string name, out DB.File file, Protocol type, Group group)
        {
            switch (type)
            {
            case Protocol.FILE_CHANGED:
            case Protocol.FILE_DELETED:
                return(db.GetFiles().TryGet(name, out file) && file.Test(group, AccessRight.WRITE));

            case Protocol.FILE_CREATED:
                if (group.CanCreateFiles && !db.GetFiles().Contains(name))
                {
                    Directory.CreateDirectory(Path.GetDirectoryName(name));
                    file = db.CreateNewFile(name, group);
                    return(true);
                }
                else
                {
                    file = null;
                    return(false);
                }

            case Protocol.REQUEST_FILE_CONTENTS:
                if (!db.GetFiles().TryGet(name, out file))
                {
                    return(false);
                }
                else
                {
                    return(file.Test(group, AccessRight.READ));
                }

            default:
                file = null;
                return(false);
            }
        }
コード例 #7
0
        /// <summary>
        /// Handles a notification from the server (mostly
        /// regardin file changes).
        /// </summary>
        /// <param name="s">Socket used for the communication.</param>
        private void HandleServerNotice(Socket s)
        {
            try
            {
                using (var stream = new NetworkStream(s))
                    using (var reader = new StreamReader(stream, encoding))
                        using (var writer = new StreamWriter(stream, encoding))
                        {
                            writer.AutoFlush = true;
                            //reader.BaseStream.ReadTimeout = 10000;

                            var    message = ProtocolHelper.ExtractProtocol(reader.ReadLine());
                            string name    = reader.ReadLine();
                            if (name.StartsWith(subTreePrefix + TrackedDirectory + @"\"))
                            {
                                name = name.Substring(subTreePrefix.Length);

                                if (message != Protocol.FILE_DELETED)
                                {
                                    writer.WriteLine(Protocol.SUCCESS);
                                }
                                else
                                {
                                    reader.ReadLine();                     // T_E token, can be ignored here.
                                }
                            }
                            else
                            {
                                if (message != Protocol.FILE_DELETED)
                                {
                                    writer.WriteLine(Protocol.FAIL);
                                }
                                else
                                {
                                    reader.ReadLine();                     // T_E token, can be ignored here.
                                }
                                writer.WriteLine(Protocol.TRANSMISSION_END);
                                return;
                            }

                            if (message == Protocol.NONE || name == null)
                            {
                                return;
                            }

                            DB.File file = null;
                            if (message == Protocol.FILE_CREATED ||
                                (name != null && !db.GetFiles().TryGet(name, out file) && message != Protocol.FILE_DELETED))
                            {
                                file = new DB.File(name);
                                file.DateModified = FileHelper.Create(file.Name);
                                if (file.DateModified != DateTime.MaxValue)
                                {
                                    db.GetFiles().Add(file);
                                }
                            }

                            if (message == Protocol.FILE_DELETED)
                            {
                                FileHelper.Delete(name);
                                if (file != null)
                                {
                                    db.GetFiles().Remove(file);
                                }
                                reader.ReadLine();                 // T_E token, can be ignored here.
                            }
                            else
                            {
                                lock (file)
                                {
                                    string tmpName = name + ".tmp";
                                    try
                                    {
                                        string line;
                                        using (var fstream = System.IO.File.OpenWrite(tmpName))
                                            using (var fileWriter = new StreamWriter(fstream, encoding))
                                            {
                                                while ((line = reader.ReadLine()) != null && line != "TRANSMISSION_END")
                                                {
                                                    fileWriter.WriteLine(line);
                                                }
                                                fileWriter.BaseStream.SetLength(fileWriter.BaseStream.Position);
                                            }

                                        FileHelper.Move(tmpName, file.Name);
                                        file.DateModified = System.IO.File.GetLastWriteTime(file.Name);
                                    }
                                    catch (IOException e)
                                    {
                                        Console.WriteLine(e);
                                        // TODO:
                                        FileHelper.Delete(tmpName);
                                    }
                                }
                            }
                        }
            }
            catch (IOException e)
            {
                // TODO:
                Console.WriteLine("HUH? {0}", e.Message);
            }
            finally
            {
                db.Save();
            }
        }