hosts = Factory.service.forHost().updateDatabaseFromWeb();
299 |
300 | if (null == hosts) {
301 | drawStatusBar(Messages.get("webConnectionError"), STATUS_ERROR);
302 | updateMainTab();
303 | return;
304 | }
305 | main.fillBlockedHostObservableList();
306 | updateMainTab();
307 | persistHostsFile();
308 | drawStatusBar(Messages.get("upToDate"), STATUS_OK);
309 | updateButton.setDisable(false);
310 | }
311 |
312 | @FXML
313 | protected void blockNewHost() {
314 | String errorMessage = "";
315 | boolean valid = true;
316 | String domain = blockedHostsTableFilter.getText();
317 |
318 | if (null == domain || 0 == domain.length()) {
319 | valid = false;
320 | errorMessage += "No valid hostname!\n";
321 | }
322 |
323 | if (valid) {
324 | drawStatusBar(Messages.get("blockNewHostStart") + " " + domain, STATUS_UPDATE);
325 |
326 | if (0 == Factory.service.forHost().addHost(domain)) {
327 | drawStatusBar(Messages.get("errorExistingDomain"), STATUS_ERROR);
328 | updateMainTab();
329 | return;
330 | }
331 |
332 | persistHostsFile();
333 | main.fillBlockedHostObservableList();
334 | updateMainTab();
335 | blockedHostsTableFilter.setText("");
336 | drawStatusBar(domain + " " + Messages.get("blockNewHostSuccess"), STATUS_OK);
337 | } else {
338 | drawStatusBar("error adding new host: " + errorMessage, STATUS_ERROR);
339 | }
340 | }
341 |
342 | @FXML
343 | protected void addCustomHost() {
344 | String errorMessage = "";
345 | boolean valid = true;
346 | String domain = customHostsTableFilter.getText();
347 | String address = newCustomAddressField.getText();
348 |
349 | if (null == domain || 0 == domain.length()) {
350 | valid = false;
351 | errorMessage += "No valid hostname!\n";
352 | }
353 | if (null == address || 0 == address.length()) {
354 | valid = false;
355 | errorMessage += "No valid IP!\n";
356 | }
357 |
358 | if (valid) {
359 | int count = Factory.service.forCustomHost().add(domain, address);
360 | if (0 >= count) {
361 | if (count<0)
362 | drawStatusBar(Messages.get("errorCustomAddress"), STATUS_ERROR);
363 | else
364 | drawStatusBar(Messages.get("errorExisitingCustomHost"), STATUS_ERROR);
365 | updateMainTab();
366 | return;
367 | }
368 |
369 | persistHostsFile();
370 | main.fillCustomHostObservableList();
371 | updateMainTab();
372 | customHostsTableFilter.setText("");
373 | newCustomAddressField.setVisible(false);
374 | drawStatusBar(domain + " " + Messages.get("newCustomHostSuccess"), STATUS_OK);
375 | } else
376 | drawStatusBar("error adding new host: " + errorMessage, STATUS_ERROR);
377 | }
378 |
379 | @FXML
380 | /**
381 | * activates/deactivates the selected host in the blocked hosts table
382 | */
383 | protected void toggleBlockedHostStatus() {
384 | Host host = blockedHostsTable.getSelectionModel().getSelectedItem();
385 |
386 | if (null == host)
387 | drawStatusBar(Messages.get("noHostSelected"),STATUS_ERROR);
388 | else {
389 | Factory.service.forHost().toggleStatus(host.getDomain());
390 |
391 | host.setActive(!host.isActive());
392 |
393 | persistHostsFile();
394 | filterBlockedHostsTable();
395 | updateMainTab();
396 |
397 | if (host.isActive())
398 | drawStatusBar(host.getDomain() + " "
399 | + Messages.get("activatedHost"), STATUS_OK);
400 | else
401 | drawStatusBar(host.getDomain() + " "
402 | + Messages.get("unactivatedHost"), STATUS_OK);
403 |
404 | blockedHostsActivationButton.setDisable(true);
405 | }
406 | }
407 |
408 | @FXML
409 | /**
410 | * activates/deactivates the selected host at the custom hosts table
411 | */
412 | protected void toggleCustomHostStatus() {
413 | CustomHost host = customHostsTable.getSelectionModel().getSelectedItem();
414 |
415 | if (null == host)
416 | drawStatusBar(Messages.get("noHostSelected"),STATUS_ERROR);
417 | else {
418 | int updated = Factory.service.forCustomHost().toggleStatus(host.getDomain(), host.getAddress());
419 |
420 | if (updated != 1) {
421 | drawStatusBar("something went wrong", STATUS_ERROR);
422 | return;
423 | }
424 | host.setActive(!host.isActive());
425 |
426 | persistHostsFile();
427 | filterCustomHostsTable();
428 | updateMainTab();
429 |
430 | if (host.isActive())
431 | drawStatusBar(host.getDomain() + " "
432 | + Messages.get("activatedCustomHost") + " "
433 | + host.getAddress(), STATUS_OK);
434 | else
435 | drawStatusBar(host.getDomain() + " "
436 | + Messages.get("unactivatedCustomHost") + " "
437 | + host.getAddress(), STATUS_OK);
438 |
439 | customHostsActivationButton.setDisable(true);
440 | }
441 | }
442 |
443 | @FXML
444 | protected void changeBlockedHostsActivationButton(){
445 | blockedHostsActivationButton.setDisable(false);
446 | Host host = blockedHostsTable.getSelectionModel().getSelectedItem();
447 | if (null == host)
448 | return;
449 | else {
450 | if (blockedHostsTable.getSelectionModel().getSelectedItem().isActive())
451 | blockedHostsActivationButton.setText(
452 | Messages.get("hostsActivationButtonUnblock"));
453 | else
454 | blockedHostsActivationButton.setText(
455 | Messages.get("hostsActivationButtonBlock"));
456 | }
457 | }
458 |
459 | @FXML
460 | protected void changeCustomHostsActivationButton(){
461 | customHostsActivationButton.setDisable(false);
462 | Host cHost = customHostsTable.getSelectionModel().getSelectedItem();
463 | if (null == cHost)
464 | return;
465 | else {
466 | if (cHost.isActive())
467 | customHostsActivationButton.setText(
468 | Messages.get("hostsActivationButtonDeactivate"));
469 | else
470 | customHostsActivationButton.setText(
471 | Messages.get("hostsActivationButtonActivate"));
472 | }
473 |
474 | }
475 |
476 | @FXML
477 | protected void filterBlockedHostsTable() {
478 | String filter = blockedHostsTableFilter.getText();
479 | if (null == filter || "".equals(filter)) {
480 | newBlockedHostButton.setDisable(true);
481 | main.fillBlockedHostObservableList();
482 | drawStatusBar(Messages.get("upToDate"), STATUS_OK);
483 | }
484 | else {
485 | main.fillBlockedHostObservableList(filter);
486 | newBlockedHostButton.setDisable(false);
487 | drawStatusBar(filter + ": " + main.getBlockedHostsData().size()
488 | + " " + Messages.get("matches"), STATUS_OK);
489 | }
490 | }
491 |
492 | @FXML
493 | protected void filterCustomHostsTable() {
494 | String filter = customHostsTableFilter.getText();
495 | if (null == filter || "".equals(filter)) {
496 | newCustomAddressField.setText("");
497 | newCustomAddressField.setVisible(false);
498 | newCustomHostButton.setDisable(true);
499 | main.fillCustomHostObservableList();
500 | drawStatusBar(Messages.get("upToDate"), STATUS_OK);
501 | }
502 | else {
503 | main.fillCustomHostObservableList(filter);
504 | newCustomAddressField.setVisible(true);
505 | newCustomHostButton.setDisable(false);
506 | drawStatusBar(filter + ": " + main.getCustomHostsData().size()
507 | + " " + Messages.get("matches"), STATUS_OK);
508 | }
509 | }
510 |
511 | /*
512 | SETTINGS
513 | */
514 |
515 | @FXML
516 | protected void toggleWindowsDNSClient() {
517 | if (System.getProperty("os.name").toLowerCase().indexOf("win") == -1) {
518 | Logger.err("Trying to modify Windows registry in no-DOS system");
519 | return;
520 | }
521 | try {
522 | boolean wasActivated = WindowsUtil.isDNSClientActivated();
523 | if (WindowsUtil.toggleWindowsDNSClient()) {
524 | if(wasActivated) {
525 | drawStatusBar(Messages.get("WindowsDNSClientDeactivated"), STATUS_OK);
526 | Logger.log("windows DNS client deactivated");
527 | }else {
528 | drawStatusBar(Messages.get("WindowsDNSClientActivated"), STATUS_OK);
529 | Logger.log("windows DNS client activated");
530 | }
531 | } else {
532 | String error = (wasActivated)?
533 | "WindowsDNSClientNotDeactivated"
534 | : "WindowsDNSClientNotActivated";
535 | Logger.err(Messages.get(error));
536 | settingDNSclientCheckBox.setSelected(!wasActivated);
537 | drawStatusBar(Messages.get(error), STATUS_ERROR);
538 | }
539 | } catch (IOException e) {
540 | // Registry cannot be read
541 | Logger.err(e.getMessage());
542 | drawStatusBar(Messages.get("oops"), STATUS_ERROR);
543 | }
544 |
545 | }
546 |
547 | @FXML
548 | protected void toggleWindowsStartup() {
549 | if (System.getProperty("os.name").toLowerCase().indexOf("win") == -1) {
550 | Logger.err("Trying to modify Windows registry in no-DOS system");
551 | return;
552 | }
553 | try {
554 | boolean wasSetUp = WindowsUtil.isRunAtStartup();
555 | if (WindowsUtil.toggleWindowsStartup()) {
556 | if(!wasSetUp) {
557 | drawStatusBar(Messages.get("WindowsStartupDeactivated"), STATUS_OK);
558 | Logger.log("windows Startup deactivated");
559 | }else {
560 | drawStatusBar(Messages.get("WindowsStartupActivated"), STATUS_OK);
561 | Logger.log("windows Startup activated");
562 | }
563 | } else {
564 | String error = (wasSetUp)?
565 | "WindowsStartupNotDeactivated"
566 | : "WindowsStartupNotActivated";
567 | Logger.err(Messages.get(error));
568 | settingStartupCheckBox.setSelected(wasSetUp);
569 | drawStatusBar(Messages.get(error), STATUS_ERROR);
570 | }
571 | } catch (IOException e) {
572 | // Registry cannot be read
573 | Logger.err(e.getMessage());
574 | drawStatusBar(Messages.get("oops"), STATUS_ERROR);
575 | }
576 | }
577 |
578 | @FXML
579 | protected void toggleVihomaStartup() {
580 | Factory.service.forConfiguration().toggleUpdateAtVihomaStart();
581 |
582 | if (Factory.service.forConfiguration().isUpdateAtVihomaStartupEnabled())
583 | drawStatusBar(Messages.get("updateAtVihomaStartupActivated"), STATUS_OK);
584 | else
585 | drawStatusBar(Messages.get("updateAtVihomaStartupDeactivated"), STATUS_OK);
586 | }
587 |
588 | @FXML
589 | protected void changeTargetAddress() {
590 | String newAddress = settingTargetDomainField.getText();
591 | if (null == newAddress || "".equals(newAddress)) {
592 | Factory.service.forConfiguration().setBlockedAddress("");
593 | }
594 | else {
595 | try {
596 | new CustomHost("237441", newAddress);
597 | Factory.service.forConfiguration().setBlockedAddress(newAddress);
598 | } catch (IllegalArgumentException e){
599 | // the address is not valid
600 | drawStatusBar(Messages.get("errorCustomAddress"), STATUS_ERROR);
601 | return;
602 | }
603 | }
604 | persistHostsFile();
605 | drawStatusBar(Messages.get("newBlockedAddress")
606 | + Factory.service.forConfiguration().getBlockedAddress(), STATUS_OK);
607 | }
608 |
609 | @FXML
610 | protected void changeWebSource() {
611 | String newWebSource = settingWebSourceField.getText();
612 | Factory.service.forConfiguration().setWebSource(newWebSource);
613 | updateCategoryCheckboxes();
614 | drawStatusBar(Messages.get("newWebSource") + " "
615 | + Factory.service.forConfiguration().getWebSource(), STATUS_OK);
616 | }
617 |
618 | @FXML
619 | protected void changeWebSourceToDefault() {
620 | settingWebSourceField.setText(Settings.get("defaultWebSourceDomain"));
621 | changeWebSource();
622 | }
623 |
624 | @FXML
625 | protected void changeStevenBlackCategories() {
626 | int categories = 0;
627 | StringBuilder chosenCategories = new StringBuilder();
628 | chosenCategories
629 | .append(Messages.get("categoriesListStart")+" ")
630 | .append(Messages.get("unifiedHosts"));
631 |
632 | if (settingStevenBlackCategoryFakenewsCheckBox.isSelected()) {
633 | categories += Host.CATEGORY_STEVENBLACK_FAKENEWS;
634 | chosenCategories.append(", ").append(Messages.get("fakenews"));
635 | }
636 | if (settingStevenBlackCategoryGamblingCheckBox.isSelected()) {
637 | categories += Host.CATEGORY_STEVENBLACK_GAMBLING;
638 | chosenCategories.append(", ").append(Messages.get("gambling"));
639 | }
640 | if (settingStevenBlackCategoryPornCheckBox.isSelected()) {
641 | categories += Host.CATEGORY_STEVENBLACK_PORN;
642 | chosenCategories.append(", ").append(Messages.get("porn"));
643 | }
644 | if (settingStevenBlackCategorySocialCheckBox.isSelected()) {
645 | categories += Host.CATEGORY_STEVENBLACK_SOCIAL;
646 | chosenCategories.append(", ").append(Messages.get("social"));
647 | }
648 |
649 | Factory.service.forConfiguration().setStevenBlackCategories(categories);
650 | drawStatusBar(chosenCategories.toString(), STATUS_OK);
651 | }
652 |
653 | private void settingsLoader() {
654 | if (System.getProperty("os.name").toLowerCase().indexOf("win") != 0) {
655 | settingDNSclientCheckBox.setDisable(true);
656 | settingStartupCheckBox.setDisable(true);
657 | return;
658 | } else {
659 | try {
660 | settingDNSclientCheckBox.setSelected(
661 | !WindowsUtil.isDNSClientActivated());
662 | settingStartupCheckBox.setSelected(
663 | WindowsUtil.isRunAtStartup());
664 | settingVihomaStartupCheckBox.setSelected(
665 | Factory.service.forConfiguration().isUpdateAtVihomaStartupEnabled());
666 | } catch (IOException e) {
667 | Logger.err(e.getMessage());
668 | }
669 | }
670 | String webSource = Factory.service.forConfiguration().getWebSource();
671 | settingWebSourceField.setText("".equals(webSource)? "":webSource);
672 | updateCategoryCheckboxes();
673 | }
674 |
675 | private void updateCategoryCheckboxes() {
676 | int categories = Factory.service.forConfiguration().getStevenBlackCategories();
677 | settingStevenBlackCategoryFakenewsCheckBox.setSelected(
678 | (categories&Host.CATEGORY_STEVENBLACK_FAKENEWS)
679 | == Host.CATEGORY_STEVENBLACK_FAKENEWS);
680 | settingStevenBlackCategoryGamblingCheckBox.setSelected(
681 | (categories&Host.CATEGORY_STEVENBLACK_GAMBLING)
682 | == Host.CATEGORY_STEVENBLACK_GAMBLING);
683 | settingStevenBlackCategoryPornCheckBox.setSelected(
684 | (categories&Host.CATEGORY_STEVENBLACK_PORN)
685 | == Host.CATEGORY_STEVENBLACK_PORN);
686 | settingStevenBlackCategorySocialCheckBox.setSelected(
687 | (categories&Host.CATEGORY_STEVENBLACK_SOCIAL)
688 | == Host.CATEGORY_STEVENBLACK_SOCIAL);
689 | if (settingWebSourceField.getText().equals(Settings.get("defaultWebSourceDomain"))
690 | || "".equals(settingWebSourceField.getText())) {
691 | settingStevenBlackCategoryFakenewsCheckBox.setDisable(false);
692 | settingStevenBlackCategoryGamblingCheckBox.setDisable(false);
693 | settingStevenBlackCategoryPornCheckBox.setDisable(false);
694 | settingStevenBlackCategorySocialCheckBox.setDisable(false);
695 | } else {
696 | settingStevenBlackCategoryFakenewsCheckBox.setDisable(true);
697 | settingStevenBlackCategoryGamblingCheckBox.setDisable(true);
698 | settingStevenBlackCategoryPornCheckBox.setDisable(true);
699 | settingStevenBlackCategorySocialCheckBox.setDisable(true);
700 | }
701 | }
702 |
703 | @FXML
704 | protected void openHelp() {
705 | if (!WebUtil.openHelp())
706 | drawStatusBar(Messages.get("helpFileNotFound"), STATUS_ERROR);
707 | }
708 |
709 | /*
710 | * ABOUT
711 | */
712 |
713 | @FXML
714 | protected void openGithubLink() {
715 | try {
716 | Desktop.getDesktop().browse(URI.create(Settings.get("sourceCodeHttpLink")));
717 | } catch (IOException e) {
718 | Logger.err(Settings.get("sourceCodeLinkError"));
719 | drawStatusBar(Messages.get("oops"), STATUS_ERROR);
720 | }
721 | }
722 |
723 | /*
724 | * COMMON
725 | */
726 | private void persistHostsFile() {
727 | try {
728 | HostsFileManager.persistHostsFile(
729 | Factory.service.forHost().findAllActive()
730 | , Factory.service.forConfiguration().getBlockedAddress()
731 | , Factory.service.forCustomHost().findAllActive());
732 | //if windows -> ipconfig /flushdns
733 | } catch (IOException e) {
734 | errorExit();
735 | }
736 | }
737 |
738 | private void drawStatusBar(String message, int status) {
739 | Platform.runLater(() -> {
740 | if (null != message) {
741 | this.statusBarLabel.setText(message);
742 | }
743 |
744 | if (STATUS_OK == status)
745 | this.statusBar.setStyle(Settings.get("statusBarColorOk"));
746 | else if (STATUS_UPDATE == status)
747 | this.statusBar.setStyle(Settings.get("statusBarColorUpdate"));
748 | else if (STATUS_ERROR == status)
749 | this.statusBar.setStyle(Settings.get("statusBarColorError"));
750 | });
751 | }
752 |
753 | private void errorExit() {
754 | main.errorExit();
755 | }
756 | }
--------------------------------------------------------------------------------
/src/application/view/RootLayout.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/src/configuration.properties:
--------------------------------------------------------------------------------
1 | #Database
2 | databaseSQLiteUrl=jdbc:sqlite:data/sqlite.db
3 | #blocked hosts sql
4 | sqlCreateHostsTable=CREATE TABLE if not exists hosts(domain varchar(255) NOT NULL PRIMARY KEY, comment varchar(255) DEFAULT NULL,updated_at integer NOT NULL DEFAULT 0, status integer NOT NULL DEFAULT 1, category integer NOT NULL DEFAULT 0, CONSTRAINT fk_hosts_categories FOREIGN KEY (category) REFERENCES categories(id))
5 | sqlDeleteAllHosts=delete from hosts
6 | sqlInsertHost=Insert into hosts(domain,category,status,comment,updated_at) values (?,?,?,?,?)
7 | sqlSelectHosts=Select * from hosts
8 | sqlSelectHostsByStatus=Select * from Hosts where (status & 1) == ?
9 | sqlSelectHostsByCategory=Select * from hosts where category = ?
10 | sqlSelectHostsByDomain=Select * from hosts where domain like ?
11 | sqlSelectHostsByDomainOrCategory=Select * from hosts where domain like ? OR category like ?
12 | sqlSelectHostsCount=Select count(domain) total from hosts where (status & 1) == 1
13 | sqlUpdateHostToggleStatus=update hosts set status = ( ((select status from hosts where domain = ?) | 1) - ((select status from hosts where domain = ?) & 1)) where domain = ?
14 | #custom hosts sql
15 | sqlCreateCustomHostsTable=Create table if not exists customHosts( domain varchar(255) NOT NULL, address varchar(255) NOT NULL, status integer NOT NULL default 1, CONSTRAINT pk_customhosts PRIMARY KEY (domain, address))
16 | sqlDeleteAllCustomHosts=delete from customHosts
17 | sqlInsertCustomHost=Insert into customHosts(domain,address,status) values (?,?,?)
18 | sqlSelectCustomHosts=Select * from customHosts
19 | sqlSelectCustomHostsByStatus=Select * from customHosts where (status & 1) == ?
20 | sqlSelectCustomHostsByDomain=Select * from customHosts where domain = ?
21 | sqlSelectCustomHostsByAddress=Select * from customHosts where address = ?
22 | sqlSelectCustomHostsByDomainOrIp=Select * from customHosts where domain like ? OR address like ?
23 | sqlSelectCustomHostsCount=Select count(domain) total from customHosts where (status & 1) == 1
24 | sqlUpdateCustomHostToggleStatus=update customHosts set status = ( ((select status from customHosts where domain = ? and address = ?) | 1) - ((select status from customHosts where domain = ? and address = ?) & 1)) where domain = ? and address = ?
25 | #configuration sql
26 | sqlCreateConfigurationTable=Create table if not exists configurations(parameter varchar(64) NOT NULL PRIMARY KEY, value varchar(255) NOT NULL)
27 | sqlDeleteAllConfigurations=delete from configuration
28 | sqlSelectConfigurations=Select * from configurations
29 | sqlSelectConfigurationByParameter=Select value from configurations where parameter = ?
30 | sqlInsertConfiguration=Insert into configurations(parameter,value) values (?,?)
31 | sqlUpdateConfiguration=Update configurations set value = ? where parameter = ?
32 | sqlSetConfiguration=IF EXISTS (SELECT * FROM configuration WHERE parameter = ?) UPDATE configuration SET value = ? ELSE INSERT INTO configuration (parameter,value) values (?,?)
33 | #UI
34 | statusBarColorOk=-fx-background-color:#7f7;
35 | statusBarColorUpdate=-fx-background-color:#fc6;
36 | statusBarColorError=-fx-background-color:#f77;
37 | #
38 | vihomaVersion=version 2019.07.17
39 | defaultWebSourceDomain=http://sbc.io
40 | StevenBlack0=http://sbc.io/hosts/hosts
41 | StevenBlack1=http://sbc.io/hosts/alternates/fakenews/hosts
42 | StevenBlack2=http://sbc.io/hosts/alternates/gambling/hosts
43 | StevenBlack4=http://sbc.io/hosts/alternates/porn/hosts
44 | StevenBlack8=http://sbc.io/hosts/alternates/social/hosts
45 | StevenBlack3=http://sbc.io/hosts/alternates/fakenews-gambling/hosts
46 | StevenBlack5=http://sbc.io/hosts/alternates/fakenews-porn/hosts
47 | StevenBlack9=http://sbc.io/hosts/alternates/fakenews-social/hosts
48 | StevenBlack6=http://sbc.io/hosts/alternates/gambling-porn/hosts
49 | StevenBlack10=http://sbc.io/hosts/alternates/gambling-social/hosts
50 | StevenBlack12=http://sbc.io/hosts/alternates/porn-social/hosts
51 | StevenBlack7=http://sbc.io/hosts/alternates/fakenews-gambling-porn/hosts
52 | StevenBlack11=http://sbc.io/hosts/alternates/fakenews-gambling-social/hosts
53 | StevenBlack13=http://sbc.io/hosts/alternates/fakenews-porn-social/hosts
54 | StevenBlack14=http://sbc.io/hosts/alternates/gambling-porn-social/hosts
55 | StevenBlack15=http://sbc.io/hosts/alternates/fakenews-gambling-porn-social/hosts
56 | defaultBlockedAddress=0.0.0.0
57 | helpPathLocationEN=/docs/help_en.html
58 | blockedHostUploadSuccess=was successfully uploaded to the central database
59 | shareHostsEnabled=host sharing enabled
60 | shareHostsDisabled=host sharing disabled
61 | sourceCodeHttpLink=https://github.com/cmabad/ViHoMa
62 | updateAtVihomaStartupDeactivated=update hosts at Vihoma startup deactivated
63 | updateAtVihomaStartupActivated=update hosts at Vihoma startup activated
64 | # HOSTS FILE
65 | hostsFilePathWindows=\\System32\\drivers\\etc\\hosts
66 | hostsFilePathLinux=/etc/hosts
67 | hostsFilePathMac=/etc/hosts
68 | hostsFilePathSolaris=/etc/inet/hosts
69 | hostsFileHeader=#Hosts file managed with ViHoMa\r\n#https://uo237441.duckdns.org\r\n#----------\r\n\r\n127.0.0.1 localhost\r\n0.0.0.0 0.0.0.0\r\n\r\n# The following lines are desirable for IPv6 capable hosts\r\n# ::1 ip6-localhost ip6-loopback\r\n# fe00::0 ip6-localnet\r\n# ff00::0 ip6-mcastprefix\r\n# ff02::1 ip6-allnodes\r\n# ff02::2 ip6-allrouters\r\n
70 | # VIHOMA LOCAL FOLDER
71 | VihomaPathWindows=\\AppData\\Local\\Vihoma\\
72 | VihomaPathLinux=/etc/vihoma/
73 | VihomaPathMac=/etc/vihoma/
74 | VihomaPathSolaris=/etc/vihoma/
75 | #ERRORS
76 | parametersCannotBeNull=The parameters of this function cannot be null
77 | wrongCustomHostIP=The IP is not valid (see Help for more info)
78 | wrongCustomHostDomain=The domain is not valid (see Help for more info)
79 | webSourceConnectionError=The connection to the web source has failed
80 | sourceCodeLinkError=Couldn't open source code web hyperlink
81 | errorRunWithoutAdminRights=The user opened the program without privileges
--------------------------------------------------------------------------------
/src/docs/help_en.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Vihoma help
6 |
12 |
13 |
14 | Vihoma
your Visual Hosts Manager
15 | Thanks for downloading and using Vihoma. This is a help guide which will be opened the first time you run the program, but it can be accessed at any time through the help link you'll find at the program's About tab.
16 | Vihoma is a program that will protect your computer from connecting to unwanted webpages. It works by updating a system file, hosts, which contains a list of domains, like www.virus.com. The connections to the webpages listed here will be automatically blocked by your operating system, keeping you away from threats.
17 | If you are not so familiar with computers, you'll use this program as a security solution. Once Vihoma is run, just click on the update button. It is not needed to keep the program running once it is updated. If your are an advanced user, you may manually block domains, add custom hosts (custom domain and IP address) and even run the program without a graphical interface.
18 |
19 |
20 | Content list
21 |
39 |
40 |
41 | A history lesson and what does Vihoma do
42 |
43 | The World Wide Web is composed of millions of computers distributed all around the world. In order to visit a webpage, the web browser needs to know where the page is located in that huge net.
Just like people and ordinary mail, there are addresses (named IP (Internet Protocol) addresses) that help us reach those external computers. As they are a secuence of numbers difficult to remember, they where replaced by Domain Names, which were texts easily rememberable by humans (like localhost or www.google.com) and which were translated by computers to IPs. This was long ago done locally (on each computer), but the huge expansion of the internet made it impossible to register every new webpage so this was externalized.
44 | That local translations were stored on a system file called hosts, which Vihoma fills with a big list of malicious websites. The Operating System (Windows, Ubuntu, MacOS...) will read that file and block those websites. It is like having an ad-blocker which affects the whole computer instead of acting only on the web browser.
45 | Once Vihoma has updated that list, it can be safely closed, the Operating System will continue with the blocking process.
46 |
47 |
48 |
49 | Where is my hosts file?
50 |
51 | The location of the hosts file changes with the operating system.
52 |
53 | - Windows: %SystemRoot%\Windows\System32\drivers\etc\hosts
54 | - GNU/Linux: /etc/hosts
55 | - MacOS X: /etc/hosts
56 |
57 | You may see its content with a text editor. Any external change will be overwritten by Vihoma.
58 |
59 |
60 |
61 | A host is blocked but I can still connect to it
62 |
63 | Once Vihoma has updated its hosts list or you have manually added one, it is necessary to restart the operating system or your network's manager so the changes can take effect.
64 | If you opt for restarting your network instead of your computer, you may do it following these steps:
65 |
66 | - If you are using Windows, open a command prompt with administrator privileges and run this command:
67 |
68 | - ipconfig /flushdns
69 |
70 |
71 | - If you are using GNU/Linux, open a Terminal and run with root privileges:
72 |
73 | - Debian/Ubuntu sudo service network-manager restart
74 | - Linux Mint sudo /etc/init.d/dns-clean start
75 | - Linux with systemd: sudo systemctl restart network.service
76 |
77 |
78 | - If you are using MacOS X, open a Terminal and run:
79 |
80 | - sudo dscacheutil -flushcache;sudo killall -HUP mDNSResponder
81 |
82 |
83 |
84 | If your operating system is not listed here, check the guide provided on Steven Black's Github hosts repository
85 |
86 |
87 |
88 |
89 | Valid IPs
90 | You can add custom hosts which will be redirected to a specific address. That address can be either IPv4 or IPv6, and has to follow these rules:
91 |
92 | - If IPv4, it has to be formed by 4 groups of numbers from 0 to 255 separated by points. Example:
93 |
96 |
97 | - If IPv6, it has to formed by 8 groups of characters which can be numbers from 0 to 9, letters from a to f and capital letters A to F. Example:
98 |
99 | - 2001:0db8:85a3:08d3:1319:8a2e:0370:7334
100 |
101 |
102 |
103 | Here are the patterns used in the program to check if an IP is valid:
104 |
105 | - \A(25[0-5]|2[0-4]\d|[0-1]?\d?\\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\z
106 | - \A(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\\d|[0-1]?\d?\d)){3}\z
107 | - \A((?:[0-9A-Fa-f]{1,4}:){6,6})(25[0-5]|2[0-4]\d|[0-1]?\d?\\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\z
108 | - \A((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)::((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)\z
109 | - \A(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\z
110 |
111 |
112 |
113 |
114 | HTTPS security risk warning
115 |
116 | If you change the blocking target address to a personal web server to monitor your blocked requests, you may find on your browser some https potential risk warnings. This will happen because the HTTPS specification section 3.1 obligates the https client (e. g. the web browser) to compare the website hostname and the final server's Certificate message domain. As you won't probably have a SSL Certificate for https://google.com, trying to redirect that domain to your personal web server will make the web browser think that a man-in-the-middle attack is taking place.
117 | You can feel safe, the web browser won't send any personal information if you don't explicitly accept the risk; it will just show you a flashy warning. HTTP connections may be redirected without problems.
118 |
119 |
120 |
121 | Vihoma local files
122 |
123 | Vihoma saves some files into your computer in order to run. Those are found inside the Vihoma folder, which may be found in:
124 |
125 | - Windows: %administrator personal folder%\AppData\Local\Vihoma\
126 | - GNU/Linux: /etc/Vihoma/
127 |
128 | Files stored there are: the local database and log files
129 | If the program detects an internal inconsistency and has to restart the database, a hosts security copy is saved here, so you can recover your custom hosts list.
130 |
131 |
132 |
133 | Running Vihoma at system startup
134 |
135 | You can automate the system host management if you allow Vihoma to update its database at system startup. It will run silently and will keep your system up to date. This option is only available on Windows, but you can configure your specific operating system to run Vihoma at the startup. To do it silently, pass to the jar file the argument quiet.
136 |
137 | If you have enabled the program startup but it doesn't work, disable and enable it again. Do this each time you change the program location.
138 |
139 |
140 |
141 | DNS Client
142 | This is applicable only to Windows operating systems.
143 |
144 | Windows has a built-in registry of domains which is no longer needed, and you can just disable it in most of the cases. If it is enabled, you may have to wait several minutes at Windows startup to have internet access. Once it is loaded, you can safely surf the internet.
145 |
146 |
147 |
148 | Custom target Address
149 |
150 | By default, all the blocked hosts will be redirected to the address 0.0.0.0. You can change this if you want, for example, redirect everything to a personal server and log statistics about the domains which are being blocked in real time.
151 |
152 |
153 |
154 | Monitoring the blocked connections
155 |
156 | The hosts file does not provide a built-in feature of counting or logging which hosts has been blocked. Nevertheless, you can monitor the HTTP connections your operating system has blocked if you redirect the unwanted websites to a custom web server. There, just listen to the incoming HTTP requests and check their header values, like that of hostname or referer.
157 |
158 |
159 |
160 | Blocked hosts list source
161 |
162 | By default, Vihoma downloads the list of blocked hosts from http://sbc.io/hosts/hosts, but you can change the input hosts file location. Just make sure that you add a valid HTTP URL (URL parameters are OK).
163 |
164 |
165 |
166 | Host categories
167 |
168 | Vihoma downloads a list of unified hosts that will prevent your computer from connecting to thousands of malicious webpages. If you leave the default web source, you can add even more webpages to block. You can click on the several checkboxes to add more hosts to the list. Each checkbox adds hosts of different categories. Feel free to combine them.
169 | Once you finish the categories selection, update the blocked lists again to amplify your protection.
170 |
171 |
172 |
--------------------------------------------------------------------------------
/src/messages_en.properties:
--------------------------------------------------------------------------------
1 | # status bar
2 | webConnectionError=The connection to the hosts repository has failed. Try later.
3 | checkingNewBlockedHosts=Searching for new malicious hosts...
4 | updatingBlockedHostsList=Updating malicious hosts list...
5 | updating=Updating, this may take a while.\nPlease do not close the application.
6 | upToDate=You are up to date. You can safely close Vihoma.
7 | upToDateAlternative=You are up to date. Alternative source used.
8 | blockNewHostStart=Blocking new host:
9 | blockNewHostUpload=Uploading new host:
10 | blockNewHostSuccess=was successfully blocked
11 | newCustomHostSuccess=was successfully added
12 | noHostSelected=To do that, you need to choose a domain first
13 | deactivatingDomain=Deactivating domain
14 | activatingDomain=Activate
15 | matches=matches
16 | WindowsDNSClientDeactivated=The network will start fast (DNS Client Autostart deactivated)
17 | WindowsDNSClientActivated=The network will take some minutes to start (DNS Client Autostart activated)
18 | WindowsStartupDeactivated=Vihoma will update the hosts at system startup
19 | WindowsStartupActivated=Vihoma won't update the hosts at system startup
20 | newBlockedAddress=The blocked hosts now will be redirected to the address
21 | newWebsource=The blocked hosts list will be downloaded from
22 | unactivatedHost=is no longer blocked
23 | activatedHost=is now blocked
24 | unactivatedCustomHost=is no longer redirected to
25 | activatedCustomHost=is now redirected to
26 | shareHostsEnabled=Blocked hosts will now be shared. Thanks!
27 | shareHostsDisabled=No information will be sent to the central database.
28 | updateAtVihomaStartupActivated=Vihoma will update the blocked hosts list at startup
29 | updateAtVihomaStartupDeactivated=Vihoma won't update the blocked hosts list at startup
30 | pleaseUpdate=Vihoma is not blocking any connections. Please update the malicious domains list.
31 | categoriesListStart=Blocked hosts at next update:
32 | unifiedHosts=basic list
33 | fakenews=fakenews
34 | gambling=gambling
35 | porn=porn
36 | social=social media
37 | newWebSource=Blocked hosts list will be updated from
38 | # LABELS
39 | blockedHosts=blocked hosts
40 | customHosts=custom hosts
41 | settingStartupCheckBox=Update Vihoma at system start (not available yet)
42 | settingUpdateVihomaStartupCheckBox=Update malicious list at program start
43 | settingDNSclientCheckBox=Make network start faster (Windows only)
44 | settingShareBlockHostsCheckBox=Help Vihoma to block more domains
45 | settingHostsFileSourceLabel=Download hosts file list from (leave blank for default):
46 | help=(?) Help
47 | StevenBlackCategoryLabel=Block additional hosts (only with default web source):
48 | #Share user-blocked domains with Vihoma's central database
49 | vihomaLabel=ViHoMa
50 | vihomaLabelBelow=Your Visual Host Manager
51 | never=never
52 | settingBlockAddressLabel=When blocking a host, use address:
53 | # Buttons
54 | hostsActivationButtonActivate=Enable domain
55 | hostsActivationButtonDeactivate=Disable domain
56 | hostsActivationButtonBlock=Block domain
57 | hostsActivationButtonUnblock=Unblock domain
58 | updateButton=Update malicious domains list
59 | defaultSourceButton=Use default
60 | # ERRORS
61 | WindowsDNSClientNotDeactivated=The DNS Client Autostart could not be deactivated. Are you the administrator?
62 | WindowsDNSClientNotActivated=The DNS Client Autostart could not be activated. Are you the administrator?
63 | WindowsStartupNotDeactivated=The program autostart coud not be deactivated. Are you the administrator?
64 | WindowsStartupNotActivated=The program autostart could not be activated. Are you the administrator?
65 | helpFileNotFound=The help file could not be opened. Check the error log for more info
66 | errorExistingDomain=That host is already stored in the database
67 | errorExisitingCustomHost=That host/address combination already exists in the database
68 | errorCustomAddress=The operation could not be done. Maybe the address does not have the IPv4 / IPv6 format?
69 | oops=Oops! Something went wrong. Check the error log for more info
70 | errorVihomaRequiresAdminRights=This program needs to be run with the administrator user. Please read the README file for more information.
71 | errorDetectedClose=The program has detected an anomaly and needs to close.
--------------------------------------------------------------------------------
/src/resources/ico-big.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cmabad/ViHoMa/b0210941c9289aaba62d93e0b47cd026472cfbfd/src/resources/ico-big.png
--------------------------------------------------------------------------------
/src/resources/ico.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cmabad/ViHoMa/b0210941c9289aaba62d93e0b47cd026472cfbfd/src/resources/ico.png
--------------------------------------------------------------------------------
/src/resources/main-tab.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cmabad/ViHoMa/b0210941c9289aaba62d93e0b47cd026472cfbfd/src/resources/main-tab.PNG
--------------------------------------------------------------------------------
/test/VihomaTesting.java:
--------------------------------------------------------------------------------
1 |
2 | import static org.junit.Assert.fail;
3 |
4 | import java.io.File;
5 | import java.io.FileNotFoundException;
6 | import java.io.IOException;
7 | import java.util.Scanner;
8 |
9 | import org.junit.Before;
10 | import org.junit.BeforeClass;
11 | import org.junit.Test;
12 |
13 | import application.Main;
14 | import application.conf.Factory;
15 | import application.model.CustomHost;
16 | import application.model.Host;
17 | import application.util.HostsFileManager;
18 | import application.util.SystemUtil;
19 | import application.util.WindowsUtil;
20 | import application.util.properties.Settings;
21 |
22 | /**
23 | * This test cases will check the functionalities of the program.
24 | * It is required to run them with administrator privileges.
25 | * THESE TESTS OVERRIDE YOUR VIHOMA DATABASE AND HOSTS FILE!
26 | * @author chris
27 | *
28 | */
29 | public class VihomaTesting {
30 |
31 | private Host testBlockedHost;
32 |
33 | @BeforeClass
34 | public static void initialSetup() {
35 | Main.configure();
36 | }
37 |
38 | @Before
39 | public void dbSetup() {
40 | Factory.service.forHost().deleteAll();
41 | Factory.service.forCustomHost().deleteAll();
42 | Factory.service.forHost().addHost("VihomaBlockedHost");
43 | testBlockedHost = Factory.service.forHost().findByDomain("VihomaBlockedHost").get(0);
44 | Factory.service.forCustomHost().add("VihomaCustomHost", "1.2.3.4");
45 | Factory.service.forConfiguration().setBlockedAddress("");
46 | Factory.service.forConfiguration().setWebSource("");
47 | persistHostsFile();
48 | }
49 |
50 | /**
51 | * looks for a term or expression in the local hosts file
52 | * @param text the string to search
53 | */
54 | private boolean existsInHostsFile(String text) {
55 | File hosts = new File(SystemUtil.getHostsPath());
56 | try {
57 | Scanner scanner = new Scanner(hosts);
58 | while (scanner.hasNextLine()) {
59 | scanner.nextLine();
60 | if (scanner.findInLine(text) != null) {
61 | scanner.close();
62 | return true;
63 | }
64 | }
65 | scanner.close();
66 | return false;
67 | } catch (FileNotFoundException e) {
68 | return false;
69 | }
70 | }
71 |
72 | private void persistHostsFile() {
73 | try {
74 | HostsFileManager.persistHostsFile(
75 | Factory.service.forHost().findAllActive()
76 | , Factory.service.forConfiguration().getBlockedAddress()
77 | , Factory.service.forCustomHost().findAllActive());
78 | } catch (IOException e) {
79 | e.printStackTrace();
80 | }
81 | }
82 |
83 | @Test
84 | /**
85 | * Use case 1. An internet connection is required.
86 | */
87 | public void updateDatabaseFromWeb() {
88 | int totalBlocked = (Factory.service.forHost().findAll()).size();
89 | // download
90 | Factory.service.forHost().updateDatabaseFromWeb();
91 | assert(totalBlocked < (Factory.service.forHost().findAll()).size());
92 | persistHostsFile();
93 | assert(existsInHostsFile(testBlockedHost.getDomain()));
94 |
95 | // unblock a host
96 | Factory.service.forHost().toggleStatus(testBlockedHost.getDomain());
97 | persistHostsFile();
98 | assert(!existsInHostsFile(testBlockedHost.getDomain()));
99 |
100 | // download again
101 | Factory.service.forHost().updateDatabaseFromWeb();
102 | persistHostsFile();
103 | assert(!existsInHostsFile(testBlockedHost.getDomain()));
104 | assert(!
105 | ((Factory.service.forHost().findByDomain(testBlockedHost.getDomain()))
106 | .get(0)).isActive().booleanValue());
107 | }
108 |
109 | @Test
110 | /**
111 | * Use case 2
112 | */
113 | public void blockHost() {
114 | Host newHost = new Host("newBlockedHost");
115 |
116 | // block correctly
117 | assert(1==
118 | Factory.service.forHost().addHost(newHost.getDomain(),Host.CATEGORY_VIHOMA));
119 |
120 | // block an existing blocked host
121 | assert(0==
122 | Factory.service.forHost().addHost(newHost.getDomain(),Host.CATEGORY_VIHOMA));
123 | }
124 |
125 | @Test
126 | /**
127 | * Use case 3
128 | */
129 | public void addCustomHost() {
130 | CustomHost cHost = new CustomHost("newCustomHost", "4.3.2.1");
131 |
132 | // add correctly
133 | assert(1==
134 | Factory.service.forCustomHost().add(cHost.getDomain(),cHost.getAddress()));
135 |
136 | // add existing custom host
137 | assert(0==
138 | Factory.service.forCustomHost().add(cHost.getDomain(),cHost.getAddress()));
139 |
140 | // add with wrong ip
141 | assert(0 > Factory.service.forCustomHost().add("wrong", "wrongAddress"));
142 | }
143 |
144 | @Test
145 | /**
146 | * Use cases 4, 8, 10, 12
147 | */
148 | public void configurationManagement() {
149 | // change blocking address
150 | String newBlockingAddress = "111.111.111.112";
151 | assert(!existsInHostsFile(newBlockingAddress));
152 | Factory.service.forConfiguration().setBlockedAddress(newBlockingAddress);
153 | persistHostsFile();
154 | assert(existsInHostsFile(newBlockingAddress));
155 |
156 | // change categories
157 | int oldCategories = Factory.service.forConfiguration().getStevenBlackCategories();
158 | Factory.service.forConfiguration()
159 | .setStevenBlackCategories(Host.CATEGORY_STEVENBLACK_BASICS);
160 | Factory.service.forConfiguration()
161 | .setStevenBlackCategories(Host.CATEGORY_STEVENBLACK_PORN);
162 | assert(oldCategories
163 | != Factory.service.forConfiguration().getStevenBlackCategories());
164 | Factory.service.forConfiguration()
165 | .setStevenBlackCategories(oldCategories);
166 |
167 | // update at start
168 | boolean updateAtStart =
169 | Factory.service.forConfiguration().isUpdateAtVihomaStartupEnabled();
170 | Factory.service.forConfiguration().toggleUpdateAtVihomaStart();
171 | assert(updateAtStart
172 | ^Factory.service.forConfiguration().isUpdateAtVihomaStartupEnabled());
173 | Factory.service.forConfiguration().toggleUpdateAtVihomaStart();
174 |
175 | // change web source
176 | String defaultDomain = Settings.get("defaultWebSourceDomain");
177 | String oldSource = Factory.service.forConfiguration().getWebSource();
178 | Factory.service.forConfiguration().setWebSource("");
179 | assert(Factory.service.forConfiguration().getWebSource().startsWith(defaultDomain));
180 | Factory.service.forConfiguration().setWebSource("testingSourceVihoma");
181 | assert(!Factory.service.forConfiguration().getWebSource().startsWith(defaultDomain));
182 | Factory.service.forConfiguration().setWebSource(oldSource);
183 | }
184 |
185 | @Test
186 | /**
187 | * Use case 7
188 | */
189 | public void changeHostActivation() {
190 | Host newHost = new Host("newBlockedHost");
191 | CustomHost cHost = new CustomHost("newCustomHost", "4.3.2.1");
192 | persistHostsFile();
193 | assert(!existsInHostsFile(newHost.getDomain()));
194 | assert(!existsInHostsFile(cHost.getDomain()));
195 |
196 | // add hosts
197 | Factory.service.forHost().addHost(newHost.getDomain(), Host.CATEGORY_VIHOMA);
198 | Factory.service.forHost().addHost("activatedDomain");
199 | Factory.service.forCustomHost().add(cHost.getDomain(), cHost.getAddress());
200 | persistHostsFile();
201 | assert(existsInHostsFile(newHost.getDomain()));
202 | assert(existsInHostsFile(cHost.getDomain()));
203 | assert(existsInHostsFile("activatedDomain"));
204 |
205 | // deactivate
206 | Factory.service.forHost().toggleStatus(newHost.getDomain());
207 | Factory.service.forCustomHost().toggleStatus(cHost.getDomain(),cHost.getAddress());
208 | persistHostsFile();
209 | assert(!existsInHostsFile(newHost.getDomain()));
210 | assert(!existsInHostsFile(cHost.getDomain()));
211 | assert(existsInHostsFile("activatedDomain"));
212 |
213 | // reactivate
214 | Factory.service.forHost().toggleStatus(newHost.getDomain());
215 | Factory.service.forCustomHost().toggleStatus(cHost.getDomain(),cHost.getAddress());
216 | persistHostsFile();
217 | assert(existsInHostsFile(newHost.getDomain()));
218 | assert(existsInHostsFile(cHost.getDomain()));
219 | assert(existsInHostsFile("activatedDomain"));
220 | }
221 |
222 | @Test
223 | /**
224 | * Use case 9.
225 | * ONLY WINDOWS OPERATING SYSTEMS
226 | */
227 | public void WindowsDNSClient() {
228 | try {
229 | boolean isActivated = WindowsUtil.isDNSClientActivated();
230 | WindowsUtil.toggleWindowsDNSClient();
231 | assert(isActivated ^ WindowsUtil.isDNSClientActivated());
232 | WindowsUtil.toggleWindowsDNSClient();
233 |
234 | } catch (IOException e) {
235 | //e.printStackTrace();
236 | fail();
237 | }
238 |
239 | }
240 |
241 | }
242 |
--------------------------------------------------------------------------------