1
|
|
|
<?php |
2
|
|
|
$defflip = (!cfip()) ? exit(header('HTTP/1.1 401 Unauthorized')) : 1; |
3
|
|
|
|
4
|
|
|
/** |
5
|
|
|
* Helper class for our cronjobs |
6
|
|
|
* Implements some common cron tasks outside |
7
|
|
|
* the scope of our web application |
8
|
|
|
**/ |
9
|
|
|
class Tools extends Base { |
10
|
|
|
public function getOnlineVersions() { |
11
|
|
|
// Fetch version online, cache for a bit |
12
|
|
|
$key = $this->config['memcache']['keyprefix'] . 'ONLINE_VERSIONS'; |
|
|
|
|
13
|
|
|
if (! $mpos_versions = $this->memcache->get($key)) { |
14
|
|
|
$url = $this->config['version_url']; |
15
|
|
|
$curl = curl_init(); |
16
|
|
|
curl_setopt($curl, CURLOPT_URL, $url); |
17
|
|
|
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); |
18
|
|
|
curl_setopt($curl, CURLOPT_HEADER, false); |
19
|
|
|
$data = curl_exec($curl); |
20
|
|
|
preg_match('/define\(\'MPOS_VERSION\', \'(.*)\'\);/', $data, $match); |
21
|
|
|
$mpos_versions['MPOS_VERSION'] = @$match[1]; |
22
|
|
|
preg_match('/define\(\'DB_VERSION\', \'(.*)\'\);/', $data, $match); |
23
|
|
|
$mpos_versions['DB_VERSION'] = @$match[1]; |
24
|
|
|
preg_match('/define\(\'CONFIG_VERSION\', \'(.*)\'\);/', $data, $match); |
25
|
|
|
$mpos_versions['CONFIG_VERSION'] = @$match[1]; |
26
|
|
|
curl_close($curl); |
27
|
|
|
return $this->memcache->setCache($key, $mpos_versions, 30); |
|
|
|
|
28
|
|
|
} else { |
29
|
|
|
return $mpos_versions; |
30
|
|
|
} |
31
|
|
|
} |
32
|
|
|
/** |
33
|
|
|
* Fetch JSON data from an API |
34
|
|
|
* @param url string API URL |
35
|
|
|
* @param target string API method |
36
|
|
|
* @param auth array Optional authentication data to be sent with |
37
|
|
|
* @return dec array JSON decoded PHP array |
38
|
|
|
**/ |
39
|
|
|
public function getApi($url, $target, $auth=NULL) { |
|
|
|
|
40
|
|
|
static $ch = null; |
41
|
|
|
static $ch = null; |
42
|
|
|
if (is_null($ch)) { |
43
|
|
|
$ch = curl_init(); |
44
|
|
|
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30); |
45
|
|
|
curl_setopt($ch, CURLOPT_TIMEOUT, 30); |
46
|
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); |
47
|
|
|
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); |
48
|
|
|
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; PHP client; '.php_uname('s').'; PHP/'.phpversion().')'); |
49
|
|
|
} |
50
|
|
|
|
51
|
|
|
$url = rtrim($url, '/'); |
52
|
|
|
$target = ltrim($target, '/'); |
53
|
|
|
curl_setopt($ch, CURLOPT_URL, $url . '/' . $target); |
54
|
|
|
// curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data); |
55
|
|
|
|
56
|
|
|
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); |
57
|
|
|
|
58
|
|
|
// run the query |
59
|
|
|
$res = curl_exec($ch); |
60
|
|
|
if ($res === false) { |
61
|
|
|
$this->setErrorMessage('Could not get reply: '.curl_error($ch)); |
62
|
|
|
return false; |
|
|
|
|
63
|
|
|
} |
64
|
|
|
$dec = json_decode($res, true); |
65
|
|
|
if (!$dec) { |
66
|
|
|
$this->setErrorMessage('Invalid data received, please make sure connection is working and requested API exists'); |
67
|
|
|
return false; |
|
|
|
|
68
|
|
|
} |
69
|
|
|
return $dec; |
70
|
|
|
} |
71
|
|
|
|
72
|
|
|
/** |
73
|
|
|
* Detect the API to properly extract information |
74
|
|
|
* @param url string API URL |
75
|
|
|
* @return data string API type |
76
|
|
|
**/ |
77
|
|
|
private function getApiType($url) { |
78
|
|
|
if (preg_match('/coinchoose.com/', $url)) { |
79
|
|
|
return 'coinchoose'; |
80
|
|
|
} else if (preg_match('/btc-e.nz/', $url)) { |
81
|
|
|
return 'btce'; |
82
|
|
|
} else if (preg_match('/cryptopia.co.nz/', $url)) { |
83
|
|
|
return 'cryptopia'; |
84
|
|
|
} else if (preg_match('/cryptorush.in/', $url)) { |
85
|
|
|
return 'cryptorush'; |
86
|
|
|
} else if (preg_match('/mintpal.com/', $url)) { |
87
|
|
|
return 'mintpal'; |
88
|
|
|
} else if (preg_match('/c-cex.com/', $url)) { |
89
|
|
|
return 'c-cex'; |
90
|
|
|
} else if (preg_match('/bittrex.com/', $url)) { |
91
|
|
|
return 'bittrex'; |
92
|
|
|
} else if (preg_match('/crypto-bridge.org/', $url)) { |
93
|
|
|
return 'cryptobridge'; |
94
|
|
|
} else if (preg_match('/yobit.net/', $url)) { |
95
|
|
|
return 'yobit'; |
96
|
|
|
} else if (preg_match('/binance.com/', $url)) { |
97
|
|
|
return 'binance'; |
98
|
|
|
} else if (preg_match('/southxchange.com/', $url)) { |
99
|
|
|
return 'southxchange'; |
100
|
|
|
} else if (preg_match('/mercatox.com/', $url)) { |
101
|
|
|
return 'mercatox'; |
102
|
|
|
} else if (preg_match('/tradeogre.com/', $url)) { |
103
|
|
|
return 'tradeogre'; |
104
|
|
|
} |
105
|
|
|
$this->setErrorMessage("API URL unknown"); |
106
|
|
|
return false; |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
/** |
110
|
|
|
* Extract price information from API data |
111
|
|
|
**/ |
112
|
|
|
public function getPrice() { |
113
|
|
|
$aData = $this->getApi($this->config['price']['url'], $this->config['price']['target']); |
114
|
|
|
$strBase = $this->config['currency']; |
115
|
|
|
$strQuote = $this->config['price']['currency']; |
116
|
|
|
// Check the API type for configured URL |
117
|
|
|
if (!$strApiType = $this->getApiType($this->config['price']['url'])) |
118
|
|
|
return false; |
119
|
|
|
// if api data is valid, extract price depending on API type |
120
|
|
|
if (is_array($aData)) { |
121
|
|
|
switch ($strApiType) { |
122
|
|
|
case 'coinchoose': |
123
|
|
|
foreach ($aData as $aItem) { |
124
|
|
|
if($strBase == $aItem[0]) |
125
|
|
|
return $aItem['price']; |
126
|
|
|
} |
127
|
|
|
break; |
128
|
|
|
case 'btce': |
129
|
|
|
return $aData['ticker']['last']; |
130
|
|
|
break; |
|
|
|
|
131
|
|
|
case 'cryptopia': |
132
|
|
|
return @$aData['Data']['LastPrice']; |
133
|
|
|
break; |
|
|
|
|
134
|
|
|
case 'cryptorush': |
135
|
|
|
return @$aData["{$strBase}/{$strQuote}"]['last_trade']; |
136
|
|
|
break; |
|
|
|
|
137
|
|
|
case 'mintpal': |
138
|
|
|
return @$aData['0']['last_price']; |
139
|
|
|
break; |
|
|
|
|
140
|
|
|
case 'c-cex': |
141
|
|
|
return @$aData['ticker']['lastprice']; |
142
|
|
|
break; |
|
|
|
|
143
|
|
|
case 'bittrex': |
144
|
|
|
return @$aData['result']['Last']; |
145
|
|
|
break; |
|
|
|
|
146
|
|
|
case 'cryptobridge': |
147
|
|
|
foreach ($aData as $aItem) { |
148
|
|
|
if("{$strBase}_{$strQuote}" == $aItem['id']) |
149
|
|
|
return $aItem['last']; |
150
|
|
|
} |
151
|
|
|
case 'yobit': |
152
|
|
|
return @$aData[strtolower($strBase) . "_" . strtolower($strQuote)]['last']; |
153
|
|
|
break; |
|
|
|
|
154
|
|
|
case 'binance': |
155
|
|
|
return @$aData['price']; |
156
|
|
|
break; |
|
|
|
|
157
|
|
|
case 'southxchange': |
158
|
|
|
return @$aData['Last']; |
159
|
|
|
break; |
|
|
|
|
160
|
|
|
case 'mercatox': |
161
|
|
|
return @$aData['pairs']["{$strBase}_{$strQuote}"]['last']; |
162
|
|
|
break; |
|
|
|
|
163
|
|
|
case 'tradeogre': |
164
|
|
|
return @$aData['price']; |
165
|
|
|
break; |
|
|
|
|
166
|
|
|
} |
167
|
|
|
} else { |
168
|
|
|
$this->setErrorMessage("Got an invalid response from ticker API"); |
169
|
|
|
return false; |
170
|
|
|
} |
171
|
|
|
// Catchall, we have no data extractor for this API url |
172
|
|
|
$this->setErrorMessage("Undefined API to getPrice() on URL " . $this->config['price']['url']); |
173
|
|
|
return false; |
174
|
|
|
} |
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
$tools = new Tools(); |
178
|
|
|
$tools->setDebug($debug); |
179
|
|
|
$tools->setConfig($config); |
180
|
|
|
$tools->setMemcache($memcache); |
181
|
|
|
|
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: