source: trunk/Modules/NetworkConfigRouterOS/RouterboardAPI.php@ 738

Last change on this file since 738 was 738, checked in by chronos, 10 years ago
  • Removed: Spaces on end of line.
  • Modified: Tabs converted to spaces.
File size: 7.5 KB
Line 
1<?php
2
3class RouterosAPI
4{
5 var $ErrorNo; // Variable for storing connection error number, if any
6 var $ErrorStr; // Variable for storing connection error text, if any
7 var $Attempts; // Connection attempt count
8 var $Connected; // Connection state
9 var $Delay; // Delay between connection attempts in seconds
10 var $Port; // Port to connect to
11 var $Timeout; // Connection attempt timeout and data read timeout
12 var $Socket; // Variable for storing socket resource
13 var $Debug;
14 var $SSL; // If SSL API connection is used. You need also change port to 8729
15
16 function __construct()
17 {
18 $this->Attempts = 5;
19 $this->Connected = false;
20 $this->Delay = 3;
21 $this->Port = 8728;
22 $this->Timeout = 3;
23 $this->Debug = false;
24 $this->SSL = false;
25 }
26
27 function EncodeLength($Length)
28 {
29 if ($Length < 0x80) {
30 $Length = chr($Length);
31 } else if ($Length < 0x4000) {
32 $Length |= 0x8000;
33 $Length = chr(($Length >> 8) & 0xFF).chr($Length & 0xFF);
34 } else if ($Length < 0x200000) {
35 $Length |= 0xC00000;
36 $Length = chr(($Length >> 16) & 0xFF).chr(($Length >> 8) & 0xFF).chr($Length & 0xFF);
37 } else if ($Length < 0x10000000) {
38 $Length |= 0xE0000000;
39 $Length = chr(($Length >> 24) & 0xFF).chr(($Length >> 16) & 0xFF).chr(($Length >> 8) & 0xFF).chr($Length & 0xFF);
40 } else if ($Length >= 0x10000000)
41 $Length = chr(0xF0).chr(($Length >> 24) & 0xFF).chr(($Length >> 16) & 0xFF).chr(($Length >> 8) & 0xFF).chr($Length & 0xFF);
42 return($Length);
43 }
44
45 function ConnectOnce($IP, $Login, $Password)
46 {
47 if($this->Connected) $this->Disconnect();
48 if($this->SSL)
49 {
50 $IP = 'ssl://'.$IP;
51 }
52 $this->Socket = @fsockopen($IP, $this->Port, $this->ErrorNo, $this->ErrorStr, $this->Timeout);
53 if($this->Socket)
54 {
55 socket_set_timeout($this->Socket, $this->Timeout);
56 $this->Write('/login');
57 $Response = $this->Read(false);
58 if ((count($Response) > 1) and ($Response[0] == '!done')) {
59 if (preg_match_all('/[^=]+/i', $Response[1], $Matches)) {
60 if ($Matches[0][0] == 'ret' && strlen($Matches[0][1]) == 32) {
61 $this->Write('/login', false);
62 $this->Write('=name=' . $Login, false);
63 $this->Write('=response=00'.md5(chr(0).$Password.pack('H*', $Matches[0][1])));
64 $Response = $this->Read(false);
65 if((count($Response) > 0) and ($Response[0] == '!done')) $this->Connected = true;
66 }
67 }
68 }
69 if(!$this->Connected) fclose($this->Socket);
70 }
71 }
72
73 function Connect($IP, $Login, $Password)
74 {
75 for($Attempt = 1; $Attempt <= $this->Attempts; $Attempt++)
76 {
77 $this->ConnectOnce($IP, $Login, $Password);
78 if($this->Connected) break;
79 sleep($this->Delay);
80 }
81 return($this->Connected);
82 }
83
84 function Disconnect()
85 {
86 if($this->Connected)
87 {
88 fclose($this->Socket);
89 $this->Connected = false;
90 }
91 }
92
93 function ParseResponse($Response)
94 {
95 if (is_array($Response)) {
96 $Parsed = array();
97 $Current = null;
98 $SingleValue = null;
99 $count = 0;
100 foreach ($Response as $x) {
101 if (in_array($x, array(
102 '!fatal',
103 '!re',
104 '!trap'
105 ))) {
106 if ($x == '!re') {
107 $Current =& $Parsed[];
108 } else
109 $Current =& $Parsed[$x][];
110 } else if ($x != '!done') {
111 if (preg_match_all('/[^=]+/i', $x, $Matches)) {
112 if ($Matches[0][0] == 'ret') {
113 $SingleValue = $Matches[0][1];
114 }
115 $Current[$Matches[0][0]] = (isset($Matches[0][1]) ? $Matches[0][1] : '');
116 }
117 }
118 }
119 if (empty($Parsed) && !is_null($SingleValue)) {
120 $Parsed = $SingleValue;
121 }
122 return $Parsed;
123 } else
124 return array();
125 }
126
127 function ArrayChangeKeyName(&$array)
128 {
129 if (is_array($array)) {
130 foreach ($array as $k => $v) {
131 $tmp = str_replace("-", "_", $k);
132 $tmp = str_replace("/", "_", $tmp);
133 if ($tmp) {
134 $array_new[$tmp] = $v;
135 } else {
136 $array_new[$k] = $v;
137 }
138 }
139 return $array_new;
140 } else {
141 return $array;
142 }
143 }
144
145 function Read($Parse = true)
146 {
147 $Line = '';
148 $Response = array();
149 while (true) {
150 // Read the first byte of input which gives us some or all of the length
151 // of the remaining reply.
152 $Byte = ord(fread($this->Socket, 1));
153 $Length = 0;
154 // If the first bit is set then we need to remove the first four bits, shift left 8
155 // and then read another byte in.
156 // We repeat this for the second and third bits.
157 // If the fourth bit is set, we need to remove anything left in the first byte
158 // and then read in yet another byte.
159 if ($Byte & 0x80) {
160 if (($Byte & 0xc0) == 0x80) {
161 $Length = (($Byte & 63) << 8) + ord(fread($this->Socket, 1));
162 } else {
163 if (($Byte & 0xe0) == 0xc0) {
164 $Length = (($Byte & 31) << 8) + ord(fread($this->Socket, 1));
165 $Length = ($Length << 8) + ord(fread($this->Socket, 1));
166 } else {
167 if (($Byte & 0xf0) == 0xe0) {
168 $Length = (($Byte & 15) << 8) + ord(fread($this->Socket, 1));
169 $Length = ($Length << 8) + ord(fread($this->Socket, 1));
170 $Length = ($Length << 8) + ord(fread($this->Socket, 1));
171 } else {
172 $Length = ord(fread($this->Socket, 1));
173 $Length = ($Length << 8) + ord(fread($this->Socket, 1));
174 $Length = ($Length << 8) + ord(fread($this->Socket, 1));
175 $Length = ($Length << 8) + ord(fread($this->Socket, 1));
176 }
177 }
178 }
179 } else {
180 $Length = $Byte;
181 }
182 // If we have got more characters to read, read them in.
183 if ($Length > 0) {
184 $Line = '';
185 $RetLen = 0;
186 while ($RetLen < $Length) {
187 $ToRead = $Length - $RetLen;
188 $Line .= fread($this->Socket, $ToRead);
189 $RetLen = strlen($Line);
190 }
191 $Response[] = $Line;
192 }
193 if($this->Debug) echo($Line);
194 // If we get a !done, make a note of it.
195 if ($Line == "!done") $ReceivedDone = true;
196 else $ReceivedDone = false;
197 $Status = socket_get_status($this->Socket);
198 if ((!$this->Connected && !$Status['unread_bytes']) ||
199 ($this->Connected && !$Status['unread_bytes'] && $ReceivedDone))
200 break;
201 }
202 if($Parse) $Response = $this->ParseResponse($Response);
203 return $Response;
204 }
205
206 function Write($Command, $Param2 = true)
207 {
208 if($Command)
209 {
210 $Data = explode("\n", $Command);
211 foreach ($Data as $Com) {
212 $Com = trim($Com);
213 fwrite($this->Socket, $this->EncodeLength(strlen($Com)).$Com);
214 }
215 if (gettype($Param2) == 'integer') {
216 fwrite($this->Socket, $this->EncodeLength(strlen('.tag='.$Param2)).'.tag='.$Param2.chr(0));
217 } else if (gettype($Param2) == 'boolean')
218 fwrite($this->Socket, ($Param2 ? chr(0) : ''));
219 return true;
220 } else
221 return false;
222 }
223
224 function Comm($Com, $Arr = array())
225 {
226 $Count = count($Arr);
227 $this->write($Com, !$Arr);
228 $i = 0;
229 foreach ($Arr as $k => $v) {
230 switch ($k[0]) {
231 case "?":
232 $el = "$k=$v";
233 break;
234 case "~":
235 $el = "$k~$v";
236 break;
237 default:
238 $el = "=$k=$v";
239 break;
240 }
241 $Last = ($i++ == $Count - 1);
242 $this->Write($el, $Last);
243 }
244 return($this->Read());
245 }
246}
Note: See TracBrowser for help on using the repository browser.