├── .gitattributes
├── .gitignore
├── Changelog.txt
├── FlagSync
├── FlagSync.Core
│ ├── BackupJob.cs
│ ├── DirectoryCreationEventArgs.cs
│ ├── DirectoryDeletionEventArgs.cs
│ ├── FileCopyErrorEventArgs.cs
│ ├── FileCopyEventArgs.cs
│ ├── FileDeletionErrorEventArgs.cs
│ ├── FileDeletionEventArgs.cs
│ ├── FileProceededEventArgs.cs
│ ├── FileSystem
│ │ ├── AccessException.cs
│ │ ├── Base
│ │ │ ├── IDirectoryInfo.cs
│ │ │ ├── IFileInfo.cs
│ │ │ ├── IFileSystem.cs
│ │ │ └── IFileSystemInfo.cs
│ │ ├── DirectoryFoundEventArgs.cs
│ │ ├── FileCountResult.cs
│ │ ├── FileCounter.cs
│ │ ├── FileFoundEventArgs.cs
│ │ ├── FileSystemScanner.cs
│ │ ├── FileSystemUnavailableException.cs
│ │ ├── Ftp
│ │ │ ├── FtpDirectoryInfo.cs
│ │ │ ├── FtpFileInfo.cs
│ │ │ └── FtpFileSystem.cs
│ │ ├── ITunes
│ │ │ ├── ITunesDirectoryInfo.cs
│ │ │ └── ITunesFileSystem.cs
│ │ └── Local
│ │ │ ├── LocalDirectoryInfo.cs
│ │ │ ├── LocalFileInfo.cs
│ │ │ └── LocalFileSystem.cs
│ ├── FlagSync.Core.csproj
│ ├── Job.cs
│ ├── JobEventArgs.cs
│ ├── JobWorker.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── SyncJob.cs
│ └── packages.config
├── FlagSync.Data
│ ├── CorruptSaveFileException.cs
│ ├── DataController.cs
│ ├── FileSystemSetting.cs
│ ├── FlagSync.Data.csproj
│ ├── FtpFileSystemSetting.cs
│ ├── ITunesFileSystemSetting.cs
│ ├── ITunesNotOpenedException.cs
│ ├── JobSetting.cs
│ ├── JobSettingsLoadingResult.cs
│ ├── LocalFileSystemSetting.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── SyncMode.cs
│ └── packages.config
├── FlagSync.Setup
│ └── FlagSync.Setup.vdproj
├── FlagSync.View
│ ├── App.xaml
│ ├── App.xaml.cs
│ ├── ByteToKiloByteConverter.cs
│ ├── FlagSync.View.csproj
│ ├── Images
│ │ ├── Add.png
│ │ ├── ApplicationIcon.ico
│ │ ├── DownArrow.png
│ │ ├── Error.png
│ │ ├── FTPServer.png
│ │ ├── Load.png
│ │ ├── Local.png
│ │ ├── OpenFolder.png
│ │ ├── Remove.png
│ │ ├── Save.png
│ │ ├── Success.png
│ │ ├── UpArrow.png
│ │ └── iTunes.png
│ ├── LogMessage.cs
│ ├── Properties
│ │ ├── AssemblyInfo.cs
│ │ ├── Resources.Designer.cs
│ │ ├── Resources.de-DE.Designer.cs
│ │ ├── Resources.de-DE.resx
│ │ ├── Resources.resx
│ │ ├── Settings.Designer.cs
│ │ └── Settings.settings
│ ├── ViewModels
│ │ ├── AboutBoxViewModel.cs
│ │ ├── FtpFileSystemViewModel.cs
│ │ ├── IFileSystemViewModel.cs
│ │ ├── ITunesFileSystemViewModel.cs
│ │ ├── JobCompositionViewModel.cs
│ │ ├── JobSettingViewModel.cs
│ │ ├── JobViewModel.cs
│ │ ├── LocalFileSystemViewModel.cs
│ │ └── MainWindowViewModel.cs
│ ├── Views
│ │ ├── AboutBox.xaml
│ │ ├── AboutBox.xaml.cs
│ │ ├── FtpFileSystemPanel.xaml
│ │ ├── FtpFileSystemPanel.xaml.cs
│ │ ├── ITunesFileSystemPanel.xaml
│ │ ├── ITunesFileSystemPanel.xaml.cs
│ │ ├── JobCompositionControl.xaml
│ │ ├── JobCompositionControl.xaml.cs
│ │ ├── LocalFileSystemPanel.xaml
│ │ ├── LocalFileSystemPanel.xaml.cs
│ │ ├── MainWindow.xaml
│ │ └── MainWindow.xaml.cs
│ ├── app.config
│ └── packages.config
├── FlagSync.sln
└── packages
│ ├── FlagFtp.0.1.2
│ ├── FlagFtp.0.1.2.nupkg
│ └── lib
│ │ ├── FlagFtp.dll
│ │ └── FlagFtp.xml
│ ├── MahApps.Metro.0.8.0.0
│ ├── MahApps.Metro.0.8.0.0.nupkg
│ ├── lib
│ │ └── net40
│ │ │ ├── MahApps.Metro.dll
│ │ │ └── System.Windows.Interactivity.dll
│ └── tools
│ │ └── install.ps1
│ ├── Rareform.1.2.0
│ ├── Rareform.1.2.0.nupkg
│ └── lib
│ │ ├── Rareform.dll
│ │ └── Rareform.xml
│ └── repositories.config
├── Releases
├── 1.0.0
│ └── FlagSync-1.0.0.exe
├── 1.1.0
│ └── FlagSync-1.1.0.exe
├── 1.2.0
│ └── FlagSync-1.2.0.rar
├── 1.2.1
│ └── FlagSync-1.2.1.rar
├── 1.3.0
│ └── FlagSync-1.3.0.rar
├── 1.3.1
│ └── FlagSync-1.3.1.rar
├── 1.3.2
│ └── FlagSync-1.3.2.rar
├── 1.3.3
│ └── FlagSync-1.3.3.zip
├── 2.0.0
│ ├── FlagSync-2.0.0-portable.rar
│ └── FlagSync-2.0.0.rar
├── 2.1.0
│ ├── FlagSync-2.1.0-portable.rar
│ └── FlagSync-2.1.0.rar
├── 2.1.1
│ ├── FlagSync-2.1.1-portable.rar
│ └── FlagSync-2.1.1.rar
├── 2.1.2
│ ├── FlagSync-2.1.2-portable.rar
│ └── FlagSync-2.1.2.rar
├── 2.1.3
│ ├── FlagSync-2.1.3-portable.rar
│ └── FlagSync-2.1.3.rar
├── 2.2.0
│ ├── FlagSync-2.2.0-portable.rar
│ └── FlagSync-2.2.0.rar
├── 2.2.1
│ ├── FlagSync-2.2.1-portable.rar
│ └── FlagSync-2.2.1.rar
├── 2.3.0
│ ├── FlagSync-2.3.0-portable.zip
│ └── FlagSync-2.3.0.zip
├── 2.3.1
│ ├── FlagSync-2.3.1-portable.zip
│ └── FlagSync-2.3.1.zip
├── 2.4.0
│ ├── FlagSync-2.4.0-portable.zip
│ └── FlagSync-2.4.0.zip
├── 2.4.1
│ ├── FlagSync-2.4.1-portable.zip
│ └── FlagSync-2.4.1.zip
└── 2.4.2
│ ├── FlagSync-2.4.2-portable.zip
│ └── FlagSync-2.4.2.zip
└── readme.md
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 | *.sln merge=union
7 | *.csproj merge=union
8 | *.vbproj merge=union
9 | *.fsproj merge=union
10 | *.dbproj merge=union
11 |
12 | # Standard to msysgit
13 | *.doc diff=astextplain
14 | *.DOC diff=astextplain
15 | *.docx diff=astextplain
16 | *.DOCX diff=astextplain
17 | *.dot diff=astextplain
18 | *.DOT diff=astextplain
19 | *.pdf diff=astextplain
20 | *.PDF diff=astextplain
21 | *.rtf diff=astextplain
22 | *.RTF diff=astextplain
23 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | _ReSharper*
3 | [Bb]in/
4 | [Oo]bj/
5 | TestResults
6 | publish
7 | _NCrunch*
8 |
9 | *.suo
10 | *.user
11 | *.psess
12 | *.vsp
13 | *.ncrunchproject
14 | *.ncrunchsolution
15 | *.pdb
16 | /Espera/packages/Caliburn.Micro.1.3.1/lib/sl4
17 | /Espera/packages/Caliburn.Micro.1.3.1/lib/sl4-windowsphone71
18 | /Espera/packages/Caliburn.Micro.1.3.1/lib/sl5
19 | /Espera/packages/Caliburn.Micro.1.3.1/lib/WinRT45
20 | /Espera/packages/Caliburn.Micro.1.3.1/tools/sl4
21 | /Espera/packages/Caliburn.Micro.1.3.1/tools/sl4-windowsphone71
22 | /Espera/packages/Caliburn.Micro.1.3.1/tools/sl5
23 | /Espera/packages/Moq.4.0.10827/lib/NET35
24 | /Espera/packages/Moq.4.0.10827/lib/Silverlight4
25 | /espera/packages/Newtonsoft.Json.4.5.9/lib/sl4
26 | /espera/packages/Newtonsoft.Json.4.5.9/lib/sl4-windowsphone71
27 | /espera/packages/Newtonsoft.Json.4.5.9/lib/winrt45
28 | /espera/packages/Newtonsoft.Json.4.5.9/lib/net20
29 | /espera/packages/Newtonsoft.Json.4.5.9/lib/net35
30 | /espera/packages/Newtonsoft.Json.4.5.9/lib/sl3-wp
--------------------------------------------------------------------------------
/Changelog.txt:
--------------------------------------------------------------------------------
1 | ----------------------------------- v2.4.2 -----------------------------------
2 |
3 | CHANGES:
4 | - Changed the look of the current job display a bit.
5 |
6 | IMPROVEMENTS:
7 | - The average speed is now hidden, when the user starts a preview.
8 |
9 | BUGFIXES:
10 | - Fixed a bug, that caused the average speed text to not appear when a new
11 | job starts.
12 | - Fixed a bug, that caused the application to crash during the calculation of
13 | the average speed.
14 | - Fixed a bug, that caused the application to crash during a synchonization
15 | with iTunes.
16 | - Fixed a bug, that caused a wrong synchronization with FTP-servers.
17 |
18 | ----------------------------------- v2.4.1 -----------------------------------
19 |
20 | CHANGES:
21 | - Changed the button style, to be closer to a metro-look.
22 |
23 | IMRPOVEMENTS:
24 | - General layout and interface improvements.
25 |
26 | BUGFIXES:
27 | - Fixed a bug, which caused the application to crash, when copying files with
28 | a size of zero bytes.
29 | - Fixed a bug, which caused the progress of the last log message during a
30 | preview to be set to 100 percent.
31 |
32 | ----------------------------------- v2.4.0 -----------------------------------
33 |
34 | FEATURES:
35 | - The progress is now shown in the taskbar, if the operating system supports
36 | this.
37 | - The order of the jobs can now be changed.
38 |
39 | BUGFIXES:
40 | - Fixed a bug, which caused the application to crash during a synchronization
41 | with iTunes.
42 | - Fixed a bug, which caused the start and preview buttons to be able to be
43 | pressed, if no job was included.
44 |
45 | ----------------------------------- v2.3.1 -----------------------------------
46 |
47 | IMPROVEMENTS:
48 | - Decreased the application's startup time.
49 | - Added a log message, if the creation of a directory failed.
50 |
51 | BUGFIXES:
52 | - Fixed a bug which caused the application to crash, if there were no file or
53 | directory changes.
54 | - Fixed a bug, which caused the mode of of job to disapear in the current job
55 | display.
56 | - Fixed some typos.
57 |
58 | ----------------------------------- v2.3.0 -----------------------------------
59 |
60 | CHANGES:
61 | - Changed the button, the tabs, the progressbar and the job setting menu
62 | style.
63 | - There is no default job anymore when the application starts.
64 | Instead, a message is displayed, that the user shoukld click on the "New"
65 | button to add a new job.
66 |
67 | IMPROVEMENTS:
68 | - The text in a log message now doesnt't cut off suddendly, instead it's
69 | prepended with dots, to indicate that there is more text.
70 | - The average speed is now calculated more accurately.
71 | - There is now an '@' in front of the average speed display.
72 |
73 | BUGFIXES:
74 | - Fixed a bug, which caused the progress of the current file not to jump to
75 | 100 percent.
76 |
77 | ----------------------------------- v2.2.1 -----------------------------------
78 |
79 | BUGFIXES:
80 | - Fixed a bug, which caused the wrong iTunes playlist to be loaded, when the
81 | user loaded a job.
82 |
83 | ----------------------------------- v2.2.0 -----------------------------------
84 |
85 | FEATURES:
86 | - Each log message now displays the size of the file.
87 |
88 | CHANGES:
89 | - Removed the detailed log, which writes to a file in the appdata directory.
90 |
91 | IMPROVEMENTS:
92 | - The average speed is now displayed dynamically, depending on the actual
93 | speed.
94 | - Improved the error displaying.
95 | - The FTP address is now validated to have the correct format.
96 | - The preview and start buttons now cannot be pressed anymore, if there are
97 | errors in the included job settings.
98 |
99 | BUGFIXES:
100 | - Fixed a bug, which caused a preview to list the subdirectories and files of
101 | a directory that should get deleted.
102 | - Fixed the misspelling of "Address" in the FTP settings panel.
103 | - Fixed a bug, which caused the application to crash if a song in iTunes got
104 | deleted, before it was synced.
105 | - Fixed a bug, which let the user select no iTunes playlist.
106 |
107 | ----------------------------------- v2.1.3 -----------------------------------
108 |
109 | BUGFIXES:
110 | - Fixed a bug which caused files to be copied into the wrong directory on a
111 | FTP-Server.
112 |
113 | ----------------------------------- v2.1.2 -----------------------------------
114 |
115 | CHANGES:
116 | - Changed the URL of the update download site.
117 | - The about box now only displays three version fields.
118 |
119 | BUGFIXES:
120 | - Fixed a bug which caused the application to crash if the target directory of
121 | an iTunes job doesn't exist.
122 | - Fixed a bug which caused the application to crash if the target directory of
123 | a FTP job doesn't exist.
124 | - Fixed a bug which caused iTunes to automatically open.
125 |
126 | ----------------------------------- v2.1.1 -----------------------------------
127 |
128 | IMPROVEMENTS:
129 | - The application now displays a popup which prompts the user to open iTunes,
130 | if iTunes is not opened and the user tries to create or load an iTunes job.
131 |
132 | BUGFIXES:
133 | - Fixed a bug, which caused all jobs to disappear, if a corrupt setting has
134 | been loaded.
135 |
136 | ----------------------------------- v2.1.0 -----------------------------------
137 |
138 | FEATURES:
139 | - The average speed is now displayed.
140 | - The application now informs in the bottom right corner, if a new version is
141 | available.
142 |
143 | CHANGES:
144 | - Changed the layout of the log, so that the current file progress is now
145 | visible beneath the total-progress progress-bar.
146 |
147 | IMPROVEMENTS:
148 | - Increased the performance of the application drastically.
149 | - Improved the file deletion handling.
150 | - The recycle-bin of a harddrive is now excluded from the synchronization and
151 | backup.
152 | - The current copy operations now gets aborted when the user stops the job.
153 |
154 | BUGFIXES:
155 | - Fixed a bug which caused the directory path to reset, if the folder
156 | selection dialog has been canceled.
157 |
158 | ----------------------------------- v2.0.0 -----------------------------------
159 |
160 | FEATURES:
161 | - Added synchronization and backup for FTP servers.
162 | - The application can now synchronize an iTunes playlist with a folder
163 | (useful for MP3-Players).
164 | - The copy progress for each separate file is now visible.
165 |
166 | IMPROVEMENTS:
167 | - Complete new user interface.
168 |
169 | ----------------------------------- v1.3.3 -----------------------------------
170 |
171 | FEATURES:
172 | - Added application icon.
173 |
174 | IMPROVEMENTS:
175 | - Many UI improvements.
176 | - Improved error handling.
177 |
178 | BUGFIXES:
179 | - Fixed a threading issue.
180 |
181 | ----------------------------------- v1.3.2 -----------------------------------
182 |
183 | CHANGES:
184 | - Removed the 64-bit version of FlagSync.
185 | - The window now maximizes at startup.
186 |
187 | IMPROVEMENTS:
188 | - Improved progress-bar (now counts size of files, not number of all files).
189 | - Elapsed time counter now stops when a job gets paused.
190 |
191 | ----------------------------------- v1.3.1 -----------------------------------
192 |
193 | FEATURES:
194 | - Added elapsed time.
195 | - Added error log, if an invalid settings file gets read.
196 |
197 | IMPROVEMENTS:
198 | - Improved log.
199 |
200 | ----------------------------------- v1.3.0 -----------------------------------
201 |
202 | CHANGES:
203 | - Limited log to 60,000 characters.
204 |
205 | IMPROVEMENTS:
206 | - Improved user interface.
207 | - Improved stop function.
208 |
209 | ----------------------------------- v1.2.1 -----------------------------------
210 |
211 | FEATURES:
212 | - Added tooltips.
213 |
214 | CHANGES:
215 | - New jobs are now at default checked.
216 | - When loading the settings, they are now at default checked.
217 |
218 | IMPROVEMENTS
219 | - Improved translations.
220 |
221 | ----------------------------------- v1.2.0 -----------------------------------
222 |
223 | FEATURES:
224 | - Added German translation.
225 |
226 | ----------------------------------- v1.1.0 -----------------------------------
227 |
228 | FEATURES:
229 | - Added job saving and loading.
230 |
231 | ----------------------------------- v1.0.0 -----------------------------------
232 |
233 | - Release of public version.
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Core/BackupJob.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using FlagSync.Core.FileSystem.Base;
3 |
4 | namespace FlagSync.Core
5 | {
6 | ///
7 | /// A backup-job performs a synchronization only from directory A to directory B, but can delete files.
8 | ///
9 | public class BackupJob : Job
10 | {
11 | ///
12 | /// Initializes a new instance of the class.
13 | ///
14 | /// The name of the job.
15 | /// The source file system.
16 | /// The target file system.
17 | /// The source directory.
18 | /// The target directory.
19 | public BackupJob(string name, IFileSystem sourceFileSystem, IFileSystem targetFileSystem, IDirectoryInfo sourceDirectory, IDirectoryInfo targetDirectory)
20 | : base(name, sourceFileSystem, targetFileSystem, sourceDirectory, targetDirectory) { }
21 |
22 | ///
23 | /// Starts the BackupJob, copies new and modified files from directory A to directory B and finally checks for deletions
24 | ///
25 | /// if set to true a preview will be performed.
26 | public override void Start(bool preview)
27 | {
28 | this.BackupDirectoryRecursively(this.DirectoryA, this.DirectoryB, !preview);
29 | this.CheckDeletionsRecursively(this.DirectoryB, this.DirectoryA, !preview);
30 |
31 | this.OnFinished(EventArgs.Empty);
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Core/DirectoryCreationEventArgs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Rareform.Extensions;
3 | using FlagSync.Core.FileSystem.Base;
4 |
5 | namespace FlagSync.Core
6 | {
7 | ///
8 | /// Provides data for the events of the and the class.
9 | ///
10 | public class DirectoryCreationEventArgs : EventArgs
11 | {
12 | ///
13 | /// Gets the directory.
14 | ///
15 | ///
16 | /// The directory.
17 | ///
18 | public IDirectoryInfo Directory { get; private set; }
19 |
20 | ///
21 | /// Gets the target directory.
22 | ///
23 | ///
24 | /// The target directory.
25 | ///
26 | public IDirectoryInfo TargetDirectory { get; private set; }
27 |
28 | ///
29 | /// Initializes a new instance of the class.
30 | ///
31 | /// The directory.
32 | /// The target directory.
33 | public DirectoryCreationEventArgs(IDirectoryInfo directory, IDirectoryInfo targetDirectory)
34 | {
35 | directory.ThrowIfNull(() => directory);
36 | targetDirectory.ThrowIfNull(() => targetDirectory);
37 |
38 | this.Directory = directory;
39 | this.TargetDirectory = targetDirectory;
40 | }
41 | }
42 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Core/DirectoryDeletionEventArgs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Rareform.Extensions;
3 |
4 | namespace FlagSync.Core
5 | {
6 | ///
7 | /// Provides data for the events of the and the class.
8 | ///
9 | public class DirectoryDeletionEventArgs : EventArgs
10 | {
11 | ///
12 | /// Gets the directory path.
13 | ///
14 | ///
15 | /// The directory path.
16 | ///
17 | public string DirectoryPath { get; private set; }
18 |
19 | ///
20 | /// Initializes a new instance of the class.
21 | ///
22 | /// The directory path.
23 | public DirectoryDeletionEventArgs(string directoryPath)
24 | {
25 | directoryPath.ThrowIfNull(() => directoryPath);
26 |
27 | this.DirectoryPath = directoryPath;
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Core/FileCopyErrorEventArgs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Rareform.Extensions;
3 | using FlagSync.Core.FileSystem.Base;
4 |
5 | namespace FlagSync.Core
6 | {
7 | ///
8 | /// Provides data for the events of the and the class.
9 | ///
10 | public class FileCopyErrorEventArgs : EventArgs
11 | {
12 | ///
13 | /// Gets the file.
14 | ///
15 | ///
16 | /// The file.
17 | ///
18 | public IFileInfo File { get; private set; }
19 |
20 | ///
21 | /// Gets the target directory.
22 | ///
23 | ///
24 | /// The target directory.
25 | ///
26 | public IDirectoryInfo TargetDirectory { get; private set; }
27 |
28 | ///
29 | /// Initializes a new instance of the class.
30 | ///
31 | /// The file.
32 | /// The target directory.
33 | public FileCopyErrorEventArgs(IFileInfo file, IDirectoryInfo targetDirectory)
34 | {
35 | file.ThrowIfNull(() => file);
36 | targetDirectory.ThrowIfNull(() => targetDirectory);
37 |
38 | this.File = file;
39 | this.TargetDirectory = targetDirectory;
40 | }
41 | }
42 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Core/FileCopyEventArgs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Rareform.Extensions;
3 | using FlagSync.Core.FileSystem.Base;
4 |
5 | namespace FlagSync.Core
6 | {
7 | ///
8 | /// Provides data for the events of the and the class.
9 | ///
10 | public class FileCopyEventArgs : EventArgs
11 | {
12 | ///
13 | /// Gets the file.
14 | ///
15 | ///
16 | /// The file.
17 | ///
18 | public IFileInfo File { get; private set; }
19 |
20 | ///
21 | /// Gets the source directory.
22 | ///
23 | ///
24 | /// The source directory.
25 | ///
26 | public IDirectoryInfo SourceDirectory { get; private set; }
27 |
28 | ///
29 | /// Gets the target directory.
30 | ///
31 | ///
32 | /// The target directory.
33 | ///
34 | public IDirectoryInfo TargetDirectory { get; private set; }
35 |
36 | ///
37 | /// Initializes a new instance of the class.
38 | ///
39 | /// The file.
40 | /// The source directory.
41 | /// The target directory.
42 | public FileCopyEventArgs(IFileInfo file, IDirectoryInfo sourceDirectory, IDirectoryInfo targetDirectory)
43 | {
44 | file.ThrowIfNull(() => file);
45 | sourceDirectory.ThrowIfNull(() => sourceDirectory);
46 | targetDirectory.ThrowIfNull(() => targetDirectory);
47 |
48 | this.File = file;
49 | this.SourceDirectory = sourceDirectory;
50 | this.TargetDirectory = targetDirectory;
51 | }
52 | }
53 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Core/FileDeletionErrorEventArgs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Rareform.Extensions;
3 | using FlagSync.Core.FileSystem.Base;
4 |
5 | namespace FlagSync.Core
6 | {
7 | ///
8 | /// Provides data for the events of the and the class.
9 | ///
10 | public class FileDeletionErrorEventArgs : EventArgs
11 | {
12 | ///
13 | /// Gets the file.
14 | ///
15 | ///
16 | /// The file.
17 | ///
18 | public IFileInfo File { get; private set; }
19 |
20 | ///
21 | /// Initializes a new instance of the class.
22 | ///
23 | /// The file.
24 | public FileDeletionErrorEventArgs(IFileInfo file)
25 | {
26 | file.ThrowIfNull(() => file);
27 |
28 | this.File = file;
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Core/FileDeletionEventArgs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Rareform.Extensions;
3 |
4 | namespace FlagSync.Core
5 | {
6 | ///
7 | /// Provides data for the events of the and the class.
8 | ///
9 | public class FileDeletionEventArgs : EventArgs
10 | {
11 | ///
12 | /// Gets the file path.
13 | ///
14 | ///
15 | /// The file path.
16 | ///
17 | public string FilePath { get; private set; }
18 |
19 | ///
20 | /// Gets the size of the file.
21 | ///
22 | ///
23 | /// The size of the file.
24 | ///
25 | public long FileSize { get; private set; }
26 |
27 | ///
28 | /// Initializes a new instance of the class.
29 | ///
30 | /// The file path.
31 | /// Size of the file.
32 | public FileDeletionEventArgs(string filePath, long fileSize)
33 | {
34 | filePath.ThrowIfNull(() => filePath);
35 |
36 | this.FilePath = filePath;
37 | this.FileSize = fileSize;
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Core/FileProceededEventArgs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Rareform.Extensions;
3 |
4 | namespace FlagSync.Core
5 | {
6 | ///
7 | /// Provides data for the events of the and the class.
8 | ///
9 | public class FileProceededEventArgs : EventArgs
10 | {
11 | ///
12 | /// Gets the length of the file.
13 | ///
14 | ///
15 | /// The length of the file.
16 | ///
17 | public long FileLength { get; private set; }
18 |
19 | ///
20 | /// Gets the name of the file.
21 | ///
22 | ///
23 | /// The name of the file.
24 | ///
25 | public string FilePath { get; private set; }
26 |
27 | ///
28 | /// Initializes a new instance of the class.
29 | ///
30 | /// The file path.
31 | /// The file length.
32 | public FileProceededEventArgs(string filePath, long fileLength)
33 | {
34 | filePath.ThrowIfNull(() => filePath);
35 |
36 | this.FilePath = filePath;
37 | this.FileLength = fileLength;
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Core/FileSystem/AccessException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace FlagSync.Core.FileSystem
4 | {
5 | ///
6 | /// The exception that is thrown, when a file or directory could not be accessed.
7 | ///
8 | public class AccessException : Exception
9 | {
10 | ///
11 | /// Initializes a new instance of the class.
12 | ///
13 | /// The exception message.
14 | /// The inner exception.
15 | public AccessException(string message, Exception innerException)
16 | : base(message, innerException)
17 | { }
18 | }
19 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Core/FileSystem/Base/IDirectoryInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace FlagSync.Core.FileSystem.Base
4 | {
5 | ///
6 | /// Provides the interface that all directory infos have to implement.
7 | ///
8 | public interface IDirectoryInfo : IFileSystemInfo
9 | {
10 | ///
11 | /// Gets the parent directory.
12 | ///
13 | IDirectoryInfo Parent { get; }
14 |
15 | ///
16 | /// Gets a value indicating whether the directory exists.
17 | ///
18 | ///
19 | /// true if the directory exists; otherwise, false.
20 | ///
21 | bool Exists { get; }
22 |
23 | ///
24 | /// Returns a list of all files in the directory.
25 | ///
26 | ///
27 | /// The files in the directory.
28 | ///
29 | ///
30 | /// The exception that is thrown if the directory is locked
31 | ///
32 | IEnumerable GetFiles();
33 |
34 | ///
35 | /// Returns a list of all directories in the directory.
36 | ///
37 | ///
38 | /// The directories in the directory.
39 | ///
40 | ///
41 | /// The exception that is thrown if the directory is locked.
42 | ///
43 | IEnumerable GetDirectories();
44 | }
45 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Core/FileSystem/Base/IFileInfo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace FlagSync.Core.FileSystem.Base
4 | {
5 | ///
6 | /// Provides the interface that all file infos have to implement.
7 | ///
8 | public interface IFileInfo : IFileSystemInfo
9 | {
10 | ///
11 | /// Gets the last write time.
12 | ///
13 | DateTime LastWriteTime { get; }
14 |
15 | ///
16 | /// Gets the length of the file.
17 | ///
18 | long Length { get; }
19 |
20 | ///
21 | /// Gets the directory.
22 | ///
23 | IDirectoryInfo Directory { get; }
24 |
25 | ///
26 | /// Gets a value indicating whether the file exists.
27 | ///
28 | ///
29 | /// true if exists; otherwise, false.
30 | ///
31 | bool Exists { get; }
32 | }
33 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Core/FileSystem/Base/IFileSystem.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using Rareform.IO;
4 |
5 | namespace FlagSync.Core.FileSystem.Base
6 | {
7 | ///
8 | /// Provides the interface that all filesystems have to implement.
9 | ///
10 | public interface IFileSystem
11 | {
12 | ///
13 | /// Occurs when the file copy progress has changed.
14 | ///
15 | event EventHandler FileCopyProgressChanged;
16 |
17 | ///
18 | /// Deletes the specified file.
19 | ///
20 | /// The file to delete.
21 | ///
22 | /// true, if the deletion has succeed; otherwise, false.
23 | ///
24 | /// The file could not be accessed.
25 | /// The file system is currently unavailable.
26 | void DeleteFile(IFileInfo file);
27 |
28 | ///
29 | /// Creates the specified directory in the target directory.
30 | ///
31 | /// The source directory.
32 | /// The target directory.
33 | ///
34 | /// true, if the creation has succeed; otherwise, false.
35 | ///
36 | /// The directory could not be accessed.
37 | /// The file system is currently unavailable.
38 | void CreateDirectory(IDirectoryInfo sourceDirectory, IDirectoryInfo targetDirectory);
39 |
40 | ///
41 | /// Deletes the specified directory.
42 | ///
43 | /// The directory to delete.
44 | ///
45 | /// true, if the deletion has succeed; otherwise, false.
46 | ///
47 | /// The directory could not be accessed.
48 | /// The file system is currently unavailable.
49 | void DeleteDirectory(IDirectoryInfo directory);
50 |
51 | ///
52 | /// Copies the specified file to the target directory.
53 | ///
54 | /// The source file system.
55 | /// The source file.
56 | /// The target directory.
57 | ///
58 | /// true, if the copy operation has succeed; otherwise, false.
59 | ///
60 | /// The source file or target directory could not be accessed.
61 | /// The file system is currently unavailable.
62 | void CopyFile(IFileSystem sourceFileSystem, IFileInfo sourceFile, IDirectoryInfo targetDirectory);
63 |
64 | ///
65 | /// Gets the file info at the specified path.
66 | ///
67 | /// The path of the file.
68 | ///
69 | /// An of the file from the specified path.
70 | ///
71 | IFileInfo GetFileInfo(string path);
72 |
73 | ///
74 | /// Gets the directory info at the specified path.
75 | ///
76 | /// The path of the directory.
77 | ///
78 | /// An of the directory from the specified path.
79 | ///
80 | IDirectoryInfo GetDirectoryInfo(string path);
81 |
82 | ///
83 | /// Determines if the file at the specified path exists.
84 | ///
85 | /// The path of the file.
86 | ///
87 | /// true, if the file exists; otherwise, false.
88 | ///
89 | bool FileExists(string path);
90 |
91 | ///
92 | /// Determines if the directory at the specified path exists.
93 | ///
94 | /// The path of the directory.
95 | ///
96 | /// true, if the directory exists; otherwise, false.
97 | ///
98 | bool DirectoryExists(string path);
99 |
100 | ///
101 | /// Opens the stream of the specified file.
102 | ///
103 | /// The file.
104 | ///
105 | /// A stream from the specified file.
106 | ///
107 | Stream OpenFileStream(IFileInfo file);
108 |
109 | ///
110 | /// Combines two paths for the specific file system.
111 | ///
112 | /// The first path.
113 | /// The second path.
114 | ///
115 | /// A path, which is the combination of the first and second path.
116 | ///
117 | string CombinePath(string path1, string path2);
118 | }
119 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Core/FileSystem/Base/IFileSystemInfo.cs:
--------------------------------------------------------------------------------
1 | namespace FlagSync.Core.FileSystem.Base
2 | {
3 | ///
4 | /// Provides the interface for the
5 | /// and the interface.
6 | ///
7 | public interface IFileSystemInfo
8 | {
9 | ///
10 | /// Gets the full name of the file or directory.
11 | ///
12 | string FullName { get; }
13 |
14 | ///
15 | /// Gets the name of the file or directory.
16 | ///
17 | string Name { get; }
18 | }
19 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Core/FileSystem/DirectoryFoundEventArgs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using FlagSync.Core.FileSystem.Base;
3 |
4 | namespace FlagSync.Core.FileSystem
5 | {
6 | ///
7 | /// Provides data for the events of the class.
8 | ///
9 | public class DirectoryFoundEventArgs : EventArgs
10 | {
11 | ///
12 | /// Gets the found the directory.
13 | ///
14 | ///
15 | /// The found directory.
16 | ///
17 | public IDirectoryInfo Directory { get; private set; }
18 |
19 | ///
20 | /// Initializes a new instance of the class.
21 | ///
22 | /// The directory that has been found.
23 | public DirectoryFoundEventArgs(IDirectoryInfo directory)
24 | {
25 | this.Directory = directory;
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Core/FileSystem/FileCountResult.cs:
--------------------------------------------------------------------------------
1 | using Rareform.Extensions;
2 |
3 | namespace FlagSync.Core.FileSystem
4 | {
5 | ///
6 | /// Contains the number of files counted and the total size of all files.
7 | ///
8 | public class FileCountResult
9 | {
10 | ///
11 | /// Gets the counted files.
12 | ///
13 | ///
14 | /// The counted files.
15 | ///
16 | public int CountedFiles { get; private set; }
17 |
18 | ///
19 | /// Gets the counted bytes.
20 | ///
21 | ///
22 | /// The counted bytes.
23 | ///
24 | public long CountedBytes { get; private set; }
25 |
26 | ///
27 | /// Initializes a new instance of the class.
28 | ///
29 | /// The counted files.
30 | /// The counted bytes.
31 | public FileCountResult(int countedFiles, long countedBytes)
32 | {
33 | this.CountedBytes = countedBytes;
34 | this.CountedFiles = countedFiles;
35 | }
36 |
37 | ///
38 | /// Initializes a new instance of the class.
39 | ///
40 | public FileCountResult()
41 | : this(0, 0)
42 | {
43 | }
44 |
45 | ///
46 | /// Implements the operator +.
47 | ///
48 | /// The first file counter result
49 | /// The second file counter result
50 | ///
51 | /// The result of the operator.
52 | ///
53 | public static FileCountResult operator +(FileCountResult a, FileCountResult b)
54 | {
55 | a.ThrowIfNull(() => a);
56 | b.ThrowIfNull(() => b);
57 |
58 | return new FileCountResult(a.CountedFiles + b.CountedFiles, a.CountedBytes + b.CountedBytes);
59 | }
60 | }
61 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Core/FileSystem/FileCounter.cs:
--------------------------------------------------------------------------------
1 | using Rareform.Extensions;
2 | using FlagSync.Core.FileSystem.Base;
3 |
4 | namespace FlagSync.Core.FileSystem
5 | {
6 | ///
7 | /// Provides a method for counting recursively the files of a directory.
8 | ///
9 | internal static class FileCounter
10 | {
11 | ///
12 | /// Counts recursively the files of the directory.
13 | ///
14 | /// The root directory.
15 | ///
16 | /// A which indicates the result of the count.
17 | ///
18 | public static FileCountResult CountFiles(IDirectoryInfo rootDirectory)
19 | {
20 | rootDirectory.ThrowIfNull(() => rootDirectory);
21 |
22 | int files = 0;
23 | long bytes = 0;
24 |
25 | var scanner = new FileSystemScanner(rootDirectory);
26 |
27 | scanner.FileFound += (sender, e) =>
28 | {
29 | files++;
30 | bytes += e.File.Length;
31 | };
32 |
33 | scanner.Start();
34 |
35 | return new FileCountResult(files, bytes);
36 | }
37 | }
38 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Core/FileSystem/FileFoundEventArgs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using FlagSync.Core.FileSystem.Base;
3 |
4 | namespace FlagSync.Core.FileSystem
5 | {
6 | ///
7 | /// Provides data for the events of the class.
8 | ///
9 | public class FileFoundEventArgs : EventArgs
10 | {
11 | ///
12 | /// Gets the found file.
13 | ///
14 | public IFileInfo File { get; private set; }
15 |
16 | ///
17 | /// Initializes a new instance of the class.
18 | ///
19 | /// The found file.
20 | public FileFoundEventArgs(IFileInfo file)
21 | {
22 | this.File = file;
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Core/FileSystem/FileSystemScanner.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Security;
5 | using FlagSync.Core.FileSystem.Base;
6 | using Rareform.Extensions;
7 |
8 | namespace FlagSync.Core.FileSystem
9 | {
10 | internal class FileSystemScanner
11 | {
12 | private readonly IDirectoryInfo rootDirectory;
13 |
14 | ///
15 | /// Gets or sets a value indicating whether the scanner is stopped.
16 | ///
17 | /// true if the scanner is stopped; otherwise, false.
18 | public bool IsStopped { get; private set; }
19 |
20 | ///
21 | /// Occurs when a file has been found.
22 | ///
23 | public event EventHandler FileFound;
24 |
25 | ///
26 | /// Occurs when a directory has been found.
27 | ///
28 | public event EventHandler DirectoryFound;
29 |
30 | ///
31 | /// Occurs when a directory has been proceeded.
32 | ///
33 | public event EventHandler DirectoryProceeded;
34 |
35 | ///
36 | /// Stops the scanner.
37 | ///
38 | public void Stop()
39 | {
40 | this.IsStopped = true;
41 | }
42 |
43 | ///
44 | /// Starts the scanner.
45 | ///
46 | public void Start()
47 | {
48 | this.ScanDirectories(this.rootDirectory);
49 | }
50 |
51 | ///
52 | /// Initializes a new instance of the class.
53 | ///
54 | /// The root directory.
55 | ///
56 | /// The exception that is thrown, if the root directory doesn't exists
57 | ///
58 | public FileSystemScanner(IDirectoryInfo rootDirectory)
59 | {
60 | rootDirectory.ThrowIfNull(() => rootDirectory);
61 |
62 | if (!rootDirectory.Exists)
63 | throw new ArgumentException("The root directory must exist!");
64 |
65 | this.rootDirectory = rootDirectory;
66 | }
67 |
68 | ///
69 | /// Raises the event.
70 | ///
71 | /// The instance containing the event data.
72 | protected virtual void OnFileFound(FileFoundEventArgs e)
73 | {
74 | this.FileFound.RaiseSafe(this, e);
75 | }
76 |
77 | ///
78 | /// Raises the event.
79 | ///
80 | /// The instance containing the event data.
81 | protected virtual void OnDirectoryFound(DirectoryFoundEventArgs e)
82 | {
83 | this.DirectoryFound.RaiseSafe(this, e);
84 | }
85 |
86 | ///
87 | /// Raises the event.
88 | ///
89 | /// The instance containing the event data.
90 | protected virtual void OnDirectoryProceeded(EventArgs e)
91 | {
92 | this.DirectoryProceeded.RaiseSafe(this, e);
93 | }
94 |
95 | ///
96 | /// Scans a directory recursively.
97 | ///
98 | /// The root directory.
99 | private void ScanDirectories(IDirectoryInfo rootDirectory)
100 | {
101 | if (this.IsStopped) { return; }
102 |
103 | try
104 | {
105 | if (rootDirectory.Exists)
106 | {
107 | IEnumerable files = rootDirectory.GetFiles();
108 |
109 | foreach (IFileInfo file in files)
110 | {
111 | if (this.IsStopped) { return; }
112 |
113 | if (file.Exists)
114 | {
115 | this.OnFileFound(new FileFoundEventArgs(file));
116 | }
117 | }
118 |
119 | IEnumerable directories = rootDirectory.GetDirectories();
120 |
121 | foreach (IDirectoryInfo directory in directories)
122 | {
123 | if (this.IsStopped)
124 | {
125 | return;
126 | }
127 |
128 | if (directory.Name == "$RECYCLE.BIN" || !directory.Exists)
129 | {
130 | continue;
131 | }
132 |
133 | this.OnDirectoryFound(new DirectoryFoundEventArgs(directory));
134 | this.ScanDirectories(directory);
135 | }
136 | }
137 | }
138 |
139 | // Catch the exceptions and don't handle anything,
140 | // we want to skip those files or directories
141 | catch (UnauthorizedAccessException)
142 | {
143 | }
144 |
145 | catch (SecurityException)
146 | {
147 | }
148 |
149 | catch (IOException)
150 | {
151 | }
152 |
153 | this.OnDirectoryProceeded(EventArgs.Empty);
154 | }
155 | }
156 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Core/FileSystem/FileSystemUnavailableException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace FlagSync.Core.FileSystem
4 | {
5 | ///
6 | /// The exception that is thrown, when the file system is unabailable.
7 | ///
8 | public class FileSystemUnavailableException : Exception
9 | {
10 | ///
11 | /// Initializes a new instance of the class.
12 | ///
13 | /// The exception message.
14 | /// The inner exception.
15 | public FileSystemUnavailableException(string message, Exception innerException)
16 | : base(message, innerException)
17 | { }
18 | }
19 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Core/FileSystem/Ftp/FtpDirectoryInfo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.IO;
5 | using System.Linq;
6 | using FlagFtp;
7 | using Rareform.Extensions;
8 | using FlagSync.Core.FileSystem.Base;
9 |
10 | namespace FlagSync.Core.FileSystem.Ftp
11 | {
12 | ///
13 | /// Represents a directory on a FTP-server.
14 | ///
15 | [DebuggerDisplay("{FullName}")]
16 | public class FtpDirectoryInfo : IDirectoryInfo
17 | {
18 | private readonly FtpClient client;
19 |
20 | ///
21 | /// Gets the full name of the directory.
22 | ///
23 | public string FullName { get; private set; }
24 |
25 | ///
26 | /// Gets the name of the directory.
27 | ///
28 | public string Name
29 | {
30 | get { return Path.GetFileName(this.FullName); }
31 | }
32 |
33 | ///
34 | /// Gets the parent directory.
35 | ///
36 | public IDirectoryInfo Parent
37 | {
38 | get
39 | {
40 | string parentDirectoryName = Path.GetDirectoryName(this.FullName).Replace("\\", "//");
41 | Uri parentDirectoryUri = new Uri(parentDirectoryName);
42 |
43 | FlagFtp.FtpDirectoryInfo directory = this.client.GetDirectoryInfo(parentDirectoryUri);
44 |
45 | return new FtpDirectoryInfo(directory.FullName, this.client);
46 | }
47 | }
48 |
49 | ///
50 | /// Gets a value indicating whether the directory exists.
51 | ///
52 | ///
53 | /// true if the directory exists; otherwise, false.
54 | ///
55 | public bool Exists
56 | {
57 | get { return true; }
58 | }
59 |
60 | ///
61 | /// Returns a list of all files in the directory.
62 | ///
63 | ///
64 | /// The files in the directory.
65 | ///
66 | ///
67 | /// The exception that is thrown if the directory is locked.
68 | ///
69 | public IEnumerable GetFiles()
70 | {
71 | return this.client
72 | .GetFiles(new Uri(this.FullName))
73 | .Where(file => file.Name != ".ftpquota")
74 | .Select(file => new FtpFileInfo(file.FullName, file.LastWriteTime, file.Length, this.client))
75 | .Cast()
76 | .ToList();
77 | }
78 |
79 | ///
80 | /// Returns a list of all directories in the directory.
81 | ///
82 | ///
83 | /// The directories in the directory.
84 | ///
85 | ///
86 | /// The exception that is thrown if the directory is locked.
87 | ///
88 | public IEnumerable GetDirectories()
89 | {
90 | return this.client
91 | .GetDirectories(new Uri(this.FullName))
92 | .Select(directory => new FtpDirectoryInfo(directory.FullName, this.client))
93 | .Cast()
94 | .ToList();
95 | }
96 |
97 | ///
98 | /// Initializes a new instance of the class.
99 | ///
100 | /// The full name.
101 | /// The client.
102 | public FtpDirectoryInfo(string fullName, FtpClient client)
103 | {
104 | fullName.ThrowIfNull(() => fullName);
105 | client.ThrowIfNull(() => client);
106 |
107 | this.FullName = fullName;
108 | this.client = client;
109 | }
110 | }
111 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Core/FileSystem/Ftp/FtpFileInfo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.IO;
4 | using FlagFtp;
5 | using Rareform.Extensions;
6 | using FlagSync.Core.FileSystem.Base;
7 |
8 | namespace FlagSync.Core.FileSystem.Ftp
9 | {
10 | ///
11 | /// Represents a file on a FTP-server
12 | ///
13 | [DebuggerDisplay("{FullName}")]
14 | public class FtpFileInfo : IFileInfo
15 | {
16 | private readonly FtpClient client;
17 |
18 | ///
19 | /// Gets the last write time.
20 | ///
21 | public DateTime LastWriteTime { get; private set; }
22 |
23 | ///
24 | /// Gets the length of the file.
25 | ///
26 | public long Length { get; private set; }
27 |
28 | ///
29 | /// Gets the directory of the file.
30 | ///
31 | public IDirectoryInfo Directory
32 | {
33 | get
34 | {
35 | FlagFtp.FtpDirectoryInfo directory =
36 | this.client.GetDirectoryInfo(new Uri(Path.GetDirectoryName(this.FullName)));
37 |
38 | return new FtpDirectoryInfo(directory.FullName, this.client);
39 | }
40 | }
41 |
42 | ///
43 | /// Gets a value indicating whether the file exists.
44 | ///
45 | ///
46 | /// true if the file exists; otherwise, false.
47 | ///
48 | public bool Exists
49 | {
50 | get { return true; }
51 | }
52 |
53 | ///
54 | /// Gets the full name of the file.
55 | ///
56 | public string FullName { get; private set; }
57 |
58 | ///
59 | /// Gets the name of the file.
60 | ///
61 | public string Name
62 | {
63 | get { return Path.GetFileName(this.FullName); }
64 | }
65 |
66 | ///
67 | /// Initializes a new instance of the class.
68 | ///
69 | /// The full name.
70 | /// The last write time.
71 | /// The length.
72 | /// The client.
73 | public FtpFileInfo(string fullName, DateTime lastWriteTime, long length, FtpClient client)
74 | {
75 | fullName.ThrowIfNull(() => fullName);
76 | client.ThrowIfNull(() => client);
77 |
78 | this.FullName = fullName;
79 | this.LastWriteTime = lastWriteTime;
80 | this.Length = length;
81 | this.client = client;
82 | }
83 | }
84 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Core/FileSystem/Ftp/FtpFileSystem.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Net;
4 | using FlagFtp;
5 | using Rareform.Extensions;
6 | using Rareform.IO;
7 | using FlagSync.Core.FileSystem.Base;
8 |
9 | namespace FlagSync.Core.FileSystem.Ftp
10 | {
11 | public class FtpFileSystem : IFileSystem
12 | {
13 | private readonly FtpClient client;
14 |
15 | ///
16 | /// Occurs when the file copy progress has changed.
17 | ///
18 | public event EventHandler FileCopyProgressChanged;
19 |
20 | ///
21 | /// Initializes a new instance of the class.
22 | ///
23 | /// The server address.
24 | /// The credentials.
25 | public FtpFileSystem(Uri serverAddress, NetworkCredential credentials)
26 | {
27 | serverAddress.ThrowIfNull(() => serverAddress);
28 | credentials.ThrowIfNull(() => credentials);
29 |
30 | this.client = new FtpClient(credentials);
31 | }
32 |
33 | ///
34 | /// Deletes the specified file.
35 | ///
36 | /// The file to delete.
37 | /// The file could not be accessed.
38 | /// The file is not of type .
39 | /// The file system is currently unavailable.
40 | public void DeleteFile(IFileInfo file)
41 | {
42 | file.ThrowIfNull(() => file);
43 |
44 | if (!(file is FtpFileInfo))
45 | throw new ArgumentException("The file must be of type FtpFileInfo.", "file");
46 |
47 | try
48 | {
49 | this.client.DeleteFile(new Uri(file.FullName));
50 | }
51 |
52 | catch (WebException ex)
53 | {
54 | switch (ex.Status)
55 | {
56 | case WebExceptionStatus.ConnectFailure:
57 | case WebExceptionStatus.ProxyNameResolutionFailure:
58 | throw new FileSystemUnavailableException("The FTP server is currently unavailable.", ex);
59 | }
60 |
61 | throw new AccessException("The file could not be accessed", ex);
62 | }
63 | }
64 |
65 | ///
66 | /// Creates the specified directory in the target directory.
67 | ///
68 | /// The source directory.
69 | /// The target directory.
70 | /// The directory could not be accessed.
71 | public void CreateDirectory(IDirectoryInfo sourceDirectory, IDirectoryInfo targetDirectory)
72 | {
73 | sourceDirectory.ThrowIfNull(() => sourceDirectory);
74 | targetDirectory.ThrowIfNull(() => targetDirectory);
75 |
76 | Uri newDirectory = (new Uri(new Uri(targetDirectory.FullName + "//"), sourceDirectory.Name));
77 |
78 | try
79 | {
80 | this.client.CreateDirectory(newDirectory);
81 | }
82 |
83 | catch (WebException ex)
84 | {
85 | switch (ex.Status)
86 | {
87 | case WebExceptionStatus.ConnectFailure:
88 | case WebExceptionStatus.ProxyNameResolutionFailure:
89 | throw new FileSystemUnavailableException("The FTP server is currently unavailable.", ex);
90 | }
91 |
92 | throw new AccessException("The directory could not be accessed", ex);
93 | }
94 | }
95 |
96 | ///
97 | /// Deletes the specified directory.
98 | ///
99 | /// The directory to delete.
100 | /// The directory could not be accessed.
101 | /// /// The directory is not of type .
102 | public void DeleteDirectory(IDirectoryInfo directory)
103 | {
104 | directory.ThrowIfNull(() => directory);
105 |
106 | if (!(directory is FtpDirectoryInfo))
107 | throw new ArgumentException("The directory must be of type FtpDirectoryInfo.", "directory");
108 |
109 | try
110 | {
111 | this.client.DeleteDirectory(new Uri(directory.FullName + "/"));
112 | }
113 |
114 | catch (WebException ex)
115 | {
116 | switch (ex.Status)
117 | {
118 | case WebExceptionStatus.ConnectFailure:
119 | case WebExceptionStatus.ProxyNameResolutionFailure:
120 | throw new FileSystemUnavailableException("The FTP server is currently unavailable.", ex);
121 | }
122 |
123 | throw new AccessException("The directory could not be accessed", ex);
124 | }
125 | }
126 |
127 | ///
128 | /// Copies the specified file to the target directory.
129 | ///
130 | /// The source file system.
131 | /// The source file.
132 | /// The target directory.
133 | /// The source file or target directory could not be accessed.
134 | /// /// The target directory is not of type .
135 | public void CopyFile(IFileSystem sourceFileSystem, IFileInfo sourceFile, IDirectoryInfo targetDirectory)
136 | {
137 | sourceFileSystem.ThrowIfNull(() => sourceFileSystem);
138 | sourceFile.ThrowIfNull(() => sourceFile);
139 | targetDirectory.ThrowIfNull(() => targetDirectory);
140 |
141 | if (!(targetDirectory is FtpDirectoryInfo))
142 | throw new ArgumentException("The target directory must be of type FtpDirectoryInfo.", "targetDirectory");
143 |
144 | Uri targetFilePath = new Uri(this.CombinePath(targetDirectory.FullName, sourceFile.Name));
145 |
146 | try
147 | {
148 | using (Stream sourceStream = sourceFileSystem.OpenFileStream(sourceFile))
149 | {
150 | using (Stream targetStream = this.client.OpenWrite(targetFilePath))
151 | {
152 | if (sourceFile.Length > 0)
153 | {
154 | var copyOperation = new StreamCopyOperation(sourceStream, targetStream, 8 * 1024, true);
155 |
156 | copyOperation.CopyProgressChanged +=
157 | (sender, e) => this.FileCopyProgressChanged.RaiseSafe(this, e);
158 |
159 | copyOperation.Execute();
160 | }
161 | }
162 | }
163 | }
164 |
165 | catch (WebException ex)
166 | {
167 | switch (ex.Status)
168 | {
169 | case WebExceptionStatus.ConnectFailure:
170 | case WebExceptionStatus.ProxyNameResolutionFailure:
171 | throw new FileSystemUnavailableException("The FTP server is currently unavailable.", ex);
172 | }
173 |
174 | throw new AccessException("The file could not be accessed", ex);
175 | }
176 | }
177 |
178 | ///
179 | /// Gets the file info at the specified path.
180 | ///
181 | /// The path of the file.
182 | ///
183 | /// An of the file from the specified path.
184 | ///
185 | public IFileInfo GetFileInfo(string path)
186 | {
187 | path.ThrowIfNull(() => path);
188 |
189 | path = FtpFileSystem.NormalizePath(path);
190 | FlagFtp.FtpFileInfo file = this.client.GetFileInfo(new Uri(path));
191 |
192 | return new FtpFileInfo(file.FullName, file.LastWriteTime, file.Length, this.client);
193 | }
194 |
195 | ///
196 | /// Gets the directory info at the specified path.
197 | ///
198 | /// The path of the directory.
199 | ///
200 | /// An of the directory from the specified path.
201 | ///
202 | public IDirectoryInfo GetDirectoryInfo(string path)
203 | {
204 | path.ThrowIfNull(() => path);
205 |
206 | path = FtpFileSystem.NormalizePath(path);
207 | FlagFtp.FtpDirectoryInfo directory = this.client.GetDirectoryInfo(new Uri(path));
208 |
209 | return new FtpDirectoryInfo(directory.FullName.Replace("%20", " "), this.client);
210 | }
211 |
212 | ///
213 | /// Determines if the file at the specified path exists.
214 | ///
215 | /// The path of the file.
216 | ///
217 | /// true, if the file exists; otherwise, false.
218 | ///
219 | public bool FileExists(string path)
220 | {
221 | path.ThrowIfNull(() => path);
222 |
223 | path = FtpFileSystem.NormalizePath(path);
224 | return this.client.FileExists(new Uri(path));
225 | }
226 |
227 | ///
228 | /// Determines if the directory at the specified path exists.
229 | ///
230 | /// The path of the directory.
231 | ///
232 | /// true, if the directory exists; otherwise, false.
233 | ///
234 | public bool DirectoryExists(string path)
235 | {
236 | path.ThrowIfNull(() => path);
237 |
238 | path = FtpFileSystem.NormalizePath(path);
239 | return this.client.DirectoryExists(new Uri(path));
240 | }
241 |
242 | ///
243 | /// Opens the stream of the specified file.
244 | ///
245 | /// The file.
246 | ///
247 | /// A stream from the specified file.
248 | ///
249 | public Stream OpenFileStream(IFileInfo file)
250 | {
251 | file.ThrowIfNull(() => file);
252 |
253 | return this.client.OpenRead(new Uri(file.FullName));
254 | }
255 |
256 | ///
257 | /// Combines two paths for the specific file system.
258 | ///
259 | /// The first path.
260 | /// The second path.
261 | ///
262 | /// A path, which is the combination of the first and second path.
263 | ///
264 | public string CombinePath(string path1, string path2)
265 | {
266 | path1.ThrowIfNull(() => path1);
267 | path2.ThrowIfNull(() => path2);
268 |
269 | return path1 + "/" + path2;
270 | }
271 |
272 | ///
273 | /// Normalizes the path.
274 | ///
275 | /// The path.
276 | ///
277 | /// A normalized representation of the path.
278 | ///
279 | private static string NormalizePath(string path)
280 | {
281 | path.ThrowIfNull(() => path);
282 |
283 | return path.Replace("//", "/").Replace("/", "//").Replace("\\", "//").Replace("%20", " ");
284 | }
285 | }
286 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Core/FileSystem/ITunes/ITunesDirectoryInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Diagnostics;
3 | using System.IO;
4 | using System.Linq;
5 | using Rareform.Extensions;
6 | using FlagSync.Core.FileSystem.Base;
7 |
8 | namespace FlagSync.Core.FileSystem.ITunes
9 | {
10 | ///
11 | /// Represents a directory in the iTunes filesystem.
12 | ///
13 | ///
14 | /// A directory in the iTunes filesystem is usually
15 | /// the representation of an artist or an album of a song.
16 | ///
17 | [DebuggerDisplay("{FullName}")]
18 | public class ITunesDirectoryInfo : IDirectoryInfo
19 | {
20 | private string name;
21 | private readonly bool isRoot;
22 | private readonly IEnumerable directories;
23 | private readonly IEnumerable files;
24 |
25 | ///
26 | /// Gets the parent directory.
27 | ///
28 | public IDirectoryInfo Parent { get; set; }
29 |
30 | ///
31 | /// Gets a value indicating whether the directory exists.
32 | ///
33 | ///
34 | /// true if the directory exists; otherwise, false.
35 | ///
36 | public bool Exists { get; private set; }
37 |
38 | ///
39 | /// Return the files in the directory.
40 | ///
41 | ///
42 | /// The files in the directory.
43 | ///
44 | ///
45 | /// The exception that is thrown if the directory is locked
46 | ///
47 | public IEnumerable GetFiles()
48 | {
49 | return this.files;
50 | }
51 |
52 | ///
53 | /// Return the directories in the directory.
54 | ///
55 | ///
56 | /// The directories in the directory
57 | ///
58 | ///
59 | /// The exception that is thrown if the directory is locked
60 | ///
61 | public IEnumerable GetDirectories()
62 | {
63 | if (this.isRoot)
64 | {
65 | return ITunesFileSystem.MapPlaylistToDirectoryStructure(this.name);
66 | }
67 |
68 | return this.directories;
69 | }
70 |
71 | ///
72 | /// Gets the full name of the directory.
73 | ///
74 | public string FullName
75 | {
76 | get { return this.isRoot ? this.name : Path.Combine(this.Parent.FullName, this.Name); }
77 | }
78 |
79 | ///
80 | /// Gets the name of the directory.
81 | ///
82 | public string Name
83 | {
84 | get { return this.name; }
85 | }
86 |
87 | ///
88 | /// Initializes a new instance of the class.
89 | /// The directory will be the root directory an a playlist.
90 | ///
91 | /// The name of the playlist.
92 | public ITunesDirectoryInfo(string playlistName)
93 | : this((ITunesDirectoryInfo)null)
94 | {
95 | playlistName.ThrowIfNull(() => playlistName);
96 |
97 | this.name = playlistName;
98 | this.isRoot = true;
99 | }
100 |
101 | ///
102 | /// Initializes a new instance of the class.
103 | /// The directory will be the last level of the directory structure and contains the files.
104 | ///
105 | /// The name of the album.
106 | /// The files that are contained in this directory.
107 | /// The parent.
108 | public ITunesDirectoryInfo(string albumName, IEnumerable files, ITunesDirectoryInfo parent)
109 | : this(parent)
110 | {
111 | albumName.ThrowIfNull(() => albumName);
112 | files.ThrowIfNull(() => files);
113 |
114 | this.name = albumName;
115 | this.files = files;
116 | }
117 |
118 | ///
119 | /// Initializes a new instance of the class.
120 | /// The directory will be the middle level of the directory structure and contains the album directories.
121 | ///
122 | /// The name of the artist.
123 | /// The directories that are contained in this directory.
124 | /// The parent.
125 | public ITunesDirectoryInfo(string artistName, IEnumerable directories, ITunesDirectoryInfo parent)
126 | : this(parent)
127 | {
128 | artistName.ThrowIfNull(() => artistName);
129 | directories.ThrowIfNull(() => directories);
130 |
131 | this.name = artistName;
132 | this.directories = directories;
133 | }
134 |
135 | ///
136 | /// Prevents a default instance of the class from being created.
137 | ///
138 | /// The parent directory.
139 | private ITunesDirectoryInfo(ITunesDirectoryInfo parent)
140 | {
141 | this.Parent = parent;
142 | this.files = Enumerable.Empty();
143 | this.directories = Enumerable.Empty();
144 | this.Exists = true;
145 | }
146 |
147 | ///
148 | /// Creates an iTunes directory info which does not exist.
149 | ///
150 | /// The name of the directory.
151 | /// The parent directory.
152 | /// A directory whichs property is set to false.
153 | public static ITunesDirectoryInfo CreateNonExistantDirectoryInfo(string name, ITunesDirectoryInfo parent)
154 | {
155 | name.ThrowIfNull(() => name);
156 | parent.ThrowIfNull(() => parent);
157 |
158 | var directory = new ITunesDirectoryInfo(parent) { name = name, Exists = false };
159 |
160 | return directory;
161 | }
162 | }
163 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Core/FileSystem/ITunes/ITunesFileSystem.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices;
6 | using Rareform.Extensions;
7 | using Rareform.IO;
8 | using Rareform.Reflection;
9 | using FlagSync.Core.FileSystem.Base;
10 | using FlagSync.Core.FileSystem.Local;
11 | using iTunesLib;
12 |
13 | namespace FlagSync.Core.FileSystem.ITunes
14 | {
15 | ///
16 | /// Represents the file system of an iTunes playlist
17 | ///
18 | public class ITunesFileSystem : IFileSystem
19 | {
20 | private IEnumerable playlistStructureChache;
21 |
22 | ///
23 | /// Occurs when the file copy progress has changed.
24 | ///
25 | public event EventHandler FileCopyProgressChanged;
26 |
27 | ///
28 | /// Deletes the specified file. This method always throws a .
29 | ///
30 | /// The file to delete.
31 | /// The file could not be accessed.
32 | /// This method is not supported.
33 | public void DeleteFile(IFileInfo file)
34 | {
35 | throw new NotSupportedException();
36 | }
37 |
38 | ///
39 | /// Creates the specified directory in the target directory. This method always throws a .
40 | ///
41 | /// The source directory.
42 | /// The target directory.
43 | /// The directory could not be accessed.
44 | /// This method is not supported.
45 | public void CreateDirectory(IDirectoryInfo sourceDirectory, IDirectoryInfo targetDirectory)
46 | {
47 | throw new NotSupportedException();
48 | }
49 |
50 | ///
51 | /// Deletes the specified directory. This method always throws a .
52 | ///
53 | /// The directory to delete.
54 | /// The directory could not be accessed.
55 | /// This method is not supported.
56 | public void DeleteDirectory(IDirectoryInfo directory)
57 | {
58 | throw new NotSupportedException();
59 | }
60 |
61 | ///
62 | /// Copies the specified file to the target directory. This method always throws a .
63 | ///
64 | /// The source file system.
65 | /// The source file.
66 | /// The target directory.
67 | /// The source file or target directory could not be accessed.
68 | /// This method is not supported.
69 | public void CopyFile(IFileSystem sourceFileSystem, IFileInfo sourceFile, IDirectoryInfo targetDirectory)
70 | {
71 | throw new NotSupportedException();
72 | }
73 |
74 | ///
75 | /// Gets the file info at the specified path.
76 | ///
77 | /// The path of the file.
78 | ///
79 | /// An of the file from the specified path.
80 | ///
81 | public IFileInfo GetFileInfo(string path)
82 | {
83 | path.ThrowIfNull(() => path);
84 |
85 | string[] split = path.Split(Path.DirectorySeparatorChar);
86 |
87 | if (split.Length < 4)
88 | throw new ArgumentException("The path is not valid.", "path");
89 |
90 | string playlist = split[0];
91 | string artist = split[1];
92 | string album = split[2];
93 | string title = split[3];
94 |
95 | var root = this.GetPlaylistStructure(playlist);
96 |
97 | IFileInfo fileInfo = root
98 | .Single(dir => dir.Name == artist)
99 | .GetDirectories()
100 | .Single(albumDir => albumDir.Name == album)
101 | .GetFiles()
102 | .Single(file => file.Name == title);
103 |
104 | return fileInfo;
105 | }
106 |
107 | ///
108 | /// Gets the directory info at the specified path.
109 | ///
110 | /// The path of the directory.
111 | ///
112 | /// An of the directory from the specified path.
113 | ///
114 | public IDirectoryInfo GetDirectoryInfo(string path)
115 | {
116 | path.ThrowIfNull(() => path);
117 |
118 | if (!this.DirectoryExists(path))
119 | {
120 | return ITunesDirectoryInfo
121 | .CreateNonExistantDirectoryInfo(Path.GetFileName(path), (ITunesDirectoryInfo)this.GetDirectoryInfo(Path.GetDirectoryName(path)));
122 | }
123 |
124 | string[] split = path.Split(Path.DirectorySeparatorChar);
125 |
126 | string playlist = split[0];
127 | string album = null;
128 |
129 | if (split.Length > 1)
130 | {
131 | string artist = split[1];
132 |
133 | if (split.Length > 2)
134 | {
135 | album = split[2];
136 | }
137 |
138 | var root = this.GetPlaylistStructure(playlist);
139 |
140 | IDirectoryInfo directoryInfo = root
141 | .SingleOrDefault(dir => dir.Name == artist);
142 |
143 | if (directoryInfo == null)
144 | {
145 | directoryInfo = ITunesDirectoryInfo
146 | .CreateNonExistantDirectoryInfo(album ?? artist, (ITunesDirectoryInfo)this.GetDirectoryInfo(Path.GetDirectoryName(path)));
147 | }
148 |
149 | else if (album != null)
150 | {
151 | directoryInfo = directoryInfo
152 | .GetDirectories()
153 | .Single(albumDir => albumDir.Name == album);
154 | }
155 |
156 | return directoryInfo;
157 | }
158 |
159 | return new ITunesDirectoryInfo(playlist);
160 | }
161 |
162 | ///
163 | /// Determines if the file at the specified path exists.
164 | ///
165 | /// The path of the file.
166 | ///
167 | /// true, if the file exists; otherwise, false.
168 | ///
169 | public bool FileExists(string path)
170 | {
171 | path.ThrowIfNull(() => path);
172 |
173 | string[] split = path.Split(Path.DirectorySeparatorChar);
174 |
175 | if (split.Length < 4)
176 | return false;
177 |
178 | string playlist = split[0];
179 | string artist = split[1];
180 | string album = split[2];
181 | string title = split[3];
182 |
183 | try
184 | {
185 | var root = this.GetPlaylistStructure(playlist);
186 |
187 | var artistDirectory = root.SingleOrDefault(dir => dir.Name == artist);
188 |
189 | if (artistDirectory != null)
190 | {
191 | var albumDirectory = artistDirectory
192 | .GetDirectories()
193 | .SingleOrDefault(albumDir => albumDir.Name == album);
194 |
195 | if (albumDirectory != null)
196 | {
197 | return albumDirectory
198 | .GetFiles()
199 | .Any(file => file.Name == title);
200 | }
201 | }
202 | }
203 |
204 | catch (COMException)
205 | {
206 | return false;
207 | }
208 |
209 | return false;
210 | }
211 |
212 | ///
213 | /// Determines if the directory at the specified path exists.
214 | ///
215 | /// The path of the directory.
216 | ///
217 | /// true, if the directory exists; otherwise, false.
218 | ///
219 | public bool DirectoryExists(string path)
220 | {
221 | path.ThrowIfNull(() => path);
222 |
223 | string[] split = path.Split(Path.DirectorySeparatorChar);
224 |
225 | if (split.Length == 1)
226 | {
227 | return PlaylistExists(split[0]);
228 | }
229 |
230 | string playlist = split[0];
231 | string artist = split[1];
232 |
233 | string album = null;
234 |
235 | if (split.Length > 2)
236 | {
237 | album = split[2];
238 | }
239 |
240 | try
241 | {
242 | var root = this.GetPlaylistStructure(playlist);
243 |
244 | if (album == null)
245 | {
246 | return root.Any(artistDir => artistDir.Name == artist);
247 | }
248 |
249 | var artistDirectory = root.SingleOrDefault(artistDir => artistDir.Name == artist);
250 |
251 | if (artistDirectory != null)
252 | {
253 | return artistDirectory
254 | .GetDirectories()
255 | .Any(albumDir => albumDir.Name == album);
256 | }
257 |
258 | return false;
259 | }
260 |
261 | catch (COMException)
262 | {
263 | return false;
264 | }
265 | }
266 |
267 | ///
268 | /// Opens the stream of the specified file.
269 | ///
270 | /// The file.
271 | ///
272 | /// A stream from the specified file.
273 | ///
274 | public Stream OpenFileStream(IFileInfo file)
275 | {
276 | file.ThrowIfNull(() => file);
277 |
278 | return File.Open(file.FullName, FileMode.Open, FileAccess.Read);
279 | }
280 |
281 | ///
282 | /// Combines two paths for the specific file system. This method always throws a .
283 | ///
284 | /// The first path.
285 | /// The second path.
286 | ///
287 | /// A path, which is the combination of the first and second path.
288 | ///
289 | public string CombinePath(string path1, string path2)
290 | {
291 | throw new NotSupportedException();
292 | }
293 |
294 | ///
295 | /// Maps the specified iTunes playlist to a directory structure.
296 | ///
297 | /// The playlist.
298 | /// A directory structure which represents the specified iTunes playlist
299 | public static IEnumerable MapPlaylistToDirectoryStructure(string playlistName)
300 | {
301 | if (String.IsNullOrEmpty(playlistName))
302 | throw new ArgumentException("The playlist name name cannot be null or empty", Reflector.GetMemberName(() => playlistName));
303 |
304 | var root = new ITunesDirectoryInfo(playlistName);
305 |
306 | var files = new iTunesApp()
307 | .LibrarySource
308 | .Playlists
309 | .ItemByName[playlistName]
310 | .Tracks
311 | .Cast();
312 |
313 | var tracksByArtist = files
314 | .GroupBy(file => file.Artist)
315 | .OrderBy(group => group.Key);
316 |
317 | var artistDirectories = new List();
318 |
319 | foreach (var artistGroup in tracksByArtist)
320 | {
321 | var albumGroups = artistGroup
322 | .GroupBy(track => track.Album);
323 |
324 | // The artist name has to be normalized, so that it doesn't contain any characters that are invalid for a path
325 | string artistName = NormalizeArtistOrAlbumName(artistGroup.Key);
326 |
327 | var albumDirectories = albumGroups
328 | .Select(album => new { Album = album, AlbumName = NormalizeArtistOrAlbumName(album.Key) })
329 | .Select
330 | (
331 | directory =>
332 | new ITunesDirectoryInfo
333 | (
334 | directory.AlbumName,
335 | directory.Album
336 | .Where(track => track.Location != null)
337 | .Select
338 | (
339 | track => (IFileInfo)new LocalFileInfo(new FileInfo(track.Location))
340 | ),
341 | null
342 | )
343 | )
344 | .ToList(); //Execute the query immediately, because a streaming causes weird bugs
345 |
346 | var artistDirectory = new ITunesDirectoryInfo(artistName, albumDirectories, root);
347 |
348 | foreach (ITunesDirectoryInfo albumDirectory in artistDirectory.GetDirectories())
349 | {
350 | albumDirectory.Parent = artistDirectory;
351 | }
352 |
353 | artistDirectories.Add(artistDirectory);
354 | }
355 |
356 | return artistDirectories;
357 | }
358 |
359 | ///
360 | /// Normalizes the name of the artist or album.
361 | ///
362 | /// Name of the artist or album.
363 | /// A normalized form of the artist or album string
364 | private static string NormalizeArtistOrAlbumName(string artistOrAlbumName)
365 | {
366 | artistOrAlbumName.ThrowIfNull(() => artistOrAlbumName);
367 |
368 | var invalidCharacters = Path.GetInvalidPathChars().Concat(Path.GetInvalidFileNameChars()).Distinct();
369 |
370 | foreach (char invalidCharacter in invalidCharacters)
371 | {
372 | artistOrAlbumName = artistOrAlbumName.Replace(invalidCharacter.ToString(), string.Empty);
373 | }
374 |
375 | return artistOrAlbumName;
376 | }
377 |
378 | ///
379 | /// Determines, if the playlist with the specified name exists.
380 | ///
381 | /// Th name of the playlist.
382 | /// True, if the playlist exists; otherwise, false.
383 | private static bool PlaylistExists(string playlistName)
384 | {
385 | var playlist = new iTunesApp()
386 | .LibrarySource
387 | .Playlists
388 | .ItemByName[playlistName];
389 |
390 | return playlist != null;
391 | }
392 |
393 | ///
394 | /// Gets the structure of the specified playlist.
395 | ///
396 | /// The playlist.
397 | /// A wich represents the playlist structure.
398 | private IEnumerable GetPlaylistStructure(string playlistName)
399 | {
400 | if (String.IsNullOrEmpty(playlistName))
401 | throw new ArgumentException("The playlist name cannot be empty", Reflector.GetMemberName(() => playlistName));
402 |
403 | if (this.playlistStructureChache == null)
404 | {
405 | this.playlistStructureChache = MapPlaylistToDirectoryStructure(playlistName);
406 | }
407 |
408 | return playlistStructureChache;
409 | }
410 | }
411 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Core/FileSystem/Local/LocalDirectoryInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Diagnostics;
3 | using System.IO;
4 | using System.Linq;
5 | using FlagSync.Core.FileSystem.Base;
6 |
7 | namespace FlagSync.Core.FileSystem.Local
8 | {
9 | ///
10 | /// Represents a directory in the local filesystem.
11 | ///
12 | ///
13 | /// The class is basically a wrapper around
14 | /// the class and abstracts it to be
15 | /// used as an .
16 | ///
17 | [DebuggerDisplay("{FullName}")]
18 | public class LocalDirectoryInfo : IDirectoryInfo
19 | {
20 | private readonly DirectoryInfo directoryInfo;
21 |
22 | ///
23 | /// Gets the parent directory.
24 | ///
25 | public IDirectoryInfo Parent
26 | {
27 | get { return new LocalDirectoryInfo(this.directoryInfo.Parent); }
28 | }
29 |
30 | ///
31 | /// Gets the full name of the directory.
32 | ///
33 | public string FullName
34 | {
35 | get { return this.directoryInfo.FullName; }
36 | }
37 |
38 | ///
39 | /// Gets the name of the directory.
40 | ///
41 | public string Name
42 | {
43 | get { return this.directoryInfo.Name; }
44 | }
45 |
46 | ///
47 | /// Gets a value indicating whether the directory exists.
48 | ///
49 | ///
50 | /// true if the directory exists; otherwise, false.
51 | ///
52 | public bool Exists
53 | {
54 | get { return this.directoryInfo.Exists; }
55 | }
56 |
57 | ///
58 | /// Initializes a new instance of the class.
59 | ///
60 | /// The directory info to wrap.
61 | public LocalDirectoryInfo(DirectoryInfo directoryInfo)
62 | {
63 | //Don't check for null here
64 |
65 | this.directoryInfo = directoryInfo;
66 | }
67 |
68 | ///
69 | /// Returns a list of all files in the directory.
70 | ///
71 | ///
72 | /// The files in the directory.
73 | ///
74 | ///
75 | /// The exception that is thrown if the directory is locked
76 | ///
77 | public IEnumerable GetFiles()
78 | {
79 | return this.directoryInfo
80 | .GetFiles()
81 | .Select(file => (IFileInfo)new LocalFileInfo(file));
82 | }
83 |
84 | ///
85 | /// Returns a list of all directories in the directory.
86 | ///
87 | ///
88 | /// The directories in the directory.
89 | ///
90 | ///
91 | /// The exception that is thrown if the directory is locked.
92 | ///
93 | public IEnumerable GetDirectories()
94 | {
95 | return this.directoryInfo
96 | .GetDirectories()
97 | .Select(directory => (IDirectoryInfo)new LocalDirectoryInfo(directory));
98 | }
99 | }
100 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Core/FileSystem/Local/LocalFileInfo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.IO;
4 | using Rareform.Extensions;
5 | using FlagSync.Core.FileSystem.Base;
6 |
7 | namespace FlagSync.Core.FileSystem.Local
8 | {
9 | ///
10 | /// Represents a file on the local file system.
11 | ///
12 | ///
13 | /// The class is basically a wrapper around
14 | /// the class and abstracts it to be
15 | /// used as an .
16 | ///
17 | [DebuggerDisplay("{FullName}")]
18 | public class LocalFileInfo : IFileInfo
19 | {
20 | private readonly FileInfo fileInfo;
21 |
22 | ///
23 | /// Gets the last write time.
24 | ///
25 | public DateTime LastWriteTime
26 | {
27 | get { return this.fileInfo.LastWriteTime; }
28 | }
29 |
30 | ///
31 | /// Gets the length of the file.
32 | ///
33 | public long Length
34 | {
35 | get { return this.fileInfo.Length; }
36 | }
37 |
38 | ///
39 | /// Gets the full name of the file.
40 | ///
41 | public string FullName
42 | {
43 | get { return this.fileInfo.FullName; }
44 | }
45 |
46 | ///
47 | /// Gets the name of the file.
48 | ///
49 | public string Name
50 | {
51 | get { return this.fileInfo.Name; }
52 | }
53 |
54 | ///
55 | /// Gets the directory.
56 | ///
57 | public IDirectoryInfo Directory
58 | {
59 | get { return new LocalDirectoryInfo(this.fileInfo.Directory); }
60 | }
61 |
62 | ///
63 | /// Gets a value indicating whether the file exists.
64 | ///
65 | ///
66 | /// true if the file exists; otherwise, false.
67 | ///
68 | public bool Exists
69 | {
70 | get { return this.fileInfo.Exists; }
71 | }
72 |
73 | ///
74 | /// Initializes a new instance of the class.
75 | ///
76 | /// The file info to wrap.
77 | public LocalFileInfo(FileInfo fileInfo)
78 | {
79 | fileInfo.ThrowIfNull(() => fileInfo);
80 |
81 | this.fileInfo = fileInfo;
82 | }
83 | }
84 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Core/FileSystem/Local/LocalFileSystem.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Security;
4 | using Rareform.Extensions;
5 | using Rareform.IO;
6 | using FlagSync.Core.FileSystem.Base;
7 |
8 | namespace FlagSync.Core.FileSystem.Local
9 | {
10 | public class LocalFileSystem : IFileSystem
11 | {
12 | ///
13 | /// Occurs when the file copy progress has changed.
14 | ///
15 | public event EventHandler FileCopyProgressChanged;
16 |
17 | ///
18 | /// Deletes the specified file.
19 | ///
20 | /// The file to delete.
21 | /// The file could not be accessed.
22 | public void DeleteFile(IFileInfo file)
23 | {
24 | file.ThrowIfNull(() => file);
25 |
26 | if (!(file is LocalFileInfo))
27 | throw new ArgumentException("The file must be of type LocalFileInfo.", "file");
28 |
29 | try
30 | {
31 | File.SetAttributes(file.FullName, FileAttributes.Normal);
32 | File.Delete(file.FullName);
33 | }
34 |
35 | catch (IOException ex)
36 | {
37 | throw new AccessException("The file could not be accessed.", ex);
38 | }
39 |
40 | catch (SecurityException ex)
41 | {
42 | throw new AccessException("The file could not be accessed.", ex);
43 | }
44 |
45 | catch (UnauthorizedAccessException ex)
46 | {
47 | throw new AccessException("The file could not be accessed.", ex);
48 | }
49 | }
50 |
51 | ///
52 | /// Creates the specified directory in the target directory.
53 | ///
54 | /// The source directory.
55 | /// The target directory.
56 | /// The directory could not be accessed.
57 | public void CreateDirectory(IDirectoryInfo sourceDirectory, IDirectoryInfo targetDirectory)
58 | {
59 | sourceDirectory.ThrowIfNull(() => sourceDirectory);
60 | targetDirectory.ThrowIfNull(() => targetDirectory);
61 |
62 | try
63 | {
64 | Directory.CreateDirectory(this.CombinePath(targetDirectory.FullName, sourceDirectory.Name));
65 | }
66 |
67 | catch (DirectoryNotFoundException ex)
68 | {
69 | throw new AccessException("The file could not be accessed.", ex);
70 | }
71 |
72 | catch (PathTooLongException ex)
73 | {
74 | throw new AccessException("The file could not be accessed.", ex);
75 | }
76 |
77 | catch (IOException ex)
78 | {
79 | throw new AccessException("The file could not be accessed.", ex);
80 | }
81 |
82 | catch (UnauthorizedAccessException ex)
83 | {
84 | throw new AccessException(ex.Message, ex);
85 | }
86 | }
87 |
88 | ///
89 | /// Deletes the specified directory.
90 | ///
91 | /// The directory to delete.
92 | /// The directory could not be accessed.
93 | public void DeleteDirectory(IDirectoryInfo directory)
94 | {
95 | directory.ThrowIfNull(() => directory);
96 |
97 | if (!(directory is LocalDirectoryInfo))
98 | throw new ArgumentException("The directory must be of type LocalDirectoryInfo.", "directory");
99 |
100 | try
101 | {
102 | Directory.Delete(directory.FullName, true);
103 | }
104 |
105 | catch (DirectoryNotFoundException ex)
106 | {
107 | throw new AccessException("The file could not be accessed.", ex);
108 | }
109 |
110 | catch (IOException ex)
111 | {
112 | throw new AccessException("The file could not be accessed.", ex);
113 | }
114 |
115 | catch (UnauthorizedAccessException ex)
116 | {
117 | throw new AccessException("The file could not be accessed.", ex);
118 | }
119 | }
120 |
121 | ///
122 | /// Copies the specified file to the target directory.
123 | ///
124 | /// The source file system.
125 | /// The source file.
126 | /// The target directory.
127 | /// The source file or target directory could not be accessed.
128 | public void CopyFile(IFileSystem sourceFileSystem, IFileInfo sourceFile, IDirectoryInfo targetDirectory)
129 | {
130 | sourceFileSystem.ThrowIfNull(() => sourceFileSystem);
131 | sourceFile.ThrowIfNull(() => sourceFile);
132 | targetDirectory.ThrowIfNull(() => targetDirectory);
133 |
134 | if (!(targetDirectory is LocalDirectoryInfo))
135 | throw new ArgumentException("The target directory must be of type LocalDirectoryInfo.", "targetDirectory");
136 |
137 | try
138 | {
139 | using (Stream sourceStream = sourceFileSystem.OpenFileStream(sourceFile))
140 | {
141 | string targetFilePath = this.CombinePath(targetDirectory.FullName, sourceFile.Name);
142 |
143 | try
144 | {
145 | using (FileStream targetStream = File.Create(targetFilePath))
146 | {
147 | if (sourceFile.Length > 0)
148 | {
149 | var copyOperation = new StreamCopyOperation(sourceStream, targetStream, 256 * 1024, true);
150 |
151 | copyOperation.CopyProgressChanged +=
152 | (sender, e) => this.FileCopyProgressChanged.RaiseSafe(this, e);
153 |
154 | copyOperation.Execute();
155 | }
156 | }
157 | }
158 |
159 | catch (IOException)
160 | {
161 | File.Delete(targetFilePath);
162 |
163 | throw;
164 | }
165 | }
166 | }
167 |
168 | catch (UnauthorizedAccessException ex)
169 | {
170 | throw new AccessException("The file could not be accessed.", ex);
171 | }
172 |
173 | catch (SecurityException ex)
174 | {
175 | throw new AccessException("The file could not be accessed.", ex);
176 | }
177 |
178 | catch (IOException ex)
179 | {
180 | throw new AccessException("The file could not be accessed.", ex);
181 | }
182 | }
183 |
184 | ///
185 | /// Gets the file info at the specified path.
186 | ///
187 | /// The path of the file.
188 | ///
189 | /// An of the file from the specified path.
190 | ///
191 | public IFileInfo GetFileInfo(string path)
192 | {
193 | path.ThrowIfNull(() => path);
194 |
195 | return new LocalFileInfo(new FileInfo(path));
196 | }
197 |
198 | ///
199 | /// Gets the directory info at the specified path.
200 | ///
201 | /// The path of the directory.
202 | ///
203 | /// An of the directory from the specified path.
204 | ///
205 | public IDirectoryInfo GetDirectoryInfo(string path)
206 | {
207 | path.ThrowIfNull(() => path);
208 |
209 | return new LocalDirectoryInfo(new DirectoryInfo(path));
210 | }
211 |
212 | ///
213 | /// Determines if the file at the specified path exists.
214 | ///
215 | /// The path of the file.
216 | ///
217 | /// true, if the file exists; otherwise, false.
218 | ///
219 | public bool FileExists(string path)
220 | {
221 | path.ThrowIfNull(() => path);
222 |
223 | return File.Exists(path);
224 | }
225 |
226 | ///
227 | /// Determines if the directory at the specified path exists.
228 | ///
229 | /// The path of the directory.
230 | ///
231 | /// true, if the directory exists; otherwise, false.
232 | ///
233 | public bool DirectoryExists(string path)
234 | {
235 | path.ThrowIfNull(() => path);
236 |
237 | return Directory.Exists(path);
238 | }
239 |
240 | ///
241 | /// Opens the stream of the specified file.
242 | ///
243 | /// The file.
244 | ///
245 | /// A stream from the specified file.
246 | ///
247 | public Stream OpenFileStream(IFileInfo file)
248 | {
249 | file.ThrowIfNull(() => file);
250 |
251 | return File.Open(file.FullName, FileMode.Open, FileAccess.Read);
252 | }
253 |
254 | ///
255 | /// Combines two paths for the specific file system.
256 | ///
257 | /// The first path.
258 | /// The second path.
259 | ///
260 | /// A path, which is the combination of the first and second path.
261 | ///
262 | public string CombinePath(string path1, string path2)
263 | {
264 | path1.ThrowIfNull(() => path1);
265 | path2.ThrowIfNull(() => path2);
266 |
267 | return Path.Combine(path1, path2);
268 | }
269 | }
270 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Core/FlagSync.Core.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | 8.0.30703
7 | 2.0
8 | {1149F3C5-DBFE-4CFD-98F6-DB396343E647}
9 | Library
10 | Properties
11 | FlagSync.Core
12 | FlagSync.Core
13 | v4.0
14 | 512
15 | Client
16 |
17 |
18 | true
19 | bin\Debug\
20 | x86
21 | bin\Debug\FlagSync.Core.dll.CodeAnalysisLog.xml
22 | true
23 | GlobalSuppressions.cs
24 | AllRules.ruleset
25 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets
26 | false
27 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules
28 | true
29 |
30 |
31 | bin\Release\
32 | x86
33 | bin\Release\FlagSync.Core.dll.CodeAnalysisLog.xml
34 | true
35 | GlobalSuppressions.cs
36 | MinimumRecommendedRules.ruleset
37 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets
38 | false
39 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules
40 | true
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 | ..\packages\FlagFtp.0.1.2\lib\FlagFtp.dll
79 |
80 |
81 | False
82 | ..\packages\Rareform.1.2.0\lib\Rareform.dll
83 |
84 |
85 |
86 |
87 |
88 | {9E93C96F-CF0D-43F6-8BA8-B807A3370712}
89 | 1
90 | 13
91 | 0
92 | tlbimp
93 | False
94 | True
95 |
96 |
97 |
98 |
99 |
100 |
101 |
108 |
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Core/JobEventArgs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Rareform.Extensions;
3 |
4 | namespace FlagSync.Core
5 | {
6 | ///
7 | /// Provides data for events of the class.
8 | ///
9 | public class JobEventArgs : EventArgs
10 | {
11 | ///
12 | /// Gets the job.
13 | ///
14 | public Job Job { get; private set; }
15 |
16 | ///
17 | /// Initializes a new instance of the class.
18 | ///
19 | /// The job.
20 | public JobEventArgs(Job job)
21 | {
22 | job.ThrowIfNull(() => job);
23 |
24 | this.Job = job;
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Core/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | // Allgemeine Informationen über eine Assembly werden über die folgenden
5 | // Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
6 | // die mit einer Assembly verknüpft sind.
7 | [assembly: AssemblyTitle("FlagSync.Core")]
8 | [assembly: AssemblyDescription("Synchronization & Backup Core")]
9 | [assembly: AssemblyConfiguration("")]
10 | [assembly: AssemblyCompany("")]
11 | [assembly: AssemblyProduct("FlagSync.Core")]
12 | [assembly: AssemblyCopyright("")]
13 | [assembly: AssemblyTrademark("")]
14 | [assembly: AssemblyCulture("")]
15 |
16 | // Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar
17 | // für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von
18 | // COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest.
19 | [assembly: ComVisible(false)]
20 |
21 | // Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
22 | [assembly: Guid("b4db4066-eaaa-4f11-b92f-2f1bd0397a5c")]
23 |
24 | // Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
25 | //
26 | // Hauptversion
27 | // Nebenversion
28 | // Buildnummer
29 | // Revision
30 | //
31 | // Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern
32 | // übernehmen, indem Sie "*" eingeben:
33 | // [assembly: AssemblyVersion("1.0.*")]
34 | [assembly: AssemblyVersion("2.4.2")]
35 | [assembly: AssemblyFileVersion("2.4.2")]
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Core/SyncJob.cs:
--------------------------------------------------------------------------------
1 | using FlagSync.Core.FileSystem.Base;
2 |
3 | namespace FlagSync.Core
4 | {
5 | public class SyncJob : Job
6 | {
7 | ///
8 | /// Initializes a new instance of the class.
9 | ///
10 | /// The name of the job.
11 | /// The file system A.
12 | /// The file system B.
13 | /// The directory A.
14 | /// The directory B.
15 | public SyncJob(string name, IFileSystem fileSystemA, IFileSystem fileSystemB, IDirectoryInfo directoryA, IDirectoryInfo directoryB)
16 | : base(name, fileSystemA, fileSystemB, directoryA, directoryB) { }
17 |
18 | ///
19 | /// Starts the job, opies new and modified files from directory A to directory B and then switches the direction.
20 | ///
21 | /// if set to true a preview will be performed.
22 | public override void Start(bool preview)
23 | {
24 | this.BackupDirectoryRecursively(this.DirectoryA, this.DirectoryB, !preview);
25 | this.BackupDirectoryRecursively(this.DirectoryB, this.DirectoryA, !preview);
26 |
27 | this.OnFinished(System.EventArgs.Empty);
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Core/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Data/CorruptSaveFileException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace FlagSync.Data
4 | {
5 | public class CorruptSaveFileException : Exception
6 | {
7 | public CorruptSaveFileException(string message, Exception innerException)
8 | : base(message, innerException)
9 | { }
10 | }
11 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Data/DataController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.IO;
5 | using System.Linq;
6 | using System.Net;
7 | using FlagSync.Core;
8 | using FlagSync.Core.FileSystem.Base;
9 | using Rareform.Serialization;
10 |
11 | namespace FlagSync.Data
12 | {
13 | ///
14 | /// Provides methods for data-access.
15 | ///
16 | public static class DataController
17 | {
18 | ///
19 | /// Gets the app data folder path.
20 | ///
21 | public static string AppDataFolderPath
22 | {
23 | get
24 | {
25 | return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "FlagSync");
26 | }
27 | }
28 |
29 | ///
30 | /// Creates the app data folder.
31 | ///
32 | public static void CreateAppDataFolder()
33 | {
34 | Directory.CreateDirectory(DataController.AppDataFolderPath);
35 | }
36 |
37 | ///
38 | /// Determines whether the iTunes application is opened.
39 | ///
40 | ///
41 | /// true if the iTunes application is opened; otherwise, false.
42 | ///
43 | public static bool IsITunesOpened()
44 | {
45 | return Process.GetProcessesByName("iTunes").Any();
46 | }
47 |
48 | ///
49 | /// Determines whether a new version of this application is available.
50 | ///
51 | /// The current version of the application.
52 | ///
53 | /// true if a new version of this application is available; otherwise, false.
54 | ///
55 | public static bool IsNewVersionAvailable(Version currentVersion)
56 | {
57 | var client = new WebClient();
58 | string versionString;
59 |
60 | try
61 | {
62 | Debug.WriteLine("Checking for newer version...");
63 | versionString = client.DownloadString("http://flagbug.bitbucket.org/flagsyncversion");
64 | Debug.WriteLine("Version on server is " + versionString);
65 | }
66 |
67 | catch (WebException)
68 | {
69 | Debug.WriteLine("Exception while retrieving the new version.");
70 | return false;
71 | }
72 |
73 | var webVersion = new Version(versionString);
74 |
75 | Debug.WriteLine("Current version is " + currentVersion);
76 |
77 | bool newVersionAvailable = webVersion > currentVersion;
78 |
79 | Debug.WriteLine("New version available: " + newVersionAvailable);
80 |
81 | return newVersionAvailable;
82 | }
83 |
84 | ///
85 | /// Tries the load the job settings from the specified path.
86 | ///
87 | /// The path to the file with the serialized setzings.
88 | /// The save file is in an invalid state.
89 | /// The iTunes process is not started..
90 | ///
91 | /// The result of the operation.
92 | ///
93 | public static IEnumerable LoadJobSettings(string path)
94 | {
95 | IEnumerable settings;
96 |
97 | try
98 | {
99 | settings = GenericXmlSerializer.DeserializeCollection(path);
100 | }
101 |
102 | catch (InvalidOperationException ex)
103 | {
104 | throw new CorruptSaveFileException("The save file is corrupt.", ex);
105 | }
106 |
107 | if (settings.Any(setting => setting.FirstFileSystemSetting is ITunesFileSystemSetting && !DataController.IsITunesOpened()))
108 | {
109 | throw new ITunesNotOpenedException("iTunes is not opened.");
110 | }
111 |
112 | return settings;
113 | }
114 |
115 | ///
116 | /// Saves the job settings to the specified path.
117 | ///
118 | /// The settings.
119 | /// The path.
120 | public static void SaveJobSettings(IEnumerable settings, string path)
121 | {
122 | GenericXmlSerializer.SerializeCollection(settings.ToList(), path);
123 | }
124 |
125 | ///
126 | /// Creates a job from the specified job setting.
127 | ///
128 | /// The job setting.
129 | ///
130 | /// A job that is created from the specified job setting.
131 | ///
132 | public static Job CreateJobFromSetting(JobSetting setting)
133 | {
134 | IFileSystem firstFileSystem = setting.FirstFileSystemSetting.GetFileSystem();
135 | IFileSystem secondFileSystem = setting.SecondFileSystemSetting.GetFileSystem();
136 |
137 | IDirectoryInfo firstRootDirectory = setting.FirstFileSystemSetting.GetRootDirectory();
138 | IDirectoryInfo secondRootDirectory = setting.SecondFileSystemSetting.GetRootDirectory();
139 |
140 | switch (setting.SyncMode)
141 | {
142 | case SyncMode.Backup:
143 | return new BackupJob(setting.Name, firstFileSystem, secondFileSystem, firstRootDirectory, secondRootDirectory);
144 |
145 | case SyncMode.Synchronization:
146 | return new SyncJob(setting.Name, firstFileSystem, secondFileSystem, firstRootDirectory, secondRootDirectory);
147 | }
148 |
149 | throw new InvalidOperationException();
150 | }
151 | }
152 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Data/FileSystemSetting.cs:
--------------------------------------------------------------------------------
1 | using FlagSync.Core.FileSystem.Base;
2 |
3 | namespace FlagSync.Data
4 | {
5 | public abstract class FileSystemSetting
6 | {
7 | public string Source { get; set; }
8 |
9 | public abstract IFileSystem GetFileSystem();
10 |
11 | public abstract IDirectoryInfo GetRootDirectory();
12 | }
13 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Data/FlagSync.Data.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | 8.0.30703
7 | 2.0
8 | {080FB9A0-A2F9-438F-8F84-60B7FB448633}
9 | Library
10 | Properties
11 | FlagSync.Data
12 | FlagSync.Data
13 | v4.0
14 | 512
15 | Client
16 |
17 |
18 | true
19 | bin\x86\Debug\
20 | DEBUG;TRACE
21 | full
22 | x86
23 | bin\Debug\FlagSync.Data.dll.CodeAnalysisLog.xml
24 | true
25 | GlobalSuppressions.cs
26 | prompt
27 | MinimumRecommendedRules.ruleset
28 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets
29 | true
30 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules
31 | true
32 |
33 |
34 | bin\x86\Release\
35 | TRACE
36 | true
37 | pdbonly
38 | x86
39 | bin\Release\FlagSync.Data.dll.CodeAnalysisLog.xml
40 | true
41 | GlobalSuppressions.cs
42 | prompt
43 | MinimumRecommendedRules.ruleset
44 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets
45 | true
46 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules
47 |
48 |
49 |
50 | ..\packages\FlagFtp.0.1.2\lib\FlagFtp.dll
51 |
52 |
53 | False
54 | ..\packages\Rareform.1.2.0\lib\Rareform.dll
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | {1149F3C5-DBFE-4CFD-98F6-DB396343E647}
75 | FlagSync.Core
76 |
77 |
78 |
79 |
80 |
81 |
82 |
89 |
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Data/FtpFileSystemSetting.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Net;
3 | using FlagFtp;
4 | using FlagSync.Core.FileSystem.Base;
5 | using FlagSync.Core.FileSystem.Ftp;
6 | using FtpDirectoryInfo = FlagSync.Core.FileSystem.Ftp.FtpDirectoryInfo;
7 |
8 | namespace FlagSync.Data
9 | {
10 | public class FtpFileSystemSetting : FileSystemSetting
11 | {
12 | public string Username { get; set; }
13 |
14 | public string Password { get; set; }
15 |
16 | public override IFileSystem GetFileSystem()
17 | {
18 | return new FtpFileSystem(new Uri(this.Source), new NetworkCredential(this.Username, this.Password));
19 | }
20 |
21 | public override IDirectoryInfo GetRootDirectory()
22 | {
23 | return new FtpDirectoryInfo(this.Source, new FtpClient(new NetworkCredential(this.Username, this.Password)));
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Data/ITunesFileSystemSetting.cs:
--------------------------------------------------------------------------------
1 | using FlagSync.Core.FileSystem.Base;
2 | using FlagSync.Core.FileSystem.ITunes;
3 |
4 | namespace FlagSync.Data
5 | {
6 | public class ITunesFileSystemSetting : FileSystemSetting
7 | {
8 | public override IFileSystem GetFileSystem()
9 | {
10 | return new ITunesFileSystem();
11 | }
12 |
13 | public override IDirectoryInfo GetRootDirectory()
14 | {
15 | return new ITunesDirectoryInfo(this.Source);
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Data/ITunesNotOpenedException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace FlagSync.Data
4 | {
5 | public class ITunesNotOpenedException : Exception
6 | {
7 | public ITunesNotOpenedException(string message)
8 | : base(message)
9 | { }
10 | }
11 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Data/JobSetting.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace FlagSync.Data
4 | {
5 | [Serializable]
6 | public class JobSetting
7 | {
8 | public FileSystemSetting FirstFileSystemSetting { get; set; }
9 |
10 | public FileSystemSetting SecondFileSystemSetting { get; set; }
11 |
12 | ///
13 | /// Gets or sets the sync mode.
14 | ///
15 | /// The sync mode.
16 | public SyncMode SyncMode { get; set; }
17 |
18 | ///
19 | /// Gets or sets the name.
20 | ///
21 | /// The name.
22 | public string Name { get; set; }
23 |
24 | ///
25 | /// Gets or sets a value indicating whether this instance is included.
26 | ///
27 | /// true if this instance is included; otherwise, false.
28 | public bool IsIncluded { get; set; }
29 |
30 | ///
31 | /// Initializes a new instance of the class.
32 | ///
33 | /// The name.
34 | public JobSetting(string name)
35 | : this()
36 | {
37 | this.Name = name;
38 | }
39 |
40 | ///
41 | /// Initializes a new instance of the class.
42 | ///
43 | public JobSetting()
44 | {
45 | this.IsIncluded = true;
46 | }
47 | }
48 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Data/JobSettingsLoadingResult.cs:
--------------------------------------------------------------------------------
1 | namespace FlagSync.Data
2 | {
3 | public enum JobSettingsLoadingResult
4 | {
5 | Succeed,
6 | ITunesNotOpened,
7 | CorruptFile
8 | }
9 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Data/LocalFileSystemSetting.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using FlagSync.Core.FileSystem.Base;
3 | using FlagSync.Core.FileSystem.Local;
4 |
5 | namespace FlagSync.Data
6 | {
7 | public class LocalFileSystemSetting : FileSystemSetting
8 | {
9 | public override IFileSystem GetFileSystem()
10 | {
11 | return new LocalFileSystem();
12 | }
13 |
14 | public override IDirectoryInfo GetRootDirectory()
15 | {
16 | return new LocalDirectoryInfo(new DirectoryInfo(this.Source));
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Data/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | // General Information about an assembly is controlled through the following
5 | // set of attributes. Change these attribute values to modify the information
6 | // associated with an assembly.
7 | [assembly: AssemblyTitle("FlagSync.Data")]
8 | [assembly: AssemblyDescription("")]
9 | [assembly: AssemblyConfiguration("")]
10 | [assembly: AssemblyCompany("")]
11 | [assembly: AssemblyProduct("FlagSync.Data")]
12 | [assembly: AssemblyCopyright("")]
13 | [assembly: AssemblyTrademark("")]
14 | [assembly: AssemblyCulture("")]
15 |
16 | // Setting ComVisible to false makes the types in this assembly not visible
17 | // to COM components. If you need to access a type in this assembly from
18 | // COM, set the ComVisible attribute to true on that type.
19 | [assembly: ComVisible(false)]
20 |
21 | // The following GUID is for the ID of the typelib if this project is exposed to COM
22 | [assembly: Guid("d5e933e1-9bb4-4ed3-967b-9c8e1612ee10")]
23 |
24 | // Version information for an assembly consists of the following four values:
25 | //
26 | // Major Version
27 | // Minor Version
28 | // Build Number
29 | // Revision
30 | //
31 | // You can specify all the values or you can default the Build and Revision Numbers
32 | // by using the '*' as shown below:
33 | // [assembly: AssemblyVersion("1.0.*")]
34 | [assembly: AssemblyVersion("2.4.2")]
35 | [assembly: AssemblyFileVersion("2.4.2")]
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Data/SyncMode.cs:
--------------------------------------------------------------------------------
1 | namespace FlagSync.Data
2 | {
3 | ///
4 | /// Specifies the sync mode of a job. Used by the class.
5 | ///
6 | public enum SyncMode
7 | {
8 | Backup,
9 | Synchronization
10 | }
11 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.Data/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/App.xaml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
25 |
26 |
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 |
3 | namespace FlagSync.View
4 | {
5 | ///
6 | /// Interaction logic for App.xaml
7 | ///
8 | public partial class App : Application
9 | {
10 | }
11 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/ByteToKiloByteConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Globalization;
3 | using System.Windows.Data;
4 |
5 | namespace FlagSync.View
6 | {
7 | [ValueConversion(typeof(long), typeof(int))]
8 | public class ByteToKiloByteConverter : IValueConverter
9 | {
10 | ///
11 | /// Converts a value.
12 | ///
13 | /// The value produced by the binding source.
14 | /// The type of the binding target property.
15 | /// The converter parameter to use.
16 | /// The culture to use in the converter.
17 | ///
18 | /// A converted value. If the method returns null, the valid null value is used.
19 | ///
20 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
21 | {
22 | long bytes = (long)value;
23 | return (int)(bytes / 1024);
24 | }
25 |
26 | ///
27 | /// Converts a value.
28 | ///
29 | /// The value that is produced by the binding target.
30 | /// The type to convert to.
31 | /// The converter parameter to use.
32 | /// The culture to use in the converter.
33 | ///
34 | /// A converted value. If the method returns null, the valid null value is used.
35 | ///
36 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
37 | {
38 | int kiloBytes = (int)value;
39 | return (long)(kiloBytes * 1024);
40 | }
41 | }
42 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/FlagSync.View.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | x86
6 | 8.0.30703
7 | 2.0
8 | {91E37F1B-FE0F-456F-8F67-4058A854FDF8}
9 | WinExe
10 | Properties
11 | FlagSync.View
12 | FlagSync
13 | v4.0
14 | 512
15 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
16 | 4
17 | Client
18 |
19 |
20 | x86
21 | true
22 | full
23 | false
24 | bin\Debug\
25 | DEBUG;TRACE
26 | prompt
27 | 4
28 | AllRules.ruleset
29 |
30 |
31 | x86
32 | pdbonly
33 | true
34 | bin\Release\
35 | TRACE
36 | prompt
37 | 4
38 |
39 |
40 | Images\ApplicationIcon.ico
41 |
42 |
43 |
44 | False
45 | ..\packages\MahApps.Metro.0.8.0.0\lib\net40\MahApps.Metro.dll
46 |
47 |
48 | False
49 | ..\packages\Rareform.1.2.0\lib\Rareform.dll
50 |
51 |
52 |
53 |
54 | ..\packages\MahApps.Metro.0.8.0.0\lib\net40\System.Windows.Interactivity.dll
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 | MSBuild:Compile
65 | Designer
66 |
67 |
68 | Designer
69 | MSBuild:Compile
70 |
71 |
72 | Designer
73 | MSBuild:Compile
74 |
75 |
76 | Designer
77 | MSBuild:Compile
78 |
79 |
80 | Designer
81 | MSBuild:Compile
82 |
83 |
84 | Designer
85 | MSBuild:Compile
86 |
87 |
88 | MSBuild:Compile
89 | Designer
90 |
91 |
92 |
93 |
94 | AboutBox.xaml
95 |
96 |
97 |
98 | App.xaml
99 | Code
100 |
101 |
102 |
103 | FtpFileSystemPanel.xaml
104 |
105 |
106 |
107 | ITunesFileSystemPanel.xaml
108 |
109 |
110 |
111 | JobCompositionControl.xaml
112 |
113 |
114 |
115 |
116 | LocalFileSystemPanel.xaml
117 |
118 |
119 |
120 |
121 |
122 | MainWindow.xaml
123 | Code
124 |
125 |
126 |
127 |
128 | Code
129 |
130 |
131 | Resources.de-DE.resx
132 | True
133 | True
134 |
135 |
136 | True
137 | True
138 | Resources.resx
139 |
140 |
141 | True
142 | Settings.settings
143 | True
144 |
145 |
146 | PublicResXFileCodeGenerator
147 | Resources.de-DE.Designer.cs
148 | Designer
149 |
150 |
151 | PublicResXFileCodeGenerator
152 | Designer
153 | Resources.Designer.cs
154 |
155 |
156 |
157 |
158 | SettingsSingleFileGenerator
159 | Settings.Designer.cs
160 |
161 |
162 |
163 |
164 |
165 | {1149F3C5-DBFE-4CFD-98F6-DB396343E647}
166 | FlagSync.Core
167 |
168 |
169 | {080FB9A0-A2F9-438F-8F84-60B7FB448633}
170 | FlagSync.Data
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 | {9E93C96F-CF0D-43F6-8BA8-B807A3370712}
198 | 1
199 | 13
200 | 0
201 | tlbimp
202 | False
203 | True
204 | True
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
226 |
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/Images/Add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/FlagSync/FlagSync.View/Images/Add.png
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/Images/ApplicationIcon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/FlagSync/FlagSync.View/Images/ApplicationIcon.ico
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/Images/DownArrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/FlagSync/FlagSync.View/Images/DownArrow.png
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/Images/Error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/FlagSync/FlagSync.View/Images/Error.png
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/Images/FTPServer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/FlagSync/FlagSync.View/Images/FTPServer.png
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/Images/Load.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/FlagSync/FlagSync.View/Images/Load.png
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/Images/Local.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/FlagSync/FlagSync.View/Images/Local.png
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/Images/OpenFolder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/FlagSync/FlagSync.View/Images/OpenFolder.png
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/Images/Remove.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/FlagSync/FlagSync.View/Images/Remove.png
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/Images/Save.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/FlagSync/FlagSync.View/Images/Save.png
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/Images/Success.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/FlagSync/FlagSync.View/Images/Success.png
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/Images/UpArrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/FlagSync/FlagSync.View/Images/UpArrow.png
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/Images/iTunes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/FlagSync/FlagSync.View/Images/iTunes.png
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/LogMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows.Media;
3 | using System.Windows.Media.Imaging;
4 | using Rareform.Extensions;
5 | using Rareform.Patterns.MVVM;
6 |
7 | namespace FlagSync.View
8 | {
9 | public class LogMessage : ViewModelBase
10 | {
11 | private int progress;
12 | private long? fileSize;
13 |
14 | ///
15 | /// Gets or sets the type (file or directory).
16 | ///
17 | /// The type.
18 | public string Type { get; private set; }
19 |
20 | ///
21 | /// Gets or sets the action.
22 | ///
23 | /// The action.
24 | public string Action { get; private set; }
25 |
26 | ///
27 | /// Gets or sets the path of file A.
28 | ///
29 | /// The path of file A.
30 | public string SourcePath { get; private set; }
31 |
32 | ///
33 | /// Gets or sets the path of file B.
34 | ///
35 | /// The path of file B.
36 | public string TargetPath { get; private set; }
37 |
38 | ///
39 | /// Gets or sets the current progress of the file (0 - 100).
40 | ///
41 | /// The current progress of the file.
42 | public int Progress
43 | {
44 | get { return this.progress; }
45 | set
46 | {
47 | if (value < 0 || value > 100)
48 | throw new ArgumentOutOfRangeException("value", "Value must be between 0 and 100");
49 |
50 | if (this.Progress != value)
51 | {
52 | this.progress = value;
53 | this.OnPropertyChanged(vm => vm.Progress);
54 | this.OnPropertyChanged(vm => vm.IsInProgress);
55 | this.OnPropertyChanged(vm => vm.Image);
56 | }
57 | }
58 | }
59 |
60 | ///
61 | /// Gets a value indicating whether the current file is in progress.
62 | ///
63 | /// true if the current file is in progress; otherwise, false.
64 | public bool IsInProgress
65 | {
66 | get { return this.Progress != 100; }
67 | }
68 |
69 | ///
70 | /// Gets the image for the log message.
71 | ///
72 | public ImageSource Image
73 | {
74 | get
75 | {
76 | if (IsInProgress && !IsErrorMessage)
77 | return null;
78 |
79 | const string successImagePath = "pack://application:,,,/FlagSync;component/Images/Success.png";
80 | const string errorImagePath = "pack://application:,,,/FlagSync;component/Images/Error.png";
81 |
82 | var logo = new BitmapImage();
83 |
84 | logo.BeginInit();
85 | logo.UriSource = new Uri(this.IsErrorMessage ? errorImagePath : successImagePath);
86 | logo.EndInit();
87 | logo.Freeze();
88 |
89 | return logo;
90 | }
91 | }
92 |
93 | ///
94 | /// Gets a value indicating whether the log message is a error message.
95 | ///
96 | ///
97 | /// true if the log message is a error message; otherwise, false.
98 | ///
99 | public bool IsErrorMessage { get; private set; }
100 |
101 | ///
102 | /// Gets the size of the file.
103 | ///
104 | ///
105 | /// The size of the file.
106 | ///
107 | public string FileSize
108 | {
109 | get
110 | {
111 | return this.fileSize.HasValue ? this.fileSize.Value.ToSizeString() : String.Empty;
112 | }
113 | }
114 |
115 | ///
116 | /// Initializes a new instance of the class.
117 | ///
118 | /// The type.
119 | /// The action.
120 | /// The source path.
121 | /// The target path.
122 | /// if set to true, the message is a error message.
123 | /// The size of the file.
124 | public LogMessage(string type, string action, string sourcePath, string targetPath, bool isErrorMessage, long? fileSize)
125 | {
126 | this.Type = type;
127 | this.Action = action;
128 | this.SourcePath = sourcePath;
129 | this.TargetPath = targetPath;
130 | this.IsErrorMessage = isErrorMessage;
131 | this.fileSize = fileSize;
132 | }
133 | }
134 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Resources;
3 | using System.Runtime.InteropServices;
4 | using System.Windows;
5 |
6 | // General Information about an assembly is controlled through the following
7 | // set of attributes. Change these attribute values to modify the information
8 | // associated with an assembly.
9 | [assembly: AssemblyTitle("FlagSync")]
10 | [assembly: AssemblyDescription("")]
11 | [assembly: AssemblyConfiguration("")]
12 | [assembly: AssemblyCompany("")]
13 | [assembly: AssemblyProduct("FlagSync")]
14 | [assembly: AssemblyCopyright("")]
15 | [assembly: AssemblyTrademark("")]
16 | [assembly: AssemblyCulture("")]
17 |
18 | // Setting ComVisible to false makes the types in this assembly not visible
19 | // to COM components. If you need to access a type in this assembly from
20 | // COM, set the ComVisible attribute to true on that type.
21 | [assembly: ComVisible(false)]
22 |
23 | //In order to begin building localizable applications, set
24 | //CultureYouAreCodingWith in your .csproj file
25 | //inside a . For example, if you are using US english
26 | //in your source files, set the to en-US. Then uncomment
27 | //the NeutralResourceLanguage attribute below. Update the "en-US" in
28 | //the line below to match the UICulture setting in the project file.
29 |
30 | [assembly: NeutralResourcesLanguage("en")]
31 |
32 | [assembly: ThemeInfo(
33 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
34 | //(used if a resource is not found in the page,
35 | // or application resource dictionaries)
36 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
37 | //(used if a resource is not found in the page,
38 | // app, or any theme specific resource dictionaries)
39 | )]
40 |
41 | // Version information for an assembly consists of the following four values:
42 | //
43 | // Major Version
44 | // Minor Version
45 | // Build Number
46 | // Revision
47 | //
48 | // You can specify all the values or you can default the Build and Revision Numbers
49 | // by using the '*' as shown below:
50 | // [assembly: AssemblyVersion("1.0.*")]
51 | [assembly: AssemblyVersion("2.4.2")]
52 | [assembly: AssemblyFileVersion("2.4.2")]
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/Properties/Resources.de-DE.Designer.cs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/FlagSync/FlagSync.View/Properties/Resources.de-DE.Designer.cs
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.239
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace FlagSync.View.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 |
26 | [global::System.Configuration.UserScopedSettingAttribute()]
27 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
28 | [global::System.Configuration.DefaultSettingValueAttribute("en-US")]
29 | public global::System.Globalization.CultureInfo Language {
30 | get {
31 | return ((global::System.Globalization.CultureInfo)(this["Language"]));
32 | }
33 | set {
34 | this["Language"] = value;
35 | }
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | en-US
7 |
8 |
9 |
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/ViewModels/AboutBoxViewModel.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 |
3 | namespace FlagSync.View.ViewModels
4 | {
5 | public class AboutBoxViewModel
6 | {
7 | ///
8 | /// Gets the application version.
9 | ///
10 | /// The application version.
11 | public static string Version
12 | {
13 | get { return Assembly.GetExecutingAssembly().GetName().Version.ToString(3); }
14 | }
15 |
16 | ///
17 | /// Gets the author of the application
18 | ///
19 | /// The author of the application.
20 | public static string Author
21 | {
22 | get { return "Dennis Daume"; }
23 | }
24 |
25 | ///
26 | /// Gets the title of the application.
27 | ///
28 | /// The title of the application.
29 | public static string Title
30 | {
31 | get { return "FlagSync"; }
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/ViewModels/FtpFileSystemViewModel.cs:
--------------------------------------------------------------------------------
1 | using System.Windows.Controls;
2 | using FlagSync.Data;
3 | using FlagSync.View.Views;
4 | using Rareform.Patterns.MVVM;
5 |
6 | namespace FlagSync.View.ViewModels
7 | {
8 | public class FtpFileSystemViewModel : ViewModelBase, IFileSystemViewModel
9 | {
10 | private readonly FtpFileSystemSetting setting;
11 |
12 | public string ServerAddress
13 | {
14 | get { return this.setting.Source; }
15 | set
16 | {
17 | if (this.setting.Source != value)
18 | {
19 | this.setting.Source = value;
20 | this.OnPropertyChanged(vm => vm.ServerAddress);
21 | }
22 | }
23 | }
24 |
25 | public string Username
26 | {
27 | get { return this.setting.Username; }
28 | set
29 | {
30 | if (this.setting.Username != value)
31 | {
32 | this.setting.Username = value;
33 | this.OnPropertyChanged(vm => vm.Username);
34 | }
35 | }
36 | }
37 |
38 | public string Password
39 | {
40 | get { return this.setting.Password; }
41 | set
42 | {
43 | if (this.setting.Password != value)
44 | {
45 | this.setting.Password = value;
46 | this.OnPropertyChanged(vm => vm.Password);
47 | }
48 | }
49 | }
50 |
51 | public FtpFileSystemViewModel(FtpFileSystemSetting setting)
52 | {
53 | this.setting = setting;
54 | }
55 |
56 | public UserControl CreateView()
57 | {
58 | return new FtpFileSystemPanel(this);
59 | }
60 | }
61 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/ViewModels/IFileSystemViewModel.cs:
--------------------------------------------------------------------------------
1 | using System.Windows.Controls;
2 |
3 | namespace FlagSync.View.ViewModels
4 | {
5 | public interface IFileSystemViewModel
6 | {
7 | UserControl CreateView();
8 | }
9 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/ViewModels/ITunesFileSystemViewModel.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using System.Windows.Controls;
4 | using FlagSync.Data;
5 | using FlagSync.View.Views;
6 | using iTunesLib;
7 | using Rareform.Patterns.MVVM;
8 |
9 | namespace FlagSync.View.ViewModels
10 | {
11 | public class ITunesFileSystemViewModel : ViewModelBase, IFileSystemViewModel
12 | {
13 | private readonly ITunesFileSystemSetting setting;
14 |
15 | public string Playlist
16 | {
17 | get { return this.setting.Source; }
18 | set
19 | {
20 | if (this.setting.Source != value)
21 | {
22 | this.setting.Source = value;
23 | this.OnPropertyChanged(vm => vm.Playlist);
24 | }
25 | }
26 | }
27 |
28 | public static IEnumerable AvailablePlaylists
29 | {
30 | get
31 | {
32 | var iTunesApp = new iTunesApp();
33 |
34 | return iTunesApp.LibrarySource.Playlists
35 | .Cast()
36 | .Where(pl => pl.Kind == ITPlaylistKind.ITPlaylistKindUser)
37 | .Select(pl => pl.Name)
38 | .OrderBy(name => name);
39 | }
40 | }
41 |
42 | public ITunesFileSystemViewModel(ITunesFileSystemSetting setting)
43 | {
44 | this.setting = setting;
45 |
46 | this.Playlist = this.setting.Source ?? AvailablePlaylists.First();
47 | }
48 |
49 | public UserControl CreateView()
50 | {
51 | return new ITunesFileSystemPanel(this);
52 | }
53 | }
54 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/ViewModels/JobCompositionViewModel.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.ObjectModel;
2 | using System.Windows.Controls;
3 | using System.Windows.Input;
4 | using FlagSync.Data;
5 | using Rareform.Patterns.MVVM;
6 |
7 | namespace FlagSync.View.ViewModels
8 | {
9 | public class JobCompositionViewModel : ViewModelBase
10 | {
11 | private readonly JobSettingViewModel setting;
12 | private IFileSystemViewModel firstFileSystem;
13 | private IFileSystemViewModel secondFileSystem;
14 |
15 | public ObservableCollection CurrentFirstFileSystem { get; private set; }
16 |
17 | public ObservableCollection CurrentSecondFileSystem { get; private set; }
18 |
19 | public IFileSystemViewModel FirstFileSystem
20 | {
21 | set
22 | {
23 | this.firstFileSystem = value;
24 |
25 | this.CurrentFirstFileSystem.Clear();
26 | this.CurrentFirstFileSystem.Add(this.firstFileSystem.CreateView());
27 | }
28 | }
29 |
30 | public IFileSystemViewModel SecondFileSystem
31 | {
32 | set
33 | {
34 | this.secondFileSystem = value;
35 |
36 | this.CurrentSecondFileSystem.Clear();
37 | this.CurrentSecondFileSystem.Add(this.secondFileSystem.CreateView());
38 | }
39 | }
40 |
41 | public string Name
42 | {
43 | get { return this.setting.Name; }
44 | set
45 | {
46 | if (this.Name != value)
47 | {
48 | this.setting.Name = value;
49 | this.OnPropertyChanged(vm => vm.Name);
50 | }
51 | }
52 | }
53 |
54 | public bool IsBackup
55 | {
56 | get { return this.setting.SyncMode == SyncMode.Backup; }
57 | set
58 | {
59 | if (this.IsBackup != value)
60 | {
61 | this.setting.SyncMode = value ? SyncMode.Backup : SyncMode.Synchronization;
62 |
63 | this.OnPropertyChanged(vm => vm.IsBackup);
64 | }
65 | }
66 | }
67 |
68 | public bool IsSynchronization
69 | {
70 | get { return this.setting.SyncMode == SyncMode.Synchronization; }
71 | set
72 | {
73 | if (this.IsSynchronization != value)
74 | {
75 | this.setting.SyncMode = value ? SyncMode.Synchronization : SyncMode.Backup;
76 |
77 | this.OnPropertyChanged(vm => vm.IsSynchronization);
78 | }
79 | }
80 | }
81 |
82 | public ICommand CreateFirstFileSystemCommand
83 | {
84 | get
85 | {
86 | return new RelayCommand
87 | (
88 | param =>
89 | {
90 | var fileSystem = (string)param;
91 |
92 | switch (fileSystem)
93 | {
94 | case "Local":
95 | var localSetting = new LocalFileSystemSetting();
96 | this.setting.FirstFileSystem = localSetting;
97 | this.FirstFileSystem = new LocalFileSystemViewModel(localSetting);
98 | break;
99 |
100 | case "Ftp":
101 | var ftpSetting = new FtpFileSystemSetting();
102 | this.setting.FirstFileSystem = ftpSetting;
103 | this.FirstFileSystem = new FtpFileSystemViewModel(ftpSetting);
104 | break;
105 |
106 | case "iTunes":
107 | var iTunesSetting = new ITunesFileSystemSetting();
108 | this.setting.FirstFileSystem = iTunesSetting;
109 | this.FirstFileSystem = new ITunesFileSystemViewModel(iTunesSetting);
110 | break;
111 | }
112 | }
113 | );
114 | }
115 | }
116 |
117 | public ICommand CreateSecondFileSystemCommand
118 | {
119 | get
120 | {
121 | return new RelayCommand
122 | (
123 | param =>
124 | {
125 | var fileSystem = (string)param;
126 |
127 | switch (fileSystem)
128 | {
129 | case "Local":
130 | var localSetting = new LocalFileSystemSetting();
131 | this.setting.SecondFileSystem = localSetting;
132 | this.SecondFileSystem = new LocalFileSystemViewModel(localSetting);
133 | break;
134 |
135 | case "Ftp":
136 | var ftpSetting = new FtpFileSystemSetting();
137 | this.setting.SecondFileSystem = ftpSetting;
138 | this.SecondFileSystem = new FtpFileSystemViewModel(ftpSetting);
139 | break;
140 | }
141 | }
142 | );
143 | }
144 | }
145 |
146 | public JobCompositionViewModel(JobSettingViewModel setting)
147 | {
148 | this.setting = setting;
149 | this.CurrentFirstFileSystem = new ObservableCollection();
150 | this.CurrentSecondFileSystem = new ObservableCollection();
151 | }
152 | }
153 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/ViewModels/JobSettingViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using FlagSync.Data;
4 | using FlagSync.View.Properties;
5 | using Rareform.Patterns.MVVM;
6 |
7 | namespace FlagSync.View.ViewModels
8 | {
9 | public class JobSettingViewModel : ViewModelBase, IDataErrorInfo
10 | {
11 | ///
12 | /// Gets or sets a value indicating whether this job is included syncing.
13 | ///
14 | ///
15 | /// true if this job is included for syncing; otherwise, false.
16 | ///
17 | public bool IsIncluded
18 | {
19 | get { return this.InternJobSetting.IsIncluded; }
20 | set
21 | {
22 | if (this.IsIncluded != value)
23 | {
24 | this.InternJobSetting.IsIncluded = value;
25 | this.OnPropertyChanged(vm => vm.IsIncluded);
26 | }
27 | }
28 | }
29 |
30 | public FileSystemSetting FirstFileSystem
31 | {
32 | get { return this.InternJobSetting.FirstFileSystemSetting; }
33 | set
34 | {
35 | if (this.FirstFileSystem != value)
36 | {
37 | this.InternJobSetting.FirstFileSystemSetting = value;
38 | this.OnPropertyChanged(vm => vm.FirstFileSystem);
39 | }
40 | }
41 | }
42 |
43 | public FileSystemSetting SecondFileSystem
44 | {
45 | get { return this.InternJobSetting.SecondFileSystemSetting; }
46 | set
47 | {
48 | if (this.SecondFileSystem != value)
49 | {
50 | this.InternJobSetting.SecondFileSystemSetting = value;
51 | this.OnPropertyChanged(vm => vm.SecondFileSystem);
52 | }
53 | }
54 | }
55 |
56 | public string Name
57 | {
58 | get { return this.InternJobSetting.Name; }
59 | set
60 | {
61 | if (this.Name != value)
62 | {
63 | this.InternJobSetting.Name = value;
64 | this.OnPropertyChanged(vm => vm.Name);
65 | }
66 | }
67 | }
68 |
69 | public SyncMode SyncMode
70 | {
71 | get { return this.InternJobSetting.SyncMode; }
72 | set
73 | {
74 | if (this.SyncMode != value)
75 | {
76 | this.InternJobSetting.SyncMode = value;
77 | this.OnPropertyChanged(vm => vm.SyncMode);
78 | this.OnPropertyChanged(vm => vm.SyncModeString);
79 | }
80 | }
81 | }
82 |
83 | ///
84 | /// Gets or sets the name.
85 | ///
86 | ///
87 | /// The name.
88 | ///
89 | public string SyncModeString
90 | {
91 | get
92 | {
93 | switch (this.SyncMode)
94 | {
95 | case SyncMode.Backup:
96 | return Resources.BackupString;
97 |
98 | case SyncMode.Synchronization:
99 | return Resources.SynchronizationString;
100 | }
101 |
102 | throw new InvalidOperationException();
103 | }
104 | }
105 |
106 | ///
107 | /// Gets the intern job setting.
108 | ///
109 | /// The intern job setting.
110 | ///
111 | public JobSetting InternJobSetting { get; private set; }
112 |
113 | ///
114 | /// Initializes a new instance of the class.
115 | ///
116 | /// The name.
117 | ///
118 | public JobSettingViewModel(string name)
119 | : this(new JobSetting(name))
120 | {
121 | }
122 |
123 | ///
124 | /// Initializes a new instance of the class.
125 | ///
126 | /// The intern job setting.
127 | ///
128 | public JobSettingViewModel(JobSetting internJobSetting)
129 | {
130 | this.InternJobSetting = internJobSetting;
131 | }
132 |
133 | public string this[string columnName]
134 | {
135 | get { throw new NotImplementedException(); }
136 | }
137 |
138 | public string Error
139 | {
140 | get { throw new NotImplementedException(); }
141 | }
142 |
143 | public bool HasErrors
144 | {
145 | get { return false; }
146 | }
147 | }
148 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/ViewModels/JobViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using FlagSync.Core;
3 | using FlagSync.View.Properties;
4 |
5 | namespace FlagSync.View.ViewModels
6 | {
7 | internal class JobViewModel
8 | {
9 | private readonly Job model;
10 |
11 | ///
12 | /// Initializes a new instance of the class.
13 | ///
14 | /// The model.
15 | public JobViewModel(Job model)
16 | {
17 | this.model = model;
18 | }
19 |
20 | ///
21 | /// Gets the directory A.
22 | ///
23 | public string DirectoryA
24 | {
25 | get { return this.model.DirectoryA.FullName; }
26 | }
27 |
28 | ///
29 | /// Gets the directory B.
30 | ///
31 | public string DirectoryB
32 | {
33 | get { return this.model.DirectoryB.FullName; }
34 | }
35 |
36 | ///
37 | /// Gets the name.
38 | ///
39 | public string Name
40 | {
41 | get { return this.model.Name; }
42 | }
43 |
44 | ///
45 | /// Gets the sync mode string.
46 | ///
47 | public string SyncModeString
48 | {
49 | get
50 | {
51 | if (this.model is BackupJob)
52 | {
53 | return Resources.BackupString;
54 | }
55 |
56 | if (this.model is SyncJob)
57 | {
58 | return Resources.SynchronizationString;
59 | }
60 |
61 | throw new NotSupportedException("No such job.");
62 | }
63 | }
64 | }
65 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/ViewModels/LocalFileSystemViewModel.cs:
--------------------------------------------------------------------------------
1 | using System.Windows.Controls;
2 | using FlagSync.Data;
3 | using FlagSync.View.Views;
4 | using Rareform.Patterns.MVVM;
5 |
6 | namespace FlagSync.View.ViewModels
7 | {
8 | public class LocalFileSystemViewModel : ViewModelBase, IFileSystemViewModel
9 | {
10 | private readonly LocalFileSystemSetting setting;
11 |
12 | public string Directory
13 | {
14 | get { return this.setting.Source; }
15 | set
16 | {
17 | if (this.setting.Source != value)
18 | {
19 | this.setting.Source = value;
20 | this.OnPropertyChanged(vm => vm.Directory);
21 | }
22 | }
23 | }
24 |
25 | public LocalFileSystemViewModel(LocalFileSystemSetting setting)
26 | {
27 | this.setting = setting;
28 | }
29 |
30 | public UserControl CreateView()
31 | {
32 | return new LocalFileSystemPanel(this);
33 | }
34 | }
35 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/Views/AboutBox.xaml:
--------------------------------------------------------------------------------
1 |
15 |
16 |
17 |
18 |
19 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
41 |
46 |
51 |
56 |
61 |
66 |
67 |
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/Views/AboutBox.xaml.cs:
--------------------------------------------------------------------------------
1 | namespace FlagSync.View.Views
2 | {
3 | ///
4 | /// Interaction logic for AboutBox.xaml
5 | ///
6 | public sealed partial class AboutBox
7 | {
8 | public AboutBox()
9 | {
10 | InitializeComponent();
11 | }
12 | }
13 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/Views/FtpFileSystemPanel.xaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
27 |
34 |
40 |
47 |
53 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/Views/FtpFileSystemPanel.xaml.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using System.Windows.Controls;
3 | using FlagSync.View.ViewModels;
4 |
5 | namespace FlagSync.View.Views
6 | {
7 | ///
8 | /// Interaction logic for FtpFileSystemPanel.xaml
9 | ///
10 | public sealed partial class FtpFileSystemPanel
11 | {
12 | private readonly FtpFileSystemViewModel viewModel;
13 |
14 | public FtpFileSystemPanel(FtpFileSystemViewModel viewModel)
15 | {
16 | InitializeComponent();
17 |
18 | this.viewModel = viewModel;
19 | this.DataContext = viewModel;
20 | }
21 |
22 | private void PasswordBox_PasswordChanged(object sender, RoutedEventArgs e)
23 | {
24 | this.viewModel.Password = ((PasswordBox)sender).Password;
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/Views/ITunesFileSystemPanel.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
22 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/Views/ITunesFileSystemPanel.xaml.cs:
--------------------------------------------------------------------------------
1 | using FlagSync.View.ViewModels;
2 |
3 | namespace FlagSync.View.Views
4 | {
5 | ///
6 | /// Interaction logic for ITunesFileSystemPanel.xaml
7 | ///
8 | public sealed partial class ITunesFileSystemPanel
9 | {
10 | private ITunesFileSystemViewModel viewModel;
11 |
12 | public ITunesFileSystemPanel(ITunesFileSystemViewModel viewModel)
13 | {
14 | InitializeComponent();
15 |
16 | this.viewModel = viewModel;
17 | this.DataContext = viewModel;
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/Views/JobCompositionControl.xaml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
23 |
28 |
32 |
36 |
51 |
67 |
83 |
84 |
87 |
88 |
91 |
97 |
102 |
106 |
122 |
138 |
139 |
142 |
143 |
146 |
151 |
155 |
156 |
160 |
163 |
167 |
171 |
172 |
173 |
174 |
175 |
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/Views/JobCompositionControl.xaml.cs:
--------------------------------------------------------------------------------
1 | using FlagSync.View.ViewModels;
2 |
3 | namespace FlagSync.View.Views
4 | {
5 | ///
6 | /// Interaction logic for JobCompositionControl.xaml
7 | ///
8 | public partial class JobCompositionControl
9 | {
10 | public JobCompositionControl(JobCompositionViewModel viewModel)
11 | {
12 | InitializeComponent();
13 |
14 | this.DataContext = viewModel;
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/Views/LocalFileSystemPanel.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
14 |
15 |
16 |
17 |
18 |
29 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/Views/LocalFileSystemPanel.xaml.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using FlagSync.View.ViewModels;
3 |
4 | namespace FlagSync.View.Views
5 | {
6 | ///
7 | /// Interaction logic for LocalFileSystemPanel.xaml
8 | ///
9 | public sealed partial class LocalFileSystemPanel
10 | {
11 | private readonly LocalFileSystemViewModel viewModel;
12 |
13 | public LocalFileSystemPanel(LocalFileSystemViewModel viewModel)
14 | {
15 | InitializeComponent();
16 |
17 | this.viewModel = viewModel;
18 | this.DataContext = viewModel;
19 | }
20 |
21 | private void directoryAButton_Click(object sender, RoutedEventArgs e)
22 | {
23 | string result = ShowFolderDialog();
24 |
25 | if (result != null)
26 | {
27 | this.viewModel.Directory = result;
28 | }
29 | }
30 |
31 | private static string ShowFolderDialog()
32 | {
33 | string selectedFolder = null;
34 |
35 | using (var dialog = new System.Windows.Forms.FolderBrowserDialog())
36 | {
37 | var result = dialog.ShowDialog();
38 |
39 | if (result == System.Windows.Forms.DialogResult.OK)
40 | {
41 | selectedFolder = dialog.SelectedPath;
42 | }
43 | }
44 |
45 | return selectedFolder;
46 | }
47 | }
48 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/Views/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Diagnostics;
4 | using System.Globalization;
5 | using System.Linq;
6 | using System.Windows;
7 | using System.Windows.Controls;
8 | using FlagSync.Data;
9 | using FlagSync.View.Properties;
10 |
11 | namespace FlagSync.View.Views
12 | {
13 | ///
14 | /// Interaction logic for MainWindow.xaml
15 | ///
16 | public sealed partial class MainWindow
17 | {
18 | ///
19 | /// Initializes a new instance of the class.
20 | ///
21 | public MainWindow()
22 | {
23 | Properties.Resources.Culture = Settings.Default.Language;
24 | InitializeComponent();
25 | }
26 |
27 | private void Window_Loaded(object sender, RoutedEventArgs e)
28 | {
29 | string[] args = Environment.GetCommandLineArgs();
30 |
31 | if (args.Length == 2)
32 | {
33 | this.WindowState = WindowState.Minimized;
34 |
35 | try
36 | {
37 | this.mainWindowViewModel.LoadJobSettings(args[1]);
38 | }
39 |
40 | catch (CorruptSaveFileException)
41 | {
42 | this.WindowState = WindowState.Maximized;
43 |
44 | MessageBox.Show
45 | (
46 | Properties.Resources.LoadSettingsErrorMessage,
47 | Properties.Resources.ErrorString,
48 | MessageBoxButton.OK,
49 | MessageBoxImage.Error
50 | );
51 |
52 | Application.Current.Shutdown();
53 | }
54 |
55 | catch (ITunesNotOpenedException)
56 | {
57 | this.WindowState = WindowState.Maximized;
58 |
59 | ShowITunesErrorMessageBox();
60 |
61 | Application.Current.Shutdown();
62 | }
63 |
64 | this.mainWindowViewModel.StartJobWorkerCommand.Execute(false);
65 | }
66 | }
67 |
68 | private void loadJobsButton_Click(object sender, RoutedEventArgs e)
69 | {
70 | using (var dialog = new System.Windows.Forms.OpenFileDialog())
71 | {
72 | dialog.Filter = "|*.xml";
73 | dialog.InitialDirectory = DataController.AppDataFolderPath;
74 | dialog.Multiselect = false;
75 |
76 | dialog.FileOk += (dialogSender, dialogEventArgs) =>
77 | {
78 | try
79 | {
80 | this.mainWindowViewModel.LoadJobSettings(dialog.FileName);
81 | }
82 | catch (CorruptSaveFileException)
83 | {
84 | MessageBox.Show
85 | (
86 | Properties.Resources.LoadSettingsErrorMessage,
87 | Properties.Resources.ErrorString,
88 | MessageBoxButton.OK,
89 | MessageBoxImage.Error
90 | );
91 | }
92 |
93 | catch (ITunesNotOpenedException)
94 | {
95 | ShowITunesErrorMessageBox();
96 | }
97 | };
98 |
99 | dialog.ShowDialog();
100 | }
101 | }
102 |
103 | private void saveJobsButton_Click(object sender, RoutedEventArgs e)
104 | {
105 | using (var dialog = new System.Windows.Forms.SaveFileDialog())
106 | {
107 | dialog.AddExtension = true;
108 | dialog.DefaultExt = ".xml";
109 | dialog.FileName = "NewJobSettings";
110 | dialog.InitialDirectory = DataController.AppDataFolderPath;
111 |
112 | dialog.FileOk += (dialogSender, dialogEventArgs) =>
113 | this.mainWindowViewModel.SaveJobSettings(dialog.FileName);
114 |
115 | dialog.ShowDialog();
116 | }
117 | }
118 |
119 | private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
120 | {
121 | ((TextBox)sender).ScrollToEnd();
122 | }
123 |
124 | private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
125 | {
126 | var messages = this.mainWindowViewModel.LogMessages;
127 | bool isPreview = this.mainWindowViewModel.IsPreview;
128 | bool isRunning = this.mainWindowViewModel.IsRunning;
129 | bool isPaused = this.mainWindowViewModel.IsPaused;
130 |
131 | if (!isPreview && messages.Any() && isRunning && !isPaused)
132 | {
133 | ((ListView)sender).ScrollIntoView(messages.Last());
134 | }
135 | }
136 |
137 | private void englishMenuItem_Click(object sender, RoutedEventArgs e)
138 | {
139 | Settings.Default.Language = new CultureInfo("en-US");
140 | Restart();
141 | }
142 |
143 | private void germanMenuItem_Click(object sender, RoutedEventArgs e)
144 | {
145 | Settings.Default.Language = new CultureInfo("de-DE");
146 | Restart();
147 | }
148 |
149 | ///
150 | /// Restarts this instance.
151 | ///
152 | private static void Restart()
153 | {
154 | var result = MessageBox.Show(
155 | Properties.Resources.ApplicationRestartMessageBoxText,
156 | Properties.Resources.ApplicationRestartMessageBoxCaption,
157 | MessageBoxButton.YesNo, MessageBoxImage.Question);
158 |
159 | if (result == MessageBoxResult.Yes)
160 | {
161 | Application.Current.Shutdown();
162 | Process.Start(System.Reflection.Assembly.GetEntryAssembly().Location);
163 | }
164 | }
165 |
166 | private void Window_Closing(object sender, CancelEventArgs e)
167 | {
168 | Settings.Default.Save();
169 | }
170 |
171 | private void aboutMenuItem_Click(object sender, RoutedEventArgs e)
172 | {
173 | var aboutBox = new AboutBox();
174 | aboutBox.ShowDialog();
175 | }
176 |
177 | private void Hyperlink_RequestNavigate(object sender, System.Windows.Navigation.RequestNavigateEventArgs e)
178 | {
179 | Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));
180 | e.Handled = true;
181 | }
182 |
183 | private static void ShowITunesErrorMessageBox()
184 | {
185 | MessageBox.Show
186 | (
187 | Properties.Resources.iTunesErrorMessageBoxText,
188 | Properties.Resources.iTunesErrorMessageBoxCaption,
189 | MessageBoxButton.OK,
190 | MessageBoxImage.Error
191 | );
192 | }
193 | }
194 | }
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | en-US
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/FlagSync/FlagSync.View/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/FlagSync/FlagSync.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 11.00
3 | # Visual Studio 2010
4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FlagSync.Core", "FlagSync.Core\FlagSync.Core.csproj", "{1149F3C5-DBFE-4CFD-98F6-DB396343E647}"
5 | EndProject
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FlagSync.View", "FlagSync.View\FlagSync.View.csproj", "{91E37F1B-FE0F-456F-8F67-4058A854FDF8}"
7 | EndProject
8 | Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "FlagSync.Setup", "FlagSync.Setup\FlagSync.Setup.vdproj", "{F1E3BF8E-9B77-404F-ADB2-FC2F8CFFB577}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FlagSync.Data", "FlagSync.Data\FlagSync.Data.csproj", "{080FB9A0-A2F9-438F-8F84-60B7FB448633}"
11 | EndProject
12 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{3E98AE14-9CE5-4194-A0F1-D23ED830E6E0}"
13 | ProjectSection(SolutionItems) = preProject
14 | ..\Changelog.txt = ..\Changelog.txt
15 | EndProjectSection
16 | EndProject
17 | Global
18 | GlobalSection(TestCaseManagementSettings) = postSolution
19 | CategoryFile = FlagSync.vsmdi
20 | EndGlobalSection
21 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
22 | Debug|x86 = Debug|x86
23 | Release|x86 = Release|x86
24 | EndGlobalSection
25 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
26 | {1149F3C5-DBFE-4CFD-98F6-DB396343E647}.Debug|x86.ActiveCfg = Debug|x86
27 | {1149F3C5-DBFE-4CFD-98F6-DB396343E647}.Debug|x86.Build.0 = Debug|x86
28 | {1149F3C5-DBFE-4CFD-98F6-DB396343E647}.Release|x86.ActiveCfg = Release|x86
29 | {1149F3C5-DBFE-4CFD-98F6-DB396343E647}.Release|x86.Build.0 = Release|x86
30 | {91E37F1B-FE0F-456F-8F67-4058A854FDF8}.Debug|x86.ActiveCfg = Debug|x86
31 | {91E37F1B-FE0F-456F-8F67-4058A854FDF8}.Debug|x86.Build.0 = Debug|x86
32 | {91E37F1B-FE0F-456F-8F67-4058A854FDF8}.Release|x86.ActiveCfg = Release|x86
33 | {91E37F1B-FE0F-456F-8F67-4058A854FDF8}.Release|x86.Build.0 = Release|x86
34 | {F1E3BF8E-9B77-404F-ADB2-FC2F8CFFB577}.Debug|x86.ActiveCfg = Debug
35 | {F1E3BF8E-9B77-404F-ADB2-FC2F8CFFB577}.Release|x86.ActiveCfg = Release
36 | {F1E3BF8E-9B77-404F-ADB2-FC2F8CFFB577}.Release|x86.Build.0 = Release
37 | {080FB9A0-A2F9-438F-8F84-60B7FB448633}.Debug|x86.ActiveCfg = Debug|x86
38 | {080FB9A0-A2F9-438F-8F84-60B7FB448633}.Debug|x86.Build.0 = Debug|x86
39 | {080FB9A0-A2F9-438F-8F84-60B7FB448633}.Release|x86.ActiveCfg = Release|x86
40 | {080FB9A0-A2F9-438F-8F84-60B7FB448633}.Release|x86.Build.0 = Release|x86
41 | EndGlobalSection
42 | GlobalSection(SolutionProperties) = preSolution
43 | HideSolutionNode = FALSE
44 | EndGlobalSection
45 | EndGlobal
46 |
--------------------------------------------------------------------------------
/FlagSync/packages/FlagFtp.0.1.2/FlagFtp.0.1.2.nupkg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/FlagSync/packages/FlagFtp.0.1.2/FlagFtp.0.1.2.nupkg
--------------------------------------------------------------------------------
/FlagSync/packages/FlagFtp.0.1.2/lib/FlagFtp.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/FlagSync/packages/FlagFtp.0.1.2/lib/FlagFtp.dll
--------------------------------------------------------------------------------
/FlagSync/packages/MahApps.Metro.0.8.0.0/MahApps.Metro.0.8.0.0.nupkg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/FlagSync/packages/MahApps.Metro.0.8.0.0/MahApps.Metro.0.8.0.0.nupkg
--------------------------------------------------------------------------------
/FlagSync/packages/MahApps.Metro.0.8.0.0/lib/net40/MahApps.Metro.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/FlagSync/packages/MahApps.Metro.0.8.0.0/lib/net40/MahApps.Metro.dll
--------------------------------------------------------------------------------
/FlagSync/packages/MahApps.Metro.0.8.0.0/lib/net40/System.Windows.Interactivity.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/FlagSync/packages/MahApps.Metro.0.8.0.0/lib/net40/System.Windows.Interactivity.dll
--------------------------------------------------------------------------------
/FlagSync/packages/MahApps.Metro.0.8.0.0/tools/install.ps1:
--------------------------------------------------------------------------------
1 | param($rootPath, $toolsPath, $package, $project)
2 |
3 | $project.DTE.ItemOperations.Navigate('http://mahapps.com/MahApps.Metro/')
--------------------------------------------------------------------------------
/FlagSync/packages/Rareform.1.2.0/Rareform.1.2.0.nupkg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/FlagSync/packages/Rareform.1.2.0/Rareform.1.2.0.nupkg
--------------------------------------------------------------------------------
/FlagSync/packages/Rareform.1.2.0/lib/Rareform.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/FlagSync/packages/Rareform.1.2.0/lib/Rareform.dll
--------------------------------------------------------------------------------
/FlagSync/packages/repositories.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Releases/1.0.0/FlagSync-1.0.0.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/Releases/1.0.0/FlagSync-1.0.0.exe
--------------------------------------------------------------------------------
/Releases/1.1.0/FlagSync-1.1.0.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/Releases/1.1.0/FlagSync-1.1.0.exe
--------------------------------------------------------------------------------
/Releases/1.2.0/FlagSync-1.2.0.rar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/Releases/1.2.0/FlagSync-1.2.0.rar
--------------------------------------------------------------------------------
/Releases/1.2.1/FlagSync-1.2.1.rar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/Releases/1.2.1/FlagSync-1.2.1.rar
--------------------------------------------------------------------------------
/Releases/1.3.0/FlagSync-1.3.0.rar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/Releases/1.3.0/FlagSync-1.3.0.rar
--------------------------------------------------------------------------------
/Releases/1.3.1/FlagSync-1.3.1.rar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/Releases/1.3.1/FlagSync-1.3.1.rar
--------------------------------------------------------------------------------
/Releases/1.3.2/FlagSync-1.3.2.rar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/Releases/1.3.2/FlagSync-1.3.2.rar
--------------------------------------------------------------------------------
/Releases/1.3.3/FlagSync-1.3.3.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/Releases/1.3.3/FlagSync-1.3.3.zip
--------------------------------------------------------------------------------
/Releases/2.0.0/FlagSync-2.0.0-portable.rar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/Releases/2.0.0/FlagSync-2.0.0-portable.rar
--------------------------------------------------------------------------------
/Releases/2.0.0/FlagSync-2.0.0.rar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/Releases/2.0.0/FlagSync-2.0.0.rar
--------------------------------------------------------------------------------
/Releases/2.1.0/FlagSync-2.1.0-portable.rar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/Releases/2.1.0/FlagSync-2.1.0-portable.rar
--------------------------------------------------------------------------------
/Releases/2.1.0/FlagSync-2.1.0.rar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/Releases/2.1.0/FlagSync-2.1.0.rar
--------------------------------------------------------------------------------
/Releases/2.1.1/FlagSync-2.1.1-portable.rar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/Releases/2.1.1/FlagSync-2.1.1-portable.rar
--------------------------------------------------------------------------------
/Releases/2.1.1/FlagSync-2.1.1.rar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/Releases/2.1.1/FlagSync-2.1.1.rar
--------------------------------------------------------------------------------
/Releases/2.1.2/FlagSync-2.1.2-portable.rar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/Releases/2.1.2/FlagSync-2.1.2-portable.rar
--------------------------------------------------------------------------------
/Releases/2.1.2/FlagSync-2.1.2.rar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/Releases/2.1.2/FlagSync-2.1.2.rar
--------------------------------------------------------------------------------
/Releases/2.1.3/FlagSync-2.1.3-portable.rar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/Releases/2.1.3/FlagSync-2.1.3-portable.rar
--------------------------------------------------------------------------------
/Releases/2.1.3/FlagSync-2.1.3.rar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/Releases/2.1.3/FlagSync-2.1.3.rar
--------------------------------------------------------------------------------
/Releases/2.2.0/FlagSync-2.2.0-portable.rar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/Releases/2.2.0/FlagSync-2.2.0-portable.rar
--------------------------------------------------------------------------------
/Releases/2.2.0/FlagSync-2.2.0.rar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/Releases/2.2.0/FlagSync-2.2.0.rar
--------------------------------------------------------------------------------
/Releases/2.2.1/FlagSync-2.2.1-portable.rar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/Releases/2.2.1/FlagSync-2.2.1-portable.rar
--------------------------------------------------------------------------------
/Releases/2.2.1/FlagSync-2.2.1.rar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/Releases/2.2.1/FlagSync-2.2.1.rar
--------------------------------------------------------------------------------
/Releases/2.3.0/FlagSync-2.3.0-portable.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/Releases/2.3.0/FlagSync-2.3.0-portable.zip
--------------------------------------------------------------------------------
/Releases/2.3.0/FlagSync-2.3.0.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/Releases/2.3.0/FlagSync-2.3.0.zip
--------------------------------------------------------------------------------
/Releases/2.3.1/FlagSync-2.3.1-portable.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/Releases/2.3.1/FlagSync-2.3.1-portable.zip
--------------------------------------------------------------------------------
/Releases/2.3.1/FlagSync-2.3.1.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/Releases/2.3.1/FlagSync-2.3.1.zip
--------------------------------------------------------------------------------
/Releases/2.4.0/FlagSync-2.4.0-portable.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/Releases/2.4.0/FlagSync-2.4.0-portable.zip
--------------------------------------------------------------------------------
/Releases/2.4.0/FlagSync-2.4.0.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/Releases/2.4.0/FlagSync-2.4.0.zip
--------------------------------------------------------------------------------
/Releases/2.4.1/FlagSync-2.4.1-portable.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/Releases/2.4.1/FlagSync-2.4.1-portable.zip
--------------------------------------------------------------------------------
/Releases/2.4.1/FlagSync-2.4.1.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/Releases/2.4.1/FlagSync-2.4.1.zip
--------------------------------------------------------------------------------
/Releases/2.4.2/FlagSync-2.4.2-portable.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/Releases/2.4.2/FlagSync-2.4.2-portable.zip
--------------------------------------------------------------------------------
/Releases/2.4.2/FlagSync-2.4.2.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flagbug/FlagSync/e1bab60d085de0685773c593ee77f7f9a5c3324c/Releases/2.4.2/FlagSync-2.4.2.zip
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # FlagSync
2 |
3 | ## Overview
4 |
5 | FlagSync is a synchronization and backup tool, that allows you to synchronize or backup your files
6 | with local folders (or an external hard- or flashdrive) or an FTP-Server, as well as synchronize your non-iPod MP3-Player with iTunes.
7 |
8 | ## Features
9 |
10 | - **Backup & Synchronization:** Make a backup to your external harddrive, or synchronize your USB-Stick with your computer.
11 | - **FTP:** Backup your data to an FTP-server or synchronize the files on the server with your PC.
12 | - **iTunes:** You use iTunes but don't have an iPod? FlagSync synchronizes your MP3-Player with iTunes!
13 | - **Batch jobs:** Create an infinite amount of jobs that can be started with one click.
14 | - **Multi-Language:** FlagSync is available in English and German.
15 | - **Portable:** FlagSync is fully portable, but a version for installation is also available.
16 |
17 | ## Media
18 |
19 | - [Addictive Tips][1] - *Aug 19 2011*
20 |
21 | ## Screenshot
22 |
23 | ***Local backup***
24 | ![Local backup][2]
25 |
26 | ***iTunes sync***
27 | ![iTunes sync][3]
28 |
29 | ***FTP backup***
30 | ![FTP backup][4]
31 |
32 | [1]: http://www.addictivetips.com/windows-tips/sync-itunes-with-portable-media-player-backup-data-on-ftp-usb-flagsync
33 | [2]: http://flagbug.github.com/flagsync/local-backup.jpg
34 | [3]: http://flagbug.github.com/flagsync/iTunes-sync.JPG
35 | [4]: http://flagbug.github.com/flagsync/ftp-backup.jpg
36 |
--------------------------------------------------------------------------------