Structure for holding information about a file
示例#1
0
        /// <summary>
        /// Insert or update file into index with the current timestamp.
        /// </summary>
        /// <param name="file"></param>
        /// <returns></returns>
        public bool Update(MyFile file)
        {
            paramPath.Value     = file.name;
            paramType.Value     = file.type.ToString(); // to ensure it is stored as a char/string instead of a numeric value
            paramModtime.Value  = file.modtime;
            paramSize.Value     = file.size;
            paramChecksum.Value = file.checksum;
            commandInsertOrReplace.ExecuteNonQuery();

            return(true);
        }
示例#2
0
        private void processOutQueue()
        {
            if (outQueue.Count > 0)
            {
                setStatus(ClientStatus.SYNCING);
                sendCommandToServer(Signal.c2s);
                MyFile myFile = Common.SendFile(outQueue.Dequeue(), socket, dataDir);
                if (myFile != null)
                {
                    fileIndex.Update(myFile); // TODO: perform this after server confirmation
                }
                processOutQueue();
            }

            setStatus(ClientStatus.READY);
        }
示例#3
0
        /// <summary>
        /// Update or insert a new entry for the file into the database
        /// </summary>
        /// <returns>
        /// Flase if there was a problem during the update
        /// </returns>
        /// <param name='user'></param>
        /// <param name='thisFile'></param>
        public bool UpdateFile(ServerUser user, MyFile thisFile)
        {
            // TODO: use OwnCloud API calls if possible perhaps: http://owncloud.org/dev/apps/database/

            string   path    = "/" + user.id + "/files/" + thisFile.name;
            string   absPath = GetDataDir(user) + thisFile.name; //Server.baseDataDir + path;
            FileInfo f       = new FileInfo(absPath);
            long     mtime   = Common.DateTimeToUnixTimestamp(f.LastWriteTimeUtc);

            DbCommand command_checkExists = dbConnection.CreateCommand();

            command_checkExists.CommandText = "SELECT count(id) FROM oc_fscache WHERE path='" + path + "'";

            int checkFound = Convert.ToInt32(command_checkExists.ExecuteScalar());

            DbCommand command = dbConnection.CreateCommand();

            if (checkFound > 0)
            {
                command.CommandText = "UPDATE oc_fscache SET mtime='" + mtime + "' WHERE path='" + path + "'";
            }
            else
            {
                // if the entry does not exist, insert it instead of updating it

                long ctime = Common.DateTimeToUnixTimestamp(f.CreationTimeUtc);

                DbCommand command_getParent = dbConnection.CreateCommand();
                command_getParent.CommandText = "SELECT id FROM oc_fscache WHERE path_hash='"
                                                + Common.Md5Hash(path.Substring(0, path.LastIndexOf('/'))) + "'";

                int parentId = Convert.ToInt32(command_getParent.ExecuteScalar());

                string mimetype = MIMEAssistant.GetMIMEType(f.Name);
                string mimepart = mimetype.Substring(0, mimetype.LastIndexOf('/'));

                bool writable  = true;  //!f.IsReadOnly;
                bool encrypted = false; // ?
                bool versioned = false; // ?

                command.CommandText = String.Format("INSERT INTO oc_fscache (parent, name, path, path_hash, size, mtime, ctime, mimetype, mimepart,`user`,writable,encrypted,versioned) "
                                                    + "VALUES('{0}', '{1}', '{2}', '{3}', '{4}', '{5}', '{6}', '{7}', '{8}', '{9}', '{10}', '{11}', '{12}')",
                                                    parentId, f.Name, path, Common.Md5Hash(path), f.Length, mtime, ctime, mimetype, mimepart, user.id, writable, encrypted, versioned);
            }

            return(command.ExecuteNonQuery() == 1);
        }
示例#4
0
文件: Common.cs 项目: jonocodes/mybox
        public static MyFile SendFile(String relPath, Socket socket, String baseDir)
        {
            MyFile myFile = null;

            try {
                String fullPath = baseDir + relPath;

                byte[] fileName    = Encoding.UTF8.GetBytes(relPath);                 //file name
                byte[] fileNameLen = BitConverter.GetBytes((Int16)(fileName.Length)); //length of file name
                byte[] fileData    = File.ReadAllBytes(fullPath);                     //file
                byte[] fileDataLen = BitConverter.GetBytes(fileData.Length);          // file length

                // TODO: make sure "file length" matches actual file size

                long   modtime   = Common.GetModTime(fullPath);    // TODO: make timestamps into int
                byte[] timestamp = BitConverter.GetBytes(modtime); // assume long = int64 = 8 bytes

                // temporarially calc checksum here, though should be done higher up
                byte[] checksum       = FileChecksumToBytes(fullPath);
                String checksumString = BitConverter.ToString(checksum).Replace("-", String.Empty).ToLower();

                Console.WriteLine("Sending file " + relPath + " " + modtime);

                socket.Send(fileNameLen);//2
                socket.Send(fileName);

                socket.Send(timestamp);   //8

                socket.Send(checksum);    //16 bytes, or 32 characters?
                socket.Send(fileDataLen); //4, TODO: set this to 8 bits for files larger then 4GB ?
                socket.Send(fileData);

                myFile = new MyFile(relPath, 'f', modtime, fileData.Length, checksumString);
            }
            catch (Exception e) {
                Console.WriteLine("Operation failed: " + e.Message);
            }

            return(myFile);
        }
示例#5
0
        /// <summary>
        /// Handle input signals from the client
        /// </summary>
        /// <param name="signal"></param>
        private void handleInput(Signal signal)
        {
            Console.WriteLine("Handling input for signal " + signal);

            switch (signal)
            {
            case Signal.c2s:

                MyFile newFile = Common.ReceiveFile(socket, dataDir);

                if (newFile != null)
                {
                    server.serverDB.UpdateFile(User, newFile);
                }

                server.SpanCatchupOperation(handle, User.id, signal, newFile.name);
                break;

            //case Signal.clientWantsToSend:
            //  String relPath = Common.ReceiveString(socket);
            //  long timestamp = Common.ReceiveTimestamp(socket);

            //  sendCommandToClient(Signal.clientWantsToSend_response);

            //  Common.SendString(socket, relPath);

            //  // reply 'yes' if it refers to a file that does not exist or if the times do not match
            //  if (File.Exists(dataDir + relPath) && Common.GetModTime(dataDir + relPath) == timestamp) {
            //    Common.SendString(socket, "no");
            //  }
            //  else {
            //    Common.SendString(socket, "yes");
            //  }
            //  break;

            case Signal.clientWants:
                String relPath = Common.ReceiveString(socket);
                if (File.Exists(dataDir + relPath))
                {
                    outQueue.Enqueue(relPath);
                    processOutQueue();
                }
                break;

            case Signal.deleteOnServer:
                relPath = Common.ReceiveString(socket);

                if (Common.DeleteLocal(dataDir + relPath))
                {
                    server.serverDB.RemoveFile(User, relPath);
                }
//            index.Remove(relPath);  // TODO: check return value

                server.SpanCatchupOperation(handle, User.id, signal, relPath);
                break;

            case Signal.createDirectoryOnServer:
                relPath = Common.ReceiveString(socket);

                if (Common.CreateLocalDirectory(dataDir + relPath))
                {
                    server.serverDB.UpdateFile(User, new MyFile(relPath, 'd', Common.GetModTime(dataDir + relPath)
                                                                , 0, "0"));
                }

                server.SpanCatchupOperation(handle, User.id, signal, relPath);
                break;

            case Signal.requestServerFileList:

                List <List <string> > fileListToSerialize = server.serverDB.GetFileListSerializable(User);

                String jsonOutStringFiles = JsonConvert.SerializeObject(fileListToSerialize);

                Console.WriteLine("sending json file list: " + jsonOutStringFiles);

                try {
                    sendCommandToClient(Signal.requestServerFileList_response);
                    Common.SendString(socket, jsonOutStringFiles);
                }
                catch (Exception e) {
                    Console.WriteLine("Error during " + Signal.requestServerFileList_response + e.Message);
                    Common.ExitError();
                }

                break;

            case Signal.attachaccount:

                String args = Common.ReceiveString(socket);

                Console.WriteLine("received " + args);

                List <string> attachInput = JsonConvert.DeserializeObject <List <string> >(args);

                String userName = attachInput[0];
                String password = attachInput[1];

                Dictionary <string, string> jsonOut = new Dictionary <string, string>();
                jsonOut.Add("serverMyboxVersion", Common.AppVersion);

                if (attachUser(userName, password))
                {
                    jsonOut.Add("status", "success");
                    //jsonOut.Add("quota", Account.quota.ToString());
                    //jsonOut.Add("salt", Account.salt);

                    server.AddToMultiMap(User.id, handle);
                }
                else
                {
                    jsonOut.Add("status", "failed");
                    jsonOut.Add("error", "login invalid");

                    close();
                    // TODO: disconnect the client here
                }

                String jsonOutString = JsonConvert.SerializeObject(jsonOut);

                try {
                    sendCommandToClient(Signal.attachaccount_response);
                    Common.SendString(socket, jsonOutString);
                }
                catch (Exception e) {
                    Console.WriteLine("Error during " + Signal.attachaccount_response + e.Message);
                    Common.ExitError();
                }

                Console.WriteLine("attachaccount_response: " + jsonOutString);

                break;

            default:
                Console.WriteLine("Unknown command");
                break;
            }
        }
示例#6
0
        /// <summary>
        /// Compares the client to the client index to the server
        /// </summary>
        private void fullSync()
        {
            writeMessage("disabling listener");
            disableDirListener(); // hack while incoming set gets figured out

            setStatus(ClientStatus.SYNCING);

            writeMessage("fullSync started  " + DateTime.Now);

            // TODO: update all time comparisons to respect server/client time differences

            // populate S
            // file list according to server
            bool listReturned = serverDiscussion(Signal.requestServerFileList, Signal.requestServerFileList_response, null);

            if (!listReturned)
            {
                throw new Exception("requestServerFileList did not return in time");
            }

            // file list according to client filesystem
            Dictionary <String, MyFile> C = getLocalFileList();

            // file list according to client index database
            Dictionary <String, MyFile> I = fileIndex.GetFiles();

            // holds the name=>action according to the I vs C vs S comparison
            Dictionary <String, Signal> fileActionList = new Dictionary <string, Signal>();

            // here we make the assumption that fullSync() is only called once and right after initial connection
            long lastSync = -1;

            if (fileIndex.FoundAtInit)
            {
                lastSync = fileIndex.LastUpdate;
            }

            writeMessage("fullSync comparing C=" + C.Count + " to I=" + I.Count + " to S=" + S.Count
                         + "   lastSync=" + lastSync);


            foreach (KeyValuePair <String, MyFile> file in C)
            {
                String name = file.Key;
                MyFile c    = file.Value;

                if (I.ContainsKey(name))
                {
                    // TODO: handle conflicts where a file and directory have the same name

                    MyFile i = I[name];

                    // if it is a file
                    if (!Directory.Exists(dataDir + name))
                    {
                        if (c.modtime != i.modtime) // if times differ
                        {
                            writeMessage(name + " " + " c.modtime=" + c.modtime + " i.modtime=" + i.modtime);
                            writeMessage(name + " = transfer from client to server since file changed");

                            fileActionList.Add(name, Signal.c2s);
                        }
                    }

                    I.Remove(name);

                    // if it is a directory, do nothing because the files will already be coppied one by one
                }
                else // if it exists in C and not in index, push to server

                {
                    if (Directory.Exists(dataDir + name))
                    {
                        writeMessage(name + " = create directory on server since new directory");
                        fileActionList.Add(name, Signal.createDirectoryOnServer);
                    }
                    else
                    {
                        writeMessage(name + " = transfer from client to server since new file");
                        fileActionList.Add(name, Signal.c2s);
                    }
                }
            }

            // now process items that are in the index and not on the client

            foreach (KeyValuePair <String, MyFile> file in I)
            {
                // delete file or directory on server
                writeMessage(file.Key + " = remove from server since it is in I but not C");
                fileActionList.Add(file.Key, Signal.deleteOnServer);
            }

            writeMessage("finished addressing C vs I");


            // TODO: handle case where there is the same name item but it is a file on the client and dir on server

            foreach (KeyValuePair <String, MyFile> file in C)
            {
                String name = file.Key;
                MyFile c    = file.Value;

                if (S.ContainsKey(name))
                {
                    MyFile s = S[name];

                    // if it is not a directory and the times are different, compare times
                    if (!Directory.Exists(dataDir + name) && c.modtime != s.modtime)
                    {
                        writeMessage(name + " " + lastSync + " c.modtime=" + c.modtime + " s.modtime=" + s.modtime);

                        if (lastSync == -1)
                        {
                            writeMessage(name + " = conflict, since index is gone the newest file cannot be determined");
                        }
                        else if (c.modtime > lastSync)
                        {
                            if (s.modtime > lastSync)
                            {
                                writeMessage(name + " = conflict (both client and server file are new)");
                            }
                            else
                            {
                                writeMessage(name + " = transfer from client to server 1");

                                if (fileActionList.ContainsKey(name)) // can this be turned into a nested function perhaps?
                                {
                                    if (fileActionList[name] != Signal.c2s)
                                    {
                                        // conflict
                                    }
                                }
                                else
                                {
                                    fileActionList.Add(name, Signal.c2s);
                                }
                            }
                        }
                        else
                        {
                            if (s.modtime > c.modtime)
                            {
                                writeMessage(name + " = transfer from server to client 1");

                                if (fileActionList.ContainsKey(name))
                                {
                                    if (fileActionList[name] != Signal.clientWants)
                                    {
                                        // conflict
                                    }
                                }
                                else
                                {
                                    fileActionList.Add(name, Signal.clientWants);
                                }
                                // TODO: set overlay icon
                            }
                            else
                            {
                                writeMessage(name + " = conflict (both client and server file are old)");
                            }
                        }
                    }
                    S.Remove(name);
                }
                else
                {
                    if (c.modtime > lastSync) // will occur if index is missing since lastSync will be -1, thus performing a merge

                    {
                        if (Directory.Exists(dataDir + name))
                        {
                            writeMessage(name + " = create directory on server");

                            if (fileActionList.ContainsKey(name))
                            {
                                if (fileActionList[name] != Signal.createDirectoryOnServer)
                                {
                                    // conflict
                                }
                            }
                            else
                            {
                                fileActionList.Add(name, Signal.createDirectoryOnServer);
                            }
                        }
                        else
                        {
                            writeMessage(name + " = transfer from client to server 2");

                            if (fileActionList.ContainsKey(name))
                            {
                                if (fileActionList[name] != Signal.c2s)
                                {
                                    // conflict
                                }
                            }
                            else
                            {
                                fileActionList.Add(name, Signal.c2s);
                            }
                        }
                    }
                    else
                    {
                        writeMessage(name + " = remove on client");

                        if (fileActionList.ContainsKey(name))
                        {
                            if (fileActionList[name] != Signal.deleteOnClient)
                            {
                                // conflict
                            }
                        }
                        else
                        {
                            fileActionList.Add(name, Signal.deleteOnClient);
                        }
                    }
                }
            }

            foreach (KeyValuePair <String, MyFile> file in S)
            {
                String name = file.Key;
                MyFile s    = file.Value;

                if (s.modtime > lastSync) // will occur if index is missing since lastSync will be -1, thus performing a merge

                {
                    if (s.type == 'd')
                    {
                        writeMessage(name + " = create local directory on client");

                        if (fileActionList.ContainsKey(name))
                        {
                            if (fileActionList[name] != Signal.createDirectoryOnClient)
                            {
                                // conflict
                            }
                        }
                        else
                        {
                            fileActionList.Add(name, Signal.createDirectoryOnClient);
                        }
                    }
                    else
                    {
                        writeMessage(name + " = transfer from server to client 2");

                        if (fileActionList.ContainsKey(name))
                        {
                            if (fileActionList[name] != Signal.clientWants)
                            {
                                // conflict
                            }
                        }
                        else
                        {
                            fileActionList.Add(name, Signal.clientWants);
                        }
                        // TODO: set overlay icon
                    }
                }
                else
                {
                    writeMessage(name + " = remove from server"); // file or directory

                    if (fileActionList.ContainsKey(name))
                    {
                        if (fileActionList[name] != Signal.deleteOnServer)
                        {
                            // conflict
                        }
                    }
                    else
                    {
                        fileActionList.Add(name, Signal.deleteOnServer);
                    }
                }
            }

            // now process the fileLists

            writeMessage("Processing " + fileActionList.Count + " items on action list...");

            foreach (KeyValuePair <String, Signal> signalItem in fileActionList)
            {
                writeMessage(" " + signalItem.Key + " => " + signalItem.Value);

                switch (signalItem.Value)
                {
                case Signal.c2s:
                    outQueue.Enqueue(signalItem.Key);
                    break;

                case Signal.createDirectoryOnServer:
                    createDirectoryOnServer(signalItem.Key);
                    break;

                case Signal.deleteOnServer:
                    deleteOnServer(signalItem.Key);
                    break;

                case Signal.clientWants:
                    requestFile(signalItem.Key);
                    break;

                case Signal.deleteOnClient:
                    if (Common.DeleteLocal(dataDir + signalItem.Key))
                    {
                        fileIndex.Remove(signalItem.Key);
                    }
                    break;

                case Signal.createDirectoryOnClient:
                    if (Common.CreateLocalDirectory(dataDir + signalItem.Key))
                    {
                        fileIndex.Update(new MyFile(signalItem.Key, 'd', Common.GetModTime(dataDir + signalItem.Key),
                                                    0, "0"));
                    }
                    break;

                default:
                    throw new Exception("Unhandled signal in action list");
                }
            }

            processOutQueue();

            writeMessage("enableing listener since sync is done");
            enableDirListener();

            writeMessage("Sync finished " + DateTime.Now);

            if (incommingFiles.Count == 0)
            {
                setStatus(ClientStatus.READY);
            }


            Thread.Sleep(2000);
            checkSync();
        }
