Initial commit
Benjamin Renard

Benjamin Renard commited on 2016-07-21 18:04:07
Showing 2 changed files, with 445 additions and 0 deletions.

... ...
@@ -0,0 +1,316 @@
1
+<?php
2
+
3
+/**
4
+ * Links :
5
+ *   * PAMI : https://github.com/marcelog/PAMI
6
+ *   * log4php : https://logging.apache.org/log4php
7
+ *   * AMI : http://ofps.oreilly.com/titles/9781449332426/asterisk-AMI.html
8
+ **/
9
+
10
+require_once 'PAMI/Autoloader/Autoloader.php';
11
+
12
+PAMI\Autoloader\Autoloader::register();
13
+
14
+use PAMI\Client\Impl\ClientImpl as PamiClient;
15
+use PAMI\Message\Action\CoreShowChannelsAction;
16
+use PAMI\Message\Action\SIPPeersAction;
17
+use PAMI\Message\Action\QueueStatusAction;
18
+use PAMI\Message\Action\MailboxCountAction;
19
+use PAMI\Message\Action\OriginateAction;
20
+use PAMI\Message\Action\HangupAction;
21
+use PAMI\Message\Action\CommandAction;
22
+use PAMI\Message\Action\DBGetAction;
23
+use PAMI\Message\Action\DBPutAction;
24
+use PAMI\Message\Action\DBDelAction;
25
+
26
+class MyAMI {
27
+	
28
+	private static $opts;
29
+	
30
+	private static $client;
31
+	
32
+	private static $started;
33
+	
34
+	function configure($opts) {
35
+		self::$opts = $opts;
36
+	}
37
+	
38
+	function start() {
39
+		if (self :: $started)
40
+			return True;
41
+		if (self::$opts) {
42
+			try {
43
+				self :: initAMI();
44
+			  self :: $client->open();
45
+			  self :: $started=True;
46
+			  return True;
47
+			}
48
+			catch(Exception $e) {
49
+				self :: log_error('Error connecting to AMI : '.$e->getMessage());
50
+			}
51
+		}
52
+		return;
53
+	}
54
+	
55
+	function initAMI() {
56
+		self :: initLog();
57
+
58
+		self::$client = new PamiClient(self::$opts['ami']);
59
+	}
60
+	
61
+	function initLog() {
62
+		require('log4php/Logger.php');
63
+		
64
+		Logger::configure(array(
65
+				'rootLogger' => array(
66
+						'appenders' => array('default'),
67
+				),
68
+				'appenders' => array(
69
+						'default' => array(
70
+								'class' => 'LoggerAppenderFile',
71
+								'layout' => array(
72
+										'class' => 'LoggerLayoutSimple'
73
+								),
74
+								'params' => array(
75
+									'file' => self :: $opts["logFile"],
76
+									'append' => true
77
+								),
78
+								'threshold' => (self :: $opts["debug"]?"DEBUG":"WARN")
79
+						)
80
+				)
81
+		));
82
+	}
83
+	
84
+	function stop() {
85
+		try {
86
+		  self :: $client->close();
87
+		  return True;
88
+		}
89
+		catch (Exception $e) {
90
+			self :: log_error('Error closing connection to AMI : '.$e->getMessage());
91
+		}
92
+		return;
93
+	}
94
+	
95
+	function listSIPPeers() {
96
+		if (!self :: start()) {
97
+			return;
98
+		}
99
+		
100
+		$response = self :: $client->send(new SIPPeersAction());
101
+		if ($response->isSuccess()) {
102
+			$peers=array();
103
+		    	foreach($response->getEvents() as $event) {
104
+				if ($event->getName() == "PeerEntry") {
105
+					$peers[$event->getObjectName()]=$event->getKeys();
106
+				}
107
+			}
108
+			return $peers;
109
+		}
110
+		else {
111
+			self :: log_action_error('listSIPPeers',$response->getMessage());
112
+		}
113
+		return;
114
+	}
115
+	
116
+	function listChannels() {
117
+		if (!self :: start()) {
118
+			return;
119
+		}
120
+		
121
+		$response = self :: $client->send(new CoreShowChannelsAction());
122
+		if ($response->isSuccess()) {
123
+			$channels=array();
124
+			foreach($response->getEvents() as $event) {
125
+				if ($event->getName() == "CoreShowChannel") {
126
+					$channels[$event->getChannel()]=$event->getKeys();
127
+				}
128
+			}
129
+			return $channels;
130
+		}
131
+		else {
132
+			self :: log_action_error('listChannels',$response->getMessage());
133
+		}
134
+		return;
135
+	}
136
+	
137
+	function listQueues() {
138
+		if (!self :: start()) {
139
+			return;
140
+		}
141
+		
142
+		$response = self :: $client->send(new QueueStatusAction());
143
+		if ($response->isSuccess()) {
144
+			$queues=array();
145
+			foreach($response->getEvents() as $event) {
146
+				if ($event->getName() == "QueueParams") {
147
+					$queues[$event->getQueue()]=array(
148
+						'params' => $event->getKeys(),
149
+						'members' => array(),
150
+						'calls' => array()
151
+					);
152
+				}
153
+				elseif ($event->getName() == "QueueMember") {
154
+					$queues[$event->getQueue()]['members'][]=$event->getKeys();
155
+				}
156
+				elseif ($event->getName() == "QueueEntry") {
157
+					$queues[$event->getKey('Queue')]['calls'][]=$event->getKeys();
158
+				}
159
+			}
160
+			return $queues;
161
+		}
162
+		else {
163
+			self :: log_action_error('listQueues',$response->getMessage());
164
+		}
165
+		return;
166
+	}
167
+
168
+	function dbGetTree() {
169
+
170
+		if (!self :: start()) {
171
+			return;
172
+		}
173
+		
174
+		$response = self :: $client->send(new CommandAction('database show'));
175
+		if ($response->isSuccess()) {
176
+			$tree=array();
177
+			foreach (explode("\n",$response->getRawContent()) as $line) {
178
+				if (preg_match('/^\/([^ ]*) *: (.*) *$/',$line,$m)) {
179
+					$ret=&$tree;
180
+					$keys=explode('/',$m[1]);
181
+					for ($i=0;$i<(count($keys)-1);$i++) {
182
+						if (!is_array($ret[$keys[$i]])) {
183
+							$ret[$keys[$i]]=array();
184
+						}
185
+						$ret=&$ret[$keys[$i]];
186
+					}
187
+					$ret[$keys[(count($keys)-1)]]=trim($m[2]);
188
+				}
189
+			}
190
+			return $tree;
191
+		}
192
+		else {
193
+			self :: log_action_error('getDBTree',$response->getMessage());
194
+		}
195
+		return;
196
+	}
197
+
198
+	function dbGet($family,$key) {
199
+		if (!self :: start()) {
200
+			return;
201
+		}
202
+		
203
+		$response = self :: $client->send(new DBGetAction($family, $key));
204
+		if ($response->isSuccess()) {
205
+			return $response->getKeys();
206
+		}
207
+		else {
208
+			self :: log_action_error('dbGet',$response->getMessage());
209
+		}
210
+		return;
211
+	}
212
+
213
+	function dbPut($family,$key,$value) {
214
+		if (!self :: start()) {
215
+			return;
216
+		}
217
+		
218
+		$response = self :: $client->send(new DBPutAction($family, $key, $value));
219
+		if ($response->isSuccess()) {
220
+			return true;
221
+		}
222
+		else {
223
+			self :: log_action_error('dbPut',$response->getMessage());
224
+		}
225
+		return;
226
+	}
227
+
228
+	function dbDel($family,$key) {
229
+		if (!self :: start()) {
230
+			return;
231
+		}
232
+		
233
+		$response = self :: $client->send(new DBDelAction($family, $key));
234
+		if ($response->isSuccess()) {
235
+			return true;
236
+		}
237
+		else {
238
+			self :: log_action_error('dbDel',$response->getMessage());
239
+		}
240
+		return;
241
+	}
242
+	
243
+	function mailboxInfos($mailbox) {
244
+		if (!self :: start()) {
245
+			return;
246
+		}
247
+		
248
+		$response = self :: $client->send(new MailboxCountAction($mailbox));
249
+		if ($response->isSuccess()) {
250
+			return $response->getKeys();
251
+		}
252
+		else {
253
+			self :: log_action_error('mailboxInfos',$response->getMessage());
254
+		}
255
+		return;
256
+	}
257
+	
258
+	function originate($channel,$params) {
259
+		if (!self :: start()) {
260
+			return;
261
+		}
262
+		
263
+		$act=new OriginateAction($channel);
264
+		if (is_array($params)) {
265
+			foreach($params as $key => $val) {
266
+				switch($key) {
267
+					case 'context':
268
+						$act -> setContext($val);
269
+						;;
270
+					case 'extension':
271
+						$act -> setExtension($val);
272
+						;;
273
+					case 'priority':
274
+						$act -> setPriority($val);
275
+						;;
276
+					case 'callerid':
277
+						$act -> setCallerId($val);
278
+						;;
279
+				}
280
+			}
281
+		}
282
+
283
+		$response = self :: $client->send($act);
284
+		if ($response->isSuccess()) {
285
+			return True;
286
+		}
287
+		else {
288
+			self :: log_action_error('mailboxInfos',$response->getMessage());
289
+		}
290
+		return;
291
+	}
292
+	
293
+	function channelHangup($channel) {
294
+		if (!self :: start()) {
295
+			return;
296
+		}
297
+		
298
+		$response = self :: $client->send(new HangupAction($channel));
299
+		if ($response->isSuccess()) {
300
+			return True;
301
+		}
302
+		else {
303
+			self :: log_action_error('channelHangup',$response->getMessage());
304
+		}
305
+		return;
306
+	}
307
+
308
+	function log_action_error($action,$msg) {
309
+		self :: log_error("Asterisk return error during $action : $msg");
310
+	}
311
+
312
+	function log_error($msg) {
313
+		error_log("MyAMI Error : $msg");
314
+		die("$msg");
315
+	}
316
+}
... ...
@@ -0,0 +1,129 @@
1
+<?php
2
+
3
+require('include.php');
4
+
5
+MyAMI :: configure(
6
+  array(
7
+    'ami' => array(
8
+      'host' => '127.0.0.1',
9
+      'scheme' => 'tcp://',
10
+      'port' => 5038,
11
+      'username' => 'manage-blacklist',
12
+      'secret' => 'xxxxxxx',
13
+      'connect_timeout' => 10000,
14
+      'read_timeout' => 10000
15
+    ),
16
+    'logFile' => '/var/log/apache2/asterisk-ami.log',
17
+    'debug' => true
18
+  )
19
+);
20
+
21
+$tree=MyAMI :: dbGetTree();
22
+$info=false;
23
+$error=false;
24
+
25
+if (isset($_POST['name']) && isset($_POST['number'])) {
26
+	if(MyAMI :: dbPut('blacklist',$_REQUEST['number'],$_REQUEST['name'])) {
27
+		$tree=MyAMI :: dbGetTree();
28
+		$info="Caller ".$_REQUEST['name']." successfully blacklisted.";
29
+	}
30
+	else {
31
+		$error="An error occured blacklisting caller ".$_REQUEST['name'].".";
32
+	}
33
+}
34
+elseif (isset($_REQUEST['delete']) && isset($tree['blacklist'][urldecode($_REQUEST['delete'])])) {
35
+	$number=urldecode($_REQUEST['delete']);
36
+	if (MyAMI :: dbDel('blacklist',$number)) {
37
+		$tree=MyAMI :: dbGetTree();
38
+		$info="Number $number successfully unblacklisted.";
39
+	}
40
+	else {
41
+		$error="An error occured unblacklisting number $number.";
42
+	}
43
+}
44
+
45
+?>
46
+
47
+
48
+<!DOCTYPE html>
49
+<html lang="en">
50
+  <head>
51
+    <meta charset="utf-8">
52
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
53
+    <meta name="viewport" content="width=device-width, initial-scale=1">
54
+
55
+    <title>Asterisk Blacklist</title>
56
+
57
+    <!-- Latest compiled and minified CSS -->
58
+    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
59
+
60
+    <!-- Optional theme -->
61
+    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css" integrity="sha384-fLW2N01lMqjakBkx3l/M9EahuwpSfeNvV63J5ezn3uZzapT0u7EYsXMjQV+0En5r" crossorigin="anonymous">
62
+
63
+    <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
64
+    <!--[if lt IE 9]>
65
+      <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
66
+      <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
67
+    <![endif]-->
68
+  </head>
69
+
70
+  <body>
71
+
72
+    <div class="container">
73
+
74
+      <h1>Asterisk callers blacklist</h1>
75
+
76
+<?php
77
+
78
+if ($error) {
79
+	echo "<div class='alert alert-warning' role='alert'>$error</div>";
80
+}
81
+if ($info) {
82
+	echo "<div class='alert alert-success' role='alert'>$info</div>";
83
+}
84
+?>
85
+      <h3>Backlist a telephone number</h3>
86
+
87
+      <form method='POST' class="form-inline">
88
+        <div class="form-group">
89
+          <label for="name">Name</label>
90
+          <input type="text" class="form-control" name="name" placeholder="Jane Doe">
91
+        </div>
92
+        <div class="form-group">
93
+          <label for="number">Number</label>
94
+          <input type="number" class="form-control" name="number" placeholder="0123456789">
95
+        </div>
96
+        <button type="submit" class="btn btn-default"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Add</button>
97
+      </form>
98
+
99
+      <h3>Current blacklisted telephone numbers <a href="index.php" class="btn btn-default" role="button"><span class="glyphicon glyphicon-refresh" aria-hidden="true"></span></a></h3>
100
+      <table class="table table-condensed">
101
+        <thead>
102
+          <tr>
103
+            <th>Name</th>
104
+            <th>Number</th>
105
+            <th>Action</th>
106
+          </tr>
107
+        </thead>
108
+        <tbody>
109
+<?php
110
+if (is_array($tree['blacklist'])) {
111
+  foreach ($tree['blacklist'] as $num => $name) {
112
+    echo "
113
+          <tr>
114
+            <td>$name</td>
115
+            <td>$num</td>
116
+            <td><a href='?delete=".urlencode($num)."'><span class='glyphicon glyphicon-trash' aria-hidden='true'></span></a></td>
117
+          </tr>\n";
118
+  }
119
+}
120
+?>
121
+        </tbody>
122
+      </table>
123
+
124
+    </div>
125
+
126
+    <!-- Latest compiled and minified JavaScript -->
127
+    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>
128
+  </body>
129
+</html>
0 130