├── .gitattributes
├── .github
└── FUNDING.yml
├── .gitignore
├── App.config
├── App.xaml
├── App.xaml.cs
├── AssemblyInfo.cs
├── AutoTotal.csproj
├── AutoTotal.sln
├── Autorun+Blocker.cs
├── FolderSpy+Utils.cs
├── LICENSE.txt
├── Properties
├── Resources.Designer.cs
├── Resources.resx
├── Resources.ru-RU.resx
├── Resources.ru.Designer.cs
├── Settings.Designer.cs
├── Settings.settings
└── launchSettings.json
├── README.md
├── README_EN.md
├── SetKeyWindow.xaml
├── SetKeyWindow.xaml.cs
├── Settings.cs
├── SettingsWindow.xaml
├── SettingsWindow.xaml.cs
├── at.ico
├── atsetup.ico
├── build.bat
├── packageicon.png
├── res
├── error.png
├── like.png
└── virustotal.png
└── setup.iss
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | custom: ['https:/boosty.to/notmalware/donate']
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Ww][Ii][Nn]32/
27 | [Aa][Rr][Mm]/
28 | [Aa][Rr][Mm]64/
29 | bld/
30 | [Bb]in/
31 | [Oo]bj/
32 | [Oo]ut/
33 | [Ll]og/
34 | [Ll]ogs/
35 |
36 | # Visual Studio 2015/2017 cache/options directory
37 | .vs/
38 | # Uncomment if you have tasks that create the project's static files in wwwroot
39 | #wwwroot/
40 |
41 | # Visual Studio 2017 auto generated files
42 | Generated\ Files/
43 |
44 | # MSTest test Results
45 | [Tt]est[Rr]esult*/
46 | [Bb]uild[Ll]og.*
47 |
48 | # NUnit
49 | *.VisualState.xml
50 | TestResult.xml
51 | nunit-*.xml
52 |
53 | # Build Results of an ATL Project
54 | [Dd]ebugPS/
55 | [Rr]eleasePS/
56 | dlldata.c
57 |
58 | # Benchmark Results
59 | BenchmarkDotNet.Artifacts/
60 |
61 | # .NET Core
62 | project.lock.json
63 | project.fragment.lock.json
64 | artifacts/
65 |
66 | # ASP.NET Scaffolding
67 | ScaffoldingReadMe.txt
68 |
69 | # StyleCop
70 | StyleCopReport.xml
71 |
72 | # Files built by Visual Studio
73 | *_i.c
74 | *_p.c
75 | *_h.h
76 | *.ilk
77 | *.meta
78 | *.obj
79 | *.iobj
80 | *.pch
81 | *.pdb
82 | *.ipdb
83 | *.pgc
84 | *.pgd
85 | *.rsp
86 | *.sbr
87 | *.tlb
88 | *.tli
89 | *.tlh
90 | *.tmp
91 | *.tmp_proj
92 | *_wpftmp.csproj
93 | *.log
94 | *.vspscc
95 | *.vssscc
96 | .builds
97 | *.pidb
98 | *.svclog
99 | *.scc
100 |
101 | # Chutzpah Test files
102 | _Chutzpah*
103 |
104 | # Visual C++ cache files
105 | ipch/
106 | *.aps
107 | *.ncb
108 | *.opendb
109 | *.opensdf
110 | *.sdf
111 | *.cachefile
112 | *.VC.db
113 | *.VC.VC.opendb
114 |
115 | # Visual Studio profiler
116 | *.psess
117 | *.vsp
118 | *.vspx
119 | *.sap
120 |
121 | # Visual Studio Trace Files
122 | *.e2e
123 |
124 | # TFS 2012 Local Workspace
125 | $tf/
126 |
127 | # Guidance Automation Toolkit
128 | *.gpState
129 |
130 | # ReSharper is a .NET coding add-in
131 | _ReSharper*/
132 | *.[Rr]e[Ss]harper
133 | *.DotSettings.user
134 |
135 | # TeamCity is a build add-in
136 | _TeamCity*
137 |
138 | # DotCover is a Code Coverage Tool
139 | *.dotCover
140 |
141 | # AxoCover is a Code Coverage Tool
142 | .axoCover/*
143 | !.axoCover/settings.json
144 |
145 | # Coverlet is a free, cross platform Code Coverage Tool
146 | coverage*.json
147 | coverage*.xml
148 | coverage*.info
149 |
150 | # Visual Studio code coverage results
151 | *.coverage
152 | *.coveragexml
153 |
154 | # NCrunch
155 | _NCrunch_*
156 | .*crunch*.local.xml
157 | nCrunchTemp_*
158 |
159 | # MightyMoose
160 | *.mm.*
161 | AutoTest.Net/
162 |
163 | # Web workbench (sass)
164 | .sass-cache/
165 |
166 | # Installshield output folder
167 | [Ee]xpress/
168 |
169 | # DocProject is a documentation generator add-in
170 | DocProject/buildhelp/
171 | DocProject/Help/*.HxT
172 | DocProject/Help/*.HxC
173 | DocProject/Help/*.hhc
174 | DocProject/Help/*.hhk
175 | DocProject/Help/*.hhp
176 | DocProject/Help/Html2
177 | DocProject/Help/html
178 |
179 | # Click-Once directory
180 | publish/
181 |
182 | # Publish Web Output
183 | *.[Pp]ublish.xml
184 | *.azurePubxml
185 | # Note: Comment the next line if you want to checkin your web deploy settings,
186 | # but database connection strings (with potential passwords) will be unencrypted
187 | *.pubxml
188 | *.publishproj
189 |
190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
191 | # checkin your Azure Web App publish settings, but sensitive information contained
192 | # in these scripts will be unencrypted
193 | PublishScripts/
194 |
195 | # NuGet Packages
196 | *.nupkg
197 | # NuGet Symbol Packages
198 | *.snupkg
199 | # The packages folder can be ignored because of Package Restore
200 | **/[Pp]ackages/*
201 | # except build/, which is used as an MSBuild target.
202 | !**/[Pp]ackages/build/
203 | # Uncomment if necessary however generally it will be regenerated when needed
204 | #!**/[Pp]ackages/repositories.config
205 | # NuGet v3's project.json files produces more ignorable files
206 | *.nuget.props
207 | *.nuget.targets
208 |
209 | # Microsoft Azure Build Output
210 | csx/
211 | *.build.csdef
212 |
213 | # Microsoft Azure Emulator
214 | ecf/
215 | rcf/
216 |
217 | # Windows Store app package directories and files
218 | AppPackages/
219 | BundleArtifacts/
220 | Package.StoreAssociation.xml
221 | _pkginfo.txt
222 | *.appx
223 | *.appxbundle
224 | *.appxupload
225 |
226 | # Visual Studio cache files
227 | # files ending in .cache can be ignored
228 | *.[Cc]ache
229 | # but keep track of directories ending in .cache
230 | !?*.[Cc]ache/
231 |
232 | # Others
233 | ClientBin/
234 | ~$*
235 | *~
236 | *.dbmdl
237 | *.dbproj.schemaview
238 | *.jfm
239 | *.pfx
240 | *.publishsettings
241 | orleans.codegen.cs
242 |
243 | # Including strong name files can present a security risk
244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
245 | #*.snk
246 |
247 | # Since there are multiple workflows, uncomment next line to ignore bower_components
248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
249 | #bower_components/
250 |
251 | # RIA/Silverlight projects
252 | Generated_Code/
253 |
254 | # Backup & report files from converting an old project file
255 | # to a newer Visual Studio version. Backup files are not needed,
256 | # because we have git ;-)
257 | _UpgradeReport_Files/
258 | Backup*/
259 | UpgradeLog*.XML
260 | UpgradeLog*.htm
261 | ServiceFabricBackup/
262 | *.rptproj.bak
263 |
264 | # SQL Server files
265 | *.mdf
266 | *.ldf
267 | *.ndf
268 |
269 | # Business Intelligence projects
270 | *.rdl.data
271 | *.bim.layout
272 | *.bim_*.settings
273 | *.rptproj.rsuser
274 | *- [Bb]ackup.rdl
275 | *- [Bb]ackup ([0-9]).rdl
276 | *- [Bb]ackup ([0-9][0-9]).rdl
277 |
278 | # Microsoft Fakes
279 | FakesAssemblies/
280 |
281 | # GhostDoc plugin setting file
282 | *.GhostDoc.xml
283 |
284 | # Node.js Tools for Visual Studio
285 | .ntvs_analysis.dat
286 | node_modules/
287 |
288 | # Visual Studio 6 build log
289 | *.plg
290 |
291 | # Visual Studio 6 workspace options file
292 | *.opt
293 |
294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
295 | *.vbw
296 |
297 | # Visual Studio LightSwitch build output
298 | **/*.HTMLClient/GeneratedArtifacts
299 | **/*.DesktopClient/GeneratedArtifacts
300 | **/*.DesktopClient/ModelManifest.xml
301 | **/*.Server/GeneratedArtifacts
302 | **/*.Server/ModelManifest.xml
303 | _Pvt_Extensions
304 |
305 | # Paket dependency manager
306 | .paket/paket.exe
307 | paket-files/
308 |
309 | # FAKE - F# Make
310 | .fake/
311 |
312 | # CodeRush personal settings
313 | .cr/personal
314 |
315 | # Python Tools for Visual Studio (PTVS)
316 | __pycache__/
317 | *.pyc
318 |
319 | # Cake - Uncomment if you are using it
320 | # tools/**
321 | # !tools/packages.config
322 |
323 | # Tabs Studio
324 | *.tss
325 |
326 | # Telerik's JustMock configuration file
327 | *.jmconfig
328 |
329 | # BizTalk build output
330 | *.btp.cs
331 | *.btm.cs
332 | *.odx.cs
333 | *.xsd.cs
334 |
335 | # OpenCover UI analysis results
336 | OpenCover/
337 |
338 | # Azure Stream Analytics local run output
339 | ASALocalRun/
340 |
341 | # MSBuild Binary and Structured Log
342 | *.binlog
343 |
344 | # NVidia Nsight GPU debugger configuration file
345 | *.nvuser
346 |
347 | # MFractors (Xamarin productivity tool) working folder
348 | .mfractor/
349 |
350 | # Local History for Visual Studio
351 | .localhistory/
352 |
353 | # BeatPulse healthcheck temp database
354 | healthchecksdb
355 |
356 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
357 | MigrationBackup/
358 |
359 | # Ionide (cross platform F# VS Code tools) working folder
360 | .ionide/
361 |
362 | # Fody - auto-generated XML schema
363 | FodyWeavers.xsd
--------------------------------------------------------------------------------
/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | True
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/App.xaml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Win32;
2 | using Notification.Wpf;
3 | using Notification.Wpf.Classes;
4 | using System.Collections.Specialized;
5 | using System.IO;
6 | using System.Windows;
7 | using System.Windows.Media.Imaging;
8 | using Application = System.Windows.Application;
9 |
10 | namespace AutoTotal {
11 |
12 | public static class Data {
13 | internal static readonly NotificationManager notificationManager = new();
14 | internal static readonly Dictionary> progressbars = new();
15 | internal static Mutex? mutex;
16 | internal static SettingsWindow? settings;
17 | }
18 |
19 | public partial class App : Application {
20 | protected override void OnStartup(StartupEventArgs e) {
21 | base.OnStartup(e);
22 | Data.mutex = new Mutex(true, "AutoTotalMutex", out bool isOnlyInstance);
23 | if (string.IsNullOrEmpty(AutoTotal.Properties.Settings.Default.VTKey)) {
24 | // Первый запуск
25 | if (!isOnlyInstance) {
26 | System.Windows.MessageBox.Show(AutoTotal.Properties.Resources.FinishFirstSetup, "AutoTotal", MessageBoxButton.OK, MessageBoxImage.Error);
27 | Environment.Exit(0);
28 | }
29 | new SetKeyWindow().ShowDialog();
30 | AutoTotal.Properties.Settings.Default.Folders = new() { Registry.GetValue(@"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders", "{374DE290-123F-4565-9164-39C4925E467B}", string.Empty)?.ToString() };
31 | AutoTotal.Properties.Settings.Default.Save();
32 | if (!Autorun.Exists()) Autorun.Add();
33 | Data.notificationManager.Show(new NotificationContent {
34 | Title = "AutoTotal",
35 | Message = AutoTotal.Properties.Resources.ProgramWillAutostart,
36 | Type = NotificationType.Information,
37 | TrimType = NotificationTextTrimType.NoTrim,
38 | LeftButtonAction = () => ShowSettings(),
39 | LeftButtonContent = AutoTotal.Properties.Resources.Settings
40 | }, expirationTime: TimeSpan.FromSeconds(10));
41 | }
42 |
43 | new Window {
44 | Width = 1,
45 | Height = 1,
46 | WindowStyle = WindowStyle.None,
47 | ShowInTaskbar = false,
48 | Visibility = Visibility.Hidden
49 | }.Show();
50 |
51 | // Сканирование из командной строки
52 | if (e.Args.Length == 2 && e.Args[0] == "/scan") Task.Run(async () => await Utils.ScanFile(e.Args[1], isOnlyInstance));
53 | if (isOnlyInstance) {
54 | NotifyIcon notifyIcon = new() {
55 | Visible = true,
56 | Icon = new Icon(AppDomain.CurrentDomain.BaseDirectory + "at.ico"),
57 | Text = AutoTotal.Properties.Resources.WorkingInBackground,
58 | ContextMenuStrip = new ContextMenuStrip {
59 | Items = {
60 | new ToolStripMenuItem(AutoTotal.Properties.Resources.Settings, null, (s, e) => ShowSettings()),
61 | new ToolStripMenuItem(AutoTotal.Properties.Resources.AddFolder, null, (s, e) => {
62 | if (Data.settings?.IsVisible ?? false) {
63 | System.Windows.MessageBox.Show(AutoTotal.Properties.Resources.AddFolderForce, AutoTotal.Properties.Resources.AddingFolder, MessageBoxButton.OK, MessageBoxImage.Warning);
64 | return;
65 | }
66 | using var folderBrowserDialog = new FolderBrowserDialog();
67 | folderBrowserDialog.SelectedPath = Registry.GetValue(@"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders", "{374DE290-123F-4565-9164-39C4925E467B}", string.Empty)!.ToString()!;
68 | DialogResult result = folderBrowserDialog.ShowDialog();
69 | if (result == DialogResult.OK && !string.IsNullOrWhiteSpace(folderBrowserDialog.SelectedPath)) {
70 | if (!AutoTotal.Properties.Settings.Default.Folders.Contains(folderBrowserDialog.SelectedPath)) {
71 | AutoTotal.Properties.Settings.Default.Folders.Add(folderBrowserDialog.SelectedPath);
72 | AutoTotal.Properties.Settings.Default.Save();
73 | FolderSpy.Add(folderBrowserDialog.SelectedPath);
74 | }
75 | }
76 | }),
77 | new ToolStripMenuItem(AutoTotal.Properties.Resources.ScanFile, null, (s, e) => {
78 | using var openFileDialog = new System.Windows.Forms.OpenFileDialog();
79 | DialogResult result = openFileDialog.ShowDialog();
80 | if (result == DialogResult.OK && !string.IsNullOrWhiteSpace(openFileDialog.FileName)) Task.Run(async () => await Utils.ScanFile(openFileDialog.FileName));
81 | }),
82 | new ToolStripMenuItem(AutoTotal.Properties.Resources.ChangeVTKey, null, (s, e) => new SetKeyWindow().Show()),
83 | new ToolStripMenuItem(AutoTotal.Properties.Resources.Exit, null, (s, e) => Environment.Exit(1))
84 | }
85 | }
86 | };
87 | if (!e.Args.Contains("/autorun")) {
88 | Data.notificationManager.Show(new NotificationContent {
89 | Title = "AutoTotal",
90 | Message = AutoTotal.Properties.Resources.Started,
91 | Type = NotificationType.Notification,
92 | TrimType = NotificationTextTrimType.NoTrim,
93 | LeftButtonAction = () => ShowSettings(),
94 | LeftButtonContent = AutoTotal.Properties.Resources.Settings,
95 | Icon = new BitmapImage(new Uri("pack://application:,,,/res/virustotal.png")),
96 | }, expirationTime: TimeSpan.FromSeconds(5));
97 | }
98 | StringCollection ToRemove = new();
99 | foreach (string? path in AutoTotal.Properties.Settings.Default.Folders) {
100 | if (!Directory.Exists(path)) {
101 | ToRemove.Add(path);
102 | Data.notificationManager.Show(new NotificationContent {
103 | Title = AutoTotal.Properties.Resources.DisappearedFolder,
104 | Message = path,
105 | Type = NotificationType.Information,
106 | TrimType = NotificationTextTrimType.NoTrim,
107 | LeftButtonAction = () => ShowSettings(),
108 | LeftButtonContent = AutoTotal.Properties.Resources.Settings
109 | }, expirationTime: TimeSpan.FromSeconds(10));
110 | }
111 | else FolderSpy.Add(path);
112 | };
113 | if (ToRemove.Count > 0) {
114 | foreach (string? path in ToRemove) AutoTotal.Properties.Settings.Default.Folders.Remove(path);
115 | AutoTotal.Properties.Settings.Default.Save();
116 | }
117 | }
118 | }
119 |
120 | private static void ShowSettings() {
121 | if (Data.settings == null) {
122 | Data.settings = new SettingsWindow();
123 | Data.settings.Closed += (sender, e) => Data.settings = null;
124 | Data.settings.Show();
125 | }
126 | else Data.settings.Focus();
127 | }
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 |
3 | [assembly: ThemeInfo(
4 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
5 | //(used if a resource is not found in the page,
6 | // or application resource dictionaries)
7 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
8 | //(used if a resource is not found in the page,
9 | // app, or any theme specific resource dictionaries)
10 | )]
11 |
--------------------------------------------------------------------------------
/AutoTotal.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | WinExe
5 | net9.0-windows10.0.19041.0
6 | enable
7 | enable
8 | true
9 | True
10 | 7.0
11 | AutoTotal.App
12 | at.ico
13 | True
14 | AutoTotal
15 | malw.ru
16 | Автоматическое сканирование файлов из Загрузок (и не только) на VirusTotal
17 | https://malw.ru/autototal
18 | packageicon.png
19 | https://github.com/ImMALWARE/AutoTotal
20 | git
21 | VirusTotal, антивирус, сканирование, VT, автоматизация
22 | $(OutputPath)
23 | ru
24 | README.md
25 | 1.1.0.0
26 | 1.1
27 | $(VersionPrefix)
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | Always
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | True
50 | True
51 | Resources.resx
52 |
53 |
54 | True
55 | True
56 | Settings.settings
57 |
58 |
59 |
60 |
61 |
62 | True
63 | \
64 |
65 |
66 | SettingsSingleFileGenerator
67 | Settings.Designer.cs
68 |
69 |
70 | True
71 | \
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 | PublicResXFileCodeGenerator
87 | Resources.Designer.cs
88 |
89 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/AutoTotal.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.8.34322.80
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoTotal", "AutoTotal.csproj", "{7BC46439-9099-4CD7-8DA3-66C97139090B}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {7BC46439-9099-4CD7-8DA3-66C97139090B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {7BC46439-9099-4CD7-8DA3-66C97139090B}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {7BC46439-9099-4CD7-8DA3-66C97139090B}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {7BC46439-9099-4CD7-8DA3-66C97139090B}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {842973A5-F469-4F73-936D-A603B0B7C80E}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/Autorun+Blocker.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Win32;
2 | using System.IO;
3 |
4 | namespace AutoTotal {
5 | internal static class Autorun {
6 | public static void Add() {
7 | using RegistryKey run = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true)!;
8 | run.SetValue("AutoTotal", AppDomain.CurrentDomain.BaseDirectory + "AutoTotal.exe /autorun");
9 | }
10 |
11 | public static void Remove() {
12 | using RegistryKey run = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true)!;
13 | run.DeleteValue("AutoTotal", false);
14 | }
15 |
16 | public static bool Exists() {
17 | using RegistryKey run = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", false)!;
18 | return !string.IsNullOrEmpty(run.GetValue("AutoTotal") as string);
19 | }
20 | }
21 |
22 | internal static class Blocker {
23 |
24 | public static void Block(string path) {
25 | File.WriteAllText(path + ":Zone.Identifier:$DATA", "[ZoneTransfer]\nZoneId=4");
26 | }
27 |
28 | public static void Unblock(string path) {
29 | File.Delete(path + ":Zone.Identifier:$DATA");
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/FolderSpy+Utils.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using Newtonsoft.Json.Linq;
3 | using System.Drawing.Imaging;
4 | using System.IO;
5 | using System.Security.Cryptography;
6 | using System.Windows;
7 | using System.Windows.Media.Imaging;
8 | using MessageBox = System.Windows.MessageBox;
9 | using Notification.Wpf;
10 | using System.Diagnostics;
11 | using System.Net.Http;
12 | using System.Net.Http.Headers;
13 | using Notification.Wpf.Classes;
14 |
15 | namespace AutoTotal {
16 | internal static class FolderSpy {
17 | private static readonly Dictionary watchers = new();
18 | private static readonly string[] extensions = new string[61] {
19 | ".apk", ".app", ".exe", ".ee", ".bat", ".cmd", ".ps1", ".cpl", ".cab", ".com",
20 | ".gadget", ".scr", ".lnk", ".msi", ".mst", ".msp", ".pif", ".paf", ".reg", ".rgs",
21 | ".vb", ".vbe", ".vbs", ".vbscript", ".ws", ".wsf", ".wsh", ".ahk", ".pdf", ".chm",
22 | ".docm", ".dotm", ".jar", ".js", ".jse", ".sct", ".jsx", ".mam", ".otm", ".potm",
23 | ".ppam", ".ppsm", ".pptm", ".py", ".pyc", ".pyo", ".xlam", ".xlsm", ".xltm", ".hta",
24 | ".dll", ".sys", ".drv", ".zip", ".rar", ".7z", ".iso", ".img", ".tar", ".wim",
25 | ".xz"};
26 | private static readonly string[] confirm_extensions = new string[9] {
27 | ".bat", ".cmd", ".js", ".pdf", ".ps1", ".py", ".pyc", ".pyo", ".vbs"
28 | };
29 |
30 | public static void Add(string? path) {
31 | if (path == null) return;
32 | if (watchers.ContainsKey(path)) return;
33 | var watcher = new FileSystemWatcher(path);
34 | watcher.Created += (sender, e) => Task.Run(() => OnFileCreated(sender, e));
35 | watcher.Renamed += (sender, e) => Task.Run(() => OnFileCreated(sender, e));
36 | watcher.IncludeSubdirectories = true;
37 | watcher.EnableRaisingEvents = true;
38 | watchers[path] = watcher;
39 | }
40 |
41 | public static void Remove(string? path) {
42 | if (path == null) return;
43 | if (watchers.TryGetValue(path, out FileSystemWatcher? watcher)) {
44 | watcher.Dispose();
45 | watchers.Remove(path);
46 | };
47 | }
48 |
49 | private static async Task OnFileCreated(object sender, FileSystemEventArgs e) {
50 |
51 | if (extensions.Contains(Path.GetExtension(e.FullPath), StringComparer.OrdinalIgnoreCase)) {
52 | if (new FileInfo(e.FullPath).Length == 0) return;
53 |
54 | async Task ScanTask() {
55 | if (Properties.Settings.Default.BlockFiles) Blocker.Block(e.FullPath);
56 | await Utils.ScanFile(e.FullPath);
57 | if (Properties.Settings.Default.BlockFiles) Blocker.Unblock(e.FullPath);
58 | }
59 |
60 | if (e.Name!.Contains("AyuGram Desktop\\") || e.Name.Contains("Telegram Desktop\\")) {
61 | TaskCompletionSource notificationWaiter = new();
62 | System.Windows.Application.Current.Dispatcher.Invoke(() => {
63 | Data.notificationManager.Show(new NotificationContent {
64 | Title = Properties.Resources.DidFileDownload.Replace("%name%", Path.GetFileName(e.Name)),
65 | Message = Properties.Resources.CantTrackTelegram,
66 | Type = NotificationType.Notification,
67 | TrimType = NotificationTextTrimType.NoTrim,
68 | Icon = Icon.ExtractAssociatedIcon(e.FullPath)?.ToBitmap().ToBitmapImage(),
69 | LeftButtonContent = Properties.Resources.Downloaded,
70 | LeftButtonAction = () => notificationWaiter.TrySetResult(true),
71 | RightButtonContent = Properties.Resources.DontScan,
72 | RightButtonAction = () => notificationWaiter.TrySetResult(false)
73 | }, expirationTime: Timeout.InfiniteTimeSpan, onClose: () => notificationWaiter.TrySetResult(true));
74 | });
75 | await notificationWaiter.Task;
76 | if (notificationWaiter.Task.Result) await ScanTask();
77 | return;
78 | }
79 |
80 | if (confirm_extensions.Contains(Path.GetExtension(e.FullPath), StringComparer.OrdinalIgnoreCase)) {
81 | System.Windows.Application.Current.Dispatcher.Invoke(() => {
82 | Data.notificationManager.Show(new NotificationContent {
83 | Title = $"{Properties.Resources.Scan} {Path.GetFileName(e.Name)}?",
84 | Message = Properties.Resources.UploadedOnlyUponConfirmation,
85 | Type = NotificationType.None,
86 | TrimType = NotificationTextTrimType.NoTrim,
87 | Icon = Icon.ExtractAssociatedIcon(e.FullPath)?.ToBitmap().ToBitmapImage(),
88 | LeftButtonAction = async () => await ScanTask(),
89 | LeftButtonContent = Properties.Resources.Scan,
90 | RightButtonContent = Properties.Resources.No,
91 | RightButtonAction = () => {},
92 | }, expirationTime: TimeSpan.FromSeconds(300));
93 | });
94 | return;
95 | }
96 | await ScanTask();
97 | }
98 | }
99 | }
100 |
101 | internal static class Utils {
102 | public static BitmapImage ToBitmapImage(this Bitmap bitmap) {
103 | using MemoryStream stream = new();
104 | bitmap.Save(stream, ImageFormat.Png);
105 | stream.Position = 0;
106 | BitmapImage bitmapImage = new();
107 | bitmapImage.BeginInit();
108 | bitmapImage.StreamSource = stream;
109 | bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
110 | bitmapImage.EndInit();
111 | return bitmapImage;
112 | }
113 |
114 | public static async Task ScanFile(string path, bool ContinueRun = true) {
115 | TaskCompletionSource notificationWaiter = new();
116 |
117 | if (!File.Exists(path)) {
118 | System.Windows.Application.Current.Dispatcher.Invoke(() => {
119 | Data.notificationManager.Show(new NotificationContent {
120 | Title = "AutoTotal",
121 | Message = Properties.Resources.FileDoesntExist,
122 | Type = NotificationType.Error,
123 | TrimType = NotificationTextTrimType.NoTrim,
124 | Icon = new BitmapImage(new Uri("pack://application:,,,/res/error.png"))
125 | }, expirationTime: TimeSpan.FromSeconds(5), onClose: () => notificationWaiter.TrySetResult(true));
126 | });
127 | await notificationWaiter.Task;
128 | if (!ContinueRun) Environment.Exit(1);
129 | return;
130 | }
131 |
132 | System.Windows.Application.Current.Dispatcher.Invoke(() => {
133 | Data.notificationManager.Show(new NotificationContent {
134 | Title = "AutoTotal",
135 | Message = Properties.Resources.Scanning + Path.GetFileName(path),
136 | Type = NotificationType.Notification,
137 | TrimType = NotificationTextTrimType.NoTrim,
138 | Icon = Icon.ExtractAssociatedIcon(path)?.ToBitmap().ToBitmapImage(),
139 | }, expirationTime: TimeSpan.FromSeconds(5));
140 | });
141 | string md5 = BitConverter.ToString(MD5.Create().ComputeHash(File.OpenRead(path))).Replace("-", "").ToLower();
142 | using HttpClient httpClient = new();
143 | httpClient.DefaultRequestHeaders.Add("x-apikey", Properties.Settings.Default.VTKey);
144 |
145 | HttpResponseMessage response;
146 | try {
147 | response = await httpClient.GetAsync("https://www.virustotal.com/api/v3/files/" + md5);
148 | }
149 | catch (HttpRequestException) {
150 | MessageBox.Show(Properties.Resources.CheckInternetConnection.Replace("%name%", Path.GetFileName(path)), Properties.Resources.ScanError, MessageBoxButton.OK, MessageBoxImage.Error);
151 | if (!ContinueRun) Environment.Exit(1);
152 | return;
153 | }
154 | JObject result = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync())!;
155 | int detects;
156 |
157 | if (result["error"]?["code"]?.ToString() == "NotFoundError") {
158 | // Файла нет на VT, нужно загружать
159 | long size = new FileInfo(path).Length;
160 | if (size / 1048576 >= 650) {
161 | MessageBox.Show(Path.GetFileName(path) + Properties.Resources.FileTooBig, Properties.Resources.ScanError, MessageBoxButton.OK, MessageBoxImage.Warning);
162 | if (!ContinueRun) Environment.Exit(1);
163 | return;
164 | }
165 | System.Windows.Application.Current.Dispatcher.Invoke(() => {
166 | Data.progressbars.Add(path, Data.notificationManager.ShowProgressBar(Properties.Resources.Uploading.Replace("%name%", Path.GetFileName(path)), false, false, "", true, 1U, "...", icon: Icon.ExtractAssociatedIcon(path)?.ToBitmap().ToBitmapImage()));
167 | });
168 | try {
169 | string uploadUrl = size / 1048576 < 32 ?
170 | "https://www.virustotal.com/api/v3/files" :
171 | JsonConvert.DeserializeObject(await httpClient.GetStringAsync("https://www.virustotal.com/api/v3/files/upload_url"))!["data"]!.ToString();
172 |
173 | using MultipartFormDataContent multi = new();
174 | FileStream fs = new(path, FileMode.Open, FileAccess.Read);
175 | StreamContent fileContent = new(fs);
176 | fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data") {
177 | Name = "\"file\"",
178 | FileName = "\"" + Path.GetFileName(path) + "\""
179 | };
180 | fileContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
181 | multi.Add(fileContent);
182 |
183 | // Запускаем в фоне метод, который будет получать и устанавливать прогресс
184 | new Task(new Action(() => ProgressTracker(Path.GetFileName(path), fs, Data.progressbars[path]))).Start();
185 | try {
186 | response = await httpClient.PostAsync(uploadUrl, multi, Data.progressbars[path].Cancel);
187 | }
188 | catch (HttpRequestException) {
189 | MessageBox.Show(Properties.Resources.CheckInternetConnection.Replace("%name%", Path.GetFileName(path)), Properties.Resources.ScanError, MessageBoxButton.OK, MessageBoxImage.Error);
190 | System.Windows.Application.Current.Dispatcher.Invoke(() => {
191 | Data.progressbars[path].Dispose();
192 | Data.progressbars.Remove(path);
193 | });
194 | if (!ContinueRun) Environment.Exit(1);
195 | return;
196 | }
197 | catch (OperationCanceledException) {
198 | System.Windows.Application.Current.Dispatcher.Invoke(() => {
199 | Data.progressbars[path].Dispose();
200 | });
201 | if (!ContinueRun) Environment.Exit(1);
202 | return;
203 | }
204 |
205 | string resp = await response.Content.ReadAsStringAsync();
206 | string url = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync())!["data"]!["links"]!["self"]!.ToString();
207 | System.Windows.Application.Current.Dispatcher.Invoke(() => {
208 | Data.progressbars[path].Dispose();
209 | Data.progressbars[path] = Data.notificationManager.ShowProgressBar(Properties.Resources.IsScanning + Path.GetFileName(path), false, false, "", true, 1U, "", icon: Icon.ExtractAssociatedIcon(path)?.ToBitmap().ToBitmapImage());
210 | });
211 |
212 | // Ждём, когда сканирование завершится
213 | while (true) {
214 | response = await httpClient.GetAsync(url);
215 | result = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync())!;
216 | if (result["error"]?["code"]?.ToString() == "QuotaExceededError") {
217 | MessageBox.Show(Properties.Resources.QuotaExceeded.Replace("%name%", Path.GetFileName(path)), Properties.Resources.TitleLimit, MessageBoxButton.OK, MessageBoxImage.Error);
218 | if (!ContinueRun) Environment.Exit(1);
219 | return;
220 | }
221 | if (result["data"]!["attributes"]!["status"]!.ToString() == "completed") break;
222 | await Task.Delay(3000);
223 | }
224 | }
225 | catch (HttpRequestException) {
226 | MessageBox.Show(Properties.Resources.CheckInternetConnection.Replace("%name%", Path.GetFileName(path)), Properties.Resources.ScanError, MessageBoxButton.OK, MessageBoxImage.Error);
227 | System.Windows.Application.Current.Dispatcher.Invoke(() => {
228 | Data.progressbars[path].Dispose();
229 | Data.progressbars.Remove(path);
230 | });
231 | if (!ContinueRun) Environment.Exit(1);
232 | return;
233 | }
234 | detects = Convert.ToInt32(result["data"]!["attributes"]!["stats"]!["malicious"]);
235 | System.Windows.Application.Current.Dispatcher.Invoke(() => {
236 | Data.progressbars[path].Dispose();
237 | Data.progressbars.Remove(path);
238 | });
239 | }
240 | else if (result["error"]?["code"]?.ToString() == "QuotaExceededError") {
241 | MessageBox.Show(Properties.Resources.QuotaExceeded.Replace("%name%", Path.GetFileName(path)), Properties.Resources.TitleLimit, MessageBoxButton.OK, MessageBoxImage.Error);
242 | if (!ContinueRun) Environment.Exit(1);
243 | return;
244 | }
245 | else {
246 | // Если файл в данный момент сканируется, ожидаем завершения
247 | if (result["data"]!["attributes"]!["last_analysis_date"] == null) {
248 | System.Windows.Application.Current.Dispatcher.Invoke(() => {
249 | Data.progressbars.Add(path, Data.notificationManager.ShowProgressBar(Properties.Resources.IsScanning + Path.GetFileName(path), false, false, "", true, 1U, "Отправка файла", icon: Icon.ExtractAssociatedIcon(path)?.ToBitmap().ToBitmapImage()));
250 | });
251 | try {
252 | while (true) {
253 | response = await httpClient.GetAsync(result["data"]!["links"]!["self"]!.ToString());
254 | result = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync())!;
255 | if (result["error"]?["code"]?.ToString() == "QuotaExceededError") {
256 | MessageBox.Show(Properties.Resources.QuotaExceeded.Replace("%name%", Path.GetFileName(path)), Properties.Resources.TitleLimit, MessageBoxButton.OK, MessageBoxImage.Error);
257 | if (!ContinueRun) Environment.Exit(1);
258 | return;
259 | }
260 | if (result["data"]!["attributes"]!["last_analysis_date"] != null) break;
261 | await Task.Delay(3000);
262 | }
263 | }
264 | catch (HttpRequestException) {
265 | MessageBox.Show(Properties.Resources.CheckInternetConnection.Replace("%name%", Path.GetFileName(path)), Properties.Resources.ScanError, MessageBoxButton.OK, MessageBoxImage.Error);
266 | System.Windows.Application.Current.Dispatcher.Invoke(() => {
267 | Data.progressbars[path].Dispose();
268 | Data.progressbars.Remove(path);
269 | });
270 | if (!ContinueRun) Environment.Exit(1);
271 | return;
272 | }
273 | System.Windows.Application.Current.Dispatcher.Invoke(() => {
274 | Data.progressbars[path].Dispose();
275 | Data.progressbars.Remove(path);
276 | });
277 | }
278 | detects = Convert.ToInt32(result["data"]!["attributes"]!["last_analysis_stats"]!["malicious"]);
279 | }
280 | System.Windows.Application.Current.Dispatcher.Invoke(() => {
281 | NotificationContent content = new() {
282 | TrimType = NotificationTextTrimType.NoTrim,
283 | LeftButtonAction = () => Process.Start(new ProcessStartInfo { FileName = "cmd.exe", Arguments = $"/c start \"\" \"{path}\"", UseShellExecute = true }),
284 | LeftButtonContent = Properties.Resources.Run,
285 | Message = detects + Properties.Resources.AVsDetected
286 | };
287 | if (detects == 0) {
288 | content.Type = NotificationType.Information;
289 | content.Title = Path.GetFileName(path) + Properties.Resources.Clean;
290 | content.Message = Properties.Resources._0detects;
291 | content.Icon = new BitmapImage(new Uri("pack://application:,,,/res/like.png"));
292 | }
293 | else if (detects < 5) {
294 | content.Type = NotificationType.Warning;
295 | content.Title = Path.GetFileName(path) + Properties.Resources.Suspicious;
296 | content.LeftButtonAction = () => Process.Start("explorer", "https://virustotal.com/gui/file/" + md5);
297 | content.LeftButtonContent = Properties.Resources.ShowReport;
298 | content.RightButtonAction = () => { File.Delete(path); };
299 | content.RightButtonContent = Properties.Resources.Delete;
300 | }
301 | else {
302 | content.Type = NotificationType.Error;
303 | content.Title = Path.GetFileName(path) + Properties.Resources.Dangerous;
304 | content.LeftButtonAction = () => Process.Start("explorer", "https://virustotal.com/gui/file/" + md5);
305 | content.LeftButtonContent = Properties.Resources.ShowReport;
306 | content.RightButtonAction = () => { File.Delete(path); };
307 | content.RightButtonContent = Properties.Resources.Delete;
308 | }
309 | Data.notificationManager.Show(content, expirationTime: TimeSpan.FromSeconds(10), onClose: () => notificationWaiter.TrySetResult(true));
310 | });
311 | await notificationWaiter.Task;
312 | if (!ContinueRun) Environment.Exit(1);
313 | }
314 |
315 | static void ProgressTracker(string name, FileStream fs, NotifierProgress<(double?, string, string, bool?)> progressbar) {
316 | int pos = 0;
317 | while (!fs.CanRead || pos != 100) {
318 | pos = (int)Math.Round(100 * (fs.Position / (double)fs.Length));
319 | System.Windows.Application.Current.Dispatcher.Invoke(() => progressbar.Report((pos, "", Properties.Resources.Uploading.Replace("%name%", name), true)));
320 | Thread.Sleep(100);
321 | }
322 | System.Windows.Application.Current.Dispatcher.Invoke(() => progressbar.Report((0, "", Properties.Resources.Processing + name, false)));
323 | }
324 | }
325 | }
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) [year] [fullname]
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // Этот код создан программой.
4 | // Исполняемая версия:4.0.30319.42000
5 | //
6 | // Изменения в этом файле могут привести к неправильной работе и будут потеряны в случае
7 | // повторной генерации кода.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace AutoTotal.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// Класс ресурса со строгой типизацией для поиска локализованных строк и т.д.
17 | ///
18 | // Этот класс создан автоматически классом StronglyTypedResourceBuilder
19 | // с помощью такого средства, как ResGen или Visual Studio.
20 | // Чтобы добавить или удалить член, измените файл .ResX и снова запустите ResGen
21 | // с параметром /str или перестройте свой проект VS.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | public class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Возвращает кэшированный экземпляр ResourceManager, использованный этим классом.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | public static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AutoTotal.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Перезаписывает свойство CurrentUICulture текущего потока для всех
51 | /// обращений к ресурсу с помощью этого класса ресурса со строгой типизацией.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | public static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 |
63 | ///
64 | /// Ищет локализованную строку, похожую на No antiviruses marked it as malicious.
65 | ///
66 | public static string _0detects {
67 | get {
68 | return ResourceManager.GetString("0detects", resourceCulture);
69 | }
70 | }
71 |
72 | ///
73 | /// Ищет локализованную строку, похожую на Add folder.
74 | ///
75 | public static string AddFolder {
76 | get {
77 | return ResourceManager.GetString("AddFolder", resourceCulture);
78 | }
79 | }
80 |
81 | ///
82 | /// Ищет локализованную строку, похожую на Add folder in settings window!.
83 | ///
84 | public static string AddFolderForce {
85 | get {
86 | return ResourceManager.GetString("AddFolderForce", resourceCulture);
87 | }
88 | }
89 |
90 | ///
91 | /// Ищет локализованную строку, похожую на Adding folder.
92 | ///
93 | public static string AddingFolder {
94 | get {
95 | return ResourceManager.GetString("AddingFolder", resourceCulture);
96 | }
97 | }
98 |
99 | ///
100 | /// Ищет локализованную строку, похожую на AutoTotal — Settings.
101 | ///
102 | public static string ATSettings {
103 | get {
104 | return ResourceManager.GetString("ATSettings", resourceCulture);
105 | }
106 | }
107 |
108 | ///
109 | /// Ищет локализованную строку, похожую на Autorun app with Windows.
110 | ///
111 | public static string Autorun {
112 | get {
113 | return ResourceManager.GetString("Autorun", resourceCulture);
114 | }
115 | }
116 |
117 | ///
118 | /// Ищет локализованную строку, похожую на antiviruses marked file as malicious.
119 | ///
120 | public static string AVsDetected {
121 | get {
122 | return ResourceManager.GetString("AVsDetected", resourceCulture);
123 | }
124 | }
125 |
126 | ///
127 | /// Ищет локализованную строку, похожую на Block files until scanned.
128 | ///
129 | public static string BlockFiles {
130 | get {
131 | return ResourceManager.GetString("BlockFiles", resourceCulture);
132 | }
133 | }
134 |
135 | ///
136 | /// Ищет локализованную строку, похожую на I cannot track when the download from Telegram Desktop will finish, so you will need to confirm it manually.
137 | ///
138 | public static string CantTrackTelegram {
139 | get {
140 | return ResourceManager.GetString("CantTrackTelegram", resourceCulture);
141 | }
142 | }
143 |
144 | ///
145 | /// Ищет локализованную строку, похожую на Change VirusTotal API key.
146 | ///
147 | public static string ChangeVTKey {
148 | get {
149 | return ResourceManager.GetString("ChangeVTKey", resourceCulture);
150 | }
151 | }
152 |
153 | ///
154 | /// Ищет локализованную строку, похожую на Changing VirusTotal API key.
155 | ///
156 | public static string ChangingVTKey {
157 | get {
158 | return ResourceManager.GetString("ChangingVTKey", resourceCulture);
159 | }
160 | }
161 |
162 | ///
163 | /// Ищет локализованную строку, похожую на Checking key.
164 | ///
165 | public static string CheckingKey {
166 | get {
167 | return ResourceManager.GetString("CheckingKey", resourceCulture);
168 | }
169 | }
170 |
171 | ///
172 | /// Ищет локализованную строку, похожую на File %name% wasn't scanned! Check internet connection!.
173 | ///
174 | public static string CheckInternetConnection {
175 | get {
176 | return ResourceManager.GetString("CheckInternetConnection", resourceCulture);
177 | }
178 | }
179 |
180 | ///
181 | /// Ищет локализованную строку, похожую на Error while checking key: .
182 | ///
183 | public static string CheckKeyError {
184 | get {
185 | return ResourceManager.GetString("CheckKeyError", resourceCulture);
186 | }
187 | }
188 |
189 | ///
190 | /// Ищет локализованную строку, похожую на is clean!.
191 | ///
192 | public static string Clean {
193 | get {
194 | return ResourceManager.GetString("Clean", resourceCulture);
195 | }
196 | }
197 |
198 | ///
199 | /// Ищет локализованную строку, похожую на is dangerous!.
200 | ///
201 | public static string Dangerous {
202 | get {
203 | return ResourceManager.GetString("Dangerous", resourceCulture);
204 | }
205 | }
206 |
207 | ///
208 | /// Ищет локализованную строку, похожую на Delete file.
209 | ///
210 | public static string Delete {
211 | get {
212 | return ResourceManager.GetString("Delete", resourceCulture);
213 | }
214 | }
215 |
216 | ///
217 | /// Ищет локализованную строку, похожую на Is %name% already download?.
218 | ///
219 | public static string DidFileDownload {
220 | get {
221 | return ResourceManager.GetString("DidFileDownload", resourceCulture);
222 | }
223 | }
224 |
225 | ///
226 | /// Ищет локализованную строку, похожую на Non-existing folder was deleted from the list.
227 | ///
228 | public static string DisappearedFolder {
229 | get {
230 | return ResourceManager.GetString("DisappearedFolder", resourceCulture);
231 | }
232 | }
233 |
234 | ///
235 | /// Ищет локализованную строку, похожую на Do not scan.
236 | ///
237 | public static string DontScan {
238 | get {
239 | return ResourceManager.GetString("DontScan", resourceCulture);
240 | }
241 | }
242 |
243 | ///
244 | /// Ищет локализованную строку, похожую на Downloaded!.
245 | ///
246 | public static string Downloaded {
247 | get {
248 | return ResourceManager.GetString("Downloaded", resourceCulture);
249 | }
250 | }
251 |
252 | ///
253 | /// Ищет локализованную строку, похожую на Exit.
254 | ///
255 | public static string Exit {
256 | get {
257 | return ResourceManager.GetString("Exit", resourceCulture);
258 | }
259 | }
260 |
261 | ///
262 | /// Ищет локализованную строку, похожую на This file doesn't exist.
263 | ///
264 | public static string FileDoesntExist {
265 | get {
266 | return ResourceManager.GetString("FileDoesntExist", resourceCulture);
267 | }
268 | }
269 |
270 | ///
271 | /// Ищет локализованную строку, похожую на is more than 650 MB, it can't be scanned on VirusTotal! Be cautious, make sure you can trust the source!.
272 | ///
273 | public static string FileTooBig {
274 | get {
275 | return ResourceManager.GetString("FileTooBig", resourceCulture);
276 | }
277 | }
278 |
279 | ///
280 | /// Ищет локализованную строку, похожую на Finish first setup!.
281 | ///
282 | public static string FinishFirstSetup {
283 | get {
284 | return ResourceManager.GetString("FinishFirstSetup", resourceCulture);
285 | }
286 | }
287 |
288 | ///
289 | /// Ищет локализованную строку, похожую на Folders list.
290 | ///
291 | public static string FoldersList {
292 | get {
293 | return ResourceManager.GetString("FoldersList", resourceCulture);
294 | }
295 | }
296 |
297 | ///
298 | /// Ищет локализованную строку, похожую на How to get?.
299 | ///
300 | public static string HowToGet {
301 | get {
302 | return ResourceManager.GetString("HowToGet", resourceCulture);
303 | }
304 | }
305 |
306 | ///
307 | /// Ищет локализованную строку, похожую на Invalid key!.
308 | ///
309 | public static string InvalidKey {
310 | get {
311 | return ResourceManager.GetString("InvalidKey", resourceCulture);
312 | }
313 | }
314 |
315 | ///
316 | /// Ищет локализованную строку, похожую на VirusTotal is scanning .
317 | ///
318 | public static string IsScanning {
319 | get {
320 | return ResourceManager.GetString("IsScanning", resourceCulture);
321 | }
322 | }
323 |
324 | ///
325 | /// Ищет локализованную строку, похожую на Key has been changed!.
326 | ///
327 | public static string KeyChanged {
328 | get {
329 | return ResourceManager.GetString("KeyChanged", resourceCulture);
330 | }
331 | }
332 |
333 | ///
334 | /// Ищет локализованную строку, похожую на - folder.
335 | ///
336 | public static string MinusFolder {
337 | get {
338 | return ResourceManager.GetString("MinusFolder", resourceCulture);
339 | }
340 | }
341 |
342 | ///
343 | /// Ищет локализованную строку, похожую на No.
344 | ///
345 | public static string No {
346 | get {
347 | return ResourceManager.GetString("No", resourceCulture);
348 | }
349 | }
350 |
351 | ///
352 | /// Ищет локализованную строку, похожую на + folder.
353 | ///
354 | public static string PlusFolder {
355 | get {
356 | return ResourceManager.GetString("PlusFolder", resourceCulture);
357 | }
358 | }
359 |
360 | ///
361 | /// Ищет локализованную строку, похожую на VirusTotal is processing.
362 | ///
363 | public static string Processing {
364 | get {
365 | return ResourceManager.GetString("Processing", resourceCulture);
366 | }
367 | }
368 |
369 | ///
370 | /// Ищет локализованную строку, похожую на Program will automatically start with Windows! You can change this in settings.
371 | ///
372 | public static string ProgramWillAutostart {
373 | get {
374 | return ResourceManager.GetString("ProgramWillAutostart", resourceCulture);
375 | }
376 | }
377 |
378 | ///
379 | /// Ищет локализованную строку, похожую на File %name% wasn't scanned! Unfortunately, the VirusTotal API usage limit has been reached. Please try scanning again after some time. Alternatively, create a new VirusTotal account and update the key to a new one..
380 | ///
381 | public static string QuotaExceeded {
382 | get {
383 | return ResourceManager.GetString("QuotaExceeded", resourceCulture);
384 | }
385 | }
386 |
387 | ///
388 | /// Ищет локализованную строку, похожую на Run.
389 | ///
390 | public static string Run {
391 | get {
392 | return ResourceManager.GetString("Run", resourceCulture);
393 | }
394 | }
395 |
396 | ///
397 | /// Ищет локализованную строку, похожую на Save.
398 | ///
399 | public static string Save {
400 | get {
401 | return ResourceManager.GetString("Save", resourceCulture);
402 | }
403 | }
404 |
405 | ///
406 | /// Ищет локализованную строку, похожую на Scan.
407 | ///
408 | public static string Scan {
409 | get {
410 | return ResourceManager.GetString("Scan", resourceCulture);
411 | }
412 | }
413 |
414 | ///
415 | /// Ищет локализованную строку, похожую на AutoTotal — Scan error.
416 | ///
417 | public static string ScanError {
418 | get {
419 | return ResourceManager.GetString("ScanError", resourceCulture);
420 | }
421 | }
422 |
423 | ///
424 | /// Ищет локализованную строку, похожую на Scan file....
425 | ///
426 | public static string ScanFile {
427 | get {
428 | return ResourceManager.GetString("ScanFile", resourceCulture);
429 | }
430 | }
431 |
432 | ///
433 | /// Ищет локализованную строку, похожую на Scanning .
434 | ///
435 | public static string Scanning {
436 | get {
437 | return ResourceManager.GetString("Scanning", resourceCulture);
438 | }
439 | }
440 |
441 | ///
442 | /// Ищет локализованную строку, похожую на Settings.
443 | ///
444 | public static string Settings {
445 | get {
446 | return ResourceManager.GetString("Settings", resourceCulture);
447 | }
448 | }
449 |
450 | ///
451 | /// Ищет локализованную строку, похожую на Show report.
452 | ///
453 | public static string ShowReport {
454 | get {
455 | return ResourceManager.GetString("ShowReport", resourceCulture);
456 | }
457 | }
458 |
459 | ///
460 | /// Ищет локализованную строку, похожую на Program was started in background, use tray icon for interacting.
461 | ///
462 | public static string Started {
463 | get {
464 | return ResourceManager.GetString("Started", resourceCulture);
465 | }
466 | }
467 |
468 | ///
469 | /// Ищет локализованную строку, похожую на is suspicious!.
470 | ///
471 | public static string Suspicious {
472 | get {
473 | return ResourceManager.GetString("Suspicious", resourceCulture);
474 | }
475 | }
476 |
477 | ///
478 | /// Ищет локализованную строку, похожую на AutoTotal — VirusTotal API limit.
479 | ///
480 | public static string TitleLimit {
481 | get {
482 | return ResourceManager.GetString("TitleLimit", resourceCulture);
483 | }
484 | }
485 |
486 | ///
487 | /// Ищет локализованную строку, похожую на Scripts and PDFs are uploaded to VT only upon confirmation.
488 | ///
489 | public static string UploadedOnlyUponConfirmation {
490 | get {
491 | return ResourceManager.GetString("UploadedOnlyUponConfirmation", resourceCulture);
492 | }
493 | }
494 |
495 | ///
496 | /// Ищет локализованную строку, похожую на Uploading %name% to VirusTotal.
497 | ///
498 | public static string Uploading {
499 | get {
500 | return ResourceManager.GetString("Uploading", resourceCulture);
501 | }
502 | }
503 |
504 | ///
505 | /// Ищет локализованную строку, похожую на https://github.com/ImMALWARE/AutoTotal/wiki/Obtaining-VirusTotal-API-Key.
506 | ///
507 | public static string WikiLink {
508 | get {
509 | return ResourceManager.GetString("WikiLink", resourceCulture);
510 | }
511 | }
512 |
513 | ///
514 | /// Ищет локализованную строку, похожую на AutoTotal is started in background.
515 | ///
516 | public static string WorkingInBackground {
517 | get {
518 | return ResourceManager.GetString("WorkingInBackground", resourceCulture);
519 | }
520 | }
521 | }
522 | }
523 |
--------------------------------------------------------------------------------
/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | No antiviruses marked it as malicious
122 |
123 |
124 | Add folder
125 |
126 |
127 | Add folder in settings window!
128 |
129 |
130 | Adding folder
131 |
132 |
133 | AutoTotal — Settings
134 |
135 |
136 | Autorun app with Windows
137 |
138 |
139 | antiviruses marked file as malicious
140 |
141 |
142 | Block files until scanned
143 |
144 |
145 | I cannot track when the download from Telegram Desktop will finish, so you will need to confirm it manually
146 |
147 |
148 | Change VirusTotal API key
149 |
150 |
151 | Changing VirusTotal API key
152 |
153 |
154 | Checking key
155 |
156 |
157 | File %name% wasn't scanned! Check internet connection!
158 |
159 |
160 | Error while checking key:
161 |
162 |
163 | is clean!
164 |
165 |
166 | is dangerous!
167 |
168 |
169 | Delete file
170 |
171 |
172 | Is %name% already download?
173 |
174 |
175 | Non-existing folder was deleted from the list
176 |
177 |
178 | Do not scan
179 |
180 |
181 | Downloaded!
182 |
183 |
184 | Exit
185 |
186 |
187 | This file doesn't exist
188 |
189 |
190 | is more than 650 MB, it can't be scanned on VirusTotal! Be cautious, make sure you can trust the source!
191 |
192 |
193 | Finish first setup!
194 |
195 |
196 | Folders list
197 |
198 |
199 | How to get?
200 |
201 |
202 | Invalid key!
203 |
204 |
205 | VirusTotal is scanning
206 |
207 |
208 | Key has been changed!
209 |
210 |
211 | - folder
212 |
213 |
214 | No
215 |
216 |
217 | + folder
218 |
219 |
220 | VirusTotal is processing
221 |
222 |
223 | Program will automatically start with Windows! You can change this in settings
224 |
225 |
226 | File %name% wasn't scanned! Unfortunately, the VirusTotal API usage limit has been reached. Please try scanning again after some time. Alternatively, create a new VirusTotal account and update the key to a new one.
227 |
228 |
229 | Run
230 |
231 |
232 | Save
233 |
234 |
235 | Scan
236 |
237 |
238 | AutoTotal — Scan error
239 |
240 |
241 | Scan file...
242 |
243 |
244 | Scanning
245 |
246 |
247 | Settings
248 |
249 |
250 | Show report
251 |
252 |
253 | Program was started in background, use tray icon for interacting
254 |
255 |
256 | is suspicious!
257 |
258 |
259 | AutoTotal — VirusTotal API limit
260 |
261 |
262 | Scripts and PDFs are uploaded to VT only upon confirmation
263 |
264 |
265 | Uploading %name% to VirusTotal
266 |
267 |
268 | https://github.com/ImMALWARE/AutoTotal/wiki/Obtaining-VirusTotal-API-Key
269 |
270 |
271 | AutoTotal is started in background
272 |
273 |
--------------------------------------------------------------------------------
/Properties/Resources.ru-RU.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | Ни один антивирус не пометил его опасным
122 |
123 |
124 | Добавить папку
125 |
126 |
127 | Добавьте папку в окне настроек!
128 |
129 |
130 | Добавление папки
131 |
132 |
133 | AutoTotal — Настройки
134 |
135 |
136 | Автозапуск приложения с Windows
137 |
138 |
139 | антивирусов пометили файл опасным
140 |
141 |
142 | Блокировать файлы на время сканирования
143 |
144 |
145 | Я не могу отследить, когда загрузка из Telegram Desktop завершится, поэтому придётся подтвердить скачивание вручную
146 |
147 |
148 | Изменить ключ API VirusTotal
149 |
150 |
151 | Изменение ключа API VirusTotal
152 |
153 |
154 | Проверка ключа
155 |
156 |
157 | Файл %name% не просканирован! Проверьте подключение к интернету!
158 |
159 |
160 | Ошибка проверки ключа:
161 |
162 |
163 | чист!
164 |
165 |
166 | опасен!
167 |
168 |
169 | Удалить файл
170 |
171 |
172 | %name% уже скачался?
173 |
174 |
175 | Несуществующая папка была удалена из списка
176 |
177 |
178 | Не сканировать
179 |
180 |
181 | Скачался!
182 |
183 |
184 | Выход
185 |
186 |
187 | Указанный файл не существует
188 |
189 |
190 | весит больше 650 МБ, его нельзя просканировать на VirusTotal! Будьте осторожны, убедитесь, что источнику можно доверять!
191 |
192 |
193 | Сначала завершите первую настройку!
194 |
195 |
196 | Список папок
197 |
198 |
199 | Как получить?
200 |
201 |
202 | Неверный ключ!
203 |
204 |
205 | VirusTotal сканирует
206 |
207 |
208 | Ключ изменён!
209 |
210 |
211 | - папка
212 |
213 |
214 | Нет
215 |
216 |
217 | + папка
218 |
219 |
220 | VirusTotal обрабатывает
221 |
222 |
223 | Программа будет запускаться автоматически при старте Windows! Это можно изменить в настройках
224 |
225 |
226 | Файл %name% не просканирован! К сожалению, достигнут лимит использования API VirusTotal. Попробуйте просканировать снова через некоторое время. Либо создайте новый аккаунт VirusTotal и измените ключ на новый.
227 |
228 |
229 | Запустить
230 |
231 |
232 | Сохранить
233 |
234 |
235 | Сканировать
236 |
237 |
238 | AutoTotal - ошибка сканирования
239 |
240 |
241 | Просканировать файл...
242 |
243 |
244 | Начато сканирование
245 |
246 |
247 | Настройки
248 |
249 |
250 | Показать отчёт
251 |
252 |
253 | Программа была запущена в фоне, используйте значок в трее для взаимодействия
254 |
255 |
256 | подозрителен!
257 |
258 |
259 | AutoTotal — лимит API VirusTotal
260 |
261 |
262 | Скрипты и PDF загружаются на VT только по подтверждению
263 |
264 |
265 | Отправка %name% на VirusTotal
266 |
267 |
268 | https://github.com/ImMALWARE/AutoTotal/wiki/%D0%9F%D0%BE%D0%BB%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D0%B5-API-%D0%BA%D0%BB%D1%8E%D1%87%D0%B0-VirusTotal
269 |
270 |
271 | AutoTotal работает в фоне
272 |
273 |
--------------------------------------------------------------------------------
/Properties/Resources.ru.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // Этот код создан программой.
4 | // Исполняемая версия:4.0.30319.42000
5 | //
6 | // Изменения в этом файле могут привести к неправильной работе и будут потеряны в случае
7 | // повторной генерации кода.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace AutoTotal.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// Класс ресурса со строгой типизацией для поиска локализованных строк и т.д.
17 | ///
18 | // Этот класс создан автоматически классом StronglyTypedResourceBuilder
19 | // с помощью такого средства, как ResGen или Visual Studio.
20 | // Чтобы добавить или удалить член, измените файл .ResX и снова запустите ResGen
21 | // с параметром /str или перестройте свой проект VS.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources___Копировать {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources___Копировать() {
33 | }
34 |
35 | ///
36 | /// Возвращает кэшированный экземпляр ResourceManager, использованный этим классом.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AutoTotal.Properties.Resources - Копировать", typeof(Resources___Копировать).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Перезаписывает свойство CurrentUICulture текущего потока для всех
51 | /// обращений к ресурсу с помощью этого класса ресурса со строгой типизацией.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // Этот код создан программой.
4 | // Исполняемая версия:4.0.30319.42000
5 | //
6 | // Изменения в этом файле могут привести к неправильной работе и будут потеряны в случае
7 | // повторной генерации кода.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace AutoTotal.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.8.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("True")]
29 | public bool BlockFiles {
30 | get {
31 | return ((bool)(this["BlockFiles"]));
32 | }
33 | set {
34 | this["BlockFiles"] = value;
35 | }
36 | }
37 |
38 | [global::System.Configuration.UserScopedSettingAttribute()]
39 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
40 | [global::System.Configuration.DefaultSettingValueAttribute("")]
41 | public string VTKey {
42 | get {
43 | return ((string)(this["VTKey"]));
44 | }
45 | set {
46 | this["VTKey"] = value;
47 | }
48 | }
49 |
50 | [global::System.Configuration.UserScopedSettingAttribute()]
51 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
52 | public global::System.Collections.Specialized.StringCollection Folders {
53 | get {
54 | return ((global::System.Collections.Specialized.StringCollection)(this["Folders"]));
55 | }
56 | set {
57 | this["Folders"] = value;
58 | }
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | True
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "profiles": {
3 | "AutoTotal": {
4 | "commandName": "Project"
5 | }
6 | }
7 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AutoTotal - автоматическое сканирование файлов из Загрузок (и не только) на VirusTotal
2 | [README in English](https://github.com/ImMALWARE/AutoTotal/blob/master/README_EN.md)
3 | ## Добавьте все папки, куда вы скачиваете файлы
4 |  \
5 | По умолчанию добавляется папка Загрузки
6 |
7 | ## Больше не нужно паранойить о том, что скачанный файл небезопасен
8 |  \
9 |  \
10 | 
11 |
12 | ## Используйте свой ключ API VirusTotal
13 | 
14 |
15 | ## Вы не сможете случайно запустить вредоносный файл до завершения сканирования
16 | ### Блокировка файлов на время сканирования (выключается в настройках)
17 | 
18 |
19 | ## Удобно просканировать файлы можно вручную
20 |  \
21 | 
22 |
23 | ## Подтверждение при автосканировании скриптов и PDF (чтобы личные файлы случайно не отправились)
24 | 
25 |
--------------------------------------------------------------------------------
/README_EN.md:
--------------------------------------------------------------------------------
1 | # AutoTotal - Automatic scanning of files from Downloads (not only) on VirusTotal
2 | [README на русском](https://github.com/ImMALWARE/AutoTotal/blob/master/README.md)
3 | ## Add all folders where you download files
4 |  \
5 | By default, the Downloads folder is added
6 |
7 | ## No need to worry about the safety of downloaded files anymore
8 |  \
9 |  \
10 | 
11 |
12 | ## Use your VirusTotal API key
13 | 
14 |
15 | ## You cannot accidentally run a malicious file until the scan is complete
16 | ### Program will block files during the scanning process
17 | 
18 |
19 | ## Conveniently scan files manually
20 |  \
21 | 
22 |
23 | ## Confirmation during automatic scanning of scripts and PDFs (to prevent personal files from being accidentally sent)
24 | 
--------------------------------------------------------------------------------
/SetKeyWindow.xaml:
--------------------------------------------------------------------------------
1 |
12 |
13 |
38 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/SetKeyWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using Notification.Wpf;
2 | using System.Diagnostics;
3 | using System.Net.Http;
4 | using System.Windows;
5 | using System.Windows.Media.Imaging;
6 | using MessageBox = System.Windows.MessageBox;
7 |
8 | namespace AutoTotal {
9 | public partial class SetKeyWindow : Window {
10 | public SetKeyWindow() {
11 | InitializeComponent();
12 | }
13 |
14 | private async void Save(object sender, RoutedEventArgs e) {
15 | SaveButton.IsEnabled = false;
16 | using HttpClient httpClient = new();
17 | httpClient.DefaultRequestHeaders.Add("x-apikey", KeyBox.Password);
18 | HttpResponseMessage response;
19 | try {
20 | response = await httpClient.GetAsync("https://www.virustotal.com/api/v3/domains/google.com");
21 | response.EnsureSuccessStatusCode();
22 | }
23 | catch (HttpRequestException ex) {
24 | MessageBox.Show(ex.Message.Contains("Unauthorized") ? Properties.Resources.InvalidKey : Properties.Resources.CheckKeyError + ex.Message, Properties.Resources.CheckingKey, MessageBoxButton.OK, MessageBoxImage.Error);
25 | SaveButton.IsEnabled = true;
26 | return;
27 | }
28 |
29 | Properties.Settings.Default.VTKey = KeyBox.Password;
30 | Properties.Settings.Default.Save();
31 | Data.notificationManager.Show(new NotificationContent {
32 | Title = "AutoTotal",
33 | Message = Properties.Resources.KeyChanged,
34 | Type = NotificationType.Notification,
35 | TrimType = NotificationTextTrimType.NoTrim,
36 | Icon = new BitmapImage(new Uri("pack://application:,,,/res/virustotal.png")),
37 | }, expirationTime: TimeSpan.FromSeconds(5));
38 | Close();
39 | }
40 |
41 | private void Help(object sender, RoutedEventArgs e) {
42 | Process.Start("explorer", Properties.Resources.WikiLink);
43 | }
44 | }
45 | }
--------------------------------------------------------------------------------
/Settings.cs:
--------------------------------------------------------------------------------
1 | namespace AutoTotal.Properties {
2 |
3 |
4 | // Этот класс позволяет обрабатывать определенные события в классе параметров:
5 | // Событие SettingChanging возникает перед изменением значения параметра.
6 | // Событие PropertyChanged возникает после изменения значения параметра.
7 | // Событие SettingsLoaded возникает после загрузки значений параметров.
8 | // Событие SettingsSaving возникает перед сохранением значений параметров.
9 | internal sealed partial class Settings {
10 |
11 | public Settings() {
12 | // // Для добавления обработчиков событий для сохранения и изменения параметров раскомментируйте приведенные ниже строки:
13 | //
14 | // this.SettingChanging += this.SettingChangingEventHandler;
15 | //
16 | // this.SettingsSaving += this.SettingsSavingEventHandler;
17 | //
18 | }
19 |
20 | private void SettingChangingEventHandler(object sender, System.Configuration.SettingChangingEventArgs e) {
21 | // Добавьте здесь код для обработки события SettingChangingEvent.
22 | }
23 |
24 | private void SettingsSavingEventHandler(object sender, System.ComponentModel.CancelEventArgs e) {
25 | // Добавьте здесь код для обработки события SettingsSaving.
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/SettingsWindow.xaml:
--------------------------------------------------------------------------------
1 |
15 |
16 |
35 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
59 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
--------------------------------------------------------------------------------
/SettingsWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Win32;
2 | using System.Windows;
3 | using System.Windows.Controls;
4 | namespace AutoTotal {
5 | public partial class SettingsWindow : Window {
6 | public SettingsWindow() {
7 | InitializeComponent();
8 | foreach (string path in Properties.Settings.Default.Folders?.OfType() ?? Enumerable.Empty()) Folders.Items.Add(new TextBlock { Text = path });
9 | BlockCheckbox.IsChecked = Properties.Settings.Default.BlockFiles;
10 | AutoRunCheckbox.IsChecked = Autorun.Exists();
11 | }
12 |
13 | private void AddFolder(object sender, RoutedEventArgs e) {
14 | using var folderBrowserDialog = new FolderBrowserDialog();
15 | folderBrowserDialog.SelectedPath = Registry.GetValue(@"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders", "{374DE290-123F-4565-9164-39C4925E467B}", string.Empty)!.ToString()!;
16 | DialogResult result = folderBrowserDialog.ShowDialog();
17 | if (result == System.Windows.Forms.DialogResult.OK && !string.IsNullOrWhiteSpace(folderBrowserDialog.SelectedPath)) {
18 | if (!Properties.Settings.Default.Folders.Contains(folderBrowserDialog.SelectedPath)) {
19 | Properties.Settings.Default.Folders.Add(folderBrowserDialog.SelectedPath);
20 | Properties.Settings.Default.Save();
21 | FolderSpy.Add(folderBrowserDialog.SelectedPath);
22 | Folders.Items.Add(new TextBlock() { Text = folderBrowserDialog.SelectedPath });
23 | }
24 | }
25 | }
26 |
27 | private void DelFolder(object sender, RoutedEventArgs e) {
28 | FolderSpy.Remove((Folders.SelectedItem as TextBlock)?.Text);
29 | Properties.Settings.Default.Folders.Remove((Folders.SelectedItem as TextBlock)?.Text);
30 | Properties.Settings.Default.Save();
31 | Folders.Items.Remove(Folders.SelectedItem);
32 | }
33 |
34 | private void Save(object sender, RoutedEventArgs e) {
35 | Properties.Settings.Default.BlockFiles = BlockCheckbox?.IsChecked ?? false;
36 | if (AutoRunCheckbox.IsChecked ?? false) {
37 | if (!Autorun.Exists()) Autorun.Add();
38 | }
39 | else if (Autorun.Exists()) Autorun.Remove();
40 | Properties.Settings.Default.Save();
41 | Close();
42 | }
43 |
44 | private void ChangeVTKey(object sender, RoutedEventArgs e) {
45 | new SetKeyWindow().Show();
46 | }
47 | }
48 | }
--------------------------------------------------------------------------------
/at.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ImMALWARE/AutoTotal/4a7ba619ddd34e05fb01a58ca3a9550eb056b2ec/at.ico
--------------------------------------------------------------------------------
/atsetup.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ImMALWARE/AutoTotal/4a7ba619ddd34e05fb01a58ca3a9550eb056b2ec/atsetup.ico
--------------------------------------------------------------------------------
/build.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | dotnet publish -c Release --self-contained
--------------------------------------------------------------------------------
/packageicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ImMALWARE/AutoTotal/4a7ba619ddd34e05fb01a58ca3a9550eb056b2ec/packageicon.png
--------------------------------------------------------------------------------
/res/error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ImMALWARE/AutoTotal/4a7ba619ddd34e05fb01a58ca3a9550eb056b2ec/res/error.png
--------------------------------------------------------------------------------
/res/like.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ImMALWARE/AutoTotal/4a7ba619ddd34e05fb01a58ca3a9550eb056b2ec/res/like.png
--------------------------------------------------------------------------------
/res/virustotal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ImMALWARE/AutoTotal/4a7ba619ddd34e05fb01a58ca3a9550eb056b2ec/res/virustotal.png
--------------------------------------------------------------------------------
/setup.iss:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ImMALWARE/AutoTotal/4a7ba619ddd34e05fb01a58ca3a9550eb056b2ec/setup.iss
--------------------------------------------------------------------------------