示例#7
0
        /// <summary>
        /// Running sync routine that compares the client files to the index. Does not consult the server.
        /// </summary>
        private void catchupSync()
        {
            writeMessage("disabling listener");
            disableDirListener(); // hack while incoming set gets figured out

            setStatus(ClientStatus.SYNCING);

            // get full local file list
            Dictionary <String, MyFile> C = getLocalFileList();

            // get index list
            Dictionary <String, MyFile> I = fileIndex.GetFiles();

            // compare to local DB
            writeMessage("catchupSync comparing C=" + C.Count + " to I=" + I.Count);

            // TODO: index updates should be transactioned/prepared

            foreach (KeyValuePair <String, MyFile> file in C)
            {
                String name = file.Key;
                MyFile c    = file.Value;

                if (I.ContainsKey(name))
                {
                    // TODO: handle conflicts where a file and directory have the same name

                    MyFile i = I[name];

                    // if it is a file
                    if (!Directory.Exists(dataDir + name))
                    {
                        if (c.modtime != i.modtime) // if times differ
                        {
                            writeMessage(name + " c.modtime=" + c.modtime + " i.modtime=" + i.modtime);

                            // if times differ, push the file to the server and update the index
                            writeMessage(name + " = transfer from client to server since file changed");
                            outQueue.Enqueue(c.name);
                        }
                    }

                    I.Remove(name);
                    // if it is a directory, do nothing because the files will already be coppied one by one
                }
                else // if it exists in C and not in index, push to server

                {
                    if (Directory.Exists(dataDir + name))
                    {
                        writeMessage(name + " = create directory on server since new directory");
                        createDirectoryOnServer(name);
                    }
                    else
                    {
                        writeMessage(name + " = transfer from client to server since new file");
                        outQueue.Enqueue(c.name);
                    }
                }
            }

            // now process items that are in the index and not on the client

            foreach (KeyValuePair <String, MyFile> file in I)
            {
                writeMessage(file.Key + " = remove from server");
                deleteOnServer(file.Key); // delete file or directory on server
            }


            // push changes to server

            processOutQueue();

            writeMessage("enableing listener since sync is done");
            enableDirListener();

//      writeMessage("Sync finished " + DateTime.UtcNow);

            if (outQueue.Count == 0)
            {
                setStatus(ClientStatus.READY);
            }

            // TODO: set to READY once incomming finish

            Thread.Sleep(2000);
            checkSync();
        }
