Merge remote-tracking branch 'LCTT/master'

This commit is contained in:
Xingyu Wang 2019-07-06 09:11:03 +08:00
commit 93eeb98e3b
5 changed files with 634 additions and 1 deletions

View File

@ -1,5 +1,5 @@
[#]: collector: (lujun9972)
[#]: translator: (zhang5788)
[#]: translator: ( )
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )

View File

@ -0,0 +1,99 @@
[#]: collector: (lujun9972)
[#]: translator: ( )
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: subject: (Copy and paste at the Linux command line with xclip)
[#]: via: (https://opensource.com/article/19/7/xclip)
[#]: author: (Scott Nesbitt https://opensource.com/users/scottnesbitt)
Copy and paste at the Linux command line with xclip
======
Learn how to get started with the Linux xclip utility.
![Green paperclips][1]
How do you usually copy all or part of a text file when working on the Linux desktop? Chances are you open the file in a text editor, select all or just the text you want to copy, and paste it somewhere else.
That works. But you can do the job a bit more efficiently at the command line using the [xclip][2] utility. xclip provides a conduit between commands you run in a terminal window and the clipboard in a Linux graphical desktop environment.
### Installing xclip
xclip isn't standard kit with many Linux distributions. To see if it's installed on your computer, open a terminal window and type **which xclip**. If that command returns output like _/usr/bin/xclip_, then you're ready to go. Otherwise, you need to install xclip.
To do that, use your distribution's package manager. Or, if you're adventurous, [grab the source code][2] from GitHub and compile it yourself.
### Doing the basics
Let's say you want to copy the contents of a file to the clipboard. There are two ways to do that with xclip. Type either:
```
`xclip file_name`
```
or
```
`xclip -sel clip file_name`
```
What's the difference between the two commands (aside from the second one being longer)? The first command works if you use the middle button on the mouse to paste text. However, not everyone does. Many people are conditioned to use a right-click menu or to press Ctrl+V to paste text. If you're one of those people (I am!), using the **-sel clip** option ensures you can paste what you want to paste.
### Using xclip with other applications
Copying the contents of a file directly to the clipboard is a neat parlor trick. Chances are, you won't be doing that very often. There are other ways you can use xclip, and those involve pairing it with another command-line application.
That pairing is done with a _pipe_ (|). The pipe redirects the output of one command line application to another. Doing that opens several possibilities. Let's take a look at three of them.
Say you're a system administrator and you need to copy the last 30 lines of a log file into a bug report. Opening the file in a text editor, scrolling down to the end, and copying and pasting is a bit of work. Why not use xclip and the [tail][3] utility to quickly and easily do the deed? Run this command to copy those last 30 lines:
```
`tail -n 30 logfile.log | xclip -sel clip`
```
Quite a bit of my writing goes into some content management system (CMS) or another for publishing on the web. However, I never use a CMS's WYSIWYG editor to write—I write offline in [plain text][4] formatted with [Markdown][5]. That said, many of those editors have an HTML mode. By using this command, I can convert a Markdown-formatted file to HTML using [Pandoc][6] and copy it to the clipboard in one fell swoop:
```
`pandoc -t html file.md | xclip -sel clip`
```
From there, I paste away.
Two of my websites are hosted using [GitLab Pages][7]. I generate the HTTPS certificates for those sites using a tool called [Certbot][8], and I need to copy the certificate for each site to GitLab whenever I renew it. Combining the [cat][9] command and xclip is faster and more efficient than using an editor. For example:
```
`cat /etc/letsencrypt/live/website/fullchain.pem | xclip -sel clip`
```
Is that all you can do with xclip? Definitely not. I'm sure you can find more uses to fit your needs.
### Final thoughts
Not everyone will use xclip. That's fine. It is, however, one of those little utilities that really comes in handy when you need it. And, as I've discovered on a few occasions, you don't know when you'll need it. When that time comes, you'll be glad xclip is there.
--------------------------------------------------------------------------------
via: https://opensource.com/article/19/7/xclip
作者:[Scott Nesbitt][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/scottnesbitt
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/life_paperclips.png?itok=j48op49T (Green paperclips)
[2]: https://github.com/astrand/xclip
[3]: https://en.wikipedia.org/wiki/Tail_(Unix)
[4]: https://plaintextproject.online
[5]: https://gumroad.com/l/learnmarkdown
[6]: https://pandoc.org
[7]: https://docs.gitlab.com/ee/user/project/pages/
[8]: https://certbot.eff.org/
[9]: https://en.wikipedia.org/wiki/Cat_(Unix)

View File

@ -0,0 +1,311 @@
[#]: collector: (lujun9972)
[#]: translator: ( )
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: subject: (Learn object-oriented programming with Python)
[#]: via: (https://opensource.com/article/19/7/get-modular-python-classes)
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
Learn object-oriented programming with Python
======
Make your code more modular with Python classes.
![Developing code.][1]
In my previous article, I explained how to [make Python modular][2] by using functions, creating modules, or both. Functions are invaluable to avoid repeating code you intend to use several times, and modules ensure that you can use your code across different projects. But there's another component to modularity: the class.
If you've heard the term _object-oriented programming_, then you may have some notion of the purpose classes serve. Programmers tend to consider a class as a virtual object, sometimes with a direct correlation to something in the physical world, and other times as a manifestation of some programming concept. Either way, the idea is that you can create a class when you want to create "objects" within a program for you or other parts of the program to interact with.
### Templates without classes
Assume you're writing a game set in a fantasy world, and you need this application to be able to drum up a variety of baddies to bring some excitement into your players' lives. Knowing quite a lot about functions, you might think this sounds like a textbook case for functions: code that needs to be repeated often but is written once with allowance for variations when called.
Here's an example of a purely function-based implementation of an enemy generator:
```
#!/usr/bin/env python3
import random
def enemy(ancestry,gear):
    enemy=ancestry
    weapon=gear
    hp=random.randrange(0,20)
    ac=random.randrange(0,20)
    return [enemy,weapon,hp,ac]
def fight(tgt):
    print("You take a swing at the " + tgt[0] + ".")
    hit=random.randrange(0,20)
    if hit > tgt[3]:
        print("You hit the " + tgt[0] + " for " + str(hit) + " damage!")
        tgt[2] = tgt[2] - hit
    else:
        print("You missed.")
foe=enemy("troll","great axe")
print("You meet a " + foe[0] + " wielding a " + foe[1])
print("Type the a key and then RETURN to attack.")
while True:
    action=input()
    if action.lower() == "a":
        fight(foe)
    if foe[2] < 1:
        print("You killed your foe!")
    else:
        print("The " + foe[0] + " has " + str(foe[2]) + " HP remaining")
```
The **enemy** function creates an enemy with several attributes, such as ancestry, a weapon, health points, and a defense rating. It returns a list of each attribute, representing the sum total of the enemy.
In a sense, this code has created an object, even though it's not using a class yet. Programmers call this "enemy" an _object_ because the result (a list of strings and integers, in this case) of the function represents a singular but complex _thing_ in the game. That is, the strings and integers in the list aren't arbitrary: together, they describe a virtual object.
When writing a collection of descriptors, you use variables so you can use them any time you want to generate an enemy. It's a little like a template.
In the example code, when an attribute of the object is needed, the corresponding list item is retrieved. For instance, to get the ancestry of an enemy, the code looks at **foe[0]**, for health points, it looks at **foe[2]** for health points, and so on.
There's nothing necessarily wrong with this approach. The code runs as expected. You could add more enemies of different types, you could create a list of enemy types and randomly select from the list during enemy creation, and so on. It works well enough, and in fact [Lua][3] uses this principle very effectively to approximate an object-oriented model.
However, there's sometimes more to an object than just a list of attributes.
### The way of the object
In Python, everything is an object. Anything you create in Python is an _instance_ of some predefined template. Even basic strings and integers are derivatives of the Python **type** class. You can witness this for yourself an interactive Python shell:
```
>>> foo=3
>>> type(foo)
<class 'int'>
>>> foo="bar"
>>> type(foo)
<class 'str'>
```
When an object is defined by a class, it is more than just a collection of attributes. Python classes have functions all their own. This is convenient, logically, because actions that pertain only to a certain class of objects are contained within that object's class.
In the example code, the fight code is a function of the main application. That works fine for a simple game, but in a complex one, there would be more than just players and enemies in the game world. There might be townsfolk, livestock, buildings, forests, and so on, and none of them ever need access to a fight function. Placing code for combat in an enemy class means your code is better organized; and in a complex application, that's a significant advantage.
Furthermore, each class has privileged access to its own local variables. An enemy's health points, for instance, isn't data that should ever change except by some function of the enemy class. A random butterfly in the game should not accidentally reduce an enemy's health to 0. Ideally, even without classes, that would never happen, but in a complex application with lots of moving parts, it's a powerful trick of the trade to ensure that parts that don't need to interact with one another never do.
Python classes are also subject to garbage collection. When an instance of a class is no longer used, it is moved out of memory. You may never know when this happens, but you tend to notice when it doesn't happen because your application takes up more memory and runs slower than it should. Isolating data sets into classes helps Python track what is in use and what is no longer needed.
### Classy Python
Here's the same simple combat game using a class for the enemy:
```
#!/usr/bin/env python3
import random
class Enemy():
    def __init__(self,ancestry,gear):
        self.enemy=ancestry
        self.weapon=gear
        self.hp=random.randrange(10,20)
        self.ac=random.randrange(12,20)
        self.alive=True
    def fight(self,tgt):
        print("You take a swing at the " + self.enemy + ".")
        hit=random.randrange(0,20)
        if self.alive and hit > self.ac:
            print("You hit the " + self.enemy + " for " + str(hit) + " damage!")
            self.hp = self.hp - hit
            print("The " + self.enemy + " has " + str(self.hp) + " HP remaining")
        else:
            print("You missed.")
        if self.hp < 1:
            self.alive=False
# game start
foe=Enemy("troll","great axe")
print("You meet a " + foe.enemy + " wielding a " + foe.weapon)
# main loop
while True:
   
    print("Type the a key and then RETURN to attack.")
       
    action=input()
    if action.lower() == "a":
        foe.fight(foe)
               
    if foe.alive == False:
        print("You have won...this time.")
        exit()
```
This version of the game handles the enemy as an object containing the same attributes (ancestry, weapon, health, and defense), plus a new attribute measuring whether the enemy has been vanquished yet, as well as a function for combat.
The first function of a class is a special function called (in Python) an _init_, or initialization, function. This is similar to a [constructor][4] in other languages; it creates an instance of the class, which is identifiable to you by its attributes and to whatever variable you use when invoking the class (**foe** in the example code).
### Self and class instances
The class' functions accept a new form of input you don't see outside of classes: **self**. If you don't include **self**, then Python has no way of knowing _which_ instance of the class to use when you call a class function. It's like challenging a single orc to a duel by saying "I'll fight the orc" in a room full of orcs; nobody knows which one you're referring to, and so bad things happen.
![Image of an Orc, CC-BY-SA by Buch on opengameart.org][5]
CC-BY-SA by Buch on opengameart.org
Each attribute created within a class is prepended with the **self** notation, which identifies that variable as an attribute of the class. Once an instance of a class is spawned, you swap out the **self** prefix with the variable representing that instance. Using this technique, you could challenge just one orc to a duel in a room full of orcs by saying "I'll fight the gorblar.orc"; when Gorblar the Orc hears **gorblar.orc**, he knows which orc you're referring to (him_self_), and so you get a fair fight instead of a brawl. In Python:
```
gorblar=Enemy("orc","sword")
print("The " + gorblar.enemy + " has " + str(gorblar.hp) + " remaining.")
```
Instead of looking to **foe[0]** (as in the functional example) or **gorblar[0]** for the enemy type, you retrieve the class attribute (**gorblar.enemy** or **gorblar.hp** or whatever value for whatever object you need).
### Local variables
If a variable in a class is not prepended with the **self** keyword, then it is a local variable, just as in any function. For instance, no matter what you do, you cannot access the **hit** variable outside the **Enemy.fight** class:
```
>>> print(foe.hit)
Traceback (most recent call last):
  File "./enclass.py", line 38, in <module>
    print(foe.hit)
AttributeError: 'Enemy' object has no attribute 'hit'
>>> print(foe.fight.hit)
Traceback (most recent call last):
  File "./enclass.py", line 38, in <module>
    print(foe.fight.hit)
AttributeError: 'function' object has no attribute 'hit'
```
The **hit** variable is contained within the Enemy class, and only "lives" long enough to serve its purpose in combat.
### More modularity
This example uses a class in the same text document as your main application. In a complex game, it's easier to treat each class almost as if it were its own self-standing application. You see this when multiple developers work on the same application: one developer works on a class, and the other works on the main program, and as long as they communicate with one another about what attributes the class must have, the two code bases can be developed in parallel.
To make this example game modular, split it into two files: one for the main application and one for the class. Were it a more complex application, you might have one file per class, or one file per logical groups of classes (for instance, a file for buildings, a file for natural surroundings, a file for enemies and NPCs, and so on).
Save one file containing just the Enemy class as **enemy.py** and another file containing everything else as **main.py**.
Here's **enemy.py**:
```
import random
class Enemy():
    def __init__(self,ancestry,gear):
        self.enemy=ancestry
        self.weapon=gear
        self.hp=random.randrange(10,20)
        self.stg=random.randrange(0,20)
        self.ac=random.randrange(0,20)
        self.alive=True
    def fight(self,tgt):
        print("You take a swing at the " + self.enemy + ".")
        hit=random.randrange(0,20)
        if self.alive and hit > self.ac:
            print("You hit the " + self.enemy + " for " + str(hit) + " damage!")
            self.hp = self.hp - hit
            print("The " + self.enemy + " has " + str(self.hp) + " HP remaining")
        else:
            print("You missed.")
        if self.hp < 1:
            self.alive=False
```
Here's **main.py**:
```
#!/usr/bin/env python3
import enemy as en
# game start
foe=en.Enemy("troll","great axe")
print("You meet a " + foe.enemy + " wielding a " + foe.weapon)
# main loop
while True:
   
    print("Type the a key and then RETURN to attack.")
    action=input()
    if action.lower() == "a":
        foe.fight(foe)
    if foe.alive == False:
        print("You have won...this time.")
        exit()
```
Importing the module **enemy.py** is done very specifically with a statement that refers to the file of classes as its name without the **.py** extension, followed by a namespace designator of your choosing (for example, **import enemy as en**). This designator is what you use in the code when invoking a class. Instead of just using **Enemy()**, you preface the class with the designator of what you imported, such as **en.Enemy**.
All of these file names are entirely arbitrary, although not uncommon in principle. It's a common convention to name the part of the application that serves as the central hub **main.py**, and a file full of classes is often named in lowercase with the classes inside it, each beginning with a capital letter. Whether you follow these conventions doesn't affect how the application runs, but it does make it easier for experienced Python programmers to quickly decipher how your application works.
There's some flexibility in how you structure your code. For instance, using the code sample, both files must be in the same directory. If you want to package just your classes as a module, then you must create a directory called, for instance, **mybad** and move your classes into it. In **main.py**, your import statement changes a little:
```
`from mybad import enemy as en`
```
Both systems produce the same results, but the latter is best if the classes you have created are generic enough that you think other developers could use them in their projects.
Regardless of which you choose, launch the modular version of the game:
```
$ python3 ./main.py
You meet a troll wielding a great axe
Type the a key and then RETURN to attack.
a
You take a swing at the troll.
You missed.
Type the a key and then RETURN to attack.
a
You take a swing at the troll.
You hit the troll for 8 damage!
The troll has 4 HP remaining
Type the a key and then RETURN to attack.
a
You take a swing at the troll.
You hit the troll for 11 damage!
The troll has -7 HP remaining
You have won...this time.
```
The game works. It's modular. And now you know what it means for an application to be object-oriented. But most importantly, you know to be specific when challenging an orc to a duel.
--------------------------------------------------------------------------------
via: https://opensource.com/article/19/7/get-modular-python-classes
作者:[Seth Kenlon][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/seth
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/code_development_programming.png?itok=M_QDcgz5 (Developing code.)
[2]: https://opensource.com/article/19/6/get-modular-python-functions
[3]: https://opensource.com/article/17/4/how-program-games-raspberry-pi
[4]: https://opensource.com/article/19/6/what-java-constructor
[5]: https://opensource.com/sites/default/files/images/orc-buch-opengameart_cc-by-sa.jpg (CC-BY-SA by Buch on opengameart.org)

View File

@ -0,0 +1,121 @@
[#]: collector: (lujun9972)
[#]: translator: ( )
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: subject: (Manage your shell environment)
[#]: via: (https://fedoramagazine.org/manage-your-shell-environment/)
[#]: author: (Eduard Lucena https://fedoramagazine.org/author/x3mboy/)
Manage your shell environment
======
![][1]
Some time ago, the Fedora Magazine has published an [article introducing ZSH][2] — an alternative shell to Fedoras default, bash. This time, were going to look into customizing it to use it in a more effective way. All of the concepts shown in this article also work in other shells such as bash.
### Alias
Aliases are shortcuts for commands. This is useful for creating short commands for actions that are performed often, but require a long command that would take too much time to type. The syntax is:
```
$ alias yourAlias='complex command with arguments'
```
They dont always need to be used for shortening long commands. Important is that you use them for tasks that you do often. An example could be:
```
$ alias dnfUpgrade='dnf -y upgrade'
```
That way, to do a system upgrade, I just type dnfUpgrade instead of the whole dnf command.
The problem of setting aliases right in the console is that once the terminal session is closed, the alias would be lost. To set them permanently, resource files are used.
### Resource Files
Resource files (or rc files) are configuration files that are loaded per user in the beginning of a session or a process (when a new terminal window is opened, or a new program like vim is started). In the case of ZSH, the resource file is _.zshrc_, and for bash its _.bashrc_.
To make the aliases permanent, you can either put them in your resource. You can edit your resource file with a text editor of your choice. This example uses vim:
```
$ vim $HOME/.zshrc
```
Or for bash:
```
$ vim $HOME/.bashrc
```
Note that the location of the resource file is specified relatively to a home directory — and thats where ZSH (or bash) are going to look for the file by default for each user.
Other option is to put your configuration in any other file, and then source it:
```
$ source /path/to/your/rc/file
```
Again, sourcing it right in your session will only apply it to the session, so to make it permanent, add the source command to your resource file. The advantage of having your source file in a different location is that you can source it any time. Or anywhere which is especially useful in shared environments.
### Environment Variables
Environment variables are values assigned to a specific name which can be then called in scripts and commands. They start with the $ dollar sign. One of the most common is $HOME that references the home directory.
As the name suggests, environment variables are a part of your environment. Set a variable using the following syntax:
```
$ http_proxy="http://your.proxy"
```
And to make it an environment variable, export it with the following command:
```
$ export $http_proxy
```
To see all the environment variables that are currently set, use the _env_ command:
```
$ env
```
The command outputs all the variables available in your session. To demonstrate how to use them in a command, try running the following echo commands:
```
$ echo $PWD
/home/fedora
$ echo $USER
fedora
```
What happens here is variable expansion — the value stored in the variable is used in your command.
Another useful variable is _$PATH_, that defines directories that your shell uses to look for binaries.
### The $PATH variable
There are many directories, or folders (the way they are called in graphical environments) that are important to the OS. Some directories are set to hold binaries you can use directly in your shell. And these directories are defined in the $PATH variable.
```
$ echo $PATH
/usr/lib64/qt-3.3/bin:/usr/share/Modules/bin:/usr/lib64/ccache:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/usr/libexec/sdcc:/usr/libexec/sdcc:/usr/bin:/bin:/sbin:/usr/sbin:/opt/FortiClient
```
This will help you when you want to have your own binaries (or scripts) accessible in the shell.
--------------------------------------------------------------------------------
via: https://fedoramagazine.org/manage-your-shell-environment/
作者:[Eduard Lucena][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://fedoramagazine.org/author/x3mboy/
[b]: https://github.com/lujun9972
[1]: https://fedoramagazine.org/wp-content/uploads/2018/05/manage-shell-env-816x345.jpg
[2]: https://fedoramagazine.org/set-zsh-fedora-system/

View File

@ -0,0 +1,102 @@
[#]: collector: (lujun9972)
[#]: translator: ( )
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: subject: (Say WHAAAT? Mozilla has Been Nominated for the “Internet Villain” Award in the UK)
[#]: via: (https://itsfoss.com/mozilla-internet-villain/)
[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
Say WHAAAT? Mozilla has Been Nominated for the “Internet Villain” Award in the UK
======
Mozilla Firefox is one of the most popular browsers available out there. A lot of users prefer it over Chrome just because it encourages privacy protection and features options to keep your Internet activity as private as possible.
But, one of the recently proposed features **[DoH (DNS-over-HTTPS)][1]** which is still in the testing phase didnt receive a good response from the UKs ISPs trade association.
So, the ISPA (Internet Services Providers Association) of UK decided to [nominate][2] Mozilla as one of the “Internet Villains” among the nominees for 2019. This is for an award ceremony to be held on 11th July in London by the ISP trade association of the UK.
![][3]
### Why “Mozilla” is the “Internet Villain” here?
In their announcement, the ISPA mentioned that Mozilla is one of the Internet Villains for supporting **DoH** (DNS-over-HTTPS).
> [@mozilla][4] is nominated for the [#ISPAs][5] [#InternetVillain][6] for their proposed approach to introduce DNS-over-HTTPS in such a way as to bypass UK filtering obligations and parental controls, undermining [#internet][7] safety standards in the UK. <https://t.co/d9NaiaJYnk> [pic.twitter.com/WeZhLq2uvi][8]
>
> — Internet Services Providers Association (ISPAUK) (@ISPAUK) [July 4, 2019][9]
Along with Mozilla, Article 13 Copyright Directive and President Donald Trump also appear in the list. Heres how ISPA explained in their announcement:
_**Mozilla**_ _ for their proposed approach to introduce DNS-over-HTTPS in such a way as to bypass UK filtering obligations and parental controls, undermining internet safety standards in the UK_.
**_Article_ _13 Copyright Directive_** _ for threatening freedom of expression online by requiring content recognition technologies across platforms_
_**President Donald Trump**_ _ for causing a huge amount of uncertainty across the complex, global telecommunications supply chain in the course of trying to protect national security_
### What is DNS-over-HTTPS?
DoH basically means that your DNS requests will be encrypted over an HTTPS connection.
Traditionally, the DNS requests are unencrypted and your DNS provider or the ISP can monitor/control your browsing activity. Without DoH, you can easily enforce blocking/content filtering through your DNS provider or the ISP can do that when they want.
[][10]
Suggested read  Firefox: The Internet's Knight in Shining Armor
However, DoH completely takes that out of the equation and hence, you get a private browsing experience.
You can explore [how Mozilla implements this partnering with Cloudflare][11] and set it up for yourself if you want.
### Is DoH helpful?
Yes and no.
Of course, on one side of the coin, it lets user bypass any content filters enforced by the DNS or the ISPs. So, it is a good thing that we want to put a stop to Internet censorship and DoH helps us with that.
But, on the other side, if you are a parent, you can no longer [set content filters][12] if your kid utilizes DoH on Mozilla Firefox. It depends on how good/bad the [firewall is configured][13].
But potentially DoH is a solution for some to bypass parental controls, which could be a bad thing.
Correct me if Im wrong here in the comments below.
Also, using DoH means that you can no longer use the local host file (in case you are using it for ad blocking or something else)
### Wrapping Up
What do you think about DoH in general? Is it good enough?
And, whats your take on ISPAs decision? Do you think that they are encouraging Internet censorship and government monitoring on netizens with this kind of announcement?
Personally, I find it hilarious. Even if DoH isnt the ultimate feature that everyone wants, it is always good to have an option to protect your privacy in some way.
Let us know your thoughts in the comments below. Meanwhile, Ill just put this quote here:
> In a time of universal deceit, telling the truth is a revolutionary act
--------------------------------------------------------------------------------
via: https://itsfoss.com/mozilla-internet-villain/
作者:[Ankush Das][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://itsfoss.com/author/ankush/
[b]: https://github.com/lujun9972
[1]: https://en.wikipedia.org/wiki/DNS_over_HTTPS
[2]: https://www.ispa.org.uk/ispa-announces-finalists-for-2019-internet-heroes-and-villains-trump-and-mozilla-lead-the-way-as-villain-nominees/
[3]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/07/mozilla-internet-villain.jpg?resize=800%2C450&ssl=1
[4]: https://twitter.com/mozilla?ref_src=twsrc%5Etfw
[5]: https://twitter.com/hashtag/ISPAs?src=hash&ref_src=twsrc%5Etfw
[6]: https://twitter.com/hashtag/InternetVillain?src=hash&ref_src=twsrc%5Etfw
[7]: https://twitter.com/hashtag/internet?src=hash&ref_src=twsrc%5Etfw
[8]: https://t.co/WeZhLq2uvi
[9]: https://twitter.com/ISPAUK/status/1146725374455373824?ref_src=twsrc%5Etfw
[10]: https://itsfoss.com/why-firefox/
[11]: https://blog.nightly.mozilla.org/2018/06/01/improving-dns-privacy-in-firefox/
[12]: https://itsfoss.com/how-to-block-porn-by-content-filtering-on-ubuntu/
[13]: https://itsfoss.com/set-up-firewall-gufw/