private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) { //ServicePointManager.ServerCertificateValidationCallback=delegate //{ // return true; //}; RemoteCertificateValidationCallback certificateCallback=new RemoteCertificateValidationCallback(ValidateServerCertificate); string syncFolder=Globals.Options.GetElementAsString("xml.Options.Paths.SyncFolder"); string ftpServer=Globals.Options.GetElementAsString("xml.Options.FTP.Server"); string ftpUser=Globals.Options.GetElementAsString("xml.Options.FTP.User"); string ftpPassword=Globals.Options.GetElementAsString("xml.Options.FTP.Password"); string ftpProtocol=Globals.Options.GetElementAsString("xml.Options.FTP.Protocol"); if(FileSystem.ExistsDirectory(syncFolder)) { if(ftpServer!=""&&ftpUser!=""&ftpPassword!=""&ftpProtocol!="") { //Connect FTPSClient client=new FTPSClient(); //NetworkCredital NetworkCredential credential=new NetworkCredential(ftpUser, ftpPassword); //client.Connect(ftpServer, credential, ESSLSupportMode.ControlAndDataChannelsRequired); client.Connect(ftpServer, credential, ESSLSupportMode.ControlAndDataChannelsRequired, certificateCallback); #region Verzeichnisstruktur überprüfen und nach Bedarf anlegen //Test auf leeres Verzeichnis IList<DirectoryListItem> files=client.GetDirectoryList(); bool existXData=false; bool existHData=false; bool existLData=false; bool existCData=false; bool existMData=false; bool existRData=false; bool existCfsInfo=false; foreach(DirectoryListItem file in files) { if(file.IsDirectory) { switch(file.Name) { case "x-data": { existXData=true; break; } case "h-data": { existHData=true; break; } case "l-data": { existLData=true; break; } case "c-data": { existCData=true; break; } case "m-data": { existMData=true; break; } case "r-data": { existRData=true; break; } } } else //File { switch(file.Name) { case "cfsinfo": { existCfsInfo=true; break; } } } } //CfsInfo anlegen if(existCfsInfo==false) { List<string> version=new List<string>(); version.Add("1"); //Repository Version string versionFilenameLocal=FileSystem.TempPath+"cfsinfo-"+Various.GetTimeID(); File.WriteAllLines(versionFilenameLocal, version.ToArray()); client.PutFile(versionFilenameLocal, "cfsinfo"); } else //Version überprüfen { string versionFilenameLocal=FileSystem.TempPath+"cfsinfo-"+Various.GetTimeID(); client.GetFile("cfsinfo", versionFilenameLocal); string[] cfsinfo=File.ReadAllLines(versionFilenameLocal); int version=Convert.ToInt32(cfsinfo[0]); if(version!=1) { MessageBox.Show("CloudFileSync ist nicht mit der Version des Repositories kompatibel!", "Hinweis", MessageBoxButtons.OK, MessageBoxIcon.Information); return; } } if(existXData==false) client.MakeDir("x-data"); //Datenordner if(existHData==false) client.MakeDir("h-data"); //Hashdaten if(existLData==false) client.MakeDir("l-data"); //Lockdaten if(existCData==false) client.MakeDir("c-data"); //Createdaten if(existMData==false) client.MakeDir("m-data"); //Modifieddaten if(existRData==false) client.MakeDir("r-data"); //Removedaten //Überprüfen ob meine Clientverzeichnisse existieren CheckAndCreateClientFolder(client, "c-data"); CheckAndCreateClientFolder(client, "m-data"); CheckAndCreateClientFolder(client, "r-data"); #endregion //Init Datenbestand (Sync) UpdateFromRemote(client, syncFolder); //Neu erzeugte oder geänderte Dateien ermitteln List<string> syncFolderFiles=FileSystem.GetFiles(syncFolder, true); //Neue Lokale Dateien hochladen foreach(string file in syncFolderFiles) { string relFilename=FileSystem.GetRelativePath(file, syncFolder, true); string hashRemote=GetHistoryHash(client, relFilename); string hashLocal=Hash.SHA1.HashFile(file); if(hashRemote!=hashLocal) { filesCreated.Add(file); } } //gelöschte Dateien ermitteln List<string> hashFiles=GetHashFiles(client); foreach(string hashFile in hashFiles) { string filenameToTest=FileSystem.GetPathWithPathDelimiter(syncFolder)+hashFile.Replace('\\', FileSystem.PathDelimiter); syncFolderFiles.Remove(filenameToTest); } foreach(string file in syncFolderFiles) { if(filesCreated.IndexOf(file)==-1) //Datei soll nicht hochgeladen werden, sondern wurde wirklich auf einem anderen Client gelöscht { string relFilename=FileSystem.GetRelativePath(file, syncFolder, true); FileSystem.RemoveFile(file); Globals.Log.Add(LogLevel.Information, "Lokal: Datei {0} wurde gelöscht.", relFilename); } } //FilesystemWatcher aktivieren fileSystemWatcher.Path=syncFolder; fileSystemWatcher.EnableRaisingEvents=true; #region Endlosschleife für Syncronisation while(true) { if(e.Cancel==true) return; List<string> fileToRemoveFromList=new List<string>(); //Dateien hochladen #region Created files lock(filesCreated) { foreach(string fileCreated in filesCreated) { string relFilename=FileSystem.GetRelativePath(fileCreated, syncFolder, true); relFilename=relFilename.Replace("\\", "/"); bool locked=GetFileLock(client, relFilename); if(locked) { if(FileSystem.IsDirectory(fileCreated)) //Directory { client.CreateDirectory("x-data/"+relFilename); fileToRemoveFromList.Add(fileCreated); Globals.Log.Add(LogLevel.Information, "Remote: Verzeichnis {0} wurde erstellt (x-data).", relFilename); //In Created Verzeichnisse legen AddFileToUpdateFolder(client, "c-data", relFilename, EFileType.Directory); //Globals.Log.Add(LogLevel.Information, "Updatedatei {0} wurde hochgeladen (c-data).", relFilename); } else //File { //Hashdatei ändern AddHistoryHash(client, fileCreated, relFilename); Globals.Log.Add(LogLevel.Information, "Remote: Hash für {0} wurde geändert (x-data).", relFilename); //Datei hochladen CreateFTPDirectories(client, "x-data/"+relFilename); client.PutFile(fileCreated, "x-data/"+relFilename); fileToRemoveFromList.Add(fileCreated); Globals.Log.Add(LogLevel.Information, "Remote: Datei {0} wurde hochgeladen (x-data).", relFilename); //In Created Verzeichnisse legen AddFileToUpdateFolder(client, "c-data", relFilename, EFileType.File); //Globals.Log.Add(LogLevel.Information, "Updatedatei {0} wurde hochgeladen (c-data).", relFilename); } } RemoveFileLock(client, relFilename); } foreach(string rFile in fileToRemoveFromList) { filesCreated.Remove(rFile); } } fileToRemoveFromList.Clear(); #endregion #region Changed Files lock(filesChanged) { foreach(string fileChanged in filesChanged) { string relFilename=FileSystem.GetRelativePath(fileChanged, syncFolder, true); relFilename=relFilename.Replace("\\", "/"); bool locked=GetFileLock(client, relFilename); if(locked) { if(FileSystem.IsDirectory(fileChanged)) //Directory { //Sollte bei Verzeichnissen ignoriert werden } else //File { //Hashdatei ändern AddHistoryHash(client, fileChanged, relFilename); Globals.Log.Add(LogLevel.Information, "Remote: Hash für {0} wurde geändert (x-data).", relFilename); //Datei hochladen client.PutFile(fileChanged, "x-data/"+relFilename); fileToRemoveFromList.Add(fileChanged); Globals.Log.Add(LogLevel.Information, "Remote: Datei {0} wurde modifiziert (x-data).", relFilename); //In Created Verzeichnisse legen AddFileToUpdateFolder(client, "m-data", relFilename, EFileType.File); } } RemoveFileLock(client, relFilename); } foreach(string rFile in fileToRemoveFromList) { filesChanged.Remove(rFile); } } fileToRemoveFromList.Clear(); #endregion #region Deleted Files lock(filesDeleted) { foreach(string fileDeleted in filesDeleted) { string relFilename=FileSystem.GetRelativePath(fileDeleted, syncFolder, true); relFilename=relFilename.Replace("\\", "/"); bool locked=GetFileLock(client, relFilename); if(locked) { if(FileSystem.IsDirectory(fileDeleted)) //Directory { client.RemoveDir(fileDeleted); //client.PutFile(fileChanged, "x-data/"+relFilename); fileToRemoveFromList.Add(fileDeleted); Globals.Log.Add(LogLevel.Information, "Remote: Verzeichnis {0} wurde gelöscht (x-data).", relFilename); //In Created Verzeichnisse legen AddFileToUpdateFolder(client, "r-data", relFilename, EFileType.File); } else //File { //Hashdatei löchen RemoveHistoryHash(client, relFilename); Globals.Log.Add(LogLevel.Information, "Remote: Hash für {0} wurde gelöscht (x-data).", relFilename); //Datei löschen client.DeleteFile("x-data/"+relFilename); fileToRemoveFromList.Add(fileDeleted); Globals.Log.Add(LogLevel.Information, "Remote: Datei {0} wurde gelöscht (x-data).", relFilename); //In Created Verzeichnisse legen AddFileToUpdateFolder(client, "r-data", relFilename, EFileType.File); } } RemoveFileLock(client, relFilename); } foreach(string rFile in fileToRemoveFromList) { filesDeleted.Remove(rFile); } } fileToRemoveFromList.Clear(); #endregion //Neue Dateien herunterladen bzw. gelöscht Dateien löschen UpdateFromRemote(client, syncFolder); //Halbe Sekunde warten Thread.Sleep(500); } #endregion //string fileInfo=Globals.Options.GetElementAsString("xml.Sync.Filesystem.Test.txt"); //client.PutFile("D:\\AlexFTPS_bin_1.0.2.zip", "xxx.xxx"); } } }