示例#8
0
        /// <summary>
        /// Deal with incoming signal from server
        /// </summary>
        /// <param name="signal"></param>
        private void handleInput(Signal signal)
        {
            if (paused)
            {
                return;
            }

            writeMessage("Handling input for signal " + signal);

            // TODO: make sure these all update the index

            setStatus(ClientStatus.SYNCING);

            switch (signal)
            {
            case Signal.s2c:
                MyFile newFile = Common.ReceiveFile(socket, dataDir);
                if (newFile != null)
                {
                    fileIndex.Update(newFile);
                    incommingFiles.Remove(newFile.name);
                    setOverlay(true);
                }
                break;

            case Signal.deleteOnClient:
                // catchup operation
                String relPath = Common.ReceiveString(socket);
                if (Common.DeleteLocal(dataDir + relPath))
                {
                    fileIndex.Remove(relPath);
                }
                break;

            case Signal.createDirectoryOnClient:
                // catchup operation
                relPath = Common.ReceiveString(socket);
                if (Common.CreateLocalDirectory(dataDir + relPath))
                {
                    fileIndex.Update(new MyFile(relPath, 'd', Common.GetModTime(dataDir + relPath), 0, "0"));
                }

                break;

            case Signal.requestServerFileList_response:

                String jsonStringFiles = Common.ReceiveString(socket);

                List <List <string> > fileDict =
                    JsonConvert.DeserializeObject <List <List <string> > >(jsonStringFiles);

                S.Clear();

                foreach (List <string> fileItem in fileDict)
                {
                    // TODO: try, catch for parse errors etc
                    S.Add(fileItem[0], new MyFile(fileItem[0], char.Parse(fileItem[1]), long.Parse(fileItem[2]),
                                                  long.Parse(fileItem[3]), fileItem[4]));
                }

                break;

            case Signal.attachaccount_response:

                // TODO: replace JSON parser with simple text parsing so we dont have to lug around the dependency

                Dictionary <string, string> jsonMap =
                    JsonConvert.DeserializeObject <Dictionary <string, string> >(Common.ReceiveString(socket));

                if (jsonMap["status"] != "success")// TODO: change to signal
                {
                    writeMessage("Unable to attach account. Server response: " + jsonMap["error"]);
                    // TODO: catch these exceptions above somewhere
                    //throw new Exception("Unable to attach account. Server response: " + jsonMap["error"]);
                    //socket.Close();
                    Stop();
                }
                else
                {
                    //writeMessage("set account salt to: " + account.Salt);

                    if (Common.AppVersion != jsonMap["serverMyboxVersion"])
                    {
                        writeMessage("Client and Server Mybox versions do not match");
                    }
                }

                break;

            default:
                writeMessage("Unknown command from server: " + signal);
                break;
            }

            lastReceivedOperation = signal;

            if (incommingFiles.Count == 0 && outQueue.Count == 0)
            {
                setStatus(ClientStatus.READY);
            }
        }
