├── .gitignore ├── LICENSE ├── README.md └── modules └── servers └── time4vps ├── assets └── js │ └── clientarea.js ├── defines.php ├── hooks.php ├── includes ├── adminarea.php ├── clientarea.php ├── helpers.php ├── hooks │ ├── adminarea.php │ └── clientarea.php └── server.php ├── install.php ├── templates └── clientarea │ ├── clientarea.tpl │ ├── pages │ ├── changedns.tpl │ ├── changehostname.tpl │ ├── changeptr.tpl │ ├── emergencyconsole.tpl │ ├── manualservicerenew.tpl │ ├── reboot.tpl │ ├── reinstall.tpl │ ├── resetfirewall.tpl │ ├── resetpassword.tpl │ ├── usagegraph.tpl │ ├── usagegraphs.tpl │ └── usagehistory.tpl │ └── serverbusy.tpl ├── time4vps.php ├── tools ├── README.md └── component_map.php ├── update.php ├── vendor ├── autoload.php ├── composer │ ├── ClassLoader.php │ ├── LICENSE │ ├── autoload_classmap.php │ ├── autoload_namespaces.php │ ├── autoload_psr4.php │ ├── autoload_real.php │ ├── autoload_static.php │ └── installed.json └── time4vps │ └── lib │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ └── src │ ├── API │ ├── Order.php │ ├── Product.php │ ├── Script.php │ ├── Server.php │ ├── Servers.php │ └── Service.php │ ├── Base │ ├── Debug.php │ ├── Endpoint.php │ └── Singleton.php │ └── Exceptions │ ├── APIException.php │ ├── AuthException.php │ ├── Exception.php │ └── InvalidTaskException.php └── whmcs.json /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | composer.phar 3 | composer.json 4 | composer.lock 5 | /vendor 6 | update-release.sh 7 | .DS_Store -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Time4VPS 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # WHMCS Time4VPS Module 4 | 5 | This is Time4VPS provisioning module for WHMCS platform. 6 | 7 | ## Installation 8 | 9 | 1. Download latest module [release](https://github.com/time4vps/whmcs/releases). 10 | 2. Upload archive folder contents to your WHMCS installation root directory. 11 | 3. Login to WHMCS admin panel. 12 | 4. Navigate to `Setup -> Products / Services -> Servers` 13 | 5. Click `Add new Server` button 14 | 6. Set following fields: 15 | - Name: `Time4VPS` 16 | - Hostname: `billing.time4vps.com` 17 | - Type: `Time4VPS Reseller Module` 18 | - Set your Time4VPS username and password accordingly 19 | 7. Create DB tables by navigating to `http:///modules/servers/time4vps/install.php` as Admin 20 | 21 | ## Product import / update 22 | Import / Update Time4VPS products by navigating to `http:///modules/servers/time4vps/update.php` as Admin. **Run it once, as every other request will reset any changes you made for existing Time4VPS products.** 23 | 24 | ## License 25 | [MIT](https://github.com/time4vps/time4vps-lib/blob/master/LICENSE) 26 | -------------------------------------------------------------------------------- /modules/servers/time4vps/assets/js/clientarea.js: -------------------------------------------------------------------------------- 1 | $(document) 2 | .on('click', '#Primary_Sidebar-Service_Details_Overview-Information', function (e) { 3 | window.location.href = $(this).attr('href'); 4 | }); -------------------------------------------------------------------------------- /modules/servers/time4vps/defines.php: -------------------------------------------------------------------------------- 1 | getMessage(); 12 | } 13 | 14 | return 'success'; 15 | } -------------------------------------------------------------------------------- /modules/servers/time4vps/includes/clientarea.php: -------------------------------------------------------------------------------- 1 | getMessage(); 19 | } 20 | 21 | if ($details['active_task'] && !in_array($action, ['UsageGraph', 'UsageGraphs', 'UsageHistory'])) { 22 | return tim4vps_ClientAreaServerBusy($details); 23 | } 24 | if ($action) { 25 | return call_user_func("time4vps_ClientArea{$action}", $params, $details); 26 | } 27 | 28 | return time4vps_clientAreaDefault($details); 29 | } 30 | 31 | /** 32 | * Default Client Area action 33 | * 34 | * @param array $details Server Details 35 | * @return array|string 36 | */ 37 | function time4vps_ClientAreaDefault($details) 38 | { 39 | return [ 40 | 'tabOverviewReplacementTemplate' => 'templates/clientarea/clientarea.tpl', 41 | 'templateVariables' => [ 42 | 'details' => $details 43 | ] 44 | ]; 45 | } 46 | 47 | function tim4vps_ClientAreaServerBusy($details) 48 | { 49 | return [ 50 | 'tabOverviewReplacementTemplate' => 'templates/clientarea/serverbusy.tpl', 51 | 'templateVariables' => [ 52 | 'details' => $details 53 | ] 54 | ]; 55 | } 56 | 57 | /** 58 | * Client Area Change DNS 59 | * 60 | * @param $params 61 | * @param $details 62 | * @return array 63 | */ 64 | function time4vps_ClientAreaChangeDNS($params, $details) 65 | { 66 | $error = null; 67 | 68 | if (!empty($_POST)) { 69 | $error = time4vps_ChangeDNS($params, $_POST['ns1'], $_POST['ns2']); 70 | if ($error === 'success') { 71 | time4vps_MarkServerDetailsObsolete($params); 72 | time4vps_Redirect(time4vps_ActionLink($params, 'ChangeDNS')); 73 | } 74 | } 75 | 76 | return [ 77 | 'tabOverviewReplacementTemplate' => 'templates/clientarea/pages/changedns.tpl', 78 | 'templateVariables' => [ 79 | 'details' => $details, 80 | 'ippattern' => '((^|\.)((25[0-5])|(2[0-4]\d)|(1\d\d)|([1-9]?\d))){4}$', 81 | 'error' => $error 82 | ] 83 | ]; 84 | } 85 | 86 | /** 87 | * Client Area Change PTR 88 | * 89 | * @param $params 90 | * @param $details 91 | * @return array 92 | */ 93 | function time4vps_ClientAreaChangePTR($params, $details) 94 | { 95 | $error = null; 96 | $ips = []; 97 | 98 | if (!empty($_POST['ip']) && !empty($_POST['ptr'])) { 99 | $error = time4vps_ChangePTR($params, $_POST['ip'], $_POST['ptr']); 100 | if ($error === 'success') { 101 | time4vps_MarkServerDetailsObsolete($params); 102 | time4vps_Redirect(time4vps_ActionLink($params, 'ChangePTR')); 103 | } 104 | } 105 | 106 | try { 107 | time4vps_InitAPI($params); 108 | $server = time4vps_ExtractServer($params); 109 | $ips = $server->additionalIPs(); 110 | $ips = array_shift($ips); 111 | } catch (Exception $e) { 112 | $error = $e->getMessage(); 113 | } 114 | 115 | return [ 116 | 'tabOverviewReplacementTemplate' => 'templates/clientarea/pages/changeptr.tpl', 117 | 'templateVariables' => [ 118 | 'details' => $details, 119 | 'error' => $error, 120 | 'ips' => $ips 121 | ] 122 | ]; 123 | } 124 | 125 | /** 126 | * Client Area Server Reboot 127 | * 128 | * @param $params 129 | * @return array|string 130 | */ 131 | function time4vps_ClientAreaReboot($params) 132 | { 133 | $last_result = null; 134 | $error = null; 135 | 136 | if (!empty($_POST['confirm'])) { 137 | $error = time4vps_Reboot($params); 138 | if ($error === 'success') { 139 | time4vps_MarkServerDetailsObsolete($params); 140 | time4vps_Redirect(time4vps_ActionLink($params, 'Reboot')); 141 | } 142 | } 143 | 144 | try { 145 | time4vps_InitAPI($params); 146 | $server = time4vps_ExtractServer($params); 147 | $last_result = $server->taskResult('server_reboot'); 148 | } catch (InvalidTaskException $e) { 149 | // No tasks yet 150 | } catch (Exception $e) { 151 | $error = $e->getMessage(); 152 | } 153 | 154 | return [ 155 | 'tabOverviewReplacementTemplate' => 'templates/clientarea/pages/reboot.tpl', 156 | 'templateVariables' => [ 157 | 'last_result' => $last_result, 158 | 'error' => $error 159 | ] 160 | ]; 161 | } 162 | 163 | /** 164 | * Client Area Password Reset 165 | * 166 | * @param $params 167 | * @return array 168 | */ 169 | function time4vps_ClientAreaResetPassword($params) 170 | { 171 | $last_result = null; 172 | $error = null; 173 | 174 | if (!empty($_POST['confirm'])) { 175 | $error = time4vps_ResetPassword($params); 176 | if ($error === 'success') { 177 | time4vps_MarkServerDetailsObsolete($params); 178 | time4vps_Redirect(time4vps_ActionLink($params, 'ResetPassword')); 179 | } 180 | } 181 | 182 | try { 183 | time4vps_InitAPI($params); 184 | $server = time4vps_ExtractServer($params); 185 | $last_result = $server->taskResult('server_reset_password'); 186 | } catch (InvalidTaskException $e) { 187 | // No tasks yet 188 | } catch (Exception $e) { 189 | $error = $e->getMessage(); 190 | } 191 | 192 | return [ 193 | 'tabOverviewReplacementTemplate' => 'templates/clientarea/pages/resetpassword.tpl', 194 | 'templateVariables' => [ 195 | 'last_result' => $last_result, 196 | 'error' => $error 197 | ] 198 | ]; 199 | } 200 | 201 | /** 202 | * Client Area Manual Service Renew 203 | * 204 | * @param $params 205 | * @return array 206 | */ 207 | function time4vps_ClientAreaManualServiceRenew($params) 208 | { 209 | $domain = $params['domain']; 210 | $unpaidInvoiceIds = getUnpaidInvoiceIds($params['userid']); 211 | $unpaidInvoiceId = getCurrentServiceUnpaidInvoiceIds($unpaidInvoiceIds, $domain); 212 | if (count($unpaidInvoiceId) !== 0) { 213 | return [ 214 | 'tabOverviewReplacementTemplate' => 'templates/clientarea/pages/manualservicerenew.tpl', 215 | 'templateVariables' => [ 216 | 'unpaidInvoice' => $unpaidInvoiceId, 217 | ] 218 | ]; 219 | } 220 | if (empty($_POST['confirm'])) { 221 | return [ 222 | 'tabOverviewReplacementTemplate' => 'templates/clientarea/pages/manualservicerenew.tpl', 223 | 'templateVariables' => [ 224 | ] 225 | ]; 226 | } else { 227 | $productDetails = getProductDetails($params['userid'], $params['serviceid'], $params['pid']); 228 | 229 | if ($productDetails['result'] !== 'success') { 230 | return [ 231 | 'tabOverviewReplacementTemplate' => 'templates/clientarea/pages/manualservicerenew.tpl', 232 | 'templateVariables' => [ 233 | 'error' => 'Something went wrong.' 234 | ] 235 | ]; 236 | } 237 | 238 | $newNextDueDate = countNextDueDate($productDetails['products']['product'][0]['billingcycle'], $productDetails['products']['product'][0]['nextduedate']); 239 | if ($newNextDueDate === null) { 240 | return [ 241 | 'tabOverviewReplacementTemplate' => 'templates/clientarea/pages/manualservicerenew.tpl', 242 | 'templateVariables' => [ 243 | 'error' => 'Something went wrong.' 244 | ] 245 | ]; 246 | } 247 | 248 | updateClientProduct($params['serviceid'], $newNextDueDate); 249 | $invoiceDescription = $productDetails['products']['product'][0]['name'] 250 | . ' ' . $productDetails['products']['product'][0]['domain'] 251 | . ' (' . date("Y-m-d") . ' - ' . $newNextDueDate . ')'; 252 | $price = $productDetails['products']['product'][0]['firstpaymentamount']; 253 | $newInvoice = createInvoice($params['userid'], $invoiceDescription, $price); 254 | 255 | if ($newInvoice['result'] !== 'success') { 256 | return [ 257 | 'tabOverviewReplacementTemplate' => 'templates/clientarea/pages/manualservicerenew.tpl', 258 | 'templateVariables' => [ 259 | 'error' => 'Something went wrong.' 260 | ] 261 | ]; 262 | } 263 | return [ 264 | 'tabOverviewReplacementTemplate' => 'templates/clientarea/pages/manualservicerenew.tpl', 265 | 'templateVariables' => [ 266 | 'success' => true, 267 | 'newInvoiceId' => $newInvoice['invoiceid'], 268 | ] 269 | ]; 270 | } 271 | } 272 | 273 | function getProductDetails($userId, $serviceId, $productId) 274 | { 275 | $command = 'GetClientsProducts'; 276 | $postData = array( 277 | 'clientid' => $userId, 278 | 'serviceid' => $serviceId, 279 | 'pid' => $productId, 280 | 'stats' => true, 281 | ); 282 | 283 | return localAPI($command, $postData); 284 | } 285 | 286 | function countNextDueDate($billingcycle, $nextDueDate) 287 | { 288 | switch ($billingcycle) { 289 | case 'Monthly': 290 | $newNextDueDate = strtotime("+1 month", strtotime($nextDueDate)); 291 | $formatedNextDueDate = date('Y-m-d', $newNextDueDate); 292 | return $formatedNextDueDate; 293 | case 'Quarterly': 294 | $newNextDueDate = strtotime("+3 months", strtotime($nextDueDate)); 295 | $formatedNextDueDate = date('Y-m-d', $newNextDueDate); 296 | return $formatedNextDueDate; 297 | case 'Semi-Annually': 298 | $newNextDueDate = strtotime("+6 months", strtotime($nextDueDate)); 299 | $formatedNextDueDate = date('Y-m-d', $newNextDueDate); 300 | return $formatedNextDueDate; 301 | case 'Annually': 302 | $newNextDueDate = strtotime("+1 year", strtotime($nextDueDate)); 303 | $formatedNextDueDate = date('Y-m-d', $newNextDueDate); 304 | return $formatedNextDueDate; 305 | case 'Biennially': 306 | $newNextDueDate = strtotime("+2 years", strtotime($nextDueDate)); 307 | $formatedNextDueDate = date('Y-m-d', $newNextDueDate); 308 | return $formatedNextDueDate; 309 | } 310 | return null; 311 | } 312 | 313 | function updateClientProduct($serviceId, $newNextDueDate) 314 | { 315 | $command = 'UpdateClientProduct'; 316 | $postData = array( 317 | 'serviceid' => $serviceId, 318 | 'nextduedate' => $newNextDueDate, 319 | ); 320 | return localAPI($command, $postData); 321 | } 322 | 323 | function createInvoice($userId, $description, $price) 324 | { 325 | $command = 'CreateInvoice'; 326 | $postData = array( 327 | 'userid' => $userId, 328 | 'status' => 'Unpaid', 329 | 'sendinvoice' => '1', 330 | 'date' => date("Y-m-d"), 331 | 'itemdescription1' => $description, 332 | 'itemamount1' => $price, 333 | 'itemtaxed1' => true, 334 | ); 335 | 336 | return localAPI($command, $postData); 337 | } 338 | 339 | function getUnpaidInvoiceIds($userId) { 340 | $command = 'GetInvoices'; 341 | $postData = array( 342 | 'userid' => $userId, 343 | 'orderby' => 'invoicenumber', 344 | 'status' => 'Unpaid' 345 | ); 346 | 347 | $unpaidInvoices = localAPI($command, $postData); 348 | $unpaidInvoiceIds = []; 349 | foreach ($unpaidInvoices['invoices']['invoice'] as $invoice) { 350 | $unpaidInvoiceIds[] = $invoice['id']; 351 | } 352 | return $unpaidInvoiceIds; 353 | } 354 | 355 | function getCurrentServiceUnpaidInvoiceIds($unpaidInvoiceIds, $domain) { 356 | $currentServiceUnpaidInvoiceIds = []; 357 | foreach ($unpaidInvoiceIds as $id) { 358 | $command = 'GetInvoice'; 359 | $postData = array( 360 | 'invoiceid' => $id, 361 | ); 362 | $invoice = localAPI($command, $postData); 363 | if (strpos($invoice['items']['item'][0]['description'], $domain) !== false) { 364 | $currentServiceUnpaidInvoiceIds[] = $id; 365 | } 366 | } 367 | return $currentServiceUnpaidInvoiceIds; 368 | } 369 | 370 | /** 371 | * Client Area Server Reinstall 372 | * 373 | * @param $params 374 | * @return array 375 | */ 376 | function time4vps_ClientAreaReinstall($params) 377 | { 378 | $last_result = null; 379 | $error = null; 380 | $oses = []; 381 | 382 | if (!empty($_POST['confirm'] && !empty($_POST['os']))) { 383 | $error = time4vps_ReinstallServer($params, $_POST['os']); 384 | if ($error === 'success') { 385 | time4vps_MarkServerDetailsObsolete($params); 386 | time4vps_Redirect(time4vps_ActionLink($params, 'Reinstall')); 387 | } 388 | } 389 | 390 | try { 391 | time4vps_InitAPI($params); 392 | 393 | $server = time4vps_ExtractServer($params); 394 | $oses = $server->availableOS(); 395 | 396 | if ($params['configoption3']) { 397 | $visible_os = explode(PHP_EOL, $params['configoption3']); 398 | 399 | foreach ($visible_os as &$o) { 400 | $o = trim($o); 401 | } 402 | 403 | foreach ($oses as $idx => $os) { 404 | if (!in_array($os['title'], $visible_os)) { 405 | unset($oses[$idx]); 406 | } 407 | } 408 | } 409 | 410 | $last_result = $server->taskResult('server_recreate'); 411 | } catch (InvalidTaskException $e) { 412 | // No tasks yet 413 | } catch (Exception $e) { 414 | $error = $e->getMessage(); 415 | } 416 | 417 | return [ 418 | 'tabOverviewReplacementTemplate' => 'templates/clientarea/pages/reinstall.tpl', 419 | 'templateVariables' => [ 420 | 'oses' => $oses, 421 | 'last_result' => $last_result, 422 | 'error' => $error 423 | ] 424 | ]; 425 | } 426 | 427 | /** 428 | * Client Area Change Server Hostname 429 | * 430 | * @param $params 431 | * @return array 432 | */ 433 | function time4vps_ClientAreaChangeHostname($params) 434 | { 435 | $last_result = null; 436 | $error = null; 437 | 438 | if (!empty($_POST['hostname'])) { 439 | $error = time4vps_ChangeHostname($params, $_POST['hostname']); 440 | if ($error === 'success') { 441 | time4vps_MarkServerDetailsObsolete($params); 442 | time4vps_Redirect(time4vps_ActionLink($params, 'ChangeHostname')); 443 | } 444 | } 445 | 446 | return [ 447 | 'tabOverviewReplacementTemplate' => 'templates/clientarea/pages/changehostname.tpl', 448 | 'templateVariables' => [ 449 | 'last_result' => $last_result, 450 | 'error' => $error 451 | ] 452 | ]; 453 | } 454 | 455 | /** 456 | * Client Area Emergency Console 457 | * 458 | * @param $params 459 | * @return array 460 | */ 461 | function time4vps_ClientAreaEmergencyConsole($params) 462 | { 463 | $last_result = null; 464 | $error = null; 465 | 466 | if (!empty($_POST['timeout'])) { 467 | $error = time4vps_EmergencyConsole($params, $_POST['timeout']); 468 | if ($error === 'success') { 469 | time4vps_MarkServerDetailsObsolete($params); 470 | time4vps_Redirect(time4vps_ActionLink($params, 'EmergencyConsole')); 471 | } 472 | } 473 | 474 | try { 475 | time4vps_InitAPI($params); 476 | $server = time4vps_ExtractServer($params); 477 | $last_result = $server->taskResult('server_web_console'); 478 | } catch (InvalidTaskException $e) { 479 | // No tasks yet 480 | } catch (Exception $e) { 481 | $error = $e->getMessage(); 482 | } 483 | 484 | return [ 485 | 'tabOverviewReplacementTemplate' => 'templates/clientarea/pages/emergencyconsole.tpl', 486 | 'templateVariables' => [ 487 | 'last_result' => $last_result, 488 | 'error' => $error 489 | ] 490 | ]; 491 | } 492 | 493 | /** 494 | * Client Area Reset Firewall 495 | * 496 | * @param $params 497 | * @return array 498 | */ 499 | function time4vps_ClientAreaResetFirewall($params) 500 | { 501 | $last_result = null; 502 | $error = null; 503 | 504 | if (!empty($_POST['confirm'])) { 505 | $error = time4vps_ResetFirewall($params); 506 | if ($error === 'success') { 507 | time4vps_MarkServerDetailsObsolete($params); 508 | time4vps_Redirect(time4vps_ActionLink($params, 'ResetFirewall')); 509 | } 510 | } 511 | 512 | try { 513 | time4vps_InitAPI($params); 514 | $server = time4vps_ExtractServer($params); 515 | $last_result = $server->taskResult('server_flush_iptables'); 516 | } catch (InvalidTaskException $e) { 517 | // No tasks yet 518 | } catch (Exception $e) { 519 | $error = $e->getMessage(); 520 | } 521 | 522 | return [ 523 | 'tabOverviewReplacementTemplate' => 'templates/clientarea/pages/resetfirewall.tpl', 524 | 'templateVariables' => [ 525 | 'last_result' => $last_result, 526 | 'error' => $error 527 | ] 528 | ]; 529 | } 530 | 531 | /** 532 | * Usage graphs 533 | * 534 | * @param $params 535 | * @return array 536 | */ 537 | function time4vps_ClientAreaUsageGraphs($params) 538 | { 539 | $error = null; 540 | $graphs = []; 541 | 542 | try { 543 | time4vps_InitAPI($params); 544 | $server = time4vps_ExtractServer($params); 545 | 546 | foreach ($server->usageGraphs() as $graph) { 547 | $graphs[$graph["type"]] = $graph; 548 | } 549 | 550 | } catch (Exception $e) { 551 | $error = $e->getMessage(); 552 | } 553 | 554 | return [ 555 | 'tabOverviewReplacementTemplate' => 'templates/clientarea/pages/usagegraphs.tpl', 556 | 'templateVariables' => [ 557 | 'error' => $error, 558 | 'graphs' => $graphs, 559 | 'url_graph_detail' => time4vps_ProductDetailsLink($params) . "&act=UsageGraph&graph=" 560 | ] 561 | ]; 562 | } 563 | 564 | /** 565 | * Particular usage graph 566 | * 567 | * @param $params 568 | * @return array 569 | */ 570 | function time4vps_ClientAreaUsageGraph($params) 571 | { 572 | $error = null; 573 | $graphs = []; 574 | $graphType = ''; 575 | 576 | $graphTypes = ['traffic', 'io', 'load', 'iops', 'netpps', 'memory', 'cpu', 'storage']; 577 | 578 | if (!empty($_GET['graph']) && in_array($_GET['graph'], $graphTypes)) { 579 | $graphType = $_GET['graph']; 580 | try { 581 | time4vps_InitAPI($params); 582 | $server = time4vps_ExtractServer($params); 583 | 584 | foreach ($server->usageGraphs(768) as $graph) { 585 | preg_match("/^({$graphType})_(.*)$/", $graph["type"], $matches); 586 | 587 | if ($matches) { 588 | $graphs[ucfirst($matches[2])] = $graph['url']; 589 | } 590 | } 591 | } catch (Exception $e) { 592 | $error = $e->getMessage(); 593 | } 594 | } else { 595 | $error = "Invalid graph type."; 596 | } 597 | 598 | return [ 599 | 'tabOverviewReplacementTemplate' => 'templates/clientarea/pages/usagegraph.tpl', 600 | 'templateVariables' => [ 601 | 'error' => $error, 602 | 'graphs' => $graphs, 603 | 'graph_type' => ucfirst($graphType) 604 | ] 605 | ]; 606 | } 607 | 608 | /** 609 | * Usage history 610 | * 611 | * @param $params 612 | * @return array 613 | */ 614 | function time4vps_ClientAreaUsageHistory($params) 615 | { 616 | $error = null; 617 | $usage_history = null; 618 | 619 | try { 620 | time4vps_InitAPI($params); 621 | $server = time4vps_ExtractServer($params); 622 | $usage_history = $server->usageHistory(); 623 | } catch (Exception $e) { 624 | $error = $e->getMessage(); 625 | } 626 | 627 | return [ 628 | 'tabOverviewReplacementTemplate' => 'templates/clientarea/pages/usagehistory.tpl', 629 | 'templateVariables' => [ 630 | 'error' => $error, 631 | 'usage_history' => array_reverse($usage_history) 632 | ] 633 | ]; 634 | } 635 | -------------------------------------------------------------------------------- /modules/servers/time4vps/includes/helpers.php: -------------------------------------------------------------------------------- 1 | benchmark(); 23 | logModuleCall('Time4VPS', "(id: {$id}) '{$args[0]}' request to '{$args[1]}'", json_encode($request, JSON_PRETTY_PRINT), (string) $response); 24 | localAPI('LogActivity', [ 25 | 'description' => "Time4VPS API request (id: {$id}) took {$benchmark} s." 26 | ]); 27 | }); 28 | } 29 | 30 | /** 31 | * Get Time4VPS server ID from params 32 | * 33 | * @param $params 34 | * @return Server|false External server ID or false 35 | * @throws Exception 36 | */ 37 | function time4vps_ExtractServer($params) 38 | { 39 | if ($server = Capsule::table(TIME4VPS_TABLE)->where('service_id', $params['serviceid'])->first()) { 40 | /** @var Server $s */ 41 | return new Server($server->external_id); 42 | } 43 | 44 | throw new Exception('Unable to find related server'); 45 | } 46 | 47 | /** 48 | * Get component ID by it's name 49 | * 50 | * @param string $name 51 | * @param int $pid 52 | * @return object|null 53 | */ 54 | function time4vps_GetComponentIdByName($name, $pid) 55 | { 56 | $component = Capsule::table('tblproductconfigoptions') 57 | ->select('tblproductconfigoptions.id') 58 | ->join('tblproductconfiglinks', 'tblproductconfiglinks.gid', '=', 'tblproductconfigoptions.gid') 59 | ->where('tblproductconfigoptions.name', $name) 60 | ->where('tblproductconfiglinks.pid', $pid) 61 | ->first(); 62 | 63 | return $component ? $component->id : null; 64 | } 65 | 66 | /** 67 | * Return main page link 68 | * 69 | * @param $params 70 | * @return string 71 | */ 72 | function time4vps_ProductDetailsLink($params) 73 | { 74 | return "clientarea.php?action=productdetails&id={$params['serviceid']}"; 75 | } 76 | 77 | /** 78 | * Return action link 79 | * 80 | * @param $params 81 | * @param $action 82 | * @return string 83 | */ 84 | function time4vps_ActionLink($params, $action) 85 | { 86 | return "clientarea.php?action=productdetails&id={$params['serviceid']}&act={$action}"; 87 | } 88 | 89 | /** 90 | * Redirect user to URL 91 | * 92 | * @param $url 93 | */ 94 | function time4vps_Redirect($url) 95 | { 96 | header("Location: {$url}"); 97 | exit(); 98 | } 99 | 100 | /** 101 | * Extract billing cycle 102 | * 103 | * @param $cycle 104 | * @return string 105 | */ 106 | function time4vps_BillingCycle($cycle) 107 | { 108 | switch ($cycle) { 109 | case 'Monthly': 110 | return 'm'; 111 | case 'Quarterly': 112 | return 'q'; 113 | case 'Semi-Annually': 114 | return 's'; 115 | case 'Annually': 116 | return 'a'; 117 | case 'Biennially': 118 | return 'b'; 119 | } 120 | 121 | return null; 122 | } 123 | 124 | /** 125 | * Extract package options from params 126 | * 127 | * @param $params 128 | * @param bool $skip_disabled 129 | * @return array 130 | */ 131 | function time4vps_ExtractComponents($params, $skip_disabled = true) 132 | { 133 | $custom = []; 134 | $map = json_decode($params['configoption5'], true); 135 | if ($params['configoptions'] && $map['components']) { 136 | foreach ($params['configoptions'] as $configoption => $enabled) { 137 | if (!$enabled && $skip_disabled) { 138 | continue; 139 | } 140 | 141 | $option = Capsule::table('tblproductconfigoptions') 142 | ->select('tblproductconfigoptions.id') 143 | ->join('tblproductconfiggroups', 'tblproductconfiggroups.id', '=', 'tblproductconfigoptions.gid') 144 | ->join('tblproductconfiglinks', 'tblproductconfiglinks.gid', '=', 'tblproductconfiggroups.id') 145 | ->where('tblproductconfiglinks.pid', $params['pid']) 146 | ->where('tblproductconfigoptions.optionname', $configoption) 147 | ->first(); 148 | 149 | if (!$option || empty($map['components'][$option->id])) { 150 | continue; 151 | } 152 | 153 | $component = $map['components'][$option->id]; 154 | $custom[$component['category_id']][$component['item_id']] = $enabled; 155 | } 156 | } 157 | 158 | return $custom; 159 | } 160 | -------------------------------------------------------------------------------- /modules/servers/time4vps/includes/hooks/adminarea.php: -------------------------------------------------------------------------------- 1 | where('id', $params['serviceid'])->update(['domainstatus' => 'Pending']); 8 | }); 9 | -------------------------------------------------------------------------------- /modules/servers/time4vps/includes/hooks/clientarea.php: -------------------------------------------------------------------------------- 1 | join('tblservers', 'tblservers.id', '=', 'tblhosting.server') 15 | ->where('tblhosting.id', $id) 16 | ->where('tblhosting.domainstatus', 'Active') 17 | ->where('tblservers.name', 'Time4VPS') 18 | ->first()) { 19 | return; 20 | } 21 | 22 | 23 | $actions = $sidebar->addChild( 24 | 'actionsMenu', [ 25 | 'name' => 'Manage Server', 26 | 'label' => Lang::trans('Management'), 27 | 'order' => 15, 28 | 'icon' => 'fas fa-cogs', 29 | ] 30 | ); 31 | 32 | $actions->addChild( 33 | 'actionsMenuRebootItem', [ 34 | 'name' => 'Reboot', 35 | 'label' => Lang::trans('Reboot'), 36 | 'uri' => "clientarea.php?action=productdetails&id={$id}&act=Reboot", 37 | 'order' => 0, 38 | 'icon' => 'fa-fw fa-sync-alt' 39 | ] 40 | ); 41 | 42 | $actions->addChild( 43 | 'actionsMenuResetPasswordItem', [ 44 | 'name' => 'Reset Password', 45 | 'label' => Lang::trans('Reset Password'), 46 | 'uri' => "clientarea.php?action=productdetails&id={$id}&act=ResetPassword", 47 | 'order' => 1, 48 | 'icon' => 'fa-key' 49 | ] 50 | ); 51 | 52 | $actions->addChild( 53 | 'actionsMenuManualServiceRenewItem', [ 54 | 'name' => 'Manual Service Renew', 55 | 'label' => Lang::trans('Manual Service Renew'), 56 | 'uri' => "clientarea.php?action=productdetails&id={$id}&act=ManualServiceRenew", 57 | 'order' => 1, 58 | 'icon' => 'fa-wallet' 59 | ] 60 | ); 61 | 62 | $actions->addChild( 63 | 'actionsMenuChangeHostnameItem', [ 64 | 'name' => 'Change Hostname', 65 | 'label' => Lang::trans('Change Hostname'), 66 | 'uri' => "clientarea.php?action=productdetails&id={$id}&act=ChangeHostname", 67 | 'order' => 2, 68 | 'icon' => 'fa-fw fa-edit' 69 | ] 70 | ); 71 | 72 | $actions->addChild( 73 | 'actionsMenuReinstallItem', [ 74 | 'name' => 'Reinstall', 75 | 'label' => Lang::trans('Reinstall'), 76 | 'uri' => "clientarea.php?action=productdetails&id={$id}&act=Reinstall", 77 | 'order' => 3, 78 | 'icon' => 'fa-fw fa-wrench' 79 | ] 80 | ); 81 | 82 | $actions->addChild( 83 | 'actionsMenuEmergencyConsoleItem', [ 84 | 'name' => 'Emergency Console', 85 | 'label' => Lang::trans('Emergency Console'), 86 | 'uri' => "clientarea.php?action=productdetails&id={$id}&act=EmergencyConsole", 87 | 'order' => 4, 88 | 'icon' => 'fa-fw fa-terminal' 89 | ] 90 | ); 91 | 92 | $actions->addChild( 93 | 'actionsMenuChangeDNSItem', [ 94 | 'name' => 'Change DNS', 95 | 'label' => Lang::trans('Change DNS'), 96 | 'uri' => "clientarea.php?action=productdetails&id={$id}&act=ChangeDNS", 97 | 'order' => 5, 98 | 'icon' => 'fa-fw fa-tags' 99 | ] 100 | ); 101 | 102 | $actions->addChild( 103 | 'actionsMenuResetFirewallItem', [ 104 | 'name' => 'Reset Firewall', 105 | 'label' => Lang::trans('Reset Firewall'), 106 | 'uri' => "clientarea.php?action=productdetails&id={$id}&act=ResetFirewall", 107 | 'order' => 6, 108 | 'icon' => 'fa-fw fa-fire' 109 | ] 110 | ); 111 | 112 | $actions->addChild( 113 | 'actionsMenuChangePTRItem', [ 114 | 'name' => 'Change PTR', 115 | 'label' => Lang::trans('Change PTR'), 116 | 'uri' => "clientarea.php?action=productdetails&id={$id}&act=ChangePTR", 117 | 'order' => 7, 118 | 'icon' => 'fa-fw fa-search' 119 | ] 120 | ); 121 | }); 122 | 123 | add_hook('ClientAreaSecondarySidebar', 1, function ($sidebar) 124 | { 125 | if ($_REQUEST['action'] !== 'productdetails' || !$_REQUEST['id']) { 126 | return; 127 | } 128 | 129 | $id = $_REQUEST['id']; 130 | 131 | if (!Capsule::table('tblhosting') 132 | ->join('tblservers', 'tblservers.id', '=', 'tblhosting.server') 133 | ->where('tblhosting.id', $id) 134 | ->where('tblhosting.domainstatus', 'Active') 135 | ->where('tblservers.name', 'Time4VPS') 136 | ->first()) { 137 | return; 138 | } 139 | 140 | $info = $sidebar->addChild( 141 | 'actionsMenu', [ 142 | 'name' => 'Server Information', 143 | 'label' => Lang::trans('Server Information'), 144 | 'order' => 15, 145 | 'icon' => 'fas fa-info', 146 | ] 147 | ); 148 | 149 | $info->addChild( 150 | 'infoMenuUsageGraphsItem', [ 151 | 'name' => 'Usage Graphs', 152 | 'label' => Lang::trans('Usage Graphs'), 153 | 'uri' => "clientarea.php?action=productdetails&id={$id}&act=UsageGraphs", 154 | 'order' => 0, 155 | 'icon' => 'fa-chart-area', 156 | ] 157 | ); 158 | 159 | $info->addChild( 160 | 'infoMenuUsageHistoryItem', [ 161 | 'name' => 'Usage History', 162 | 'label' => Lang::trans('Usage History'), 163 | 'uri' => "clientarea.php?action=productdetails&id={$id}&act=UsageHistory", 164 | 'order' => 0, 165 | 'icon' => 'fa-chart-bar', 166 | ] 167 | ); 168 | }); 169 | 170 | add_hook('ClientAreaFooterOutput', 1, function ($params) { 171 | if ($params['module'] === 'time4vps' && $params['action'] === 'productdetails') { 172 | return ''; 173 | } 174 | }); 175 | -------------------------------------------------------------------------------- /modules/servers/time4vps/includes/server.php: -------------------------------------------------------------------------------- 1 | create($product_id, 'serverhost.name', time4vps_BillingCycle($params['model']['billingcycle']), time4vps_ExtractComponents($params), $params['configoption4']); 34 | 35 | $service_id = (new Service())->fromOrder($order['order_num']); 36 | 37 | Capsule::table(TIME4VPS_TABLE)->insert([ 38 | 'external_id' => $service_id, 39 | 'service_id' => $params['serviceid'], 40 | 'details_updated' => null 41 | ]); 42 | } catch (Exception $e) { 43 | return 'Cannot create account. ' . $e->getMessage(); 44 | } 45 | return 'success'; 46 | } 47 | 48 | /** 49 | * Terminate account 50 | * 51 | * @param $params 52 | * @return string 53 | */ 54 | function time4vps_TerminateAccount($params) 55 | { 56 | time4vps_InitAPI($params); 57 | 58 | try { 59 | $server = time4vps_ExtractServer($params); 60 | } catch (Exception $e) { 61 | return $e->getMessage(); 62 | } 63 | 64 | try { 65 | (new Service($server->id()))->cancel('No need, terminated by API', true); 66 | } catch (Exception $e) { 67 | return 'Cannot terminate account. ' . $e->getMessage(); 68 | } 69 | 70 | return 'success'; 71 | } 72 | 73 | /** 74 | * Upgrade package or config option 75 | * 76 | * @param $params 77 | * @return string 78 | * @throws Exception 79 | */ 80 | function time4vps_ChangePackage($params) 81 | { 82 | time4vps_InitAPI($params); 83 | 84 | try { 85 | $server = time4vps_ExtractServer($params); 86 | } catch (Exception $e) { 87 | return $e->getMessage(); 88 | } 89 | 90 | try { 91 | $service = new Service($server->id()); 92 | } catch (Exception $e) { 93 | return $e->getMessage(); 94 | } 95 | 96 | $details = $server->details(); 97 | 98 | if ((int)$params['configoption1'] !== (int)$details['package_id']) { 99 | $service->orderUpgrade(['package' => $params['configoption1']], time4vps_BillingCycle($params['model']['billingcycle'])); 100 | } 101 | 102 | $service->orderUpgrade(['resources' => time4vps_ExtractComponents($params, false)], time4vps_BillingCycle($params['model']['billingcycle'])); 103 | 104 | return 'success'; 105 | } 106 | 107 | /** 108 | * Changes server password 109 | * 110 | * @param $params 111 | * @return string 112 | */ 113 | function time4vps_ResetPassword($params) 114 | { 115 | time4vps_InitAPI($params); 116 | 117 | try { 118 | $server = time4vps_ExtractServer($params); 119 | $server->resetPassword(); 120 | } catch (Exception $e) { 121 | return 'Cannot change server password. ' . $e->getMessage(); 122 | } 123 | 124 | return 'success'; 125 | } 126 | 127 | /** 128 | * Reboot server 129 | * 130 | * @param $params 131 | * @return string 132 | */ 133 | function time4vps_Reboot($params) 134 | { 135 | time4vps_InitAPI($params); 136 | 137 | try { 138 | $server = time4vps_ExtractServer($params); 139 | $server->reboot(); 140 | } catch (Exception $e) { 141 | return 'Cannot reboot server. ' . $e->getMessage(); 142 | } 143 | 144 | return 'success'; 145 | } 146 | 147 | /** 148 | * Change DNS Servers 149 | * 150 | * @param $params 151 | * @param string $ns1 152 | * @param string $ns2 153 | * @param string $ns3 154 | * @param string $ns4 155 | * @return string 156 | */ 157 | function time4vps_ChangeDNS($params, $ns1, $ns2 = '', $ns3 = '', $ns4 = '') 158 | { 159 | time4vps_InitAPI($params); 160 | 161 | try { 162 | $server = time4vps_extractServer($params); 163 | $server->setDNS($ns1, $ns2, $ns3, $ns4); 164 | } catch (Exception $e) { 165 | return 'Cannot change DNS. ' . $e->getMessage(); 166 | } 167 | 168 | return 'success'; 169 | } 170 | 171 | /** 172 | * Change PTR Record 173 | * 174 | * @param $params 175 | * @param $ip 176 | * @param $ptr 177 | * @return string 178 | */ 179 | function time4vps_ChangePTR($params, $ip, $ptr) 180 | { 181 | time4vps_InitAPI($params); 182 | 183 | try { 184 | $server = time4vps_ExtractServer($params); 185 | $server->setPTR($ip, $ptr); 186 | } catch (Exception $e) { 187 | return 'Cannot change PTR. ' . $e->getMessage(); 188 | } 189 | 190 | return 'success'; 191 | } 192 | 193 | /** 194 | * Reinstall server 195 | * 196 | * @param $params 197 | * @param $os 198 | * @return string 199 | */ 200 | function time4vps_ReinstallServer($params, $os) 201 | { 202 | time4vps_InitAPI($params); 203 | 204 | try { 205 | $server = time4vps_ExtractServer($params); 206 | $server->reinstall($os, null, $params['configoption2']); 207 | } catch (Exception $e) { 208 | return 'Cannot reinstall server. ' . $e->getMessage(); 209 | } 210 | 211 | return 'success'; 212 | } 213 | 214 | /** 215 | * Change server hostname 216 | * 217 | * @param $params 218 | * @param $hostname 219 | * @return string 220 | */ 221 | function time4vps_ChangeHostname($params, $hostname) 222 | { 223 | time4vps_InitAPI($params); 224 | 225 | try { 226 | $server = time4vps_ExtractServer($params); 227 | $server->rename($hostname); 228 | } catch (Exception $e) { 229 | return 'Cannot rename server. ' . $e->getMessage(); 230 | } 231 | 232 | return 'success'; 233 | } 234 | 235 | /** 236 | * Launch emergency console 237 | * 238 | * @param $params 239 | * @param $timeout 240 | * @return string 241 | */ 242 | function time4vps_EmergencyConsole($params, $timeout) 243 | { 244 | time4vps_InitAPI($params); 245 | 246 | try { 247 | $server = time4vps_ExtractServer($params); 248 | $server->emergencyConsole($timeout); 249 | } catch (Exception $e) { 250 | return 'Cannot launch emergency console. ' . $e->getMessage(); 251 | } 252 | 253 | return 'success'; 254 | } 255 | 256 | /** 257 | * Reset firewall to default settings 258 | * 259 | * @param $params 260 | * @return string 261 | */ 262 | function time4vps_ResetFirewall($params) 263 | { 264 | time4vps_InitAPI($params); 265 | 266 | try { 267 | $server = time4vps_ExtractServer($params); 268 | $server->flushFirewall(); 269 | } catch (Exception $e) { 270 | return 'Cannot reset firewall. ' . $e->getMessage(); 271 | } 272 | 273 | return 'success'; 274 | } 275 | 276 | /** 277 | * Update server details table 278 | * 279 | * @param $params 280 | * @param bool $force 281 | * @return array|false 282 | * @throws Exception 283 | */ 284 | function time4vps_GetServerDetails($params, $force = false) 285 | { 286 | $row = Capsule::table(TIME4VPS_TABLE)->where('service_id', $params['serviceid'])->first(); 287 | 288 | $current_details = $row->details ? json_decode($row->details, true) : []; 289 | $last_update = $row->details_updated ? strtotime($row->details_updated) : null; 290 | 291 | if ($force || !$current_details || !$last_update || $current_details['active_task'] || time() - $last_update > 5 * 60) { 292 | 293 | $update = []; 294 | 295 | time4vps_InitAPI($params); 296 | 297 | $server = time4vps_ExtractServer($params); 298 | 299 | // Update service details 300 | $service = (new Service($server->id()))->details(); 301 | 302 | $update['lastupdate'] = date('Y-m-d H:i:s', time()); 303 | $update['domainstatus'] = $service['status']; 304 | 305 | if ($update['domainstatus'] === 'Active') { 306 | 307 | // Update server details 308 | $details = $server->details(); 309 | 310 | if ($details['active_task']) { 311 | return $details; 312 | } 313 | 314 | $dns_servers = !empty($details['dns_servers']) ? $details['dns_servers'] : []; 315 | 316 | // Set password to empty 317 | if (!$details['os']) { 318 | $update['username'] = ''; 319 | $update['password'] = ''; 320 | } 321 | 322 | // Usage 323 | $update = array_merge([ 324 | 'domain' => $details['domain'], 325 | 'diskusage' => $details['disk_usage'], 326 | 'disklimit' => $details['disk_limit'], 327 | 'bwusage' => $details['bw_in'] + $details['bw_out'], 328 | 'bwlimit' => $details['bw_limit'], 329 | 'dedicatedip' => $details['ip'], 330 | 'assignedips' => implode(',', $details['additional_ip']), 331 | 'ns1' => !empty($dns_servers[0]) ? $dns_servers[0] : null, 332 | 'ns2' => !empty($dns_servers[1]) ? $dns_servers[1] : null, 333 | 'username' => preg_match('/^kvm-win-/', $details['os']) ? 'Administrator' : 'root', 334 | ], $update); 335 | 336 | // Extract password 337 | foreach ($details['last_tasks'] as $task) { 338 | if (in_array($task['name'], ['server_reset_password', 'server_recreate']) && $task['results']) { 339 | preg_match('/Password:\s(.*)\s?/', $task['results'], $new_password); 340 | if ($new_password) { 341 | /** @noinspection PhpUndefinedFunctionInspection */ 342 | $update['password'] = encrypt(trim($new_password[1])); 343 | } 344 | } 345 | } 346 | 347 | // Extract components 348 | $map = json_decode($params['configoption5'], true); 349 | $component_map = array_flip($map['components']); 350 | 351 | foreach ($details['components'] as $component) { 352 | if (empty($component_map[$component['id']])) { 353 | continue; 354 | } 355 | 356 | Capsule::table('tblhostingconfigoptions') 357 | ->where([ 358 | 'relid' => $params['serviceid'], 359 | 'configid' => $component_map[$component['id']], 360 | 'optionid' => $component_map[$component['id']] 361 | ]) 362 | ->update(['qty' => $component['selected'] ? 1 : 0]); 363 | } 364 | 365 | // Unset last tasks 366 | unset($details['last_tasks']); 367 | 368 | // Cache data 369 | Capsule::table(TIME4VPS_TABLE) 370 | ->where('service_id', $params['serviceid']) 371 | ->update([ 372 | 'details' => json_encode($details), 373 | 'details_updated' => $update['lastupdate'] 374 | ]); 375 | 376 | $current_details = $details; 377 | } 378 | 379 | // Update WHMCS info 380 | Capsule::table('tblhosting') 381 | ->where('id', $params['serviceid']) 382 | ->update($update); 383 | } 384 | 385 | return $current_details; 386 | } 387 | 388 | /** 389 | * Update server details table and mark details as obsolete 390 | * 391 | * @param $params 392 | */ 393 | function time4vps_MarkServerDetailsObsolete($params) 394 | { 395 | /** @noinspection PhpUndefinedClassInspection */ 396 | Capsule::table(TIME4VPS_TABLE) 397 | ->where('service_id', $params['serviceid']) 398 | ->update([ 399 | 'details_updated' => null 400 | ]); 401 | } -------------------------------------------------------------------------------- /modules/servers/time4vps/install.php: -------------------------------------------------------------------------------- 1 | hasTable('sm_time4vps')) { 16 | try { 17 | Capsule::schema() 18 | ->table('sm_time4vps', function ($table) { 19 | /** @var $table Object */ 20 | $table->text('details')->nullable(); 21 | $table->timestamp('details_updated')->nullable(); 22 | }); 23 | } catch (PDOException $e) { 24 | // Column already exists 25 | if ($e->getCode() !== '42S21') { 26 | throw $e; 27 | } 28 | } 29 | Capsule::schema()->rename('sm_time4vps', TIME4VPS_TABLE); 30 | } 31 | 32 | /** Create service ID maping table */ 33 | if (!Capsule::schema()->hasTable(TIME4VPS_TABLE)) { 34 | Capsule::schema()->create( 35 | TIME4VPS_TABLE, 36 | function ($table) { 37 | /** @var $table Object */ 38 | $table->integer('service_id')->unique(); 39 | $table->integer('external_id')->index(); 40 | $table->text('details')->nullable(); 41 | $table->timestamp('details_updated')->nullable(); 42 | } 43 | ); 44 | } 45 | 46 | if ($_GET['truncate']) { 47 | 48 | // Delete components 49 | Capsule::table('tblproductconfiglinks')->truncate(); 50 | Capsule::table('tblproductconfiggroups')->truncate(); 51 | Capsule::table('tblproductconfigoptions')->truncate(); 52 | Capsule::table('tblproductconfigoptionssub')->truncate(); 53 | 54 | // Delete products 55 | Capsule::table('tblproducts')->truncate(); 56 | 57 | // Delete upgrades 58 | Capsule::table('tblproduct_upgrade_products')->truncate(); 59 | 60 | // Delete pricing 61 | Capsule::table('tblpricing')->truncate(); 62 | 63 | // Upgrades 64 | Capsule::table('tblupgrades')->truncate(); 65 | 66 | // Config options 67 | Capsule::table('tblhostingconfigoptions')->truncate(); 68 | 69 | echo 'Product tables truncated. '; 70 | } else { 71 | echo 'Install successfull. '; 72 | } 73 | echo 'If you want to import all products from Time4VPS, run update.'; -------------------------------------------------------------------------------- /modules/servers/time4vps/templates/clientarea/clientarea.tpl: -------------------------------------------------------------------------------- 1 | {if !$details} 2 |
3 |
4 |
5 | Server is being provisioned. Please wait. 6 |
7 |
8 |
9 | {else} 10 |

