Domrobot::updateRecord()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
c 2
b 1
f 0
dl 0
loc 8
rs 9.4285
cc 1
eloc 5
nc 1
nop 2
1
<?php
2
/**
3
     * Created by PhpStorm.
4
     * User: joerg
5
     * Date: 14.02.16
6
     * Time: 20:31
7
     * copied and modified from https://github.com/inwx/php-client
8
     */
9
namespace Bingemer\InwxBundle\Classes;
10
11
/**
12
 * Class Domrobot
13
 * @package Bingemer\InwxBundle\Classes
14
 */
15
class Domrobot
16
{
17
    private $debug = false;
18
    private $address;
19
    private $language;
20
    private $customer = "";
21
    private $clTRID = null;
22
23
    private $_ver = "2.4";
24
    private $_cachedir;
25
    private $_cookiefile = NULL;
26
    private $loginResult = NULL;
27
28
    /**
29
     * Domrobot constructor.
30
     * @param $address
31
     * @param string $locale
32
     * @param $cache_dir
33
     * @param $username
34
     * @param $password
35
     * @param null $sharedSecret
36
     */
37
    public function __construct($address, $locale = 'en', $cache_dir, $username, $password, $sharedSecret = null)
38
    {
39
        $this->address = (substr($address, -1) != "/") ? $address . "/" : $address;
40
        $this->_cachedir = $cache_dir;
41
        $this->_cookiefile = tempnam($this->_cachedir, 'INWX');
42
        $this->setLanguage($locale);
43
        $this->loginResult = $this->login($username, $password, $sharedSecret);
44
    }
45
46
    /**
47
     * @param string $name
48
     * @param $ip
49
     * @param string $domain
50
     * @param string $type
51
     * @param int $ttl
52
     * @return mixed|string
53
     */
54
    public function createRecord($name, $ip, $domain = 'somedomainnameyouwishtoupgrade.de', $type = 'A', $ttl = 3600)
55
    {
56
        if (strpos($name, $domain) === false) {
57
            $name = $name . "." . $domain;
58
        }
59
        try {
60
            $result = $this->call('nameserver', 'createRecord', array(
61
                'domain' => $domain,
62
                'type' => $type,
63
                'name' => $name,
64
                'content' => $ip,
65
                'ttl' => $ttl
66
            ));
67
            return $result;
68
        } catch (\Exception $e) {
69
            return $e->getMessage();
70
        }
71
    }
72
73
    /**
74
     * @param integer $id
75
     * @param $ip
76
     * @return mixed
77
     */
78
    public function updateRecord($id, $ip)
79
    {
80
        $result = $this->call('nameserver', 'updateRecord', array(
81
            'id' => $id,
82
            'content' => $ip
83
        ));
84
        return $result;
85
    }
86
87
    /**
88
     * @param integer $id
89
     * @param bool $testing
90
     * @return mixed
91
     */
92
    public function deleteRecord($id, $testing = false)
93
    {
94
        $result = $this->call('nameserver', 'deleteRecord', array(
95
            'id' => $id,
96
            'testing' => $testing
97
        ));
98
        return $result;
99
    }
100
101
    /**
102
     * @param $username
103
     * @param $password
104
     * @param null $sharedSecret
105
     * @return mixed
106
     */
107
    public function login($username, $password, $sharedSecret = null)
108
    {
109
        $fp = fopen($this->_cookiefile, "w");
110
        fclose($fp);
111
112
        $params = array();
113
        if (!empty($this->language)) {
114
            $params['lang'] = $this->language;
115
        } else {
116
            $params['lang'] = "en"; //fallback
117
        }
118
        $params['user'] = $username;
119
        $params['pass'] = $password;
120
121
        $loginRes = $this->call('account', 'login', $params);
122
        if (!empty($sharedSecret) && $loginRes['code'] == 1000 && !empty($loginRes['resData']['tfa'])) {
123
            $_tan = $this->_getSecretCode($sharedSecret);
124
            $unlockRes = $this->call('account', 'unlock', array('tan' => $_tan));
125
            if ($unlockRes['code'] == 1000) {
126
                return $loginRes;
127
            } else {
128
                return $unlockRes;
129
            }
130
        } else {
131
            return $loginRes;
132
        }
133
    }
134
135
    /**
136
     * @param string $object
137
     * @param string $method
138
     * @param array $params
139
     * @return mixed
140
     */
141
    public function call($object, $method, array $params = array())
0 ignored issues
show
Coding Style introduced by
call uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
142
    {
143
        if (isset($this->customer) && $this->customer != "") {
144
            $params['subuser'] = $this->customer;
145
        }
146
        if (!empty($this->clTRID)) {
147
            $params['clTRID'] = $this->clTRID;
148
        }
149
150
        $request = xmlrpc_encode_request(strtolower($object . "." . $method), $params, array("encoding" => "UTF-8", "escaping" => "markup", "verbosity" => "no_white_space"));
151
        $header = array();
152
        $header[] = "Content-Type: text/xml";
153
        $header[] = "Connection: keep-alive";
154
        $header[] = "Keep-Alive: 300";
155
        $header[] = "X-FORWARDED-FOR: " . @$_SERVER['HTTP_X_FORWARDED_FOR'];
156
        $ch = curl_init();
157
        curl_setopt($ch, CURLOPT_URL, $this->address);
158
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
159
        curl_setopt($ch, CURLOPT_TIMEOUT, 65);
160
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
161
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
162
        curl_setopt($ch, CURLOPT_COOKIEFILE, $this->_cookiefile);
163
        curl_setopt($ch, CURLOPT_COOKIEJAR, $this->_cookiefile);
164
        curl_setopt($ch, CURLOPT_POST, true);
165
        curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
166
        curl_setopt($ch, CURLOPT_USERAGENT, "DomRobot/{$this->_ver} (PHP " . phpversion() . ")");
167
        $response = curl_exec($ch);
168
        curl_close($ch);
169
        if ($this->debug) {
170
            echo "Request:\n" . $request . "\n";
171
            echo "Response:\n" . $response . "\n";
172
        }
173
        return xmlrpc_decode($response, 'UTF-8');
174
    }
175
176
    /**
177
     * @param $secret
178
     * @return string
179
     */
180
    private function _getSecretCode($secret)
181
    {
182
        $_timeSlice = floor(time() / 30);
183
        $_codeLength = 6;
184
185
        $secretKey = $this->_base32Decode($secret);
186
        // Pack time into binary string
187
        $time = chr(0) . chr(0) . chr(0) . chr(0) . pack('N*', $_timeSlice);
188
        // Hash it with users secret key
189
        $hm = hash_hmac('SHA1', $time, $secretKey, true);
190
        // Use last nipple of result as index/offset
191
        $offset = ord(substr($hm, -1)) & 0x0F;
192
        // grab 4 bytes of the result
193
        $hashPart = substr($hm, $offset, 4);
194
195
        // Unpak binary value
196
        $value = unpack('N', $hashPart);
197
        $value = $value[1];
198
        // Only 32 bits
199
        $value = $value & 0x7FFFFFFF;
200
201
        $modulo = pow(10, $_codeLength);
202
        return str_pad($value % $modulo, $_codeLength, '0', STR_PAD_LEFT);
203
    }
204
205
    /**
206
     * @param $secret
207
     * @return string|false
208
     */
209
    private function _base32Decode($secret)
210
    {
211
        if (empty($secret)) {
212
            return '';
213
        }
214
215
        $base32chars = $this->_getBase32LookupTable();
216
        $base32charsFlipped = array_flip($base32chars);
217
218
        $paddingCharCount = substr_count($secret, $base32chars[32]);
219
        $allowedValues = array(6, 4, 3, 1, 0);
220
        if (!in_array($paddingCharCount, $allowedValues)) {
221
            return false;
222
        }
223
        for ($i = 0; $i < 4; $i++) {
224
            if ($paddingCharCount == $allowedValues[$i] &&
225
                substr($secret, -($allowedValues[$i])) != str_repeat($base32chars[32], $allowedValues[$i])
226
            ) {
227
                return false;
228
            }
229
        }
230
        $secret = str_replace('=', '', $secret);
231
        $secret = str_split($secret);
232
        $secretCount = count($secret);
233
        $binaryString = "";
234
        for ($i = 0; $i < $secretCount; $i = $i + 8) {
235
            $x = "";
236
            if (!in_array($secret[$i], $base32chars)) {
237
                return false;
238
            }
239
            for ($j = 0; $j < 8; $j++) {
240
                $x .= str_pad(base_convert(@$base32charsFlipped[@$secret[$i + $j]], 10, 2), 5, '0', STR_PAD_LEFT);
241
            }
242
            $eightBits = str_split($x, 8);
243
            $eightBitsCount = count($eightBits);
244
            for ($z = 0; $z < $eightBitsCount; $z++) {
245
                $binaryString .= (($y = chr(base_convert($eightBits[$z], 2, 10))) || ord($y) == 48) ? $y : "";
246
            }
247
        }
248
        return $binaryString;
249
    }
250
251
    /**
252
     * @return string[]
253
     */
254
    private function _getBase32LookupTable()
255
    {
256
        return array(
257
            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 7
258
            'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', // 15
259
            'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 23
260
            'Y', 'Z', '2', '3', '4', '5', '6', '7', // 31
261
            '=' // padding char
262
        );
263
    }
264
265
    /**
266
     *  logout on destruct
267
     */
268
    public function __destruct()
269
    {
270
        $this->logout();
271
    }
272
273
    /**
274
     * @return mixed
275
     */
276
    public function logout()
277
    {
278
        $ret = $this->call('account', 'logout');
279
        if (file_exists($this->_cookiefile)) {
280
            unlink($this->_cookiefile);
281
        }
282
        return $ret;
283
    }
284
285
    /**
286
     * @return string
287
     */
288
    public function getLanguage()
289
    {
290
        return $this->language;
291
    }
292
293
    /**
294
     * @param string $language
295
     */
296
    public function setLanguage($language)
297
    {
298
        $this->language = $language;
299
    }
300
301
    /**
302
     * @return bool
303
     */
304
    public function getDebug()
305
    {
306
        return $this->debug;
307
    }
308
309
    /**
310
     * @param bool $debug
311
     */
312
    public function setDebug($debug = false)
313
    {
314
        $this->debug = (bool)$debug;
315
    }
316
317
    /**
318
     * @return string
319
     */
320
    public function getCookiefile()
321
    {
322
        return $this->_cookiefile;
323
    }
324
325
    /**
326
     * @param $file
327
     * @throws \Exception
328
     */
329
    public function setCookiefile($file)
330
    {
331
        if ((file_exists($file) && !is_writable($file)) || (!file_exists($file) && !is_writeable(dirname($file)))) {
332
            throw new \Exception("Cannot write cookiefile: '{$this->_cookiefile}'. Please check file/folder permissions.", 2400);
333
        }
334
        $this->_cookiefile = $file;
335
    }
336
337
    /**
338
     * @return string
339
     */
340
    public function getCustomer()
341
    {
342
        return $this->customer;
343
    }
344
345
    /**
346
     * @param $customer
347
     */
348
    public function setCustomer($customer)
349
    {
350
        $this->customer = (string)$customer;
351
    }
352
353
    /**
354
     * @return string
355
     */
356
    public function getClTrId()
357
    {
358
        return $this->clTRID;
359
    }
360
361
    /**
362
     * @param $clTrId
363
     */
364
    public function setClTrId($clTrId)
365
    {
366
        $this->clTRID = (string)$clTrId;
367
    }
368
}