示例#9
0
文件: Common.cs 项目: jonocodes/mybox
        /// <summary>
        /// Receive a file over a socket
        /// </summary>
        /// <param name="socket"></param>
        /// <param name="baseDir">the base directory the file will live in</param>
        /// <returns></returns>
        public static MyFile ReceiveFile(Socket socket, string baseDir)
        {
            byte[] buffer = new byte[buf_size];

            MyFile myFile = null;

            try {
                // receive order: name length, name, timestamp, checksum, data length, data

                socket.Receive(buffer, 2, 0);
                Int16 nameLength = BitConverter.ToInt16(buffer, 0);

                socket.Receive(buffer, nameLength, 0);
                String relPath = System.Text.Encoding.UTF8.GetString(buffer, 0, nameLength);

                // timestamp
                socket.Receive(buffer, 8, 0); // TODO: make timestamps into int
                DateTime timestamp = UnixTimeStampToDateTime(BitConverter.ToInt64(buffer, 0));

                // checksum
                socket.Receive(buffer, 16, 0);
                String checksumString = BitConverter.ToString(buffer, 0, 16).Replace("-", String.Empty).ToLower();

                String tempLocation = TempDir + Path.DirectorySeparatorChar + "mb" +
                                      DateTimeToUnixTimestamp(DateTime.Now).ToString() + _random.Next(0, 26).ToString() + _random.Next(0, 26).ToString();

                Console.WriteLine("Receiving file: " + relPath);
                Console.WriteLine("  timestmp:" + DateTimeToUnixTimestamp(timestamp) + " checksum: " + checksumString);
                Console.WriteLine("  temp: " + tempLocation);

                // data
                socket.Receive(buffer, 4, 0); // assumes filesize cannot be larger then int bytes, 4GB?
                Int32 fileLength = BitConverter.ToInt32(buffer, 0);

                int fileBytesRead = 0;

                MD5 md5 = MD5.Create();

                using (FileStream fs = File.Create(tempLocation, buf_size)) {
                    using (CryptoStream cs = new CryptoStream(fs, md5, CryptoStreamMode.Write)) {
                        while (fileBytesRead + buf_size <= fileLength)
                        {
                            fileBytesRead += socket.Receive(buffer, buf_size, 0);
                            cs.Write(buffer, 0, buf_size);
                        }

                        if (fileBytesRead < fileLength)
                        {
                            socket.Receive(buffer, fileLength - fileBytesRead, 0); // make sure this reads to the end
                            cs.Write(buffer, 0, fileLength - fileBytesRead);
                        }
                    }
                }

                String calculatedChecksum = BitConverter.ToString(md5.Hash).Replace("-", String.Empty).ToLower();

                // network fault tolerance, varify checksum before moving file from temp to dir
                System.Console.WriteLine("  calculated checksum: " + calculatedChecksum);

                if (calculatedChecksum == checksumString)
                {
                    File.Move(tempLocation, baseDir + relPath);
                    File.SetLastWriteTimeUtc(baseDir + relPath, timestamp);

                    myFile = new MyFile(relPath, 'f', timestamp.Ticks, fileLength, checksumString);
                }
                else
                {
                    throw new Exception("Received file checksum did not match");
                }
            }
            catch (Exception e) {
                Console.WriteLine("Operation failed: " + e.Message);
            }

            return(myFile);
        }