Server Info

11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | {if $details.label} 19 | 20 | 21 | 22 | 23 | {/if} 24 | 25 | 26 | 27 | 28 | 29 | 30 | 34 | 35 | 36 | 37 | 41 | 42 | 43 | 44 | 48 | 49 | {if $details.os} 50 | 51 | 52 | 53 | 54 | {if $details.additional_ip} 55 | 56 | 57 | 62 | 63 | {/if} 64 | {/if} 65 |
Hostname{$details.domain}
Label{$details.label}
Processor{$details.cpu_cores} x {$details.cpu_frequency} Mhz
RAM 31 | {$details.ram_limit} MB 32 | ({$details.ram_used} MB used) 33 |
HDD 38 | {$details.disk_limit / 1024} GB 39 | ({($details.disk_usage / 1024)|number_format:2} GB used) 40 |
Bandwidth 45 | {$details.bw_limit / 1024} GB 46 | (In {$details.bw_in} MB, Out {$details.bw_out} MB, Total {$details.bw_in + $details.bw_out} MB) 47 |
Main IP{$details.ip}
Additional IPs 58 | {foreach from=$details.additional_ip item=ip} 59 | {$ip} 60 | {/foreach} 61 |
66 | {/if} -------------------------------------------------------------------------------- /modules/servers/time4vps/templates/clientarea/pages/changedns.tpl: -------------------------------------------------------------------------------- 1 | {if $error} 2 |
3 | {$error} 4 |
5 | {/if} 6 | 7 |

