]> git.mxchange.org Git - friendica.git/blob - src/Console/ServerBlock.php
7c17fdc5756a353d09c767f8043294a2904dc72a
[friendica.git] / src / Console / ServerBlock.php
1 <?php
2 /**
3  * @copyright Copyright (C) 2020, Friendica
4  *
5  * @license GNU AGPL version 3 or any later version
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU Affero General Public License as
9  * published by the Free Software Foundation, either version 3 of the
10  * License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Affero General Public License for more details.
16  *
17  * You should have received a copy of the GNU Affero General Public License
18  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19  *
20  */
21
22 namespace Friendica\Console;
23
24 use Asika\SimpleConsole\CommandArgsException;
25 use Asika\SimpleConsole\Console;
26 use Console_Table;
27 use Friendica\Core\Config\IConfig;
28
29 /**
30  * Manage blocked servers
31  *
32  * With this tool, you can list the current blocked servers
33  * or you can add / remove a blocked server from the list
34  */
35 class ServerBlock extends Console
36 {
37         const DEFAULT_REASON = 'blocked';
38
39         protected $helpOptions = ['h', 'help', '?'];
40
41         /**
42          * @var IConfig
43          */
44         private $config;
45
46         protected function getHelp()
47         {
48                 $help = <<<HELP
49 console serverblock - Manage blocked server domain patterns
50 Usage
51         bin/console serverblock [-h|--help|-?] [-v]
52         bin/console serverblock add <pattern> <reason> [-h|--help|-?] [-v]
53         bin/console serverblock remove <pattern> [-h|--help|-?] [-v]
54         bin/console serverblock export <filename>
55         bin/console serverblock import <filename>
56
57 Description
58         With this tool, you can list the current blocked server domain patterns
59         or you can add / remove a blocked server domain pattern from the list.
60         Using the export and import options you can share your server blocklist
61         with other node admins by CSV files.
62         
63         Patterns are case-insensitive shell wildcard comprising the following special characters:
64         - * : Any number of characters
65         - ? : Any single character
66         - [<char1><char2>...] : char1 or char2 or...
67
68 Options
69         -h|--help|-? Show help information
70         -v                 Show more debug information.
71 HELP;
72                 return $help;
73         }
74
75         public function __construct(IConfig $config, $argv = null)
76         {
77                 parent::__construct($argv);
78
79                 $this->config = $config;
80         }
81
82         protected function doExecute()
83         {
84                 if (count($this->args) == 0) {
85                         $this->printBlockedServers($this->config);
86                         return 0;
87                 }
88
89                 switch ($this->getArgument(0)) {
90                         case 'add':
91                                 return $this->addBlockedServer($this->config);
92                         case 'remove':
93                                 return $this->removeBlockedServer($this->config);
94                         case 'export':
95                                 return $this->exportBlockedServers($this->config);
96                         case 'import':
97                                 return $this->importBlockedServers($this->config);
98                         default:
99                                 throw new CommandArgsException('Unknown command.');
100                                 break;
101                 }
102         }
103
104         /**
105          * Exports the list of blocked domains including the reason for the
106          * block to a CSV file.
107          *
108          * @param IConfig $config
109          */
110         private function exportBlockedServers(IConfig $config)
111         {
112                 $filename = $this->getArgument(1);
113                 $blocklist = $config->get('system', 'blocklist', []);
114                 $fp = fopen($filename, 'w');
115                 foreach ($blocklist as $domain) {
116                         fputcsv($fp, $domain);
117                 }
118         }
119         /**
120          * Imports a list of domains and a reason for the block from a CSV
121          * file, e.g. created with the export function.
122          *
123          * @param IConfig $config
124          */
125         private function importBlockedServers(IConfig $config)
126         {
127                 $filename = $this->getArgument(1);
128                 $currBlockList = $config->get('system', 'blocklist', []);
129                 $newBlockList = [];
130                 if (($fp = fopen($filename, 'r')) !== FALSE) {
131                         while (($data = fgetcsv($fp, 1000, ',')) !== FALSE) {
132                                 $domain = $data[0];
133                                 if (count($data)  == 0) {
134                                         $reason = self::DEFAULT_REASON;
135                                 } else {
136                                         $reason = $data[1];
137                                 }
138                                 $data = [
139                                         'domain' => $domain,
140                                         'reason' => $reason
141                                 ];
142                                 if (!in_array($data, $newBlockList))
143                                         $newBlockList[] = $data;
144                         }
145                         foreach ($currBlockList as $blocked) {
146                                 if (!in_array($blocked, $newBlockList))
147                                         $newBlockList[] = $blocked;
148                         }
149                         if ($config->set('system', 'blocklist', $newBlockList)) {
150                                 $this->out(sprintf("Entries from %s that were not blocked before are now blocked", $filename));
151                                 return 0;
152                         } else {
153                                 $this->out(sprintf("Couldn't save '%s' as blocked server", $domain));
154                                 return 1;
155                         }
156
157                 }
158         }
159
160         /**
161          * Prints the whole list of blocked domains including the reason
162          *
163          /* @param IConfig $config
164          */
165         private function printBlockedServers(IConfig $config)
166         {
167                 $table = new Console_Table();
168                 $table->setHeaders(['Domain', 'Reason']);
169                 $blocklist = $config->get('system', 'blocklist', []);
170                 foreach ($blocklist as $domain) {
171                         $table->addRow($domain);
172                 }
173                 $this->out($table->getTable());
174         }
175
176         /**
177          * Adds a server to the blocked list
178          *
179          * @param IConfig $config
180          *
181          * @return int The return code (0 = success, 1 = failed)
182          */
183         private function addBlockedServer(IConfig $config)
184         {
185                 if (count($this->args) < 2 || count($this->args) > 3) {
186                         throw new CommandArgsException('Add needs a domain and optional a reason.');
187                 }
188
189                 $domain = $this->getArgument(1);
190                 $reason = (count($this->args) === 3) ? $this->getArgument(2) : self::DEFAULT_REASON;
191
192                 $update = false;
193
194                 $currBlockList = $config->get('system', 'blocklist', []);
195                 $newBlockList = [];
196                 foreach ($currBlockList  as $blocked) {
197                         if ($blocked['domain'] === $domain) {
198                                 $update = true;
199                                 $newBlockList[] = [
200                                         'domain' => $domain,
201                                         'reason' => $reason,
202                                 ];
203                         } else {
204                                 $newBlockList[] = $blocked;
205                         }
206                 }
207
208                 if (!$update) {
209                         $newBlockList[] = [
210                                 'domain' => $domain,
211                                 'reason' => $reason,
212                         ];
213                 }
214
215                 if ($config->set('system', 'blocklist', $newBlockList)) {
216                         if ($update) {
217                                 $this->out(sprintf("The domain '%s' is now updated. (Reason: '%s')", $domain, $reason));
218                         } else {
219                                 $this->out(sprintf("The domain '%s' is now blocked. (Reason: '%s')", $domain, $reason));
220                         }
221                         return 0;
222                 } else {
223                         $this->out(sprintf("Couldn't save '%s' as blocked server", $domain));
224                         return 1;
225                 }
226         }
227
228         /**
229          * Removes a server from the blocked list
230          *
231          * @param IConfig $config
232          *
233          * @return int The return code (0 = success, 1 = failed)
234          */
235         private function removeBlockedServer(IConfig $config)
236         {
237                 if (count($this->args) !== 2) {
238                         throw new CommandArgsException('Remove needs a second parameter.');
239                 }
240
241                 $domain = $this->getArgument(1);
242
243                 $found = false;
244
245                 $currBlockList = $config->get('system', 'blocklist', []);
246                 $newBlockList = [];
247                 foreach ($currBlockList as $blocked) {
248                         if ($blocked['domain'] === $domain) {
249                                 $found = true;
250                         } else {
251                                 $newBlockList[] = $blocked;
252                         }
253                 }
254
255                 if (!$found) {
256                         $this->out(sprintf("The domain '%s' is not blocked.", $domain));
257                         return 1;
258                 }
259
260                 if ($config->set('system', 'blocklist', $newBlockList)) {
261                         $this->out(sprintf("The domain '%s' is not more blocked", $domain));
262                         return 0;
263                 } else {
264                         $this->out(sprintf("Couldn't remove '%s' from blocked servers", $domain));
265                         return 1;
266                 }
267         }
268 }