示例#10
0
        /// <summary>
        /// Update or insert a new entry for the file into the database
        /// </summary>
        /// <returns>
        /// Flase if there was a problem during the update
        /// </returns>
        /// <param name='user'></param>
        /// <param name='thisFile'></param>
        public bool UpdateFile(ServerUser user, MyFile thisFile)
        {
            // TODO: use OwnCloud API calls if possible perhaps: http://owncloud.org/dev/apps/database/

              string path = "/" + user.id + "/files/" + thisFile.name;
              string absPath = GetDataDir(user) + thisFile.name; //Server.baseDataDir + path;
              FileInfo f = new FileInfo (absPath);
              long mtime = Common.DateTimeToUnixTimestamp(f.LastWriteTimeUtc);

              DbCommand command_checkExists = dbConnection.CreateCommand();
              command_checkExists.CommandText = "SELECT count(id) FROM oc_fscache WHERE path='"+ path +"'";

              int checkFound = Convert.ToInt32(command_checkExists.ExecuteScalar());

              DbCommand command = dbConnection.CreateCommand();

              if (checkFound > 0) {
            command.CommandText = "UPDATE oc_fscache SET mtime='" + mtime + "' WHERE path='"+ path +"'";
              } else {
            // if the entry does not exist, insert it instead of updating it

            long ctime =  Common.DateTimeToUnixTimestamp(f.CreationTimeUtc);

            DbCommand command_getParent = dbConnection.CreateCommand ();
            command_getParent.CommandText = "SELECT id FROM oc_fscache WHERE path_hash='"
              + Common.Md5Hash(path.Substring(0, path.LastIndexOf('/'))) + "'";

            int parentId = Convert.ToInt32 (command_getParent.ExecuteScalar ());

            string mimetype = MIMEAssistant.GetMIMEType(f.Name);
            string mimepart = mimetype.Substring(0, mimetype.LastIndexOf('/'));

            bool writable = true; //!f.IsReadOnly;
            bool encrypted = false; // ?
            bool versioned = false; // ?

            command.CommandText = String.Format("INSERT INTO oc_fscache (parent, name, path, path_hash, size, mtime, ctime, mimetype, mimepart,`user`,writable,encrypted,versioned) "
                                            + "VALUES('{0}', '{1}', '{2}', '{3}', '{4}', '{5}', '{6}', '{7}', '{8}', '{9}', '{10}', '{11}', '{12}')",
                                            parentId, f.Name, path, Common.Md5Hash(path), f.Length, mtime, ctime, mimetype, mimepart, user.id, writable, encrypted, versioned);
              }

              return (command.ExecuteNonQuery() == 1);
        }
示例#11
0
文件: Common.cs 项目: jonocodes/mybox
        public static MyFile SendFile(String relPath, Socket socket, String baseDir)
        {
            MyFile myFile = null;

              try {
            String fullPath = baseDir + relPath;

            byte[] fileName = Encoding.UTF8.GetBytes(relPath); //file name
            byte[] fileNameLen = BitConverter.GetBytes((Int16)(fileName.Length)); //length of file name
            byte[] fileData = File.ReadAllBytes(fullPath); //file
            byte[] fileDataLen = BitConverter.GetBytes(fileData.Length); // file length

            // TODO: make sure "file length" matches actual file size

            long modtime = Common.GetModTime(fullPath); // TODO: make timestamps into int
            byte[] timestamp = BitConverter.GetBytes(modtime); // assume long = int64 = 8 bytes

            // temporarially calc checksum here, though should be done higher up
            byte[] checksum = FileChecksumToBytes(fullPath);
            String checksumString = BitConverter.ToString(checksum).Replace("-", String.Empty).ToLower();

            Console.WriteLine("Sending file " + relPath + " " + modtime);

            socket.Send(fileNameLen);//2
            socket.Send(fileName);

            socket.Send(timestamp);//8

            socket.Send(checksum);//16 bytes, or 32 characters?
            socket.Send(fileDataLen);//4, TODO: set this to 8 bits for files larger then 4GB ?
            socket.Send(fileData);

            myFile = new MyFile(relPath, 'f', modtime, fileData.Length, checksumString);
              }
              catch (Exception e) {
            Console.WriteLine("Operation failed: " + e.Message);
              }

              return myFile;
        }
示例#12
0
文件: Common.cs 项目: jonocodes/mybox
        /// <summary>
        /// Receive a file over a socket
        /// </summary>
        /// <param name="socket"></param>
        /// <param name="baseDir">the base directory the file will live in</param>
        /// <returns></returns>
        public static MyFile ReceiveFile(Socket socket, string baseDir)
        {
            byte[] buffer = new byte[buf_size];

              MyFile myFile = null;

              try {
            // receive order: name length, name, timestamp, checksum, data length, data

            socket.Receive(buffer, 2, 0);
            Int16 nameLength = BitConverter.ToInt16(buffer, 0);

            socket.Receive(buffer, nameLength, 0);
            String relPath = System.Text.Encoding.UTF8.GetString(buffer, 0, nameLength);

            // timestamp
            socket.Receive(buffer, 8, 0); // TODO: make timestamps into int
            DateTime timestamp = UnixTimeStampToDateTime(BitConverter.ToInt64(buffer, 0));

            // checksum
            socket.Receive(buffer, 16, 0);
            String checksumString = BitConverter.ToString(buffer, 0, 16).Replace("-", String.Empty).ToLower();

            String tempLocation = TempDir + Path.DirectorySeparatorChar + "mb" +
              DateTimeToUnixTimestamp(DateTime.Now).ToString() + _random.Next(0, 26).ToString() + _random.Next(0, 26).ToString();

            Console.WriteLine("Receiving file: " + relPath);
            Console.WriteLine("  timestmp:" + DateTimeToUnixTimestamp(timestamp) + " checksum: " + checksumString);
            Console.WriteLine("  temp: " + tempLocation);

            // data
            socket.Receive(buffer, 4, 0); // assumes filesize cannot be larger then int bytes, 4GB?
            Int32 fileLength = BitConverter.ToInt32(buffer, 0);

            int fileBytesRead = 0;

            MD5 md5 = MD5.Create();

            using (FileStream fs = File.Create(tempLocation, buf_size)) {
              using (CryptoStream cs = new CryptoStream(fs, md5, CryptoStreamMode.Write)) {

            while (fileBytesRead + buf_size <= fileLength) {
              fileBytesRead += socket.Receive(buffer, buf_size, 0);
              cs.Write(buffer, 0, buf_size);
            }

            if (fileBytesRead < fileLength) {
              socket.Receive(buffer, fileLength - fileBytesRead, 0);  // make sure this reads to the end
              cs.Write(buffer, 0, fileLength - fileBytesRead);
            }
              }
            }

            String calculatedChecksum = BitConverter.ToString(md5.Hash).Replace("-", String.Empty).ToLower();

            // network fault tolerance, varify checksum before moving file from temp to dir
            System.Console.WriteLine("  calculated checksum: " + calculatedChecksum);

            if (calculatedChecksum == checksumString) {

              File.Move(tempLocation, baseDir + relPath);
              File.SetLastWriteTimeUtc(baseDir + relPath, timestamp);

              myFile = new MyFile(relPath, 'f', timestamp.Ticks, fileLength, checksumString);
            }
            else
              throw new Exception("Received file checksum did not match");
              }
              catch (Exception e) {
            Console.WriteLine("Operation failed: " + e.Message);
              }

              return myFile;
        }