Change DNS servers

8 | 9 |
10 |
11 | 12 |
13 | 14 |
15 |
16 |
17 | 18 |
19 | 20 |
21 |
22 |
23 | 24 |
25 |
26 | -------------------------------------------------------------------------------- /modules/servers/time4vps/templates/clientarea/pages/changehostname.tpl: -------------------------------------------------------------------------------- 1 | {if $error} 2 |
3 | {$error} 4 |
5 | {/if} 6 | 7 |

Change Hostname

8 | 9 |
10 | Before changing hostname, make sure that hostname A record is pointed to your server IP address. 11 |
12 | 13 |
14 |
15 | 16 |
17 | 18 |
19 |
20 |
21 | 22 |
23 |
-------------------------------------------------------------------------------- /modules/servers/time4vps/templates/clientarea/pages/changeptr.tpl: -------------------------------------------------------------------------------- 1 | {if $error} 2 |
3 | {$error} 4 |
5 | {/if} 6 | 7 |

Change PTR

8 | 9 | {if !$ips} 10 |
11 | Server does not have additional IP addresses. 12 |
13 | {else} 14 |
15 |
16 | 17 |
18 | 24 |
25 |
26 |
27 | 28 |
29 | 30 |
31 |
32 |
33 | 34 |
35 |
36 | {/if} -------------------------------------------------------------------------------- /modules/servers/time4vps/templates/clientarea/pages/emergencyconsole.tpl: -------------------------------------------------------------------------------- 1 | {if $error} 2 |
3 | {$error} 4 |
5 | {/if} 6 | 7 |

Emergency Console

8 | 9 |
10 | WARNING: We do not recommend to use console for daily server access, it's designed only for emergency situations! 11 |
12 | 13 | {if $last_result.completed} 14 |

Your last emergency console was launched at {$last_result.completed|date_format:'%c'}:

15 |
{$last_result.results}
16 |
17 | {/if} 18 | 19 |
20 |
21 |
22 |
23 |

How long do you want to access console on {$account.domain} server?

24 |
25 | {foreach from=['1h', '3h', '6h', '12h', '24h'] item=t} 26 | 29 | {/foreach} 30 |
31 |
32 |
33 | 34 |
35 |
36 |
37 |
-------------------------------------------------------------------------------- /modules/servers/time4vps/templates/clientarea/pages/manualservicerenew.tpl: -------------------------------------------------------------------------------- 1 | {if $error} 2 |
3 | {$error} 4 |
5 | {elseif $success} 6 |
7 | New invoice has been issued #{$newInvoiceId}. 8 |
9 | {/if} 10 |

Manual Service Renew


11 | {if $success} 12 | You currently have an outstanding invoices for this service: 13 |
  • Invoice: #{$newInvoiceId}
  • 14 | {elseif count($unpaidInvoice) !== 0} 15 | You currently have an outstanding invoices for this service: 16 | {foreach from=$unpaidInvoice item=$id} 17 |
  • Invoice: #{$id}
  • 18 | {/foreach} 19 | {else} 20 |
    21 |
    22 | If you'd like to issue renewal invoice for this service sooner, click on button below. 23 |
    24 | 25 | 26 | 27 |
    28 | {/if} -------------------------------------------------------------------------------- /modules/servers/time4vps/templates/clientarea/pages/reboot.tpl: -------------------------------------------------------------------------------- 1 | {if $error} 2 |
    3 | {$error} 4 |
    5 | {/if} 6 | 7 |

    Server Reboot

    8 | 9 | {if $last_result.completed} 10 |

    Your server was rebooted at {$last_result.completed|date_format:'%c'}:

    11 |
    {$last_result.results}
    12 |
    13 | {/if} 14 | 15 |
    16 | 17 | 18 | 19 |
    -------------------------------------------------------------------------------- /modules/servers/time4vps/templates/clientarea/pages/reinstall.tpl: -------------------------------------------------------------------------------- 1 | {if $error} 2 |
    3 | {$error} 4 |
    5 | {/if} 6 | 7 |

    Reinstall Server

    8 | 9 | {if $last_result.completed} 10 |

    Your server was reinstalled at {$last_result.completed|date_format:'%c'}:

    11 |
    {$last_result.results}
    12 |
    13 | {/if} 14 | 15 |
    16 |
    17 | 18 |
    19 | 24 |
    25 |
    26 |
    27 |
    28 | 32 |
    33 |
    34 |
    35 | 36 |
    37 |
    -------------------------------------------------------------------------------- /modules/servers/time4vps/templates/clientarea/pages/resetfirewall.tpl: -------------------------------------------------------------------------------- 1 | {if $error} 2 |
    3 | {$error} 4 |
    5 | {/if} 6 | 7 |

    Reset Firewall

    8 | 9 | {if $last_result.completed} 10 |

    Your firewall was reset at {$last_result.completed|date_format:'%c'}:

    11 |
    {$last_result.results}
    12 |
    13 | {/if} 14 | 15 |
    16 | 17 | 18 |
    19 | -------------------------------------------------------------------------------- /modules/servers/time4vps/templates/clientarea/pages/resetpassword.tpl: -------------------------------------------------------------------------------- 1 | {if $error} 2 |
    3 | {$error} 4 |
    5 | {/if} 6 | 7 |

    Reset Password

    8 | 9 | {if $last_result.completed} 10 |

    Your password was reset at {$last_result.completed|date_format:'%c'}:

    11 |
    {$last_result.results}
    12 |
    13 | {/if} 14 | 15 |
    16 | 17 | 18 |
    19 | -------------------------------------------------------------------------------- /modules/servers/time4vps/templates/clientarea/pages/usagegraph.tpl: -------------------------------------------------------------------------------- 1 | {if $error} 2 |
    3 | {$error} 4 |
    5 | {/if} 6 | 7 |

    {$graph_type} usage

    8 | 9 | {foreach from=$graphs item=url key=period} 10 |
    11 |
    12 |

    {$period}

    13 | {$period} 14 |
    15 |
    16 | {/foreach} -------------------------------------------------------------------------------- /modules/servers/time4vps/templates/clientarea/pages/usagegraphs.tpl: -------------------------------------------------------------------------------- 1 | {if $error} 2 |
    3 | {$error} 4 |
    5 | {/if} 6 | 7 |

    Usage Graphs

    8 | 9 | {if $graphs} 10 |
    11 |
    12 |

    Traffic

    13 | Traffic 14 |
    15 |
    16 |

    Packets

    17 | Packets 18 |
    19 |
    20 |
    21 |
    22 |

    CPU

    23 | CPU 24 |
    25 |
    26 |

    Load

    27 | Load 28 |
    29 |
    30 |
    31 |
    32 |

    I/O

    33 | I/O 34 |
    35 |
    36 |

    IOPS

    37 | IOPS 38 |
    39 |
    40 |
    41 |
    42 |

    Memory

    43 | Memory 44 |
    45 |
    46 |

    Storage

    47 | Storage 48 |
    49 |
    50 | {else} 51 |
    52 | Server graphs are not available yet. 53 |
    54 | {/if} -------------------------------------------------------------------------------- /modules/servers/time4vps/templates/clientarea/pages/usagehistory.tpl: -------------------------------------------------------------------------------- 1 | {if $error} 2 |
    3 | {$error} 4 |
    5 | {/if} 6 | 7 |

    Usage History

    8 | 9 | {if $usage_history} 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | {foreach from=$usage_history item=item} 22 | 23 | {assign var=year value=$item.year} 24 | {assign var=month value=$item.month} 25 | {assign var=history_date value="$year-$month-01"} 26 | 27 | 28 | 29 | 30 | 37 | 44 | 45 | {/foreach} 46 |
    PeriodDownloadUploadTotal BandwidthDisk QuotaInode Quota
    {$history_date|date_format:"%B, %Y"}{($item.bw_in/1024)|number_format:3} GB{($item.bw_out/1024)|number_format:3} GB{(($item.bw_in+$item.bw_out)/1024)|number_format:3} GB 31 | {if $item.quota_usage} 32 | {($item.quota_usage/1024)|number_format:2} GB / {($item.quota_limit/1024)|number_format:0} GB 33 | {else} 34 | - 35 | {/if} 36 | 38 | {if $item.inode_usage} 39 | {$item.inode_usage} / {$item.inode_limit} 40 | {else} 41 | - 42 | {/if} 43 |
    47 | {else} 48 |
    49 | Server usage history is not available yet. 50 |
    51 | {/if} -------------------------------------------------------------------------------- /modules/servers/time4vps/templates/clientarea/serverbusy.tpl: -------------------------------------------------------------------------------- 1 |
    2 |
    3 |
    4 | {assign var=active_task value=$details.active_task} 5 | {assign var=time value=$smarty.now|date_format:"%s"} 6 | {assign var=seconds value=$active_task.activated|date_format:"%s"} 7 | {assign var=seconds value=$time-$seconds} 8 | {assign var=minutes value=$seconds/60|string_format:"%d"} 9 | {assign var=seconds value=$seconds%60} 10 | 11 |

    12 |

    Server is busy.

    13 |

    Task initiated: {$active_task.activated|date_format:'%c'}

    14 | {if $minutes|intval >= 0 && $seconds|intval > 0} 15 |

    Time Elapsed: {$minutes|intval}m {$seconds|intval}s

    16 | {/if} 17 |
    18 |
    19 |
    20 | 21 | -------------------------------------------------------------------------------- /modules/servers/time4vps/time4vps.php: -------------------------------------------------------------------------------- 1 | 'Time4VPS Reseller Module', 30 | 'APIVersion' => '1.1', 31 | 'RequiresServer' => true, 32 | ]; 33 | } 34 | 35 | /** 36 | * Module configuration options 37 | * 38 | * @return array 39 | */ 40 | function time4vps_ConfigOptions() 41 | { 42 | return [ 43 | "product" => [ 44 | "FriendlyName" => "Product", 45 | "Type" => "dropdown", 46 | "Loader" => "time4vps_ProductLoaderFunction", 47 | "SimpleMode" => true 48 | ], 49 | "init_script" => [ 50 | "FriendlyName" => "Init Script", 51 | "Type" => "dropdown", 52 | "Loader" => "time4vps_InitScriptLoaderFunction", 53 | "SimpleMode" => true 54 | ], 55 | "show_oses" => [ 56 | "FriendlyName" => "OS List", 57 | "Type" => "textarea", 58 | "Rows" => "3", 59 | "Cols" => "50", 60 | "Description" => "OS list visible to customer (each in new line)", 61 | "SimpleMode" => true 62 | ], 63 | "promo_code" => [ 64 | "FriendlyName" => "Promotion code", 65 | "Type" => "textarea", 66 | "SimpleMode" => true, 67 | "Description" => "Promotion code" 68 | ], 69 | "component_map" => [ 70 | "FriendlyName" => "Component Map", 71 | "Type" => "textarea", 72 | "SimpleMode" => false, 73 | "Description" => "JSON formated object (WHMCS component ID = Time4VPS component ID)" 74 | ] 75 | ]; 76 | } 77 | 78 | /** 79 | * Loads product list in Module configuration menu 80 | * 81 | * @param $params 82 | * @return array 83 | * @throws APIException 84 | * @throws AuthException 85 | */ 86 | function time4vps_ProductLoaderFunction($params) 87 | { 88 | time4vps_InitAPI($params); 89 | 90 | $products = new Product(); 91 | 92 | $available_products = []; 93 | foreach ($products->getAvailableVPS() as $product) { 94 | $available_products[$product['id']] = $product['name']; 95 | } 96 | 97 | return $available_products; 98 | } 99 | 100 | /** 101 | * Get available scripts for server provisioning 102 | * 103 | * @param $params 104 | * @return array 105 | * @throws APIException 106 | * @throws AuthException 107 | */ 108 | function time4vps_InitScriptLoaderFunction($params) 109 | { 110 | time4vps_InitAPI($params); 111 | 112 | $script = new Script(); 113 | 114 | $available_scripts = ['' => '']; 115 | foreach ($script->all() as $script) { 116 | $available_scripts[$script['id']] = "{$script['name']} ({$script['syntax']})"; 117 | } 118 | 119 | return $available_scripts; 120 | } 121 | 122 | /** 123 | * Test API connection 124 | * 125 | * @param $params 126 | * @return array 127 | */ 128 | function time4vps_TestConnection($params) 129 | { 130 | try { 131 | time4vps_ProductLoaderFunction($params); 132 | $success = true; 133 | $errorMsg = ''; 134 | } catch (Exception $e) { 135 | $success = false; 136 | $errorMsg = $e->getMessage(); 137 | } 138 | 139 | return [ 140 | 'success' => $success, 141 | 'error' => $errorMsg 142 | ]; 143 | } 144 | 145 | /** 146 | * Show Client Area 147 | * 148 | * @param $params 149 | * @return array|string 150 | */ 151 | function time4vps_ClientArea($params) 152 | { 153 | return time4vps_ParseClientAreaRequest($params); 154 | } 155 | 156 | /** 157 | * Custom Admin Area Buttons 158 | * 159 | * @return array 160 | */ 161 | function time4vps_AdminCustomButtonArray() 162 | { 163 | return [ 164 | 'Update Details' => 'UpdateServerDetails' 165 | ]; 166 | } 167 | -------------------------------------------------------------------------------- /modules/servers/time4vps/tools/README.md: -------------------------------------------------------------------------------- 1 | # Tools 2 | ## https://\/modules/servers/time4vps/tools/component_map.php 3 | This tool is intended for easier generation of mapping between WHMCS and Time4VPS component. You need to be logged in as WHMCS admin to be able to use this tool. Also, products and components must be imported from Time4VPS via install/update script. 4 | -------------------------------------------------------------------------------- /modules/servers/time4vps/tools/component_map.php: -------------------------------------------------------------------------------- 1 | where('type', 'time4vps')->first(); 20 | 21 | if (!$data) { 22 | die('No module server found'); 23 | } 24 | 25 | // Save function 26 | if ($_POST) { 27 | foreach ($_POST['products'] as $product_id => $components) { 28 | $component_map = [ 29 | 'addons' => [], 30 | 'components' => [] 31 | ]; 32 | foreach ($components as $component_id => $map) { 33 | $map = explode('_', $map); 34 | $component_map['components'][$component_id] = [ 35 | 'item_id' => (int) $map[0], 36 | 'category_id' => (int) $map[1] 37 | ]; 38 | } 39 | 40 | Capsule::table('tblproducts') 41 | ->where(['id' => $product_id]) 42 | ->update([ 43 | 'configoption5' => json_encode($component_map, JSON_PRETTY_PRINT) 44 | ]); 45 | } 46 | } 47 | 48 | 49 | $decrypt = localAPI('DecryptPassword', ['password2' => $data->password]); 50 | 51 | $api = [ 52 | 'serverhttpprefix' => $data->secure === 'on' ? 'https' : 'http', 53 | 'serverhostname' => $data->hostname, 54 | 'serverusername' => $data->username, 55 | 'serverpassword' => $decrypt['password'] 56 | ]; 57 | 58 | time4vps_InitAPI($api); 59 | 60 | $t4v_products = []; 61 | $available_vps = (new Time4VPS\API\Product())->getAvailableVPS(); 62 | foreach ($available_vps as $vps) { 63 | $t4v_products[$vps['id']] = $vps; 64 | } 65 | 66 | $products = Capsule::table('tblproducts')->where([ 67 | 'servertype' => 'time4vps' 68 | ])->get(); 69 | 70 | echo 'Component mapping'; 71 | echo '
    '; 72 | foreach ($products as $product) { 73 | 74 | if (empty($t4v_products[$product->configoption1])) { 75 | continue; 76 | } 77 | 78 | $t4v_product = $t4v_products[$product->configoption1]; 79 | 80 | $local_components = Capsule::table('tblproductconfiglinks') 81 | ->select('tblproductconfigoptions.*') 82 | ->join('tblproductconfigoptions', 'tblproductconfigoptions.gid', '=', 'tblproductconfiglinks.gid') 83 | ->where('pid', $product->id) 84 | ->get(); 85 | 86 | echo "

    {$product->name}

    "; 87 | 88 | echo "
      "; 89 | 90 | $current_map = json_decode($product->configoption5, true); 91 | 92 | foreach ($local_components as $local_component) { 93 | $selected_id = 0; 94 | if (!empty($current_map['components'][$local_component->id])) { 95 | $selected_id = $current_map['components'][$local_component->id]['item_id']; 96 | } 97 | 98 | echo "
    • "; 99 | echo "'; 105 | 106 | echo "
    • "; 107 | } 108 | 109 | echo "
    "; 110 | 111 | echo '
    '; 112 | } 113 | echo ''; 114 | echo '
    '; 115 | echo ''; -------------------------------------------------------------------------------- /modules/servers/time4vps/update.php: -------------------------------------------------------------------------------- 1 | ' . PHP_EOL; 37 | $repl .= "\t\t\t\t" . '' . PHP_EOL; 38 | $repl .= "\t\t\t\t" . '' . PHP_EOL; 39 | $repl .= "\t\t\t\t" . '' . PHP_EOL; 40 | $repl .= "\t\t\t" . '{else $1 && $productinfo.module neq "time4vps"}' . PHP_EOL; 41 | $tpl = preg_replace('/(if \$productinfo\.type eq "server")}/', $repl, $tpl); 42 | file_put_contents($tpl_path, $tpl); 43 | } 44 | 45 | /** Update products */ 46 | require_once dirname(__FILE__) . '/vendor/autoload.php'; 47 | require_once dirname(__FILE__) . '/includes/helpers.php'; 48 | 49 | $data = Capsule::table('tblservers')->where('type', 'time4vps')->first(); 50 | 51 | if (!$data) { 52 | die('No module server found'); 53 | } 54 | 55 | $decrypt = localAPI('DecryptPassword', ['password2' => $data->password]); 56 | 57 | $api = [ 58 | 'serverhttpprefix' => $data->secure === 'on' ? 'https' : 'http', 59 | 'serverhostname' => $data->hostname, 60 | 'serverusername' => $data->username, 61 | 'serverpassword' => $decrypt['password'] 62 | ]; 63 | 64 | time4vps_InitAPI($api); 65 | 66 | $products = (new Time4VPS\API\Product())->getAvailableVPS(); 67 | 68 | /** Create product group */ 69 | $gid = Capsule::table('tblproductgroups')->where(['name' => 'VPS Servers'])->first(); 70 | if (!$gid) { 71 | $gid = Capsule::table('tblproductgroups')->insertGetId(['name' => 'VPS Servers']); 72 | } else { 73 | $gid = $gid->id; 74 | } 75 | 76 | /** 77 | * 78 | * Import Time4VPS products 79 | * 80 | */ 81 | 82 | /** Map t4v product id => whmcs product id */ 83 | $product_map = []; 84 | 85 | /** Iterate each product */ 86 | foreach ($products as $product) { 87 | 88 | /** Create or Update WHMCS Product */ 89 | Capsule::table('tblproducts')->updateOrInsert([ 90 | 'configoption1' => $product['id'], 91 | 'servertype' => 'time4vps' 92 | ], [ 93 | 'name' => $product['name'], 94 | 'gid' => $gid, 95 | 'type' => 'server', 96 | 'description' => $product['description'], 97 | 'autosetup' => 'payment', 98 | 'paytype' => 'recurring', 99 | 'tax' => 1, 100 | 'configoptionsupgrade' => 1 101 | ]); 102 | 103 | /** Get product */ 104 | $p = Capsule::table('tblproducts')->where([ 105 | 'configoption1' => $product['id'], 106 | 'servertype' => 'time4vps' 107 | ])->first(); 108 | 109 | if (!$p) { 110 | throw new Exception("Product {$product['id']} was not found"); 111 | } 112 | 113 | /** Map it for later use */ 114 | $product_map[$product['id']] = $p->id; 115 | 116 | /** Add product prices */ 117 | Capsule::table('tblpricing')->updateOrInsert([ 118 | 'relid' => $p->id, 119 | 'type' => 'product' 120 | ], [ 121 | 'currency' => 1, 122 | 'msetupfee' => $product['prices']['m_setup'] ?? 0, 123 | 'qsetupfee' => $product['prices']['q_setup'] ?? 0, 124 | 'ssetupfee' => $product['prices']['s_setup'] ?? 0, 125 | 'asetupfee' => $product['prices']['a_setup'] ?? 0, 126 | 'bsetupfee' => $product['prices']['b_setup'] ?? 0, 127 | 'monthly' => $product['prices']['m'] ?? -1, 128 | 'quarterly' => $product['prices']['q'] ?? -1, 129 | 'semiannually' => $product['prices']['s'] ?? -1, 130 | 'annually' => $product['prices']['a'] ?? -1, 131 | 'biennially' => $product['prices']['b'] ?? -1, 132 | 'triennially' => -1 133 | ]); 134 | 135 | /** Create components for product */ 136 | if ($product['components']) { 137 | $component_map = [ 138 | 'addons' => [], 139 | 'components' => [] 140 | ]; 141 | 142 | /** Create configuration group */ 143 | $cgroup = [ 144 | 'name' => "Configurable options for '{$product['name']}'" 145 | ]; 146 | 147 | Capsule::table('tblproductconfiggroups')->updateOrInsert($cgroup, $cgroup); 148 | $cg = Capsule::table('tblproductconfiggroups')->where($cgroup)->first(); 149 | 150 | /** Assign configuration group to product */ 151 | $clinks = [ 152 | 'gid' => $cg->id, 153 | 'pid' => $p->id 154 | ]; 155 | Capsule::table('tblproductconfiglinks')->updateOrInsert($clinks, $clinks); 156 | 157 | /** Create configuration option */ 158 | foreach ($product['components'] as $component) { 159 | $copt = [ 160 | 'gid' => $cg->id, 161 | 'optionname' => $component['name'], 162 | 'optiontype' => 3 163 | ]; 164 | Capsule::table('tblproductconfigoptions')->updateOrInsert($copt, $copt); 165 | $co = Capsule::table('tblproductconfigoptions')->where($copt)->first(); 166 | 167 | /** Add pricing */ 168 | $cgroupsub = [ 169 | 'configid' => $co->id, 170 | 'optionname' => '' 171 | ]; 172 | 173 | Capsule::table('tblproductconfigoptionssub')->updateOrInsert($cgroupsub, $cgroupsub); 174 | $cos = Capsule::table('tblproductconfigoptionssub')->where('configid', $co->id)->first(); 175 | 176 | Capsule::table('tblpricing')->updateOrInsert([ 177 | 'type' => 'configoptions', 178 | 'relid' => $cos->id 179 | ], [ 180 | 'type' => 'configoptions', 181 | 'relid' => $cos->id, 182 | 'currency' => 1, 183 | 'msetupfee' => $component['prices']['m_setup'] ?? 0, 184 | 'qsetupfee' => $component['prices']['q_setup'] ?? 0, 185 | 'ssetupfee' => $component['prices']['s_setup'] ?? 0, 186 | 'asetupfee' => $component['prices']['a_setup'] ?? 0, 187 | 'bsetupfee' => $component['prices']['b_setup'] ?? 0, 188 | 'monthly' => $component['prices']['m'] ?? -1, 189 | 'quarterly' => $component['prices']['q'] ?? -1, 190 | 'semiannually' => $component['prices']['s'] ?? -1, 191 | 'annually' => $component['prices']['a'] ?? -1, 192 | 'biennially' => $component['prices']['b'] ?? -1, 193 | 'triennially' => -1 194 | ]); 195 | 196 | $component_map['components'][$cos->id] = [ 197 | 'item_id' => $component['id'], 198 | 'category_id' => $component['category_id'] 199 | ]; 200 | } 201 | 202 | /** Update component map */ 203 | Capsule::table('tblproducts') 204 | ->where(['id' => $p->id]) 205 | ->update([ 206 | 'configoption5' => json_encode($component_map, JSON_PRETTY_PRINT) 207 | ]); 208 | } 209 | } 210 | 211 | /** Set product upgrades */ 212 | foreach ($products as $product) { 213 | 214 | /** Check if product has upgrades and has product map */ 215 | if (!$product['upgrades'] || empty($product_map[$product['id']])) { 216 | continue; 217 | } 218 | 219 | /** Get WHMCS product id */ 220 | $whmcs_pid = $product_map[$product['id']]; 221 | 222 | /** Delete upgrades */ 223 | Capsule::table('tblproduct_upgrade_products')->where('product_id', $whmcs_pid)->delete(); 224 | 225 | /** Create upgrades */ 226 | foreach ($product['upgrades'] as $upgrade) { 227 | if (!empty($product_map[$upgrade])) { 228 | $upgrade_product_id = $product_map[$upgrade]; 229 | Capsule::table('tblproduct_upgrade_products')->insertGetId([ 230 | 'product_id' => $whmcs_pid, 231 | 'upgrade_product_id' => $upgrade_product_id 232 | ]); 233 | } 234 | } 235 | } 236 | 237 | echo 'Update complete!'; -------------------------------------------------------------------------------- /modules/servers/time4vps/vendor/autoload.php: -------------------------------------------------------------------------------- 1 | 7 | * Jordi Boggiano 8 | * 9 | * For the full copyright and license information, please view the LICENSE 10 | * file that was distributed with this source code. 11 | */ 12 | 13 | namespace Composer\Autoload; 14 | 15 | /** 16 | * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. 17 | * 18 | * $loader = new \Composer\Autoload\ClassLoader(); 19 | * 20 | * // register classes with namespaces 21 | * $loader->add('Symfony\Component', __DIR__.'/component'); 22 | * $loader->add('Symfony', __DIR__.'/framework'); 23 | * 24 | * // activate the autoloader 25 | * $loader->register(); 26 | * 27 | * // to enable searching the include path (eg. for PEAR packages) 28 | * $loader->setUseIncludePath(true); 29 | * 30 | * In this example, if you try to use a class in the Symfony\Component 31 | * namespace or one of its children (Symfony\Component\Console for instance), 32 | * the autoloader will first look for the class under the component/ 33 | * directory, and it will then fallback to the framework/ directory if not 34 | * found before giving up. 35 | * 36 | * This class is loosely based on the Symfony UniversalClassLoader. 37 | * 38 | * @author Fabien Potencier 39 | * @author Jordi Boggiano 40 | * @see http://www.php-fig.org/psr/psr-0/ 41 | * @see http://www.php-fig.org/psr/psr-4/ 42 | */ 43 | class ClassLoader 44 | { 45 | // PSR-4 46 | private $prefixLengthsPsr4 = array(); 47 | private $prefixDirsPsr4 = array(); 48 | private $fallbackDirsPsr4 = array(); 49 | 50 | // PSR-0 51 | private $prefixesPsr0 = array(); 52 | private $fallbackDirsPsr0 = array(); 53 | 54 | private $useIncludePath = false; 55 | private $classMap = array(); 56 | private $classMapAuthoritative = false; 57 | private $missingClasses = array(); 58 | private $apcuPrefix; 59 | 60 | public function getPrefixes() 61 | { 62 | if (!empty($this->prefixesPsr0)) { 63 | return call_user_func_array('array_merge', $this->prefixesPsr0); 64 | } 65 | 66 | return array(); 67 | } 68 | 69 | public function getPrefixesPsr4() 70 | { 71 | return $this->prefixDirsPsr4; 72 | } 73 | 74 | public function getFallbackDirs() 75 | { 76 | return $this->fallbackDirsPsr0; 77 | } 78 | 79 | public function getFallbackDirsPsr4() 80 | { 81 | return $this->fallbackDirsPsr4; 82 | } 83 | 84 | public function getClassMap() 85 | { 86 | return $this->classMap; 87 | } 88 | 89 | /** 90 | * @param array $classMap Class to filename map 91 | */ 92 | public function addClassMap(array $classMap) 93 | { 94 | if ($this->classMap) { 95 | $this->classMap = array_merge($this->classMap, $classMap); 96 | } else { 97 | $this->classMap = $classMap; 98 | } 99 | } 100 | 101 | /** 102 | * Registers a set of PSR-0 directories for a given prefix, either 103 | * appending or prepending to the ones previously set for this prefix. 104 | * 105 | * @param string $prefix The prefix 106 | * @param array|string $paths The PSR-0 root directories 107 | * @param bool $prepend Whether to prepend the directories 108 | */ 109 | public function add($prefix, $paths, $prepend = false) 110 | { 111 | if (!$prefix) { 112 | if ($prepend) { 113 | $this->fallbackDirsPsr0 = array_merge( 114 | (array) $paths, 115 | $this->fallbackDirsPsr0 116 | ); 117 | } else { 118 | $this->fallbackDirsPsr0 = array_merge( 119 | $this->fallbackDirsPsr0, 120 | (array) $paths 121 | ); 122 | } 123 | 124 | return; 125 | } 126 | 127 | $first = $prefix[0]; 128 | if (!isset($this->prefixesPsr0[$first][$prefix])) { 129 | $this->prefixesPsr0[$first][$prefix] = (array) $paths; 130 | 131 | return; 132 | } 133 | if ($prepend) { 134 | $this->prefixesPsr0[$first][$prefix] = array_merge( 135 | (array) $paths, 136 | $this->prefixesPsr0[$first][$prefix] 137 | ); 138 | } else { 139 | $this->prefixesPsr0[$first][$prefix] = array_merge( 140 | $this->prefixesPsr0[$first][$prefix], 141 | (array) $paths 142 | ); 143 | } 144 | } 145 | 146 | /** 147 | * Registers a set of PSR-4 directories for a given namespace, either 148 | * appending or prepending to the ones previously set for this namespace. 149 | * 150 | * @param string $prefix The prefix/namespace, with trailing '\\' 151 | * @param array|string $paths The PSR-4 base directories 152 | * @param bool $prepend Whether to prepend the directories 153 | * 154 | * @throws \InvalidArgumentException 155 | */ 156 | public function addPsr4($prefix, $paths, $prepend = false) 157 | { 158 | if (!$prefix) { 159 | // Register directories for the root namespace. 160 | if ($prepend) { 161 | $this->fallbackDirsPsr4 = array_merge( 162 | (array) $paths, 163 | $this->fallbackDirsPsr4 164 | ); 165 | } else { 166 | $this->fallbackDirsPsr4 = array_merge( 167 | $this->fallbackDirsPsr4, 168 | (array) $paths 169 | ); 170 | } 171 | } elseif (!isset($this->prefixDirsPsr4[$prefix])) { 172 | // Register directories for a new namespace. 173 | $length = strlen($prefix); 174 | if ('\\' !== $prefix[$length - 1]) { 175 | throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); 176 | } 177 | $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; 178 | $this->prefixDirsPsr4[$prefix] = (array) $paths; 179 | } elseif ($prepend) { 180 | // Prepend directories for an already registered namespace. 181 | $this->prefixDirsPsr4[$prefix] = array_merge( 182 | (array) $paths, 183 | $this->prefixDirsPsr4[$prefix] 184 | ); 185 | } else { 186 | // Append directories for an already registered namespace. 187 | $this->prefixDirsPsr4[$prefix] = array_merge( 188 | $this->prefixDirsPsr4[$prefix], 189 | (array) $paths 190 | ); 191 | } 192 | } 193 | 194 | /** 195 | * Registers a set of PSR-0 directories for a given prefix, 196 | * replacing any others previously set for this prefix. 197 | * 198 | * @param string $prefix The prefix 199 | * @param array|string $paths The PSR-0 base directories 200 | */ 201 | public function set($prefix, $paths) 202 | { 203 | if (!$prefix) { 204 | $this->fallbackDirsPsr0 = (array) $paths; 205 | } else { 206 | $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; 207 | } 208 | } 209 | 210 | /** 211 | * Registers a set of PSR-4 directories for a given namespace, 212 | * replacing any others previously set for this namespace. 213 | * 214 | * @param string $prefix The prefix/namespace, with trailing '\\' 215 | * @param array|string $paths The PSR-4 base directories 216 | * 217 | * @throws \InvalidArgumentException 218 | */ 219 | public function setPsr4($prefix, $paths) 220 | { 221 | if (!$prefix) { 222 | $this->fallbackDirsPsr4 = (array) $paths; 223 | } else { 224 | $length = strlen($prefix); 225 | if ('\\' !== $prefix[$length - 1]) { 226 | throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); 227 | } 228 | $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; 229 | $this->prefixDirsPsr4[$prefix] = (array) $paths; 230 | } 231 | } 232 | 233 | /** 234 | * Turns on searching the include path for class files. 235 | * 236 | * @param bool $useIncludePath 237 | */ 238 | public function setUseIncludePath($useIncludePath) 239 | { 240 | $this->useIncludePath = $useIncludePath; 241 | } 242 | 243 | /** 244 | * Can be used to check if the autoloader uses the include path to check 245 | * for classes. 246 | * 247 | * @return bool 248 | */ 249 | public function getUseIncludePath() 250 | { 251 | return $this->useIncludePath; 252 | } 253 | 254 | /** 255 | * Turns off searching the prefix and fallback directories for classes 256 | * that have not been registered with the class map. 257 | * 258 | * @param bool $classMapAuthoritative 259 | */ 260 | public function setClassMapAuthoritative($classMapAuthoritative) 261 | { 262 | $this->classMapAuthoritative = $classMapAuthoritative; 263 | } 264 | 265 | /** 266 | * Should class lookup fail if not found in the current class map? 267 | * 268 | * @return bool 269 | */ 270 | public function isClassMapAuthoritative() 271 | { 272 | return $this->classMapAuthoritative; 273 | } 274 | 275 | /** 276 | * APCu prefix to use to cache found/not-found classes, if the extension is enabled. 277 | * 278 | * @param string|null $apcuPrefix 279 | */ 280 | public function setApcuPrefix($apcuPrefix) 281 | { 282 | $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null; 283 | } 284 | 285 | /** 286 | * The APCu prefix in use, or null if APCu caching is not enabled. 287 | * 288 | * @return string|null 289 | */ 290 | public function getApcuPrefix() 291 | { 292 | return $this->apcuPrefix; 293 | } 294 | 295 | /** 296 | * Registers this instance as an autoloader. 297 | * 298 | * @param bool $prepend Whether to prepend the autoloader or not 299 | */ 300 | public function register($prepend = false) 301 | { 302 | spl_autoload_register(array($this, 'loadClass'), true, $prepend); 303 | } 304 | 305 | /** 306 | * Unregisters this instance as an autoloader. 307 | */ 308 | public function unregister() 309 | { 310 | spl_autoload_unregister(array($this, 'loadClass')); 311 | } 312 | 313 | /** 314 | * Loads the given class or interface. 315 | * 316 | * @param string $class The name of the class 317 | * @return bool|null True if loaded, null otherwise 318 | */ 319 | public function loadClass($class) 320 | { 321 | if ($file = $this->findFile($class)) { 322 | includeFile($file); 323 | 324 | return true; 325 | } 326 | } 327 | 328 | /** 329 | * Finds the path to the file where the class is defined. 330 | * 331 | * @param string $class The name of the class 332 | * 333 | * @return string|false The path if found, false otherwise 334 | */ 335 | public function findFile($class) 336 | { 337 | // class map lookup 338 | if (isset($this->classMap[$class])) { 339 | return $this->classMap[$class]; 340 | } 341 | if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) { 342 | return false; 343 | } 344 | if (null !== $this->apcuPrefix) { 345 | $file = apcu_fetch($this->apcuPrefix.$class, $hit); 346 | if ($hit) { 347 | return $file; 348 | } 349 | } 350 | 351 | $file = $this->findFileWithExtension($class, '.php'); 352 | 353 | // Search for Hack files if we are running on HHVM 354 | if (false === $file && defined('HHVM_VERSION')) { 355 | $file = $this->findFileWithExtension($class, '.hh'); 356 | } 357 | 358 | if (null !== $this->apcuPrefix) { 359 | apcu_add($this->apcuPrefix.$class, $file); 360 | } 361 | 362 | if (false === $file) { 363 | // Remember that this class does not exist. 364 | $this->missingClasses[$class] = true; 365 | } 366 | 367 | return $file; 368 | } 369 | 370 | private function findFileWithExtension($class, $ext) 371 | { 372 | // PSR-4 lookup 373 | $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; 374 | 375 | $first = $class[0]; 376 | if (isset($this->prefixLengthsPsr4[$first])) { 377 | $subPath = $class; 378 | while (false !== $lastPos = strrpos($subPath, '\\')) { 379 | $subPath = substr($subPath, 0, $lastPos); 380 | $search = $subPath.'\\'; 381 | if (isset($this->prefixDirsPsr4[$search])) { 382 | $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); 383 | foreach ($this->prefixDirsPsr4[$search] as $dir) { 384 | if (file_exists($file = $dir . $pathEnd)) { 385 | return $file; 386 | } 387 | } 388 | } 389 | } 390 | } 391 | 392 | // PSR-4 fallback dirs 393 | foreach ($this->fallbackDirsPsr4 as $dir) { 394 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { 395 | return $file; 396 | } 397 | } 398 | 399 | // PSR-0 lookup 400 | if (false !== $pos = strrpos($class, '\\')) { 401 | // namespaced class name 402 | $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) 403 | . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); 404 | } else { 405 | // PEAR-like class name 406 | $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; 407 | } 408 | 409 | if (isset($this->prefixesPsr0[$first])) { 410 | foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { 411 | if (0 === strpos($class, $prefix)) { 412 | foreach ($dirs as $dir) { 413 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { 414 | return $file; 415 | } 416 | } 417 | } 418 | } 419 | } 420 | 421 | // PSR-0 fallback dirs 422 | foreach ($this->fallbackDirsPsr0 as $dir) { 423 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { 424 | return $file; 425 | } 426 | } 427 | 428 | // PSR-0 include paths. 429 | if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { 430 | return $file; 431 | } 432 | 433 | return false; 434 | } 435 | } 436 | 437 | /** 438 | * Scope isolated include. 439 | * 440 | * Prevents access to $this/self from included files. 441 | */ 442 | function includeFile($file) 443 | { 444 | include $file; 445 | } 446 | -------------------------------------------------------------------------------- /modules/servers/time4vps/vendor/composer/LICENSE: -------------------------------------------------------------------------------- 1 | Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Upstream-Name: Composer 3 | Upstream-Contact: Jordi Boggiano 4 | Source: https://github.com/composer/composer 5 | 6 | Files: * 7 | Copyright: 2016, Nils Adermann 8 | 2016, Jordi Boggiano 9 | License: Expat 10 | 11 | Files: src/Composer/Util/TlsHelper.php 12 | Copyright: 2016, Nils Adermann 13 | 2016, Jordi Boggiano 14 | 2013, Evan Coury 15 | License: Expat and BSD-2-Clause 16 | 17 | License: BSD-2-Clause 18 | Redistribution and use in source and binary forms, with or without modification, 19 | are permitted provided that the following conditions are met: 20 | . 21 | * Redistributions of source code must retain the above copyright notice, 22 | this list of conditions and the following disclaimer. 23 | . 24 | * Redistributions in binary form must reproduce the above copyright notice, 25 | this list of conditions and the following disclaimer in the documentation 26 | and/or other materials provided with the distribution. 27 | . 28 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 29 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 30 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 31 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 32 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 33 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 34 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 35 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 36 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 37 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 | 39 | License: Expat 40 | Permission is hereby granted, free of charge, to any person obtaining a copy 41 | of this software and associated documentation files (the "Software"), to deal 42 | in the Software without restriction, including without limitation the rights 43 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 44 | copies of the Software, and to permit persons to whom the Software is furnished 45 | to do so, subject to the following conditions: 46 | . 47 | The above copyright notice and this permission notice shall be included in all 48 | copies or substantial portions of the Software. 49 | . 50 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 51 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 52 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 53 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 54 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 55 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 56 | THE SOFTWARE. 57 | -------------------------------------------------------------------------------- /modules/servers/time4vps/vendor/composer/autoload_classmap.php: -------------------------------------------------------------------------------- 1 | array($vendorDir . '/time4vps/lib/src'), 10 | ); 11 | -------------------------------------------------------------------------------- /modules/servers/time4vps/vendor/composer/autoload_real.php: -------------------------------------------------------------------------------- 1 | = 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); 27 | if ($useStaticLoader) { 28 | require_once __DIR__ . '/autoload_static.php'; 29 | 30 | call_user_func(\Composer\Autoload\ComposerStaticInitd3403daee88462847926ac72030765b4::getInitializer($loader)); 31 | } else { 32 | $map = require __DIR__ . '/autoload_namespaces.php'; 33 | foreach ($map as $namespace => $path) { 34 | $loader->set($namespace, $path); 35 | } 36 | 37 | $map = require __DIR__ . '/autoload_psr4.php'; 38 | foreach ($map as $namespace => $path) { 39 | $loader->setPsr4($namespace, $path); 40 | } 41 | 42 | $classMap = require __DIR__ . '/autoload_classmap.php'; 43 | if ($classMap) { 44 | $loader->addClassMap($classMap); 45 | } 46 | } 47 | 48 | $loader->register(true); 49 | 50 | return $loader; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /modules/servers/time4vps/vendor/composer/autoload_static.php: -------------------------------------------------------------------------------- 1 | 11 | array ( 12 | 'Time4VPS\\' => 9, 13 | ), 14 | ); 15 | 16 | public static $prefixDirsPsr4 = array ( 17 | 'Time4VPS\\' => 18 | array ( 19 | 0 => __DIR__ . '/..' . '/time4vps/lib/src', 20 | ), 21 | ); 22 | 23 | public static function getInitializer(ClassLoader $loader) 24 | { 25 | return \Closure::bind(function () use ($loader) { 26 | $loader->prefixLengthsPsr4 = ComposerStaticInitd3403daee88462847926ac72030765b4::$prefixLengthsPsr4; 27 | $loader->prefixDirsPsr4 = ComposerStaticInitd3403daee88462847926ac72030765b4::$prefixDirsPsr4; 28 | 29 | }, null, ClassLoader::class); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /modules/servers/time4vps/vendor/composer/installed.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "time4vps/lib", 4 | "version": "v1.0.0", 5 | "version_normalized": "1.0.0.0", 6 | "source": { 7 | "type": "git", 8 | "url": "https://github.com/time4vps/time4vps-lib.git", 9 | "reference": "df901964fe737da0db91bc92399a3e16fba34988" 10 | }, 11 | "dist": { 12 | "type": "zip", 13 | "url": "https://api.github.com/repos/time4vps/time4vps-lib/zipball/df901964fe737da0db91bc92399a3e16fba34988", 14 | "reference": "df901964fe737da0db91bc92399a3e16fba34988", 15 | "shasum": "" 16 | }, 17 | "require": { 18 | "ext-curl": "*", 19 | "ext-json": "*", 20 | "php": ">=7.0" 21 | }, 22 | "time": "2020-04-22T12:18:43+00:00", 23 | "type": "library", 24 | "installation-source": "dist", 25 | "autoload": { 26 | "psr-4": { 27 | "Time4VPS\\": "src/" 28 | } 29 | }, 30 | "notification-url": "https://packagist.org/downloads/", 31 | "license": [ 32 | "MIT" 33 | ], 34 | "authors": [ 35 | { 36 | "name": "Algirdas Čičinskas", 37 | "email": "algirdas.c@iv.lt" 38 | } 39 | ], 40 | "description": "UserAPI library for Time4VPS Hosting provider.", 41 | "homepage": "https://www.time4vps.com/", 42 | "keywords": [ 43 | "api", 44 | "hosting", 45 | "time4vps", 46 | "vps" 47 | ] 48 | } 49 | ] 50 | -------------------------------------------------------------------------------- /modules/servers/time4vps/vendor/time4vps/lib/.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | composer.phar 3 | /vendor -------------------------------------------------------------------------------- /modules/servers/time4vps/vendor/time4vps/lib/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020 Time4VPS 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. -------------------------------------------------------------------------------- /modules/servers/time4vps/vendor/time4vps/lib/README.md: -------------------------------------------------------------------------------- 1 | # Time4VPS User API PHP Library 2 | 3 | Time4VPS lib is a PHP library that makes easy to interact with Time4VPS UserAPI. 4 | 5 | ## Installation 6 | Use `composer` package manager to install library: 7 | ```bash 8 | composer install time4vps/lib 9 | ``` 10 | 11 | ## Usage 12 | 13 | ```php 14 | require_once '/vendor/autoload.php'; 15 | 16 | // Auth details 17 | $username = 'user'; 18 | $password = 'pass123'; 19 | 20 | // Setup endpoint 21 | Time4VPS\Base\Endpoint::BaseURL('https://billing.time4vps.com/api/'); 22 | Time4VPS\Base\Endpoint::Auth($username, $password); 23 | 24 | // Get server details 25 | $server_id = 748457; 26 | $server = new Time4VPS\API\Server($server_id); 27 | 28 | var_dump($server->details()); 29 | 30 | // Reboot server 31 | try { 32 | $server->reboot(); 33 | } catch (Time4VPS\Exceptions\APIException $e) { 34 | die("Failed to reboot server: {$e->getMessage()}"); 35 | } 36 | ``` 37 | 38 | ## License 39 | [MIT](https://github.com/time4vps/time4vps-lib/blob/master/LICENSE) -------------------------------------------------------------------------------- /modules/servers/time4vps/vendor/time4vps/lib/src/API/Order.php: -------------------------------------------------------------------------------- 1 | order_id = (int) $order_id; 29 | if ($this->order_id <= 0) { 30 | throw new Exception("Product ID '{$order_id}' is invalid"); 31 | } 32 | } 33 | } 34 | 35 | /** 36 | * Order new product 37 | * 38 | * @param int $product_id Product ID 39 | * @param null|string $domain Domain name (use serverhost.name for whitelabel domain) 40 | * @param string $cycle Billing period symbol (m - monthly, q - quarterly, s - semiannually, a - annually, b - biennially) 41 | * @param array $custom Additional options data available for sop products 42 | * @param string $promocode Promotion code 43 | * @return array 44 | * @throws APIException|AuthException 45 | */ 46 | public function create($product_id, $domain = null, $cycle = 'm', $custom = [], $promocode = null) 47 | { 48 | return $this->post("/{$product_id}", [ 49 | 'domain' => $domain, 50 | 'cycle' => $cycle, 51 | 'custom' => $custom, 52 | 'promocode' => $promocode, 53 | ]); 54 | } 55 | } -------------------------------------------------------------------------------- /modules/servers/time4vps/vendor/time4vps/lib/src/API/Product.php: -------------------------------------------------------------------------------- 1 | product_id = (int) $product_id; 29 | if ($this->product_id <= 0) { 30 | throw new Exception("Product ID '{$product_id}' is invalid"); 31 | } 32 | } 33 | } 34 | 35 | /** 36 | * Get product configuration details 37 | * 38 | * @return array 39 | * @throws APIException|AuthException 40 | */ 41 | public function details() 42 | { 43 | $this->mustHave('product_id'); 44 | 45 | $this->endpoint = 'order'; 46 | return $this->get("/{$this->product_id}"); 47 | } 48 | 49 | /** 50 | * Get available VPS servers 51 | * 52 | * @return array 53 | * @throws APIException|AuthException 54 | */ 55 | public function getAvailableVPS() 56 | { 57 | $this->endpoint = 'category'; 58 | return $this->get('/available/vps'); 59 | } 60 | } -------------------------------------------------------------------------------- /modules/servers/time4vps/vendor/time4vps/lib/src/API/Script.php: -------------------------------------------------------------------------------- 1 | script_id = (int) $script_id; 27 | if ($this->script_id <= 0) { 28 | throw new Exception("Script ID '{$script_id}' is invalid"); 29 | } 30 | } 31 | } 32 | 33 | /** 34 | * Get available init scripts 35 | * 36 | * @return array 37 | * @throws APIException|AuthException 38 | */ 39 | public function all() 40 | { 41 | return $this->get('/'); 42 | } 43 | 44 | /** 45 | * Get script details 46 | * 47 | * @param null|string $field 48 | * @return array 49 | * @throws APIException|AuthException 50 | */ 51 | public function details($field = null) 52 | { 53 | $this->mustHave('script_id'); 54 | 55 | $return = $this->get("/{$this->script_id}"); 56 | return $field ? $return[$field] : $return; 57 | } 58 | } -------------------------------------------------------------------------------- /modules/servers/time4vps/vendor/time4vps/lib/src/API/Server.php: -------------------------------------------------------------------------------- 1 | server_id = (int)$server_id; 31 | if ($this->server_id <= 0) { 32 | throw new Exception("Server ID '{$server_id}' is invalid"); 33 | } 34 | } 35 | } 36 | 37 | /** 38 | * Server ID 39 | * 40 | * @return int 41 | * @throws APIException|AuthException 42 | */ 43 | public function id() 44 | { 45 | $this->mustHave('server_id'); 46 | return $this->server_id; 47 | } 48 | 49 | /** 50 | * Get all active servers 51 | * 52 | * @return array 53 | * @throws APIException|AuthException 54 | */ 55 | public function all() 56 | { 57 | return $this->get('/'); 58 | } 59 | 60 | /** 61 | * Get server details 62 | * 63 | * @return array Server Details 64 | * @throws APIException|AuthException 65 | */ 66 | public function details() 67 | { 68 | $this->mustHave('server_id'); 69 | 70 | return $this->get("/{$this->server_id}"); 71 | } 72 | 73 | /** 74 | * Reboot server 75 | * 76 | * @return int Task ID 77 | * @throws APIException|AuthException 78 | */ 79 | public function reboot() 80 | { 81 | $this->mustHave('server_id'); 82 | 83 | $response = $this->post("/{$this->server_id}/reboot"); 84 | return (int) $response['task_id']; 85 | } 86 | 87 | /** 88 | * Reinstall server 89 | * 90 | * @param string $os OS code from available OS list 91 | * @param string $ssh_key SSH Key 92 | * @param int $script Init Script ID 93 | * @return int Task ID 94 | * @throws APIException|AuthException 95 | */ 96 | public function reinstall($os, $ssh_key = null, $script = null) 97 | { 98 | $this->mustHave('server_id'); 99 | 100 | $response = $this->post("/{$this->server_id}/reinstall", [ 101 | 'os' => $os, 102 | 'ssh_key' => $ssh_key, 103 | 'script' => $script 104 | ]); 105 | 106 | return (int) $response['task_id']; 107 | } 108 | 109 | /** 110 | * Launch emergency console 111 | * 112 | * @param string $timeout 1h, 3h, 12h, etc. 113 | * @param bool $whitelabel Use whitelabel hostname for web based console 114 | * @return int Task ID 115 | * @throws APIException|AuthException 116 | */ 117 | public function emergencyConsole($timeout = '1h', $whitelabel = true) 118 | { 119 | $this->mustHave('server_id'); 120 | 121 | $response = $this->post("/{$this->server_id}/webconsole", [ 122 | 'timeout' => $timeout, 123 | 'whitelabel' => $whitelabel ? 'true' : 'false' 124 | ]); 125 | 126 | return (int) $response['task_id']; 127 | } 128 | 129 | /** 130 | * Changes the hostname of your server. Hostname must pointed to your server main IP address. 131 | * 132 | * @param string $hostname FQDN hostname pointed to main server IP address 133 | * @return int Task ID 134 | * @throws APIException|AuthException 135 | */ 136 | public function rename($hostname) 137 | { 138 | $this->mustHave('server_id'); 139 | 140 | $response = $this->post("/{$this->server_id}/rename", [ 141 | 'hostname' => $hostname 142 | ]); 143 | 144 | return (int) $response['task_id']; 145 | } 146 | 147 | /** 148 | * Password reset 149 | * 150 | * @return int Task ID 151 | * @throws APIException|AuthException 152 | */ 153 | public function resetPassword() 154 | { 155 | $this->mustHave('server_id'); 156 | 157 | $response = $this->post("/{$this->server_id}/resetpassword"); 158 | return (int) $response['task_id']; 159 | } 160 | 161 | /** 162 | * Changes PTR record for the additional IP (if server has more than one IPv4 address). 163 | * 164 | * @param string $ip_address Additional IP address 165 | * @param string $hostname FQDN hostname pointed to additional IP address 166 | * @return int Task ID 167 | * @throws APIException|AuthException 168 | */ 169 | public function setPTR($ip_address, $hostname) 170 | { 171 | $this->mustHave('server_id'); 172 | 173 | $response = $this->post("/{$this->server_id}/changeptr", [ 174 | 'ip_address' => $ip_address, 175 | 'hostname' => $hostname 176 | ]); 177 | 178 | return (int) $response['task_id']; 179 | } 180 | 181 | /** 182 | * Flush server firewall 183 | * 184 | * @return int Task ID 185 | * @throws APIException|AuthException 186 | */ 187 | public function flushFirewall() 188 | { 189 | $this->mustHave('server_id'); 190 | 191 | $response = $this->post("/{$this->server_id}/flushfirewall"); 192 | return (int) $response['task_id']; 193 | } 194 | 195 | /** 196 | * Change DNS servers 197 | * 198 | * @param string $ns1 Nameserver 1 IP 199 | * @param string $ns2 Nameserver 2 IP 200 | * @param string $ns3 Nameserver 3 IP 201 | * @param string $ns4 Nameserver 4 IP 202 | * @return int Task ID 203 | * @throws APIException|AuthException 204 | */ 205 | public function setDNS($ns1, $ns2 = '', $ns3 = '', $ns4 = '') 206 | { 207 | $this->mustHave('server_id'); 208 | 209 | $response = $this->post("/{$this->server_id}/changedns", [ 210 | 'ns1' => $ns1, 211 | 'ns2' => $ns2, 212 | 'ns3' => $ns3, 213 | 'ns4' => $ns4 214 | ]); 215 | 216 | return (int) $response['task_id']; 217 | } 218 | 219 | /** 220 | * Get available OS list for server 221 | * 222 | * @return array OS List 223 | * @throws APIException|AuthException 224 | */ 225 | public function availableOS() 226 | { 227 | $this->mustHave('server_id'); 228 | return $this->get("/{$this->server_id}/oses"); 229 | } 230 | 231 | /** 232 | * Server usage graphs 233 | * 234 | * @param $width int Image width 235 | * @return array Usage graph array 236 | * @throws APIException|AuthException 237 | */ 238 | public function usageGraphs($width = 576) 239 | { 240 | $this->mustHave('server_id'); 241 | return $this->get("/{$this->server_id}/graphs/{$width}"); 242 | } 243 | 244 | /** 245 | * Server usage history 246 | * 247 | * @return array Usage history array 248 | * @throws APIException|AuthException 249 | */ 250 | public function usageHistory() 251 | { 252 | $this->mustHave('server_id'); 253 | return $this->get("/{$this->server_id}/history"); 254 | } 255 | 256 | /** 257 | * Additional IPs 258 | * 259 | * @return array 260 | * @throws APIException|AuthException 261 | */ 262 | public function additionalIPs() 263 | { 264 | $this->mustHave('server_id'); 265 | return $this->get("/{$this->server_id}/ips"); 266 | } 267 | 268 | /** 269 | * Get task result 270 | * 271 | * @param $task 272 | * @return array 273 | * @throws APIException|AuthException|InvalidTaskException 274 | */ 275 | public function taskResult($task) 276 | { 277 | $this->mustHave('server_id'); 278 | 279 | try { 280 | $response = $this->get("/{$this->server_id}/task/{$task}"); 281 | } catch (APIException $e) { 282 | if ($e->getMessage() === 'Invalid task ID') { 283 | throw new InvalidTaskException($e); 284 | } 285 | throw $e; 286 | } 287 | 288 | return $response; 289 | } 290 | 291 | } -------------------------------------------------------------------------------- /modules/servers/time4vps/vendor/time4vps/lib/src/API/Servers.php: -------------------------------------------------------------------------------- 1 | get(); 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /modules/servers/time4vps/vendor/time4vps/lib/src/API/Service.php: -------------------------------------------------------------------------------- 1 | service_id = (int) $service_id; 27 | if ($this->service_id <= 0) { 28 | throw new Exception("Service ID '{$service_id}' is invalid"); 29 | } 30 | } 31 | } 32 | 33 | /** 34 | * Get account details 35 | * 36 | * @return array 37 | * @throws APIException|AuthException 38 | */ 39 | public function details() 40 | { 41 | $this->mustHave('service_id'); 42 | $details = $this->get("/{$this->service_id}"); 43 | return array_shift($details); 44 | } 45 | 46 | /** 47 | * Get all services 48 | * 49 | * @return array 50 | * @throws APIException|AuthException 51 | */ 52 | public function all() 53 | { 54 | return $this->get('/'); 55 | } 56 | 57 | /** 58 | * Get service ID from order number 59 | * 60 | * @param $order_num 61 | * @return int 62 | * @throws APIException|AuthException 63 | */ 64 | public function fromOrder($order_num) 65 | { 66 | $response = $this->get("/order/{$order_num}"); 67 | 68 | return (int) $response['account_id']; 69 | } 70 | 71 | /** 72 | * Cancel / terminate account 73 | * 74 | * @param string $reason Termination reason 75 | * @param bool $immediate Immediate termination 76 | * @return array 77 | * @throws APIException|AuthException 78 | */ 79 | public function cancel($reason, $immediate = false) 80 | { 81 | $this->mustHave('service_id'); 82 | 83 | return $this->post("/{$this->service_id}/cancel", [ 84 | 'immediate' => $immediate, 85 | 'reason' => $reason 86 | ]); 87 | } 88 | 89 | /** 90 | * Get available upgrades 91 | * 92 | * @return array 93 | * @throws APIException|AuthException 94 | */ 95 | public function upgrades() 96 | { 97 | $this->mustHave('service_id'); 98 | 99 | return $this->get("/{$this->service_id}/upgrade"); 100 | } 101 | 102 | /** 103 | * List addons 104 | * 105 | * @return array 106 | * @throws APIException|AuthException 107 | */ 108 | public function addons() 109 | { 110 | $this->mustHave('service_id'); 111 | 112 | return $this->get("/{$this->service_id}/addon"); 113 | } 114 | 115 | /** 116 | * Upgrade service 117 | * 118 | * @param array $upgrades 119 | * @param string $cycle 120 | * @return array 121 | * @throws APIException|AuthException 122 | */ 123 | public function orderUpgrade($upgrades, $cycle = null) 124 | { 125 | $this->mustHave('service_id'); 126 | 127 | return $this->post("/{$this->service_id}/upgrade", array_merge($upgrades, [ 128 | 'cycle' => $cycle, 129 | 'send' => true 130 | ])); 131 | } 132 | 133 | /** 134 | * Add addon to service 135 | * 136 | * @param $addon_id 137 | * @return array 138 | * @throws APIException|AuthException 139 | */ 140 | public function orderAddon($addon_id) 141 | { 142 | $this->mustHave('service_id'); 143 | 144 | return $this->post("/{$this->service_id}/addon", [ 145 | 'addon_id' => $addon_id 146 | ]); 147 | } 148 | } -------------------------------------------------------------------------------- /modules/servers/time4vps/vendor/time4vps/lib/src/Base/Debug.php: -------------------------------------------------------------------------------- 1 | benchmark_start = microtime(true); 12 | } 13 | 14 | public function benchmark() 15 | { 16 | return microtime(true) - $this->benchmark_start; 17 | } 18 | 19 | public function log() 20 | { 21 | //TODO: To be implemented 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /modules/servers/time4vps/vendor/time4vps/lib/src/Base/Endpoint.php: -------------------------------------------------------------------------------- 1 | endpoint = trim($endpoint, '/'); 52 | } 53 | 54 | /** 55 | * Base API Url 56 | * 57 | * @param $url 58 | */ 59 | public static function BaseURL($url) 60 | { 61 | self::$base_url = $url; 62 | } 63 | 64 | /** 65 | * Set auth details 66 | * 67 | * @param $username 68 | * @param $password 69 | */ 70 | public static function Auth($username, $password) 71 | { 72 | self::$api_username = $username; 73 | self::$api_password = $password; 74 | } 75 | 76 | /** 77 | * Set debug function 78 | * 79 | * @param $function 80 | */ 81 | public static function DebugFunction($function) 82 | { 83 | self::$debug_function = $function; 84 | } 85 | 86 | /** 87 | * @param string $path API relative path 88 | * @return array 89 | * @throws APIException|AuthException 90 | */ 91 | public function get($path = "") 92 | { 93 | return $this->request('GET', $path); 94 | } 95 | 96 | /** 97 | * @param string $path API relative path 98 | * @param array $data Post Data 99 | * @return array 100 | * @throws APIException|AuthException 101 | */ 102 | public function post($path = "", $data = []) 103 | { 104 | return $this->request('POST', $path, $data); 105 | } 106 | 107 | /** 108 | * GET method 109 | * 110 | * @param string $method GET, POST, PUT, DELETE 111 | * @param string $path API relative path 112 | * @param array $data Post Data 113 | * @param callable $logFunction For debug purposes 114 | * @return array 115 | * @throws APIException|AuthException 116 | */ 117 | public function request($method, $path, $data = null, $logFunction = null) 118 | { 119 | $url = self::$base_url . "{$this->endpoint}{$path}"; 120 | 121 | $curl = curl_init(); 122 | 123 | curl_setopt_array($curl, [ 124 | CURLOPT_URL => $url, 125 | CURLOPT_RETURNTRANSFER => true, 126 | CURLOPT_FOLLOWLOCATION => true, 127 | CURLOPT_ENCODING => "utf-8", 128 | CURLOPT_TIMEOUT => 30, 129 | CURLOPT_CUSTOMREQUEST => $method, 130 | CURLOPT_USERPWD => self::$api_username . ':' . self::$api_password, 131 | CURLOPT_POSTFIELDS => $data ? json_encode($data) : null, 132 | CURLOPT_HTTPHEADER => [ 133 | 'Content-Type: application/json' 134 | ] 135 | ]); 136 | 137 | $response = curl_exec($curl); 138 | $error = curl_error($curl); 139 | curl_close($curl); 140 | 141 | if (is_callable(self::$debug_function)) { 142 | $args = func_get_args(); 143 | $args[1] = $url; 144 | call_user_func(self::$debug_function, $args, $data, $response); 145 | } 146 | 147 | if ($error) { 148 | throw new APIException("Request error: {$error}"); 149 | } 150 | 151 | $response = json_decode($response, true); 152 | if (json_last_error() !== JSON_ERROR_NONE) { 153 | throw new APIException("Received invalid response from API"); 154 | } 155 | 156 | if (array_key_exists('error', $response)) { 157 | $error = array_shift($response['error']); 158 | 159 | if ($error === 'wronglogin') { 160 | throw new AuthException('Invalid username / password combination'); 161 | } 162 | 163 | if (!is_string($error)) { 164 | array_unshift($response['error'], $error); 165 | $error = json_encode($response['error']); 166 | } 167 | 168 | throw new APIException($error); 169 | } 170 | 171 | return $response; 172 | } 173 | 174 | /** 175 | * Check some fields before doing API requests 176 | * 177 | * @param $field 178 | * @throws APIException 179 | */ 180 | protected function mustHave($field) 181 | { 182 | if (!$this->$field) { 183 | throw new APIException("{$field} is not set"); 184 | } 185 | } 186 | } -------------------------------------------------------------------------------- /modules/servers/time4vps/vendor/time4vps/lib/src/Base/Singleton.php: -------------------------------------------------------------------------------- 1 |