Compare commits
176 Commits
Author | SHA1 | Date | |
---|---|---|---|
130451e1ae | |||
d36f39af8f | |||
518917aac6 | |||
dbc3a2623c | |||
d31edde9d6 | |||
32943b40be | |||
23790d3258 | |||
ffa55cdee5 | |||
6f5d49cd2f | |||
850581d328 | |||
1d0d3f13ab | |||
c82b6b6acf | |||
532fbf7337 | |||
c4afd6da7f | |||
a812e3a3e0 | |||
a15510e62a | |||
78d1634470 | |||
cc8d810d45 | |||
68d3c9181c | |||
e206a583fd | |||
ca27c47b75 | |||
2c67108cf1 | |||
dee4c78e93 | |||
a6c004e1cb | |||
8318bb4e6b | |||
b27e0adca9 | |||
2925d3a1e3 | |||
add28c2fca | |||
afbab3dd42 | |||
b68e4d2e68 | |||
c8f4574984 | |||
60c573821b | |||
e6e993cf21 | |||
ca0edb4e17 | |||
ed9a411095 | |||
c69fb1cae2 | |||
d30aadc5e4 | |||
b732cfd90e | |||
46a56c12e3 | |||
9b2d42610a | |||
ef85bdb02f | |||
23763ed308 | |||
9fcdf04005 | |||
60babfa7b5 | |||
4cdde32cb1 | |||
538850b323 | |||
47393b4da9 | |||
87167b7770 | |||
81572a61a4 | |||
3412ecc7de | |||
3ab38897f9 | |||
8c2471d1d2 | |||
b0937a424a | |||
171b938d3a | |||
61c1d25096 | |||
f885b8e8a3 | |||
2bb664e241 | |||
c9058769ce | |||
6d15437333 | |||
7c5958c8c1 | |||
1a4a0f2c10 | |||
629d9e8ed4 | |||
b9e987570c | |||
b95788262d | |||
3bb55320e3 | |||
7a9f937a9e | |||
c00e51adda | |||
0cc526e29a | |||
16f0642007 | |||
e1f7b324cb | |||
8f0ff3e786 | |||
9023f89456 | |||
140b756994 | |||
ca59c89e1d | |||
4e23918999 | |||
758a0a99a9 | |||
b6cf9bec0b | |||
6e07c3ae85 | |||
ef76aadc16 | |||
8e960107fc | |||
c4e702ee2f | |||
08790e7295 | |||
cfefd38a31 | |||
37a5ee8566 | |||
e5c8aae758 | |||
99d393d0c0 | |||
e6280d597b | |||
18db9cd280 | |||
6aab647f48 | |||
b8b4623078 | |||
6a79cff233 | |||
4c02283fd0 | |||
403de91fba | |||
4ee3743cf3 | |||
77e48dae8b | |||
0745532951 | |||
b53116d22a | |||
f7df824145 | |||
f154322f99 | |||
a76ba6ee8b | |||
61b3f5b5f5 | |||
b153e5b595 | |||
9ab0b6a0fa | |||
a7f191f058 | |||
012a1ecfab | |||
dc70a49f52 | |||
bc7380eab7 | |||
f4da09a26e | |||
de3312055a | |||
699289662b | |||
bae079f71c | |||
28f4624e8d | |||
fbd215e741 | |||
2437096473 | |||
dfeee540cf | |||
a0b9e85f38 | |||
08153e6ec1 | |||
2660f5d2d0 | |||
82e67f0b83 | |||
41dd0d86e7 | |||
c8004f1a27 | |||
61edfb932a | |||
747a67b691 | |||
b938db9e5d | |||
1ec8049068 | |||
848dcb5caf | |||
afe6b34fd6 | |||
fceb79bdc3 | |||
83457fd9fc | |||
cdd5da757d | |||
c6086c615f | |||
0cad73a17f | |||
d2fa9be8d1 | |||
617e628b04 | |||
35d679ed2c | |||
8824489704 | |||
a7502aa8fb | |||
375403135e | |||
db49d0f4b5 | |||
c4fb99479b | |||
091f4fb638 | |||
8db3d6c679 | |||
ddd7fb49fe | |||
c6a203b1f0 | |||
6de63bed63 | |||
9552a14de5 | |||
9d379b3fbd | |||
4f3e5972b0 | |||
be65976310 | |||
8728af4332 | |||
07870d05ad | |||
cee6f8949c | |||
3bdf44ddbe | |||
17c1675b4a | |||
54d1c4439d | |||
e710bd2862 | |||
5309cb26db | |||
8072fe40eb | |||
702f2b443c | |||
a44190c1c2 | |||
3871b51f0f | |||
d9a20f7213 | |||
a70b954981 | |||
95e79439a2 | |||
7ea118ec1e | |||
ae83cbeef4 | |||
8047ed9555 | |||
c907a4044f | |||
f12c7724fd | |||
c8696f8d1a | |||
63bba0efb0 | |||
2063ae4159 | |||
349a1d3250 | |||
cfb81596ae | |||
91c90f05f8 | |||
abefcf4a73 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,6 +1,7 @@
|
||||
config.php
|
||||
.DS_Store
|
||||
.vscode/
|
||||
ui/ui/compiled
|
||||
ui/compiled/*.php
|
||||
ui/cache/*.php
|
||||
test.php
|
||||
|
9
.htaccess_firewall
Normal file
9
.htaccess_firewall
Normal file
@ -0,0 +1,9 @@
|
||||
<Files *.php>
|
||||
Order Deny,Allow
|
||||
Deny from all
|
||||
</Files>
|
||||
|
||||
<Files index.php>
|
||||
Order Allow,Deny
|
||||
Allow from all
|
||||
</Files>
|
100
CHANGELOG.md
100
CHANGELOG.md
@ -2,6 +2,106 @@
|
||||
|
||||
# CHANGELOG
|
||||
|
||||
## 2024.3.18
|
||||
|
||||
- Add Broadcasting SMS by @Focuslinkstech
|
||||
- Fix Notification with Bills
|
||||
|
||||
## 2024.3.16
|
||||
|
||||
- Fix Zero Charging
|
||||
- Fix Disconnect Customer from Radius without loop by @Gerandonk
|
||||
|
||||
## 2024.3.15
|
||||
|
||||
- Fix Customer View to list active Plan
|
||||
- Additional Bill using Customer Attributes
|
||||
|
||||
## 2024.3.14
|
||||
|
||||
- Add Note to Invoices
|
||||
- Add Additional Bill
|
||||
- View Invoice from Customer side
|
||||
|
||||
## 2024.3.13
|
||||
|
||||
- Postpaid System
|
||||
- Additional Cost
|
||||
|
||||
## 2024.3.12
|
||||
|
||||
- Check if Validity Period, so calculate price will not affected other validity
|
||||
- Add firewall using .htaccess for apache only
|
||||
- Multiple Payment Gateway by @Focuslinkstech
|
||||
- Fix Logic Multiple Payment gateway
|
||||
- Fix delete Attribute
|
||||
- Allow Delete Payment Gateway
|
||||
- Allow Delete Plugin
|
||||
|
||||
## 2024.3.6
|
||||
|
||||
- change attributes view
|
||||
|
||||
## 2024.3.4
|
||||
|
||||
- add [[username]] for reminder
|
||||
- fix agent show when editing
|
||||
- fix password admin when sending notification
|
||||
- add file exists for pages
|
||||
|
||||
## 2024.3.3
|
||||
|
||||
- Change loading button by @Focuslinkstech
|
||||
- Add Customer Announcements by @Gerandonk
|
||||
- Add PPPOE Period Validity by @Gerandonk
|
||||
|
||||
## 2024.2.29
|
||||
|
||||
- Fix Hook Functionality
|
||||
- Change Customer Menu
|
||||
|
||||
## 2024.2.28
|
||||
|
||||
- Fix Buy Plan with Balance
|
||||
- Add Expired date for reminder
|
||||
|
||||
## 2024.2.27
|
||||
|
||||
- fix path notification
|
||||
- redirect to dashboard if already login
|
||||
|
||||
## 2024.2.26
|
||||
|
||||
- Clean Unused JS and CSS
|
||||
- Add some Authorization check
|
||||
- Custom Path for folder
|
||||
- fix some bugs
|
||||
|
||||
## 2024.2.23
|
||||
|
||||
- Integrate with PhpNuxBill Printer
|
||||
- Fix Invoice
|
||||
- add admin ID in transaction
|
||||
|
||||
## 2024.2.22
|
||||
|
||||
- Add Loading when click submit
|
||||
- link to settings when hide widget
|
||||
|
||||
## 2024.2.21
|
||||
|
||||
- Fix SQL Installer
|
||||
- remove multiple space in language
|
||||
- Change Phone Number require OTP by @Focuslinkstech
|
||||
- Change burst Form
|
||||
- Delete Table Responsive, first Column Freeze
|
||||
|
||||
## 2024.2.20
|
||||
|
||||
- Fix list admin
|
||||
- Burst Limit
|
||||
- Pace Loading by @Focuslinkstech
|
||||
|
||||
## 2024.2.19
|
||||
|
||||
- Start API Development
|
||||
|
59
init.php
59
init.php
@ -37,21 +37,26 @@ function _autoloader($class)
|
||||
}
|
||||
spl_autoload_register('_autoloader');
|
||||
|
||||
|
||||
if (!file_exists($root_path . 'config.php')) {
|
||||
$root_path .= '..' . DIRECTORY_SEPARATOR;
|
||||
if (!file_exists($root_path . 'config.php')) {
|
||||
die("config.php file not found");
|
||||
r2('install');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!file_exists($root_path . File::pathFixer('system/orm.php'))) {
|
||||
die($root_path . "orm.php file not found");
|
||||
}
|
||||
|
||||
if (!file_exists($root_path . File::pathFixer('system/uploads/notifications.default.json'))) {
|
||||
die($root_path . File::pathFixer("system/uploads/notifications.default.json file not found"));
|
||||
$UPLOAD_PATH = $root_path . File::pathFixer('system/uploads');
|
||||
$CACHE_PATH = $root_path . File::pathFixer('system/cache');
|
||||
$PAGES_PATH = $root_path . File::pathFixer('pages');
|
||||
$PLUGIN_PATH = $root_path . File::pathFixer('system/plugin');
|
||||
$PAYMENTGATEWAY_PATH = $root_path . File::pathFixer('system/paymentgateway');
|
||||
$UI_PATH = 'ui';
|
||||
|
||||
if (!file_exists($UPLOAD_PATH . File::pathFixer('/notifications.default.json'))) {
|
||||
die($UPLOAD_PATH . File::pathFixer("/notifications.default.json file not found"));
|
||||
}
|
||||
|
||||
require_once $root_path . 'config.php';
|
||||
@ -70,13 +75,13 @@ if ($_app_stage != 'Live') {
|
||||
define('U', APP_URL . '/index.php?_route=');
|
||||
|
||||
// notification message
|
||||
if (file_exists($root_path . File::pathFixer("system/uploads/notifications.json"))) {
|
||||
$_notifmsg = json_decode(file_get_contents($root_path . File::pathFixer('system/uploads/notifications.json')), true);
|
||||
if (file_exists($UPLOAD_PATH . DIRECTORY_SEPARATOR . "notifications.json")) {
|
||||
$_notifmsg = json_decode(file_get_contents($UPLOAD_PATH . DIRECTORY_SEPARATOR . 'notifications.json'), true);
|
||||
}
|
||||
$_notifmsg_default = json_decode(file_get_contents($root_path . File::pathFixer('system/uploads/notifications.default.json')), true);
|
||||
$_notifmsg_default = json_decode(file_get_contents($UPLOAD_PATH . DIRECTORY_SEPARATOR . 'notifications.default.json'), true);
|
||||
|
||||
//register all plugin
|
||||
foreach (glob(File::pathFixer($root_path . File::pathFixer("system/plugin/*.php"))) as $filename) {
|
||||
foreach (glob(File::pathFixer($PLUGIN_PATH . DIRECTORY_SEPARATOR . '*.php')) as $filename) {
|
||||
try {
|
||||
include $filename;
|
||||
} catch (Throwable $e) {
|
||||
@ -90,6 +95,7 @@ $result = ORM::for_table('tbl_appconfig')->find_many();
|
||||
foreach ($result as $value) {
|
||||
$config[$value['setting']] = $value['value'];
|
||||
}
|
||||
$_c = $config;
|
||||
if (empty($http_proxy) && !empty($config['http_proxy'])) {
|
||||
$http_proxy = $config['http_proxy'];
|
||||
if (empty($http_proxyauth) && !empty($config['http_proxyauth'])) {
|
||||
@ -110,7 +116,7 @@ if ((!empty($radius_user) && $config['radius_enable']) || _post('radius_enable')
|
||||
if (empty($config['language'])) {
|
||||
$config['language'] = 'english';
|
||||
}
|
||||
$lan_file = $root_path .File::pathFixer('system/lan/' . $config['language'] . '.json');
|
||||
$lan_file = $root_path . File::pathFixer('system/lan/' . $config['language'] . '.json');
|
||||
if (file_exists($lan_file)) {
|
||||
$_L = json_decode(file_get_contents($lan_file), true);
|
||||
$_SESSION['Lang'] = $_L;
|
||||
@ -219,7 +225,38 @@ function sendWhatsapp($phone, $txt)
|
||||
Message::sendWhatsapp($phone, $txt);
|
||||
}
|
||||
|
||||
function r2($to, $ntype = 'e', $msg = '')
|
||||
{
|
||||
if ($msg == '') {
|
||||
header("location: $to");
|
||||
exit;
|
||||
}
|
||||
$_SESSION['ntype'] = $ntype;
|
||||
$_SESSION['notify'] = $msg;
|
||||
header("location: $to");
|
||||
exit;
|
||||
}
|
||||
|
||||
if(!isset($api_secret)){
|
||||
function _alert($text, $type = 'success', $url = "home", $time = 3)
|
||||
{
|
||||
global $ui;
|
||||
if (!isset($ui)) return;
|
||||
if (strlen($url) > 4) {
|
||||
if (substr($url, 0, 4) != "http") {
|
||||
$url = U . $url;
|
||||
}
|
||||
} else {
|
||||
$url = U . $url;
|
||||
}
|
||||
$ui->assign('text', $text);
|
||||
$ui->assign('type', $type);
|
||||
$ui->assign('time', $time);
|
||||
$ui->assign('url', $url);
|
||||
$ui->display('alert.tpl');
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
if (!isset($api_secret)) {
|
||||
$api_secret = $db_password;
|
||||
}
|
||||
|
@ -33,13 +33,6 @@ CREATE TABLE `tbl_customers` (
|
||||
`last_login` datetime DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
DROP TABLE IF EXISTS `tbl_customers_meta`;
|
||||
CREATE TABLE `tbl_customers_meta` (
|
||||
`id` int(11) NOT NULL,
|
||||
`customer_id` int(11) NOT NULL,
|
||||
`meta_key` varchar(64) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
|
||||
`meta_value` longtext COLLATE utf8mb4_general_ci
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
DROP TABLE IF EXISTS `tbl_logs`;
|
||||
CREATE TABLE `tbl_logs` (
|
||||
@ -98,7 +91,7 @@ CREATE TABLE `tbl_plans` (
|
||||
`data_limit` int(10) UNSIGNED DEFAULT NULL,
|
||||
`data_unit` enum('MB','GB') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
|
||||
`validity` int(10) NOT NULL,
|
||||
`validity_unit` enum('Mins','Hrs','Days','Months') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
|
||||
`validity_unit` enum('Mins','Hrs','Days','Months','Period') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
|
||||
`shared_users` int(10) DEFAULT NULL,
|
||||
`routers` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
|
||||
`is_radius` tinyint(1) NOT NULL DEFAULT '0' COMMENT '1 is radius',
|
||||
@ -149,7 +142,7 @@ CREATE TABLE `tbl_users` (
|
||||
`username` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
|
||||
`fullname` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
|
||||
`password` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
|
||||
`user_type` enum('Admin','Sales') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
|
||||
`user_type` enum('SuperAdmin','Admin','Report','Agent','Sales') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
|
||||
`status` enum('Active','Inactive') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'Active',
|
||||
`last_login` datetime DEFAULT NULL,
|
||||
`creationdate` datetime NOT NULL
|
||||
@ -188,22 +181,6 @@ CREATE TABLE `tb_languages` (
|
||||
`id` int(11) NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
DROP TABLE IF EXISTS `tbl_customers_fields`;
|
||||
CREATE TABLE tbl_customers_fields (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT,
|
||||
customer_id INT NOT NULL,
|
||||
field_name VARCHAR(255) NOT NULL,
|
||||
field_value VARCHAR(255) NOT NULL,
|
||||
FOREIGN KEY (customer_id) REFERENCES tbl_customers(id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
ALTER TABLE `tbl_voucher` ADD `generated_by` INT NOT NULL DEFAULT '0' COMMENT 'id admin' AFTER `status`;
|
||||
ALTER TABLE `tbl_users` ADD `root` INT NOT NULL DEFAULT '0' COMMENT 'for sub account' AFTER `id`;
|
||||
ALTER TABLE `tbl_users` CHANGE `user_type` `user_type` ENUM('SuperAdmin','Admin','Report','Agent','Sales') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL;
|
||||
ALTER TABLE `tbl_users` CHANGE `password` `password` VARCHAR(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL;
|
||||
ALTER TABLE `tbl_users` ADD `phone` VARCHAR(32) NOT NULL DEFAULT '' AFTER `password`, ADD `email` VARCHAR(128) NOT NULL DEFAULT '' AFTER `phone`, ADD `city` VARCHAR(64) NOT NULL DEFAULT '' COMMENT 'kota' AFTER `email`, ADD `subdistrict` VARCHAR(64) NOT NULL DEFAULT '' COMMENT 'kecamatan' AFTER `city`, ADD `ward` VARCHAR(64) NOT NULL DEFAULT '' COMMENT 'kelurahan' AFTER `subdistrict`;
|
||||
ALTER TABLE `tbl_customers` ADD `created_by` INT NOT NULL DEFAULT '0' AFTER `auto_renewal`;
|
||||
|
||||
ALTER TABLE `tbl_appconfig`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
@ -213,9 +190,6 @@ ALTER TABLE `tbl_bandwidth`
|
||||
ALTER TABLE `tbl_customers`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
ALTER TABLE `tbl_customers_meta`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
ALTER TABLE `tbl_logs`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
@ -256,9 +230,6 @@ ALTER TABLE `tbl_bandwidth`
|
||||
ALTER TABLE `tbl_customers`
|
||||
MODIFY `id` int(10) NOT NULL AUTO_INCREMENT;
|
||||
|
||||
ALTER TABLE `tbl_customers_meta`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
|
||||
|
||||
ALTER TABLE `tbl_logs`
|
||||
MODIFY `id` int(10) NOT NULL AUTO_INCREMENT;
|
||||
|
||||
@ -326,3 +297,24 @@ VALUES (
|
||||
'2022-09-06 16:09:50',
|
||||
'2014-06-23 01:43:07'
|
||||
);
|
||||
|
||||
DROP TABLE IF EXISTS `tbl_customers_fields`;
|
||||
CREATE TABLE tbl_customers_fields (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT,
|
||||
customer_id INT NOT NULL,
|
||||
field_name VARCHAR(255) NOT NULL,
|
||||
field_value VARCHAR(255) NOT NULL,
|
||||
FOREIGN KEY (customer_id) REFERENCES tbl_customers(id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
ALTER TABLE `tbl_voucher` ADD `generated_by` INT NOT NULL DEFAULT '0' COMMENT 'id admin' AFTER `status`;
|
||||
ALTER TABLE `tbl_users` ADD `root` INT NOT NULL DEFAULT '0' COMMENT 'for sub account' AFTER `id`;
|
||||
ALTER TABLE `tbl_users` CHANGE `password` `password` VARCHAR(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL;
|
||||
ALTER TABLE `tbl_users` ADD `phone` VARCHAR(32) NOT NULL DEFAULT '' AFTER `password`, ADD `email` VARCHAR(128) NOT NULL DEFAULT '' AFTER `phone`, ADD `city` VARCHAR(64) NOT NULL DEFAULT '' COMMENT 'kota' AFTER `email`, ADD `subdistrict` VARCHAR(64) NOT NULL DEFAULT '' COMMENT 'kecamatan' AFTER `city`, ADD `ward` VARCHAR(64) NOT NULL DEFAULT '' COMMENT 'kelurahan' AFTER `subdistrict`;
|
||||
ALTER TABLE `tbl_customers` ADD `created_by` INT NOT NULL DEFAULT '0' AFTER `auto_renewal`;
|
||||
ALTER TABLE `tbl_plans` ADD `list_expired` VARCHAR(32) NOT NULL DEFAULT '' COMMENT 'address list' AFTER `pool_expired`;
|
||||
ALTER TABLE `tbl_bandwidth` ADD `burst` VARCHAR(128) NOT NULL DEFAULT '' AFTER `rate_up_unit`;
|
||||
ALTER TABLE `tbl_transactions` ADD `admin_id` INT NOT NULL DEFAULT '1' AFTER `type`;
|
||||
ALTER TABLE `tbl_user_recharges` ADD `admin_id` INT NOT NULL DEFAULT '1' AFTER `type`;
|
||||
ALTER TABLE `tbl_plans` CHANGE `allow_purchase` `prepaid` ENUM('yes','no') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT 'yes' COMMENT 'is prepaid';
|
||||
ALTER TABLE `tbl_transactions` ADD `note` VARCHAR(256) NOT NULL DEFAULT '' COMMENT 'for note' AFTER `type`;
|
@ -1 +1,3 @@
|
||||
Pengumuman!!<br>Besok libur<br><br>Announcement!!<br>Tomorrow holiday<br>
|
||||
Pengumuman!!<br>Besok libur<br><br>Announcement!!<br>Tomorrow holiday<br><br>
|
||||
<br>
|
||||
This Announcement is for Login Page.
|
8
pages_template/Announcement_Customer.html
Normal file
8
pages_template/Announcement_Customer.html
Normal file
@ -0,0 +1,8 @@
|
||||
Pengumuman Pelanggan!!<br>
|
||||
Besok libur<br>
|
||||
<br>
|
||||
Customer Announcement!!<br>
|
||||
Tomorrow holiday<br>
|
||||
<br>
|
||||
<br>
|
||||
This Announcement is for Customer Dashboard
|
19
system/.htaccess
Normal file
19
system/.htaccess
Normal file
@ -0,0 +1,19 @@
|
||||
<Files *.php>
|
||||
Order Deny,Allow
|
||||
Deny from all
|
||||
</Files>
|
||||
|
||||
<Files cron.php>
|
||||
Order Allow,Deny
|
||||
Allow from all
|
||||
</Files>
|
||||
|
||||
<Files api.php>
|
||||
Order Allow,Deny
|
||||
Allow from all
|
||||
</Files>
|
||||
|
||||
<Files cron_reminder.php>
|
||||
Order Allow,Deny
|
||||
Allow from all
|
||||
</Files>
|
@ -46,9 +46,6 @@ $req = _get('r');
|
||||
$token = _get('token');
|
||||
$routes = explode('/', $req);
|
||||
$handler = $routes[0];
|
||||
if ($handler == '') {
|
||||
$handler = 'default';
|
||||
}
|
||||
|
||||
if(empty($token)){
|
||||
showResult(false, Lang::T("Token is invalid"));
|
||||
@ -83,6 +80,11 @@ if($token == $config['api_key']){
|
||||
}
|
||||
}
|
||||
|
||||
if(!isset($handler) || empty($handler)){
|
||||
showResult(true, Lang::T("Token is valid"));
|
||||
}
|
||||
|
||||
|
||||
if($handler == 'isValid'){
|
||||
showResult(true, Lang::T("Token is valid"));
|
||||
}
|
||||
|
@ -1,21 +1,24 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
|
||||
* by https://t.me/ibnux
|
||||
**/
|
||||
|
||||
|
||||
Class Admin{
|
||||
class Admin
|
||||
{
|
||||
|
||||
public static function getID(){
|
||||
public static function getID()
|
||||
{
|
||||
global $db_password;
|
||||
if(isset($_SESSION['aid'])){
|
||||
if (isset($_SESSION['aid'])) {
|
||||
return $_SESSION['aid'];
|
||||
}else if(isset($_COOKIE['aid'])){
|
||||
} else if (isset($_COOKIE['aid'])) {
|
||||
// id.time.sha1
|
||||
$tmp = explode('.',$_COOKIE['aid']);
|
||||
if(sha1($tmp[0].$tmp[1].$db_password)==$tmp[2]){
|
||||
if($tmp[1] < 86400*7){
|
||||
$tmp = explode('.', $_COOKIE['aid']);
|
||||
if (sha1($tmp[0] . '.' . $tmp[1] . '.' . $db_password) == $tmp[2]) {
|
||||
if (time() - $tmp[1] < 86400 * 7) {
|
||||
$_SESSION['aid'] = $tmp[0];
|
||||
return $tmp[0];
|
||||
}
|
||||
@ -24,23 +27,31 @@ Class Admin{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static function setCookie($aid){
|
||||
public static function setCookie($aid)
|
||||
{
|
||||
global $db_password;
|
||||
if(isset($aid)){
|
||||
if (isset($aid)) {
|
||||
$time = time();
|
||||
setcookie('aid', $aid.'.'.$time.'.'.sha1($aid.'.'.$time.'.'.$db_password), time()+86400*7);
|
||||
setcookie('aid', $aid . '.' . $time . '.' . sha1($aid . '.' . $time . '.' . $db_password), time() + 86400 * 7);
|
||||
}
|
||||
}
|
||||
|
||||
public static function removeCookie(){
|
||||
if(isset($_COOKIE['aid'])){
|
||||
setcookie('aid', '', time()-86400);
|
||||
public static function removeCookie()
|
||||
{
|
||||
if (isset($_COOKIE['aid'])) {
|
||||
setcookie('aid', '', time() - 86400);
|
||||
}
|
||||
}
|
||||
|
||||
public static function _info(){
|
||||
$id = Admin::getID();
|
||||
$d = ORM::for_table('tbl_users')->find_one($id);
|
||||
return $d;
|
||||
public static function _info($id = 0)
|
||||
{
|
||||
if (empty($id) && $id == 0) {
|
||||
$id = Admin::getID();
|
||||
}
|
||||
if ($id) {
|
||||
return ORM::for_table('tbl_users')->find_one($id);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,8 +18,9 @@ $menu_registered = array();
|
||||
* @param string icon from ion icon, ion-person, only for AFTER_
|
||||
* @param string label for showing label or number of notification or update
|
||||
* @param string color Label color
|
||||
* @param string auth authorization ['SuperAdmin', 'Admin', 'Report', 'Agent', 'Sales'] will only show in this user, empty array for all users
|
||||
*/
|
||||
function register_menu($name, $admin, $function, $position, $icon = '', $label = '', $color = 'success')
|
||||
function register_menu($name, $admin, $function, $position, $icon = '', $label = '', $color = 'success', $auth = [])
|
||||
{
|
||||
global $menu_registered;
|
||||
$menu_registered[] = [
|
||||
@ -29,13 +30,15 @@ function register_menu($name, $admin, $function, $position, $icon = '', $label =
|
||||
"icon" => $icon,
|
||||
"function" => $function,
|
||||
"label" => $label,
|
||||
"color" => $color
|
||||
"color" => $color,
|
||||
"auth" => $auth
|
||||
];
|
||||
}
|
||||
|
||||
$hook_registered = array();
|
||||
|
||||
function register_hook($action, $function){
|
||||
global $hook_registered;
|
||||
$hook_registered[] = [
|
||||
'action' => $action,
|
||||
'function' => $function
|
||||
|
@ -12,6 +12,7 @@ class Lang
|
||||
{
|
||||
global $_L, $lan_file, $config;
|
||||
$_L = $_SESSION['Lang'];
|
||||
$key = preg_replace('/\s+/', ' ', $key);
|
||||
if (!empty($_L[$key])) {
|
||||
return $_L[$key];
|
||||
}
|
||||
|
@ -60,25 +60,30 @@ class Message
|
||||
global $config;
|
||||
run_hook('send_whatsapp'); #HOOK
|
||||
if (!empty($config['wa_url'])) {
|
||||
$waurl = str_replace('[number]', urlencode($phone), $config['wa_url']);
|
||||
$waurl = str_replace('[number]', urlencode(Lang::phoneFormat($phone)), $config['wa_url']);
|
||||
$waurl = str_replace('[text]', urlencode($txt), $waurl);
|
||||
return Http::getData($waurl);
|
||||
}
|
||||
}
|
||||
|
||||
public static function sendPackageNotification($phone, $name, $package, $price, $message, $via)
|
||||
public static function sendPackageNotification($customer, $package, $price, $message, $via)
|
||||
{
|
||||
$msg = str_replace('[[name]]', $name, $message);
|
||||
global $u;
|
||||
$msg = str_replace('[[name]]', $customer['fullname'], $message);
|
||||
$msg = str_replace('[[username]]', $customer['username'], $msg);
|
||||
$msg = str_replace('[[package]]', $package, $msg);
|
||||
$msg = str_replace('[[price]]', $price, $msg);
|
||||
if($u){
|
||||
$msg = str_replace('[[expired_date]]', Lang::dateAndTimeFormat($u['expiration'], $u['time']), $msg);
|
||||
}
|
||||
if (
|
||||
!empty($phone) && strlen($phone) > 5
|
||||
!empty($customer['phonenumber']) && strlen($customer['phonenumber']) > 5
|
||||
&& !empty($message) && in_array($via, ['sms', 'wa'])
|
||||
) {
|
||||
if ($via == 'sms') {
|
||||
Message::sendSMS($phone, $msg);
|
||||
Message::sendSMS($customer['phonenumber'], $msg);
|
||||
} else if ($via == 'wa') {
|
||||
Message::sendWhatsapp($phone, $msg);
|
||||
Message::sendWhatsapp($customer['phonenumber'], $msg);
|
||||
}
|
||||
}
|
||||
return "$via: $msg";
|
||||
@ -111,6 +116,9 @@ class Message
|
||||
$textInvoice = str_replace('[[phone]]', $config['phone'], $textInvoice);
|
||||
$textInvoice = str_replace('[[invoice]]', $trx['invoice'], $textInvoice);
|
||||
$textInvoice = str_replace('[[date]]', Lang::dateAndTimeFormat($trx['recharged_on'], $trx['recharged_time']), $textInvoice);
|
||||
if (!empty($trx['note'])) {
|
||||
$textInvoice = str_replace('[[note]]', $trx['note'], $textInvoice);
|
||||
}
|
||||
$gc = explode("-", $trx['method']);
|
||||
$textInvoice = str_replace('[[payment_gateway]]', trim($gc[0]), $textInvoice);
|
||||
$textInvoice = str_replace('[[payment_channel]]', trim($gc[1]), $textInvoice);
|
||||
@ -118,8 +126,11 @@ class Message
|
||||
$textInvoice = str_replace('[[plan_name]]', $trx['plan_name'], $textInvoice);
|
||||
$textInvoice = str_replace('[[plan_price]]', Lang::moneyFormat($trx['price']), $textInvoice);
|
||||
$textInvoice = str_replace('[[name]]', $cust['fullname'], $textInvoice);
|
||||
$textInvoice = str_replace('[[note]]', $cust['note'], $textInvoice);
|
||||
$textInvoice = str_replace('[[user_name]]', $trx['username'], $textInvoice);
|
||||
$textInvoice = str_replace('[[user_password]]', $cust['password'], $textInvoice);
|
||||
$textInvoice = str_replace('[[username]]', $trx['username'], $textInvoice);
|
||||
$textInvoice = str_replace('[[password]]', $cust['password'], $textInvoice);
|
||||
$textInvoice = str_replace('[[expired_date]]', Lang::dateAndTimeFormat($trx['expiration'], $trx['time']), $textInvoice);
|
||||
$textInvoice = str_replace('[[footer]]', $config['note'], $textInvoice);
|
||||
|
||||
|
@ -515,6 +515,18 @@ class Mikrotik
|
||||
$client->sendSync($smsRequest);
|
||||
}
|
||||
|
||||
public static function getIpHotspotUser($client, $username){
|
||||
global $_app_stage;
|
||||
if ($_app_stage == 'demo') {
|
||||
return null;
|
||||
}
|
||||
$printRequest = new RouterOS\Request(
|
||||
'/ip hotspot active print',
|
||||
RouterOS\Query::where('user', $username)
|
||||
);
|
||||
return $client->sendSync($printRequest)->getProperty('address');
|
||||
}
|
||||
|
||||
public static function addIpToAddressList($client, $ip, $listName, $comment = '')
|
||||
{
|
||||
global $_app_stage;
|
||||
|
@ -17,9 +17,9 @@ class Package
|
||||
* @param string $channel channel payment gateway
|
||||
* @return boolean
|
||||
*/
|
||||
public static function rechargeUser($id_customer, $router_name, $plan_id, $gateway, $channel)
|
||||
public static function rechargeUser($id_customer, $router_name, $plan_id, $gateway, $channel, $note = '')
|
||||
{
|
||||
global $_c;
|
||||
global $config, $admin, $c, $p, $b, $t, $d, $zero;
|
||||
$date_now = date("Y-m-d H:i:s");
|
||||
$date_only = date("Y-m-d");
|
||||
$time_only = date("H:i:s");
|
||||
@ -30,11 +30,52 @@ class Package
|
||||
}
|
||||
|
||||
$c = ORM::for_table('tbl_customers')->where('id', $id_customer)->find_one();
|
||||
$p = ORM::for_table('tbl_plans')->where('id', $plan_id)->where('enabled', '1')->find_one();
|
||||
$p = ORM::for_table('tbl_plans')->where('id', $plan_id)->find_one();
|
||||
|
||||
$add_cost = 0;
|
||||
$bills = [];
|
||||
// Zero cost recharge
|
||||
if (isset($zero) && $zero == 1) {
|
||||
$p['price'] = 0;
|
||||
} else {
|
||||
// Additional cost
|
||||
list($bills, $add_cost) = User::getBills($id_customer);
|
||||
if ($add_cost > 0 && $router_name != 'balance') {
|
||||
foreach ($bills as $k => $v) {
|
||||
$note .= $k . " : " . Lang::moneyFormat($v) . "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!$p['enabled']) {
|
||||
if (!isset($admin) || !isset($admin['id']) || empty($admin['id'])) {
|
||||
r2(U . 'home', 'e', Lang::T('Plan Not found'));
|
||||
}
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) {
|
||||
r2(U . 'dashboard', 'e', Lang::T('Plan Not found'));
|
||||
}
|
||||
}
|
||||
|
||||
if ($p['validity_unit'] == 'Period') {
|
||||
$day_exp = User::getAttribute("Expired Date", $c['id']); //ORM::for_table('tbl_customers_fields')->where('field_name', 'Expired Date')->where('customer_id', $c['id'])->find_one();
|
||||
if (!$day_exp) {
|
||||
$day_exp = 20;
|
||||
// $day_exp = date('d', strtotime($c['created_at']));
|
||||
// if (empty($day_exp) || $day_exp > 28) {
|
||||
// $day_exp = 1;
|
||||
// }
|
||||
$f = ORM::for_table('tbl_customers_fields')->create();
|
||||
$f->customer_id = $c['id'];
|
||||
$f->field_name = 'Expired Date';
|
||||
$f->field_value = $day_exp;
|
||||
$f->save();
|
||||
}
|
||||
}
|
||||
|
||||
if ($router_name == 'balance') {
|
||||
// insert table transactions
|
||||
$inv = "INV-" . Package::_raid(5);
|
||||
$inv = "INV-" . Package::_raid();
|
||||
$t = ORM::for_table('tbl_transactions')->create();
|
||||
$t->invoice = $inv;
|
||||
$t->username = $c['username'];
|
||||
@ -47,6 +88,11 @@ class Package
|
||||
$t->method = "$gateway - $channel";
|
||||
$t->routers = $router_name;
|
||||
$t->type = "Balance";
|
||||
if ($admin) {
|
||||
$t->admin_id = ($admin['id']) ? $admin['id'] : '0';
|
||||
} else {
|
||||
$t->admin_id = '0';
|
||||
}
|
||||
$t->save();
|
||||
|
||||
$balance_before = $c['balance'];
|
||||
@ -54,9 +100,9 @@ class Package
|
||||
$balance = $c['balance'] + $p['price'];
|
||||
|
||||
$textInvoice = Lang::getNotifText('invoice_balance');
|
||||
$textInvoice = str_replace('[[company_name]]', $_c['CompanyName'], $textInvoice);
|
||||
$textInvoice = str_replace('[[address]]', $_c['address'], $textInvoice);
|
||||
$textInvoice = str_replace('[[phone]]', $_c['phone'], $textInvoice);
|
||||
$textInvoice = str_replace('[[company_name]]', $config['CompanyName'], $textInvoice);
|
||||
$textInvoice = str_replace('[[address]]', $config['address'], $textInvoice);
|
||||
$textInvoice = str_replace('[[phone]]', $config['phone'], $textInvoice);
|
||||
$textInvoice = str_replace('[[invoice]]', $inv, $textInvoice);
|
||||
$textInvoice = str_replace('[[date]]', Lang::dateTimeFormat($date_now), $textInvoice);
|
||||
$textInvoice = str_replace('[[payment_gateway]]', $gateway, $textInvoice);
|
||||
@ -67,25 +113,63 @@ class Package
|
||||
$textInvoice = str_replace('[[name]]', $c['fullname'], $textInvoice);
|
||||
$textInvoice = str_replace('[[user_name]]', $c['username'], $textInvoice);
|
||||
$textInvoice = str_replace('[[user_password]]', $c['password'], $textInvoice);
|
||||
$textInvoice = str_replace('[[footer]]', $_c['note'], $textInvoice);
|
||||
$textInvoice = str_replace('[[footer]]', $config['note'], $textInvoice);
|
||||
$textInvoice = str_replace('[[balance_before]]', Lang::moneyFormat($balance_before), $textInvoice);
|
||||
$textInvoice = str_replace('[[balance]]', Lang::moneyFormat($balance), $textInvoice);
|
||||
|
||||
if ($_c['user_notification_payment'] == 'sms') {
|
||||
if ($config['user_notification_payment'] == 'sms') {
|
||||
Message::sendSMS($c['phonenumber'], $textInvoice);
|
||||
} else if ($_c['user_notification_payment'] == 'wa') {
|
||||
} else if ($config['user_notification_payment'] == 'wa') {
|
||||
Message::sendWhatsapp($c['phonenumber'], $textInvoice);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1 Customer only can have 1 PPPOE and 1 Hotspot Plan, 1 prepaid and 1 postpaid
|
||||
*/
|
||||
$b = ORM::for_table('tbl_user_recharges')
|
||||
->select('tbl_user_recharges.id', 'id')
|
||||
->select('customer_id')
|
||||
->select('username')
|
||||
->select('plan_id')
|
||||
->select('namebp')
|
||||
->select('recharged_on')
|
||||
->select('recharged_time')
|
||||
->select('expiration')
|
||||
->select('time')
|
||||
->select('status')
|
||||
->select('method')
|
||||
->select('tbl_user_recharges.routers', 'routers')
|
||||
->select('tbl_user_recharges.type', 'type')
|
||||
->select('admin_id')
|
||||
->select('prepaid')
|
||||
->where('customer_id', $id_customer)
|
||||
->where('tbl_user_recharges.routers', $router_name)
|
||||
->where('tbl_user_recharges.Type', $p['type'])
|
||||
->where('prepaid', $p['prepaid'])
|
||||
->join('tbl_plans', array('tbl_plans.id', '=', 'tbl_user_recharges.plan_id'))
|
||||
->find_one();
|
||||
|
||||
run_hook("recharge_user");
|
||||
|
||||
$b = ORM::for_table('tbl_user_recharges')->where('customer_id', $id_customer)->where('routers', $router_name)->find_one();
|
||||
|
||||
$mikrotik = Mikrotik::info($router_name);
|
||||
if ($p['validity_unit'] == 'Months') {
|
||||
$date_exp = date("Y-m-d", strtotime('+' . $p['validity'] . ' month'));
|
||||
} else if ($p['validity_unit'] == 'Period') {
|
||||
$date_tmp = date("Y-m-$day_exp", strtotime('+' . $p['validity'] . ' month'));
|
||||
$dt1 = new DateTime("$date_only");
|
||||
$dt2 = new DateTime("$date_tmp");
|
||||
$diff = $dt2->diff($dt1);
|
||||
$sum = $diff->format("%a"); // => 453
|
||||
if ($sum >= 35) {
|
||||
$date_exp = date("Y-m-$day_exp", strtotime('+0 month'));
|
||||
} else {
|
||||
$date_exp = date("Y-m-$day_exp", strtotime('+' . $p['validity'] . ' month'));
|
||||
};
|
||||
$time = date("23:59:00");
|
||||
} else if ($p['validity_unit'] == 'Days') {
|
||||
$date_exp = date("Y-m-d", strtotime('+' . $p['validity'] . ' day'));
|
||||
} else if ($p['validity_unit'] == 'Hrs') {
|
||||
@ -100,22 +184,14 @@ class Package
|
||||
|
||||
if ($p['type'] == 'Hotspot') {
|
||||
if ($b) {
|
||||
if ($p['is_radius']) {
|
||||
Radius::customerAddPlan($c, $p, "$date_exp $time");
|
||||
}else{
|
||||
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
||||
Mikrotik::removeHotspotUser($client, $c['username']);
|
||||
Mikrotik::removePpoeUser($client, $c['username']);
|
||||
Mikrotik::removeHotspotActiveUser($client, $c['username']);
|
||||
Mikrotik::removePpoeActive($client, $c['username']);
|
||||
Mikrotik::addHotspotUser($client, $p, $c);
|
||||
}
|
||||
|
||||
if ($b['namebp'] == $p['name_plan'] && $b['status'] == 'on') {
|
||||
// if it same internet plan, expired will extend
|
||||
if ($p['validity_unit'] == 'Months') {
|
||||
$date_exp = date("Y-m-d", strtotime($b['expiration'] . ' +' . $p['validity'] . ' months'));
|
||||
$time = $b['time'];
|
||||
} else if ($p['validity_unit'] == 'Period') {
|
||||
$date_exp = date("Y-m-$day_exp", strtotime($b['expiration'] . ' +' . $p['validity'] . ' months'));
|
||||
$time = date("23:59:00");
|
||||
} else if ($p['validity_unit'] == 'Days') {
|
||||
$date_exp = date("Y-m-d", strtotime($b['expiration'] . ' +' . $p['validity'] . ' days'));
|
||||
$time = $b['time'];
|
||||
@ -130,6 +206,15 @@ class Package
|
||||
}
|
||||
}
|
||||
|
||||
if ($p['is_radius']) {
|
||||
Radius::customerAddPlan($c, $p, "$date_exp $time");
|
||||
} else {
|
||||
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
||||
Mikrotik::removeHotspotUser($client, $c['username']);
|
||||
Mikrotik::removeHotspotActiveUser($client, $c['username']);
|
||||
Mikrotik::addHotspotUser($client, $p, $c);
|
||||
}
|
||||
|
||||
$b->customer_id = $id_customer;
|
||||
$b->username = $c['username'];
|
||||
$b->plan_id = $plan_id;
|
||||
@ -142,31 +227,74 @@ class Package
|
||||
$b->method = "$gateway - $channel";
|
||||
$b->routers = $router_name;
|
||||
$b->type = "Hotspot";
|
||||
if ($admin) {
|
||||
$b->admin_id = ($admin['id']) ? $admin['id'] : '0';
|
||||
} else {
|
||||
$b->admin_id = '0';
|
||||
}
|
||||
$b->save();
|
||||
|
||||
// insert table transactions
|
||||
$t = ORM::for_table('tbl_transactions')->create();
|
||||
$t->invoice = "INV-" . Package::_raid(5);
|
||||
$t->invoice = "INV-" . Package::_raid();
|
||||
$t->username = $c['username'];
|
||||
$t->plan_name = $p['name_plan'];
|
||||
$t->price = $p['price'];
|
||||
if ($p['validity_unit'] == 'Period') {
|
||||
// Postpaid price from field
|
||||
$add_inv = User::getAttribute("Invoice", $id_customer);
|
||||
if (empty($add_inv) or $add_inv == 0) {
|
||||
$t->price = $p['price'] + $add_cost;
|
||||
} else {
|
||||
$t->price = $add_inv + $add_cost;
|
||||
}
|
||||
} else {
|
||||
$t->price = $p['price'] + $add_cost;
|
||||
}
|
||||
$t->recharged_on = $date_only;
|
||||
$t->recharged_time = $time_only;
|
||||
$t->expiration = $date_exp;
|
||||
$t->time = $time;
|
||||
$t->method = "$gateway - $channel";
|
||||
$t->routers = $router_name;
|
||||
$t->note = $note;
|
||||
$t->type = "Hotspot";
|
||||
if ($admin) {
|
||||
$t->admin_id = ($admin['id']) ? $admin['id'] : '0';
|
||||
} else {
|
||||
$t->admin_id = '0';
|
||||
}
|
||||
$t->save();
|
||||
|
||||
if ($p['validity_unit'] == 'Period') {
|
||||
// insert price to fields for invoice next month
|
||||
$fl = ORM::for_table('tbl_customers_fields')->where('field_name', 'Invoice')->where('customer_id', $c['id'])->find_one();
|
||||
if (!$fl) {
|
||||
$fl = ORM::for_table('tbl_customers_fields')->create();
|
||||
$fl->customer_id = $c['id'];
|
||||
$fl->field_name = 'Invoice';
|
||||
$fl->field_value = $p['price'];
|
||||
$fl->save();
|
||||
} else {
|
||||
$fl->customer_id = $c['id'];
|
||||
$fl->field_value = $p['price'];
|
||||
$fl->save();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Message::sendTelegram("#u$c[username] $c[fullname] #recharge #Hotspot \n" . $p['name_plan'] .
|
||||
"\nRouter: " . $router_name .
|
||||
"\nGateway: " . $gateway .
|
||||
"\nChannel: " . $channel .
|
||||
"\nPrice: " . Lang::moneyFormat($p['price']) .
|
||||
"\nNote:\n" . $note);
|
||||
} else {
|
||||
if ($p['is_radius']) {
|
||||
Radius::customerAddPlan($c, $p, "$date_exp $time");
|
||||
}else{
|
||||
} else {
|
||||
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
||||
Mikrotik::removeHotspotUser($client, $c['username']);
|
||||
Mikrotik::removePpoeUser($client, $c['username']);
|
||||
Mikrotik::removeHotspotActiveUser($client, $c['username']);
|
||||
Mikrotik::removePpoeActive($client, $c['username']);
|
||||
Mikrotik::addHotspotUser($client, $p, $c);
|
||||
}
|
||||
|
||||
@ -183,48 +311,83 @@ class Package
|
||||
$d->method = "$gateway - $channel";
|
||||
$d->routers = $router_name;
|
||||
$d->type = "Hotspot";
|
||||
if ($admin) {
|
||||
$d->admin_id = ($admin['id']) ? $admin['id'] : '0';
|
||||
} else {
|
||||
$d->admin_id = '0';
|
||||
}
|
||||
$d->save();
|
||||
|
||||
// insert table transactions
|
||||
$t = ORM::for_table('tbl_transactions')->create();
|
||||
$t->invoice = "INV-" . Package::_raid(5);
|
||||
$t->invoice = "INV-" . Package::_raid();
|
||||
$t->username = $c['username'];
|
||||
$t->plan_name = $p['name_plan'];
|
||||
$t->price = $p['price'];
|
||||
if ($p['validity_unit'] == 'Period') {
|
||||
// Postpaid price always zero for first time
|
||||
$t->price = 0 + $add_cost;
|
||||
} else {
|
||||
$t->price = $p['price'] + $add_cost;
|
||||
}
|
||||
$t->recharged_on = $date_only;
|
||||
$t->recharged_time = $time_only;
|
||||
$t->expiration = $date_exp;
|
||||
$t->time = $time;
|
||||
$t->method = "$gateway - $channel";
|
||||
$t->routers = $router_name;
|
||||
$t->note = $note;
|
||||
$t->type = "Hotspot";
|
||||
if ($admin) {
|
||||
$t->admin_id = ($admin['id']) ? $admin['id'] : '0';
|
||||
} else {
|
||||
$t->admin_id = '0';
|
||||
}
|
||||
$t->save();
|
||||
|
||||
if ($p['validity_unit'] == 'Period' && $p['price'] != 0) {
|
||||
// insert price to fields for invoice next month
|
||||
$fl = ORM::for_table('tbl_customers_fields')->where('field_name', 'Invoice')->where('customer_id', $c['id'])->find_one();
|
||||
if (!$fl) {
|
||||
$fl = ORM::for_table('tbl_customers_fields')->create();
|
||||
$fl->customer_id = $c['id'];
|
||||
$fl->field_name = 'Invoice';
|
||||
// Calculating Price
|
||||
$sd = new DateTime("$date_only");
|
||||
$ed = new DateTime("$date_exp");
|
||||
$td = $ed->diff($sd);
|
||||
$fd = $td->format("%a");
|
||||
$gi = ($p['price'] / 30) * $fd;
|
||||
if ($gi > $p['price']) {
|
||||
$fl->field_value = $p['price'];
|
||||
} else {
|
||||
$fl->field_value = $gi;
|
||||
}
|
||||
$fl->save();
|
||||
} else {
|
||||
$fl->customer_id = $c['id'];
|
||||
$fl->field_value = $p['price'];
|
||||
$fl->save();
|
||||
}
|
||||
}
|
||||
|
||||
Message::sendTelegram("#u$c[username] $c[fullname] #buy #Hotspot \n" . $p['name_plan'] .
|
||||
"\nRouter: " . $router_name .
|
||||
"\nGateway: " . $gateway .
|
||||
"\nChannel: " . $channel .
|
||||
"\nPrice: " . Lang::moneyFormat($p['price']) .
|
||||
"\nNote:\n" . $note);
|
||||
}
|
||||
Message::sendTelegram("#u$c[username] #buy #Hotspot \n" . $p['name_plan'] .
|
||||
"\nRouter: " . $router_name .
|
||||
"\nGateway: " . $gateway .
|
||||
"\nChannel: " . $channel .
|
||||
"\nPrice: " . Lang::moneyFormat($p['price']));
|
||||
} else {
|
||||
|
||||
if ($b) {
|
||||
if ($p['is_radius']) {
|
||||
Radius::customerAddPlan($c, $p, "$date_exp $time");
|
||||
}else{
|
||||
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
||||
Mikrotik::removeHotspotUser($client, $c['username']);
|
||||
Mikrotik::removePpoeUser($client, $c['username']);
|
||||
Mikrotik::removeHotspotActiveUser($client, $c['username']);
|
||||
Mikrotik::removePpoeActive($client, $c['username']);
|
||||
Mikrotik::addPpoeUser($client, $p, $c);
|
||||
}
|
||||
|
||||
|
||||
if ($b['namebp'] == $p['name_plan'] && $b['status'] == 'on') {
|
||||
// if it same internet plan, expired will extend
|
||||
if ($p['validity_unit'] == 'Months') {
|
||||
$date_exp = date("Y-m-d", strtotime($b['expiration'] . ' +' . $p['validity'] . ' months'));
|
||||
$time = $b['time'];
|
||||
} else if ($p['validity_unit'] == 'Period') {
|
||||
$date_exp = date("Y-m-$day_exp", strtotime($b['expiration'] . ' +' . $p['validity'] . ' months'));
|
||||
$time = date("23:59:00");
|
||||
} else if ($p['validity_unit'] == 'Days') {
|
||||
$date_exp = date("Y-m-d", strtotime($b['expiration'] . ' +' . $p['validity'] . ' days'));
|
||||
$time = $b['time'];
|
||||
@ -239,6 +402,15 @@ class Package
|
||||
}
|
||||
}
|
||||
|
||||
if ($p['is_radius']) {
|
||||
Radius::customerAddPlan($c, $p, "$date_exp $time");
|
||||
} else {
|
||||
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
||||
Mikrotik::removePpoeUser($client, $c['username']);
|
||||
Mikrotik::removePpoeActive($client, $c['username']);
|
||||
Mikrotik::addPpoeUser($client, $p, $c);
|
||||
}
|
||||
|
||||
$b->customer_id = $id_customer;
|
||||
$b->username = $c['username'];
|
||||
$b->plan_id = $plan_id;
|
||||
@ -251,30 +423,72 @@ class Package
|
||||
$b->method = "$gateway - $channel";
|
||||
$b->routers = $router_name;
|
||||
$b->type = "PPPOE";
|
||||
if ($admin) {
|
||||
$b->admin_id = ($admin['id']) ? $admin['id'] : '0';
|
||||
} else {
|
||||
$b->admin_id = '0';
|
||||
}
|
||||
$b->save();
|
||||
|
||||
// insert table transactions
|
||||
$t = ORM::for_table('tbl_transactions')->create();
|
||||
$t->invoice = "INV-" . Package::_raid(5);
|
||||
$t->invoice = "INV-" . Package::_raid();
|
||||
$t->username = $c['username'];
|
||||
$t->plan_name = $p['name_plan'];
|
||||
$t->price = $p['price'];
|
||||
if ($p['validity_unit'] == 'Period') {
|
||||
// Postpaid price from field
|
||||
$add_inv = User::getAttribute("Invoice", $id_customer);
|
||||
if (empty($add_inv) or $add_inv == 0) {
|
||||
$t->price = $p['price'] + $add_cost;
|
||||
} else {
|
||||
$t->price = $add_inv + $add_cost;
|
||||
}
|
||||
} else {
|
||||
$t->price = $p['price'] + $add_cost;
|
||||
}
|
||||
$t->recharged_on = $date_only;
|
||||
$t->recharged_time = $time_only;
|
||||
$t->expiration = $date_exp;
|
||||
$t->time = $time;
|
||||
$t->method = "$gateway - $channel";
|
||||
$t->routers = $router_name;
|
||||
$t->note = $note;
|
||||
$t->type = "PPPOE";
|
||||
if ($admin) {
|
||||
$t->admin_id = ($admin['id']) ? $admin['id'] : '0';
|
||||
} else {
|
||||
$t->admin_id = '0';
|
||||
}
|
||||
$t->save();
|
||||
|
||||
if ($p['validity_unit'] == 'Period' && $p['price'] != 0) {
|
||||
// insert price to fields for invoice next month
|
||||
$fl = ORM::for_table('tbl_customers_fields')->where('field_name', 'Invoice')->where('customer_id', $c['id'])->find_one();
|
||||
if (!$fl) {
|
||||
$fl = ORM::for_table('tbl_customers_fields')->create();
|
||||
$fl->customer_id = $c['id'];
|
||||
$fl->field_name = 'Invoice';
|
||||
$fl->field_value = $p['price'];
|
||||
$fl->save();
|
||||
} else {
|
||||
$fl->customer_id = $c['id'];
|
||||
$fl->field_value = $p['price'];
|
||||
$fl->save();
|
||||
}
|
||||
}
|
||||
|
||||
Message::sendTelegram("#u$c[username] $c[fullname] #recharge #PPPOE \n" . $p['name_plan'] .
|
||||
"\nRouter: " . $router_name .
|
||||
"\nGateway: " . $gateway .
|
||||
"\nChannel: " . $channel .
|
||||
"\nPrice: " . Lang::moneyFormat($p['price']) .
|
||||
"\nNote:\n" . $note);
|
||||
} else {
|
||||
if ($p['is_radius']) {
|
||||
Radius::customerAddPlan($c, $p, "$date_exp $time");
|
||||
}else{
|
||||
} else {
|
||||
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
||||
Mikrotik::removeHotspotUser($client, $c['username']);
|
||||
Mikrotik::removePpoeUser($client, $c['username']);
|
||||
Mikrotik::removeHotspotActiveUser($client, $c['username']);
|
||||
Mikrotik::removePpoeActive($client, $c['username']);
|
||||
Mikrotik::addPpoeUser($client, $p, $c);
|
||||
}
|
||||
@ -292,30 +506,77 @@ class Package
|
||||
$d->method = "$gateway - $channel";
|
||||
$d->routers = $router_name;
|
||||
$d->type = "PPPOE";
|
||||
if ($admin) {
|
||||
$d->admin_id = ($admin['id']) ? $admin['id'] : '0';
|
||||
} else {
|
||||
$d->admin_id = '0';
|
||||
}
|
||||
$d->save();
|
||||
|
||||
// insert table transactions
|
||||
$t = ORM::for_table('tbl_transactions')->create();
|
||||
$t->invoice = "INV-" . Package::_raid(5);
|
||||
$t->invoice = "INV-" . Package::_raid();
|
||||
$t->username = $c['username'];
|
||||
$t->plan_name = $p['name_plan'];
|
||||
$t->price = $p['price'];
|
||||
if ($p['validity_unit'] == 'Period') {
|
||||
// Postpaid price always zero for first time
|
||||
$t->price = 0 + $add_cost;
|
||||
} else {
|
||||
$t->price = $p['price'] + $add_cost;
|
||||
}
|
||||
$t->recharged_on = $date_only;
|
||||
$t->recharged_time = $time_only;
|
||||
$t->expiration = $date_exp;
|
||||
$t->time = $time;
|
||||
$t->method = "$gateway - $channel";
|
||||
$t->note = $note;
|
||||
$t->routers = $router_name;
|
||||
if ($admin) {
|
||||
$t->admin_id = ($admin['id']) ? $admin['id'] : '0';
|
||||
} else {
|
||||
$t->admin_id = '0';
|
||||
}
|
||||
$t->type = "PPPOE";
|
||||
$t->save();
|
||||
}
|
||||
Message::sendTelegram("#u$c[username] #buy #PPPOE \n" . $p['name_plan'] .
|
||||
"\nRouter: " . $router_name .
|
||||
"\nGateway: " . $gateway .
|
||||
"\nChannel: " . $channel .
|
||||
"\nPrice: " . Lang::moneyFormat($p['price']));
|
||||
}
|
||||
|
||||
if ($p['validity_unit'] == 'Period' && $p['price'] != 0) {
|
||||
// insert price to fields for invoice next month
|
||||
$fl = ORM::for_table('tbl_customers_fields')->where('field_name', 'Invoice')->where('customer_id', $c['id'])->find_one();
|
||||
if (!$fl) {
|
||||
$fl = ORM::for_table('tbl_customers_fields')->create();
|
||||
$fl->customer_id = $c['id'];
|
||||
$fl->field_name = 'Invoice';
|
||||
// Calculating Price
|
||||
$sd = new DateTime("$date_only");
|
||||
$ed = new DateTime("$date_exp");
|
||||
$td = $ed->diff($sd);
|
||||
$fd = $td->format("%a");
|
||||
$gi = ($p['price'] / 30) * $fd;
|
||||
if ($gi > $p['price']) {
|
||||
$fl->field_value = $p['price'];
|
||||
} else {
|
||||
$fl->field_value = $gi;
|
||||
}
|
||||
$fl->save();
|
||||
} else {
|
||||
$fl->customer_id = $c['id'];
|
||||
$fl->field_value = $p['price'];
|
||||
$fl->save();
|
||||
}
|
||||
}
|
||||
|
||||
Message::sendTelegram("#u$c[username] $c[fullname] #buy #PPPOE \n" . $p['name_plan'] .
|
||||
"\nRouter: " . $router_name .
|
||||
"\nGateway: " . $gateway .
|
||||
"\nChannel: " . $channel .
|
||||
"\nPrice: " . Lang::moneyFormat($p['price']) .
|
||||
"\nNote:\n" . $note);
|
||||
}
|
||||
}
|
||||
if (is_array($bills) && count($bills) > 0) {
|
||||
User::billsPaid($bills, $id_customer);
|
||||
}
|
||||
run_hook("recharge_user_finish");
|
||||
Message::sendInvoice($c, $t);
|
||||
return true;
|
||||
}
|
||||
@ -323,11 +584,11 @@ class Package
|
||||
public static function changeTo($username, $plan_id, $from_id)
|
||||
{
|
||||
$c = ORM::for_table('tbl_customers')->where('username', $username)->find_one();
|
||||
$p = ORM::for_table('tbl_plans')->where('id', $plan_id)->where('enabled', '1')->find_one();
|
||||
$p = ORM::for_table('tbl_plans')->where('id', $plan_id)->find_one();
|
||||
$b = ORM::for_table('tbl_user_recharges')->find_one($from_id);
|
||||
if($p['routers'] == $b['routers'] && $b['routers'] != 'radius'){
|
||||
if ($p['routers'] == $b['routers'] && $b['routers'] != 'radius') {
|
||||
$mikrotik = Mikrotik::info($p['routers']);
|
||||
}else{
|
||||
} else {
|
||||
$mikrotik = Mikrotik::info($b['routers']);
|
||||
}
|
||||
// delete first
|
||||
@ -336,54 +597,46 @@ class Package
|
||||
if (!$p['is_radius']) {
|
||||
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
||||
Mikrotik::removeHotspotUser($client, $c['username']);
|
||||
Mikrotik::removePpoeUser($client, $c['username']);
|
||||
Mikrotik::removeHotspotActiveUser($client, $c['username']);
|
||||
Mikrotik::removePpoeActive($client, $c['username']);
|
||||
}
|
||||
} else {
|
||||
if (!$p['is_radius']) {
|
||||
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
||||
Mikrotik::removeHotspotUser($client, $c['username']);
|
||||
Mikrotik::removePpoeUser($client, $c['username']);
|
||||
Mikrotik::removeHotspotActiveUser($client, $c['username']);
|
||||
Mikrotik::removePpoeActive($client, $c['username']);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($b) {
|
||||
if (!$p['is_radius']) {
|
||||
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
||||
Mikrotik::removeHotspotUser($client, $c['username']);
|
||||
Mikrotik::removePpoeUser($client, $c['username']);
|
||||
Mikrotik::removeHotspotActiveUser($client, $c['username']);
|
||||
Mikrotik::removePpoeActive($client, $c['username']);
|
||||
}
|
||||
} else {
|
||||
if (!$p['is_radius']) {
|
||||
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
||||
Mikrotik::removeHotspotUser($client, $c['username']);
|
||||
Mikrotik::removePpoeUser($client, $c['username']);
|
||||
Mikrotik::removeHotspotActiveUser($client, $c['username']);
|
||||
Mikrotik::removePpoeActive($client, $c['username']);
|
||||
}
|
||||
}
|
||||
}
|
||||
// call the next mikrotik
|
||||
if($p['routers'] != $b['routers'] && $p['routers'] != 'radius'){
|
||||
if ($p['routers'] != $b['routers'] && $p['routers'] != 'radius') {
|
||||
$mikrotik = Mikrotik::info($p['routers']);
|
||||
}
|
||||
if ($p['type'] == 'Hotspot') {
|
||||
if ($b) {
|
||||
if ($p['is_radius']) {
|
||||
Radius::customerAddPlan($c, $p, $b['expiration'].''.$b['time']);
|
||||
}else{
|
||||
Radius::customerAddPlan($c, $p, $b['expiration'] . '' . $b['time']);
|
||||
} else {
|
||||
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
||||
Mikrotik::addHotspotUser($client, $p, $c);
|
||||
}
|
||||
} else {
|
||||
if ($p['is_radius']) {
|
||||
Radius::customerAddPlan($c, $p, $b['expiration'].''.$b['time']);
|
||||
}else{
|
||||
Radius::customerAddPlan($c, $p, $b['expiration'] . '' . $b['time']);
|
||||
} else {
|
||||
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
||||
Mikrotik::addHotspotUser($client, $p, $c);
|
||||
}
|
||||
@ -392,14 +645,14 @@ class Package
|
||||
if ($b) {
|
||||
if ($p['is_radius']) {
|
||||
Radius::customerAddPlan($c, $p);
|
||||
}else{
|
||||
} else {
|
||||
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
||||
Mikrotik::addPpoeUser($client, $p, $c);
|
||||
}
|
||||
} else {
|
||||
if ($p['is_radius']) {
|
||||
Radius::customerAddPlan($c, $p);
|
||||
}else{
|
||||
} else {
|
||||
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
||||
Mikrotik::addPpoeUser($client, $p, $c);
|
||||
}
|
||||
@ -408,8 +661,114 @@ class Package
|
||||
}
|
||||
|
||||
|
||||
public static function _raid($l)
|
||||
public static function _raid()
|
||||
{
|
||||
return substr(str_shuffle(str_repeat('0123456789', $l)), 0, $l);
|
||||
return ORM::for_table('tbl_transactions')->max('id') + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param in tbl_transactions
|
||||
* @param string $router_name router name for this package
|
||||
* @param int $plan_id plan id for this package
|
||||
* @param string $gateway payment gateway name
|
||||
* @param string $channel channel payment gateway
|
||||
* @return boolean
|
||||
*/
|
||||
public static function createInvoice($in)
|
||||
{
|
||||
global $config, $admin, $ui;
|
||||
$date = Lang::dateAndTimeFormat($in['recharged_on'], $in['recharged_time']);
|
||||
if ($admin['id'] != $in['admin_id'] && $in['admin_id'] > 0) {
|
||||
$_admin = Admin::_info($in['admin_id']);
|
||||
// if admin not deleted
|
||||
if ($_admin) $admin = $_admin;
|
||||
} else {
|
||||
$admin['fullname'] = 'Customer';
|
||||
}
|
||||
$note = '';
|
||||
//print
|
||||
$invoice = Lang::pad($config['CompanyName'], ' ', 2) . "\n";
|
||||
$invoice .= Lang::pad($config['address'], ' ', 2) . "\n";
|
||||
$invoice .= Lang::pad($config['phone'], ' ', 2) . "\n";
|
||||
$invoice .= Lang::pad("", '=') . "\n";
|
||||
$invoice .= Lang::pads("Invoice", $in['invoice'], ' ') . "\n";
|
||||
$invoice .= Lang::pads(Lang::T('Date'), $date, ' ') . "\n";
|
||||
$invoice .= Lang::pads(Lang::T('Sales'), $admin['fullname'], ' ') . "\n";
|
||||
$invoice .= Lang::pad("", '=') . "\n";
|
||||
$invoice .= Lang::pads(Lang::T('Type'), $in['type'], ' ') . "\n";
|
||||
$invoice .= Lang::pads(Lang::T('Plan Name'), $in['plan_name'], ' ') . "\n";
|
||||
if (!empty($in['note'])) {
|
||||
$in['note'] = str_replace("\r", "", $in['note']);
|
||||
$tmp = explode("\n", $in['note']);
|
||||
foreach ($tmp as $t) {
|
||||
if (strpos($t, " : ") === false) {
|
||||
if (!empty($t)) {
|
||||
$note .= "$t\n";
|
||||
}
|
||||
} else {
|
||||
$tmp2 = explode(" : ", $t);
|
||||
$invoice .= Lang::pads($tmp2[0], $tmp2[1], ' ') . "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
$invoice .= Lang::pads(Lang::T('Total'), Lang::moneyFormat($in['price']), ' ') . "\n";
|
||||
$method = explode("-", $in['method']);
|
||||
$invoice .= Lang::pads($method[0], $method[1], ' ') . "\n";
|
||||
if (!empty($note)) {
|
||||
$invoice .= Lang::pad("", '=') . "\n";
|
||||
$invoice .= Lang::pad($note, ' ', 2) . "\n";
|
||||
}
|
||||
$invoice .= Lang::pad("", '=') . "\n";
|
||||
$invoice .= Lang::pads(Lang::T('Username'), $in['username'], ' ') . "\n";
|
||||
$invoice .= Lang::pads(Lang::T('Password'), '**********', ' ') . "\n";
|
||||
if ($in['type'] != 'Balance') {
|
||||
$invoice .= Lang::pads(Lang::T('Created On'), Lang::dateAndTimeFormat($in['recharged_on'], $in['recharged_time']), ' ') . "\n";
|
||||
$invoice .= Lang::pads(Lang::T('Expires On'), Lang::dateAndTimeFormat($in['expiration'], $in['time']), ' ') . "\n";
|
||||
}
|
||||
$invoice .= Lang::pad("", '=') . "\n";
|
||||
$invoice .= Lang::pad($config['note'], ' ', 2) . "\n";
|
||||
$ui->assign('invoice', $invoice);
|
||||
$config['printer_cols'] = 30;
|
||||
//whatsapp
|
||||
$invoice = Lang::pad($config['CompanyName'], ' ', 2) . "\n";
|
||||
$invoice .= Lang::pad($config['address'], ' ', 2) . "\n";
|
||||
$invoice .= Lang::pad($config['phone'], ' ', 2) . "\n";
|
||||
$invoice .= Lang::pad("", '=') . "\n";
|
||||
$invoice .= Lang::pads("Invoice", $in['invoice'], ' ') . "\n";
|
||||
$invoice .= Lang::pads(Lang::T('Date'), $date, ' ') . "\n";
|
||||
$invoice .= Lang::pads(Lang::T('Sales'), $admin['fullname'], ' ') . "\n";
|
||||
$invoice .= Lang::pad("", '=') . "\n";
|
||||
$invoice .= Lang::pads(Lang::T('Type'), $in['type'], ' ') . "\n";
|
||||
$invoice .= Lang::pads(Lang::T('Plan Name'), $in['plan_name'], ' ') . "\n";
|
||||
if (!empty($in['note'])) {
|
||||
$invoice .= Lang::pad("", '=') . "\n";
|
||||
foreach ($tmp as $t) {
|
||||
if (strpos($t, " : ") === false) {
|
||||
if (!empty($t)) {
|
||||
$invoice .= Lang::pad($t, ' ', 2) . "\n";
|
||||
}
|
||||
} else {
|
||||
$tmp2 = explode(" : ", $t);
|
||||
$invoice .= Lang::pads($tmp2[0], $tmp2[1], ' ') . "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
$invoice .= Lang::pads(Lang::T('Total'), Lang::moneyFormat($in['price']), ' ') . "\n";
|
||||
$invoice .= Lang::pads($method[0], $method[1], ' ') . "\n";
|
||||
if (!empty($note)) {
|
||||
$invoice .= Lang::pad("", '=') . "\n";
|
||||
$invoice .= Lang::pad($note, ' ', 2) . "\n";
|
||||
}
|
||||
$invoice .= Lang::pad("", '=') . "\n";
|
||||
$invoice .= Lang::pads(Lang::T('Username'), $in['username'], ' ') . "\n";
|
||||
$invoice .= Lang::pads(Lang::T('Password'), '**********', ' ') . "\n";
|
||||
if ($in['type'] != 'Balance') {
|
||||
$invoice .= Lang::pads(Lang::T('Created On'), Lang::dateAndTimeFormat($in['recharged_on'], $in['recharged_time']), ' ') . "\n";
|
||||
$invoice .= Lang::pads(Lang::T('Expires On'), Lang::dateAndTimeFormat($in['expiration'], $in['time']), ' ') . "\n";
|
||||
}
|
||||
$invoice .= Lang::pad("", '=') . "\n";
|
||||
$invoice .= Lang::pad($config['note'], ' ', 2) . "\n";
|
||||
$ui->assign('whatsapp', urlencode("```$invoice```"));
|
||||
$ui->assign('in', $in);
|
||||
}
|
||||
}
|
||||
|
@ -18,10 +18,14 @@ class Paginator
|
||||
$page = (int)(empty(_get('p')) ? 1 : _get('p'));
|
||||
$pagination = "";
|
||||
foreach($colVal as $k=>$v) {
|
||||
if(strpos($v,'%') === false) {
|
||||
if(!is_array($v) && strpos($v,'%') === false) {
|
||||
$table = $table->where($k, $v);
|
||||
}else{
|
||||
$table = $table->where_like($k, $v);
|
||||
if(is_array($v)){
|
||||
$table = $table->where_in($k, $v);
|
||||
}else{
|
||||
$table = $table->where_like($k, $v);
|
||||
}
|
||||
}
|
||||
}
|
||||
$totalReq = $table->count();
|
||||
|
@ -301,7 +301,11 @@ class Radius
|
||||
if ($_app_stage == 'demo') {
|
||||
return null;
|
||||
}
|
||||
$nas = Radius::getTableNas()->findMany();
|
||||
/**
|
||||
* Fix loop to all Nas but still detecting Hotspot Multylogin from other Nas
|
||||
*/
|
||||
$act = ORM::for_table('radacct')->where_raw("acctstoptime IS NULL")->where('username', $username)->find_one();
|
||||
$nas = Radius::getTableNas()->where('nasname', $act['nasipaddress'])->find_many();
|
||||
$count = count($nas) * 15;
|
||||
set_time_limit($count);
|
||||
$result = [];
|
||||
@ -310,7 +314,7 @@ class Radius
|
||||
if (!empty($n['ports'])) {
|
||||
$port = $n['ports'];
|
||||
}
|
||||
$result[] = $n['nasname'] . ': ' . @shell_exec("echo 'User-Name = $username' | " . Radius::getClient() . " " . trim($n['nasname']) . ":$port disconnect '" . $n['secret'] . "'");
|
||||
$result[] = $n['nasname'] . ': ' . @shell_exec("echo 'User-Name = $username,Framed-IP-Address = " . $act['framedipaddress'] . "' | radclient -x " . trim($n['nasname']) . ":$port disconnect '" . $n['secret'] . "'");
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
@ -8,15 +8,16 @@
|
||||
|
||||
class User
|
||||
{
|
||||
public static function getID(){
|
||||
public static function getID()
|
||||
{
|
||||
global $db_password;
|
||||
if(isset($_SESSION['uid'])){
|
||||
if (isset($_SESSION['uid']) && !empty($_SESSION['uid'])) {
|
||||
return $_SESSION['uid'];
|
||||
}else if(isset($_COOKIE['uid'])){
|
||||
} else if (isset($_COOKIE['uid'])) {
|
||||
// id.time.sha1
|
||||
$tmp = explode('.',$_COOKIE['uid']);
|
||||
if(sha1($tmp[0].$tmp[1].$db_password)==$tmp[2]){
|
||||
if($tmp[1] < 86400*30){
|
||||
$tmp = explode('.', $_COOKIE['uid']);
|
||||
if (sha1($tmp[0] . '.' . $tmp[1] . '.' . $db_password) == $tmp[2]) {
|
||||
if (time() - $tmp[1] < 86400 * 30) {
|
||||
$_SESSION['uid'] = $tmp[0];
|
||||
return $tmp[0];
|
||||
}
|
||||
@ -25,35 +26,174 @@ class User
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static function setCookie($uid){
|
||||
global $db_password;
|
||||
if(isset($uid)){
|
||||
$time = time();
|
||||
setcookie('uid', $uid.'.'.$time.'.'.sha1($uid.'.'.$time.'.'.$db_password), time()+86400*30);
|
||||
}
|
||||
}
|
||||
|
||||
public static function removeCookie(){
|
||||
if(isset($_COOKIE['uid'])){
|
||||
setcookie('uid', '', time()-86400);
|
||||
}
|
||||
}
|
||||
|
||||
public static function _info()
|
||||
public static function getBills($id = 0)
|
||||
{
|
||||
$id = User::getID();
|
||||
if (!$id) {
|
||||
$id = User::getID();
|
||||
if (!$id) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
$addcost = 0;
|
||||
$bills = [];
|
||||
$attrs = User::getAttributes('Bill', $id);
|
||||
foreach ($attrs as $k => $v) {
|
||||
// if has : then its an installment
|
||||
if (strpos($v, ":") === false) {
|
||||
// Not installment
|
||||
$bills[$k] = $v;
|
||||
$addcost += $v;
|
||||
} else {
|
||||
// installment
|
||||
list($cost, $rem) = explode(":", $v);
|
||||
// :0 installment is done
|
||||
if (!empty($rem)) {
|
||||
$bills[$k] = $cost;
|
||||
$addcost += $cost;
|
||||
}
|
||||
}
|
||||
}
|
||||
return [$bills, $addcost];
|
||||
}
|
||||
|
||||
public static function billsPaid($bills, $id = 0)
|
||||
{
|
||||
if (!$id) {
|
||||
$id = User::getID();
|
||||
if (!$id) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
foreach ($bills as $k => $v) {
|
||||
// if has : then its an installment
|
||||
$v = User::getAttribute($k, $id);
|
||||
if (strpos($v, ":") === false) {
|
||||
// Not installment, no need decrement
|
||||
} else {
|
||||
// installment
|
||||
list($cost, $rem) = explode(":", $v);
|
||||
// :0 installment is done
|
||||
if ($rem != 0) {
|
||||
User::setAttribute($k, "$cost:".($rem - 1), $id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function setAttribute($name, $value, $id = 0)
|
||||
{
|
||||
if (!$id) {
|
||||
$id = User::getID();
|
||||
if (!$id) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
$f = ORM::for_table('tbl_customers_fields')->where('field_name', $name)->where('customer_id', $id)->find_one();
|
||||
if (!$f) {
|
||||
$f = ORM::for_table('tbl_customers_fields')->create();
|
||||
$f->customer_id = $id;
|
||||
$f->field_name = $name;
|
||||
$f->field_value = $value;
|
||||
$f->save();
|
||||
$result = $f->id();
|
||||
if ($result) {
|
||||
return $result;
|
||||
}
|
||||
} else {
|
||||
$f->field_value = $value;
|
||||
$f->save();
|
||||
return $f['id'];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static function getAttribute($name, $id = 0)
|
||||
{
|
||||
if (!$id) {
|
||||
$id = User::getID();
|
||||
if (!$id) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
$f = ORM::for_table('tbl_customers_fields')->where('field_name', $name)->where('customer_id', $id)->find_one();
|
||||
if ($f) {
|
||||
return $f['field_value'];
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
public static function getAttributes($endWith, $id = 0)
|
||||
{
|
||||
if (!$id) {
|
||||
$id = User::getID();
|
||||
if (!$id) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
$attrs = [];
|
||||
$f = ORM::for_table('tbl_customers_fields')->where_like('field_name', "%$endWith")->where('customer_id', $id)->find_many();
|
||||
if ($f) {
|
||||
foreach ($f as $k) {
|
||||
$attrs[$k['field_name']] = $k['field_value'];
|
||||
}
|
||||
return $attrs;
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
public static function setCookie($uid)
|
||||
{
|
||||
global $db_password;
|
||||
if (isset($uid)) {
|
||||
$time = time();
|
||||
setcookie('uid', $uid . '.' . $time . '.' . sha1($uid . '.' . $time . '.' . $db_password), time() + 86400 * 30);
|
||||
}
|
||||
}
|
||||
|
||||
public static function removeCookie()
|
||||
{
|
||||
if (isset($_COOKIE['uid'])) {
|
||||
setcookie('uid', '', time() - 86400);
|
||||
}
|
||||
}
|
||||
|
||||
public static function _info($id = 0)
|
||||
{
|
||||
if (!$id) {
|
||||
$id = User::getID();
|
||||
}
|
||||
$d = ORM::for_table('tbl_customers')->find_one($id);
|
||||
|
||||
if(empty($d['username'])){
|
||||
if (empty($d['username'])) {
|
||||
r2(U . 'logout', 'd', '');
|
||||
}
|
||||
return $d;
|
||||
}
|
||||
|
||||
public static function _billing()
|
||||
public static function _billing($id = 0)
|
||||
{
|
||||
$id = User::getID();
|
||||
$d = ORM::for_table('tbl_user_recharges')->where('customer_id', $id)->find_many();
|
||||
if (!$id) {
|
||||
$id = User::getID();
|
||||
}
|
||||
$d = ORM::for_table('tbl_user_recharges')
|
||||
->select('tbl_user_recharges.id', 'id')
|
||||
->select('customer_id')
|
||||
->select('username')
|
||||
->select('plan_id')
|
||||
->select('namebp')
|
||||
->select('recharged_on')
|
||||
->select('recharged_time')
|
||||
->select('expiration')
|
||||
->select('time')
|
||||
->select('status')
|
||||
->select('method')
|
||||
->select('tbl_user_recharges.routers', 'routers')
|
||||
->select('tbl_user_recharges.type', 'type')
|
||||
->select('admin_id')
|
||||
->select('prepaid')
|
||||
->where('customer_id', $id)
|
||||
->join('tbl_plans', array('tbl_plans.id', '=', 'tbl_user_recharges.plan_id'))
|
||||
->find_many();
|
||||
return $d;
|
||||
}
|
||||
}
|
||||
|
@ -5,33 +5,18 @@
|
||||
|
||||
**/
|
||||
|
||||
function r2($to, $ntype = 'e', $msg = '')
|
||||
{
|
||||
if ($msg == '') {
|
||||
header("location: $to");
|
||||
exit;
|
||||
}
|
||||
$_SESSION['ntype'] = $ntype;
|
||||
$_SESSION['notify'] = $msg;
|
||||
header("location: $to");
|
||||
exit;
|
||||
}
|
||||
|
||||
if (file_exists('config.php')) {
|
||||
require('config.php');
|
||||
} else {
|
||||
r2('install');
|
||||
}
|
||||
|
||||
try {
|
||||
require_once 'init.php';
|
||||
} catch (Throwable $e) {
|
||||
$ui = new Smarty();
|
||||
$ui->setTemplateDir(['custom' => File::pathFixer('ui/ui_custom/'), 'default' => File::pathFixer('ui/ui/')]);
|
||||
$ui->setTemplateDir([
|
||||
'custom' => File::pathFixer($UI_PATH . '/ui_custom/'),
|
||||
'default' => File::pathFixer($UI_PATH . '/ui/')
|
||||
]);
|
||||
$ui->assign('_url', APP_URL . '/index.php?_route=');
|
||||
$ui->setCompileDir(File::pathFixer('ui/compiled/'));
|
||||
$ui->setConfigDir(File::pathFixer('ui/conf/'));
|
||||
$ui->setCacheDir(File::pathFixer('ui/cache/'));
|
||||
$ui->setCompileDir(File::pathFixer($UI_PATH . '/compiled/'));
|
||||
$ui->setConfigDir(File::pathFixer($UI_PATH . '/conf/'));
|
||||
$ui->setCacheDir(File::pathFixer($UI_PATH . '/cache/'));
|
||||
$ui->assign("error_title", "PHPNuxBill Crash");
|
||||
if (_auth()) {
|
||||
$ui->assign("error_message", $e->getMessage() . '<br>');
|
||||
@ -42,11 +27,14 @@ try {
|
||||
die();
|
||||
} catch (Exception $e) {
|
||||
$ui = new Smarty();
|
||||
$ui->setTemplateDir(['custom' => File::pathFixer('ui/ui_custom/'), 'default' => File::pathFixer('ui/ui/')]);
|
||||
$ui->setTemplateDir([
|
||||
'custom' => File::pathFixer($UI_PATH . '/ui_custom/'),
|
||||
'default' => File::pathFixer($UI_PATH . '/ui/')
|
||||
]);
|
||||
$ui->assign('_url', APP_URL . '/index.php?_route=');
|
||||
$ui->setCompileDir(File::pathFixer('ui/compiled/'));
|
||||
$ui->setConfigDir(File::pathFixer('ui/conf/'));
|
||||
$ui->setCacheDir(File::pathFixer('ui/cache/'));
|
||||
$ui->setCompileDir(File::pathFixer($UI_PATH . '/compiled/'));
|
||||
$ui->setConfigDir(File::pathFixer($UI_PATH . '/conf/'));
|
||||
$ui->setCacheDir(File::pathFixer($UI_PATH . '/cache/'));
|
||||
$ui->assign("error_title", "PHPNuxBill Crash");
|
||||
if (_auth()) {
|
||||
$ui->assign("error_message", $e->getMessage() . '<br>');
|
||||
@ -66,24 +54,33 @@ function _notify($msg, $type = 'e')
|
||||
$ui = new Smarty();
|
||||
$ui->assign('_kolaps', $_COOKIE['kolaps']);
|
||||
if (!empty($config['theme']) && $config['theme'] != 'default') {
|
||||
$_theme = APP_URL . '/ui/themes/' . $config['theme'];
|
||||
$ui->setTemplateDir(['custom' => File::pathFixer('ui/ui_custom/'), 'theme' => File::pathFixer('ui/themes/' . $config['theme']), 'default' => File::pathFixer('ui/ui/')]);
|
||||
$_theme = APP_URL . '/' . $UI_PATH . '/themes/' . $config['theme'];
|
||||
$ui->setTemplateDir([
|
||||
'custom' => File::pathFixer($UI_PATH . '/ui_custom/'),
|
||||
'theme' => File::pathFixer($UI_PATH . '/themes/' . $config['theme']),
|
||||
'default' => File::pathFixer($UI_PATH . '/ui/')
|
||||
]);
|
||||
} else {
|
||||
$_theme = APP_URL . '/ui/ui';
|
||||
$ui->setTemplateDir(['custom' => File::pathFixer('ui/ui_custom/'), 'default' => File::pathFixer('ui/ui/')]);
|
||||
$_theme = APP_URL . '/' . $UI_PATH . '/ui';
|
||||
$ui->setTemplateDir([
|
||||
'custom' => File::pathFixer($UI_PATH . '/ui_custom/'),
|
||||
'default' => File::pathFixer($UI_PATH . '/ui/')
|
||||
]);
|
||||
}
|
||||
$ui->assign('_theme', $_theme);
|
||||
$ui->addTemplateDir(File::pathFixer('system/paymentgateway/ui/'), 'pg');
|
||||
$ui->addTemplateDir(File::pathFixer('system/plugin/ui/'), 'plugin');
|
||||
$ui->setCompileDir(File::pathFixer('ui/compiled/'));
|
||||
$ui->setConfigDir(File::pathFixer('ui/conf/'));
|
||||
$ui->setCacheDir(File::pathFixer('ui/cache/'));
|
||||
$ui->addTemplateDir($PAYMENTGATEWAY_PATH . File::pathFixer('/ui/'), 'pg');
|
||||
$ui->addTemplateDir($PLUGIN_PATH . File::pathFixer('/ui/'), 'plugin');
|
||||
$ui->setCompileDir(File::pathFixer($UI_PATH . '/compiled/'));
|
||||
$ui->setConfigDir(File::pathFixer($UI_PATH . '/conf/'));
|
||||
$ui->setCacheDir(File::pathFixer($UI_PATH . '/cache/'));
|
||||
$ui->assign('app_url', APP_URL);
|
||||
$ui->assign('_domain', str_replace('www.', '', parse_url(APP_URL, PHP_URL_HOST)));
|
||||
$ui->assign('_url', APP_URL . '/index.php?_route=');
|
||||
$ui->assign('_path', __DIR__);
|
||||
$ui->assign('_c', $config);
|
||||
$ui->assign('_L', $_L);
|
||||
$ui->assign('UPLOAD_PATH', str_replace($root_path, '', $UPLOAD_PATH));
|
||||
$ui->assign('CACHE_PATH', str_replace($root_path, '', $CACHE_PATH));
|
||||
$ui->assign('PAGES_PATH', str_replace($root_path, '', $PAGES_PATH));
|
||||
$ui->assign('_system_menu', 'dashboard');
|
||||
|
||||
function _msglog($type, $msg)
|
||||
@ -101,7 +98,6 @@ if (isset($_SESSION['notify'])) {
|
||||
unset($_SESSION['ntype']);
|
||||
}
|
||||
|
||||
|
||||
// Routing Engine
|
||||
$req = _get('_route');
|
||||
$routes = explode('/', $req);
|
||||
@ -110,8 +106,9 @@ $handler = $routes[0];
|
||||
if ($handler == '') {
|
||||
$handler = 'default';
|
||||
}
|
||||
$admin = Admin::_info();
|
||||
try {
|
||||
$sys_render = $root_path.File::pathFixer('system/controllers/' . $handler . '.php');
|
||||
$sys_render = $root_path . File::pathFixer('system/controllers/' . $handler . '.php');
|
||||
if (file_exists($sys_render)) {
|
||||
$menus = array();
|
||||
// "name" => $name,
|
||||
@ -121,15 +118,17 @@ try {
|
||||
$ui->assign('_system_menu', $routes[0]);
|
||||
foreach ($menu_registered as $menu) {
|
||||
if ($menu['admin'] && _admin(false)) {
|
||||
$menus[$menu['position']] .= '<li' . (($routes[1] == $menu['function']) ? ' class="active"' : '') . '><a href="' . U . 'plugin/' . $menu['function'] . '">';
|
||||
if (!empty($menu['icon'])) {
|
||||
$menus[$menu['position']] .= '<i class="' . $menu['icon'] . '"></i>';
|
||||
if (count($menu['auth']) == 0 || in_array($admin['user_type'], $menu['auth'])) {
|
||||
$menus[$menu['position']] .= '<li' . (($routes[1] == $menu['function']) ? ' class="active"' : '') . '><a href="' . U . 'plugin/' . $menu['function'] . '">';
|
||||
if (!empty($menu['icon'])) {
|
||||
$menus[$menu['position']] .= '<i class="' . $menu['icon'] . '"></i>';
|
||||
}
|
||||
if (!empty($menu['label'])) {
|
||||
$menus[$menu['position']] .= '<span class="pull-right-container">';
|
||||
$menus[$menu['position']] .= '<small class="label pull-right bg-' . $menu['color'] . '">' . $menu['label'] . '</small></span>';
|
||||
}
|
||||
$menus[$menu['position']] .= '<span class="text">' . $menu['name'] . '</span></a></li>';
|
||||
}
|
||||
if (!empty($menu['label'])) {
|
||||
$menus[$menu['position']] .= '<span class="pull-right-container">';
|
||||
$menus[$menu['position']] .= '<small class="label pull-right bg-' . $menu['color'] . '">' . $menu['label'] . '</small></span>';
|
||||
}
|
||||
$menus[$menu['position']] .= '<span class="text">' . $menu['name'] . '</span></a></li>';
|
||||
} else if (!$menu['admin'] && _auth(false)) {
|
||||
$menus[$menu['position']] .= '<li' . (($routes[1] == $menu['function']) ? ' class="active"' : '') . '><a href="' . U . 'plugin/' . $menu['function'] . '">';
|
||||
if (!empty($menu['icon'])) {
|
||||
|
@ -42,17 +42,17 @@ switch ($action) {
|
||||
$c = ORM::for_table('tbl_user_recharges')->where('username', $user['username'])->find_one();
|
||||
if ($c) {
|
||||
$p = ORM::for_table('tbl_plans')->where('id', $c['plan_id'])->find_one();
|
||||
if($p['is_radius']){
|
||||
if($c['type'] == 'Hotspot' || ($c['type'] == 'PPPOE' && empty($d['pppoe_password']))){
|
||||
if ($p['is_radius']) {
|
||||
if ($c['type'] == 'Hotspot' || ($c['type'] == 'PPPOE' && empty($d['pppoe_password']))) {
|
||||
Radius::customerUpsert($d, $p);
|
||||
}
|
||||
}else{
|
||||
} else {
|
||||
$mikrotik = Mikrotik::info($c['routers']);
|
||||
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
||||
if ($c['type'] == 'Hotspot') {
|
||||
Mikrotik::setHotspotUser($client, $c['username'], $npass);
|
||||
Mikrotik::removeHotspotActiveUser($client, $user['username']);
|
||||
} else if(empty($d['pppoe_password'])){
|
||||
Mikrotik::setHotspotUser($client, $c['username'], $npass);
|
||||
Mikrotik::removeHotspotActiveUser($client, $user['username']);
|
||||
} else if (empty($d['pppoe_password'])) {
|
||||
// only change when pppoe_password empty
|
||||
Mikrotik::setPpoeUser($client, $c['username'], $npass);
|
||||
Mikrotik::removePpoeActive($client, $user['username']);
|
||||
@ -84,7 +84,7 @@ switch ($action) {
|
||||
$ui->assign('d', $d);
|
||||
$ui->display('user-profile.tpl');
|
||||
} else {
|
||||
r2(U . 'home', 'e', $_L['Account_Not_Found']);
|
||||
r2(U . 'home', 'e', Lang::T('Account Not Found'));
|
||||
}
|
||||
break;
|
||||
|
||||
@ -122,6 +122,133 @@ switch ($action) {
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 'phone-update':
|
||||
|
||||
$d = ORM::for_table('tbl_customers')->find_one($user['id']);
|
||||
if ($d) {
|
||||
//run_hook('customer_view_edit_profile'); #HOOK
|
||||
$ui->assign('d', $d);
|
||||
$ui->display('user-phone-update.tpl');
|
||||
} else {
|
||||
r2(U . 'home', 'e', Lang::T('Account Not Found'));
|
||||
}
|
||||
break;
|
||||
|
||||
case 'phone-update-otp':
|
||||
$phone = _post('phone');
|
||||
$username = $user['username'];
|
||||
$otpPath = $CACHE_PATH . '/sms/';
|
||||
|
||||
// Validate the phone number format
|
||||
if (!preg_match('/^[0-9]{10,}$/', $phone)) {
|
||||
r2(U . 'accounts/phone-update', 'e', Lang::T('Invalid phone number format'));
|
||||
}
|
||||
|
||||
if (empty($config['sms_url'])) {
|
||||
r2(U . 'accounts/phone-update', 'e', Lang::T('SMS server not Available, Please try again later'));
|
||||
}
|
||||
|
||||
if (!empty($config['sms_url'])) {
|
||||
if (!empty($phone)) {
|
||||
$d = ORM::for_table('tbl_customers')->where('username', $username)->where('phonenumber', $phone)->find_one();
|
||||
if ($d) {
|
||||
r2(U . 'accounts/phone-update', 'e', Lang::T('You cannot use your current phone number'));
|
||||
}
|
||||
if (!file_exists($otpPath)) {
|
||||
mkdir($otpPath);
|
||||
touch($otpPath . 'index.html');
|
||||
}
|
||||
$otpFile = $otpPath . sha1($username . $db_password) . ".txt";
|
||||
$phoneFile = $otpPath . sha1($username . $db_password) . "_phone.txt";
|
||||
|
||||
// expired 10 minutes
|
||||
if (file_exists($otpFile) && time() - filemtime($otpFile) < 1200) {
|
||||
r2(U . 'accounts/phone-update', 'e', Lang::T('Please wait ' . (1200 - (time() - filemtime($otpFile))) . ' seconds before sending another SMS'));
|
||||
} else {
|
||||
$otp = rand(100000, 999999);
|
||||
file_put_contents($otpFile, $otp);
|
||||
file_put_contents($phoneFile, $phone);
|
||||
// send send OTP to user
|
||||
if ($config['phone_otp_type'] === 'sms') {
|
||||
Message::sendSMS($phone, $config['CompanyName'] . "\n Your Verification code is: $otp");
|
||||
} elseif ($config['phone_otp_type'] === 'whatsapp') {
|
||||
Message::sendWhatsapp($phone, $config['CompanyName'] . "\n Your Verification code is: $otp");
|
||||
} elseif ($config['phone_otp_type'] === 'both') {
|
||||
Message::sendSMS($phone, $config['CompanyName'] . "\n Your Verification code is: $otp");
|
||||
Message::sendWhatsapp($phone, $config['CompanyName'] . "\n Your Verification code is: $otp");
|
||||
}
|
||||
//redirect after sending OTP
|
||||
r2(U . 'accounts/phone-update', 'e', Lang::T('Verification code has been sent to your phone'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'phone-update-post':
|
||||
$phone = _post('phone');
|
||||
$otp_code = _post('otp');
|
||||
$username = $user['username'];
|
||||
$otpPath = $CACHE_PATH . '/sms/';
|
||||
|
||||
// Validate the phone number format
|
||||
if (!preg_match('/^[0-9]{10,}$/', $phone)) {
|
||||
r2(U . 'accounts/phone-update', 'e', Lang::T('Invalid phone number format'));
|
||||
exit();
|
||||
}
|
||||
|
||||
if (!empty($config['sms_url'])) {
|
||||
$otpFile = $otpPath . sha1($username . $db_password) . ".txt";
|
||||
$phoneFile = $otpPath . sha1($username . $db_password) . "_phone.txt";
|
||||
|
||||
// Check if OTP file exists
|
||||
if (!file_exists($otpFile)) {
|
||||
r2(U . 'accounts/phone-update', 'e', Lang::T('Please request OTP first'));
|
||||
exit();
|
||||
}
|
||||
|
||||
// expired 10 minutes
|
||||
if (time() - filemtime($otpFile) > 1200) {
|
||||
unlink($otpFile);
|
||||
unlink($phoneFile);
|
||||
r2(U . 'accounts/phone-update', 'e', Lang::T('Verification code expired'));
|
||||
exit();
|
||||
} else {
|
||||
$code = file_get_contents($otpFile);
|
||||
|
||||
// Check if OTP code matches
|
||||
if ($code != $otp_code) {
|
||||
r2(U . 'accounts/phone-update', 'e', Lang::T('Wrong Verification code'));
|
||||
exit();
|
||||
}
|
||||
|
||||
// Check if the phone number matches the one that requested the OTP
|
||||
$savedPhone = file_get_contents($phoneFile);
|
||||
if ($savedPhone !== $phone) {
|
||||
r2(U . 'accounts/phone-update', 'e', Lang::T('The phone number does not match the one that requested the OTP'));
|
||||
exit();
|
||||
}
|
||||
|
||||
// OTP verification successful, delete OTP and phone number files
|
||||
unlink($otpFile);
|
||||
unlink($phoneFile);
|
||||
}
|
||||
} else {
|
||||
r2(U . 'accounts/phone-update', 'e', Lang::T('SMS server not available'));
|
||||
exit();
|
||||
}
|
||||
|
||||
// Update the phone number in the database
|
||||
$d = ORM::for_table('tbl_customers')->where('username', $username)->find_one();
|
||||
if ($d) {
|
||||
$d->phonenumber = Lang::phoneFormat($phone);
|
||||
$d->save();
|
||||
}
|
||||
|
||||
r2(U . 'accounts/profile', 's', Lang::T('Phone number updated successfully'));
|
||||
break;
|
||||
|
||||
default:
|
||||
$ui->display('a404.tpl');
|
||||
}
|
||||
|
@ -5,6 +5,10 @@
|
||||
* by https://t.me/ibnux
|
||||
**/
|
||||
|
||||
if(Admin::getID()){
|
||||
r2(U.'dashboard');
|
||||
}
|
||||
|
||||
if (isset($routes['1'])) {
|
||||
$do = $routes['1'];
|
||||
} else {
|
||||
@ -26,19 +30,16 @@ switch ($do) {
|
||||
$d->last_login = date('Y-m-d H:i:s');
|
||||
$d->save();
|
||||
_log($username . ' ' . Lang::T('Login Successful'), $d['user_type'], $d['id']);
|
||||
r2(U . 'dashboard');
|
||||
_alert(Lang::T('Login Successful'),'success', "dashboard");
|
||||
} else {
|
||||
_msglog('e', Lang::T('Invalid Username or Password'));
|
||||
_log($username . ' ' . Lang::T('Failed Login'), $d['user_type']);
|
||||
r2(U . 'admin');
|
||||
_alert(Lang::T('Invalid Username or Password'),'danger', "admin");
|
||||
}
|
||||
} else {
|
||||
_msglog('e', Lang::T('Invalid Username or Password'));
|
||||
r2(U . 'admin');
|
||||
_alert(Lang::T('Invalid Username or Password'),'danger', "admin");
|
||||
}
|
||||
} else {
|
||||
_msglog('e', Lang::T('Invalid Username or Password'));
|
||||
r2(U . 'admin');
|
||||
_alert(Lang::T('Invalid Username or Password'),'danger', "admin");
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -13,7 +13,6 @@ $ui->assign('_title', Lang::T('Network'));
|
||||
$ui->assign('_system_menu', 'network');
|
||||
|
||||
$action = $routes['1'];
|
||||
$admin = Admin::_info();
|
||||
$ui->assign('_admin', $admin);
|
||||
|
||||
switch ($action) {
|
||||
@ -39,10 +38,18 @@ switch ($action) {
|
||||
case 'plan':
|
||||
$server = _post('server');
|
||||
$jenis = _post('jenis');
|
||||
if($server=='radius'){
|
||||
$d = ORM::for_table('tbl_plans')->where('is_radius', 1)->where('type', $jenis)->where('enabled', '1')->find_many();
|
||||
if(in_array($admin['user_type'], array('SuperAdmin', 'Admin'))){
|
||||
if($server=='radius'){
|
||||
$d = ORM::for_table('tbl_plans')->where('is_radius', 1)->where('type', $jenis)->find_many();
|
||||
}else{
|
||||
$d = ORM::for_table('tbl_plans')->where('routers', $server)->where('type', $jenis)->find_many();
|
||||
}
|
||||
}else{
|
||||
$d = ORM::for_table('tbl_plans')->where('routers', $server)->where('type', $jenis)->where('enabled', '1')->find_many();
|
||||
if($server=='radius'){
|
||||
$d = ORM::for_table('tbl_plans')->where('is_radius', 1)->where('type', $jenis)->where('enabled', '1')->find_many();
|
||||
}else{
|
||||
$d = ORM::for_table('tbl_plans')->where('routers', $server)->where('type', $jenis)->where('enabled', '1')->find_many();
|
||||
}
|
||||
}
|
||||
$ui->assign('d', $d);
|
||||
|
||||
|
@ -9,7 +9,6 @@ $ui->assign('_title', Lang::T('Bandwidth Plans'));
|
||||
$ui->assign('_system_menu', 'services');
|
||||
|
||||
$action = $routes['1'];
|
||||
$admin = Admin::_info();
|
||||
$ui->assign('_admin', $admin);
|
||||
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) {
|
||||
@ -35,15 +34,22 @@ switch ($action) {
|
||||
break;
|
||||
|
||||
case 'add':
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) {
|
||||
_alert(Lang::T('You do not have permission to access this page'),'danger', "dashboard");
|
||||
}
|
||||
run_hook('view_add_bandwidth'); #HOOK
|
||||
$ui->display('bandwidth-add.tpl');
|
||||
break;
|
||||
|
||||
case 'edit':
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) {
|
||||
_alert(Lang::T('You do not have permission to access this page'),'danger', "dashboard");
|
||||
}
|
||||
$id = $routes['2'];
|
||||
run_hook('view_edit_bandwith'); #HOOK
|
||||
$d = ORM::for_table('tbl_bandwidth')->find_one($id);
|
||||
if($d){
|
||||
$ui->assign('burst',explode(" ", $d['burst']));
|
||||
$ui->assign('d',$d);
|
||||
$ui->display('bandwidth-edit.tpl');
|
||||
}else{
|
||||
@ -52,6 +58,9 @@ switch ($action) {
|
||||
break;
|
||||
|
||||
case 'delete':
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) {
|
||||
_alert(Lang::T('You do not have permission to access this page'),'danger', "dashboard");
|
||||
}
|
||||
$id = $routes['2'];
|
||||
run_hook('delete_bandwidth'); #HOOK
|
||||
$d = ORM::for_table('tbl_bandwidth')->find_one($id);
|
||||
@ -62,12 +71,27 @@ switch ($action) {
|
||||
break;
|
||||
|
||||
case 'add-post':
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) {
|
||||
_alert(Lang::T('You do not have permission to access this page'),'danger', "dashboard");
|
||||
}
|
||||
$name = _post('name');
|
||||
$rate_down = _post('rate_down');
|
||||
$rate_down_unit = _post('rate_down_unit');
|
||||
$rate_up = _post('rate_up');
|
||||
$rate_up_unit = _post('rate_up_unit');
|
||||
run_hook('add_bandwidth'); #HOOK
|
||||
$isBurst = true;
|
||||
$burst = "";
|
||||
if(isset($_POST['burst'])){
|
||||
foreach($_POST['burst'] as $b){
|
||||
if(empty($b)){
|
||||
$isBurst = false;
|
||||
}
|
||||
}
|
||||
if($isBurst){
|
||||
$burst = implode(' ', $_POST['burst']);
|
||||
};
|
||||
}
|
||||
$msg = '';
|
||||
if(Validator::Length($name,16,4) == false){
|
||||
$msg .= 'Name should be between 5 to 15 characters'. '<br>';
|
||||
@ -88,6 +112,7 @@ switch ($action) {
|
||||
$d->rate_down_unit = $rate_down_unit;
|
||||
$d->rate_up = $rate_up;
|
||||
$d->rate_up_unit = $rate_up_unit;
|
||||
$d->burst = $burst;
|
||||
$d->save();
|
||||
|
||||
r2(U . 'bandwidth/list', 's', Lang::T('Data Created Successfully'));
|
||||
@ -97,12 +122,27 @@ switch ($action) {
|
||||
break;
|
||||
|
||||
case 'edit-post':
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) {
|
||||
_alert(Lang::T('You do not have permission to access this page'),'danger', "dashboard");
|
||||
}
|
||||
$name = _post('name');
|
||||
$rate_down = _post('rate_down');
|
||||
$rate_down_unit = _post('rate_down_unit');
|
||||
$rate_up = _post('rate_up');
|
||||
$rate_up_unit = _post('rate_up_unit');
|
||||
run_hook('edit_bandwidth'); #HOOK
|
||||
run_hook('edit_bandwidth'); #HOOK
|
||||
$isBurst = true;
|
||||
$burst = "";
|
||||
if(isset($_POST['burst'])){
|
||||
foreach($_POST['burst'] as $b){
|
||||
if(empty($b)){
|
||||
$isBurst = false;
|
||||
}
|
||||
}
|
||||
if($isBurst){
|
||||
$burst = implode(' ', $_POST['burst']);
|
||||
};
|
||||
}
|
||||
$msg = '';
|
||||
if(Validator::Length($name,16,4) == false){
|
||||
$msg .= 'Name should be between 5 to 15 characters'. '<br>';
|
||||
@ -128,6 +168,7 @@ switch ($action) {
|
||||
$d->rate_down_unit = $rate_down_unit;
|
||||
$d->rate_up = $rate_up;
|
||||
$d->rate_up_unit = $rate_up_unit;
|
||||
$d->burst = $burst;
|
||||
$d->save();
|
||||
|
||||
r2(U . 'bandwidth/list', 's', Lang::T('Data Updated Successfully'));
|
||||
|
@ -9,14 +9,14 @@
|
||||
$action = $routes['1'];
|
||||
|
||||
|
||||
if(file_exists('system/paymentgateway/'.$action.'.php')){
|
||||
include 'system/paymentgateway/'.$action.'.php';
|
||||
if(function_exists($action.'_payment_notification')){
|
||||
if (file_exists($PAYMENTGATEWAY_PATH . DIRECTORY_SEPARATOR . $action . '.php')) {
|
||||
include $PAYMENTGATEWAY_PATH . DIRECTORY_SEPARATOR . $action . '.php';
|
||||
if (function_exists($action . '_payment_notification')) {
|
||||
run_hook('callback_payment_notification'); #HOOK
|
||||
call_user_func($action.'_payment_notification');
|
||||
call_user_func($action . '_payment_notification');
|
||||
die();
|
||||
}
|
||||
}
|
||||
|
||||
header('HTTP/1.1 404 Not Found');
|
||||
echo 'Not Found';
|
||||
echo 'Not Found';
|
||||
|
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
|
||||
* by https://t.me/ibnux
|
||||
@ -11,12 +12,11 @@ $ui->assign('_system_menu', 'settings');
|
||||
$plugin_repository = 'https://hotspotbilling.github.io/Plugin-Repository/repository.json';
|
||||
|
||||
$action = $routes['1'];
|
||||
$admin = Admin::_info();
|
||||
$ui->assign('_admin', $admin);
|
||||
$cache = File::pathFixer('system/cache/codecanyon.json');
|
||||
$cache = File::pathFixer($CACHE_PATH . '/codecanyon.json');
|
||||
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) {
|
||||
r2(U . "dashboard", 'e', Lang::T('You do not have permission to access this page'));
|
||||
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
|
||||
}
|
||||
if (empty($config['envato_token'])) {
|
||||
r2(U . 'settings/app', 'w', '<a href="' . U . 'settings/app#envato' . '">Envato Personal Access Token</a> is not set');
|
||||
@ -25,14 +25,14 @@ if (empty($config['envato_token'])) {
|
||||
switch ($action) {
|
||||
|
||||
case 'install':
|
||||
if (!is_writeable(File::pathFixer('system/cache/'))) {
|
||||
if (!is_writeable(File::pathFixer($CACHE_PATH . '/'))) {
|
||||
r2(U . "codecanyon", 'e', 'Folder system/cache/ is not writable');
|
||||
}
|
||||
if (!is_writeable(File::pathFixer('system/plugin/'))) {
|
||||
r2(U . "codecanyon", 'e', 'Folder system/plugin/ is not writable');
|
||||
if (!is_writeable($PLUGIN_PATH)) {
|
||||
r2(U . "codecanyon", 'e', 'Folder plugin/ is not writable');
|
||||
}
|
||||
if (!is_writeable(File::pathFixer('system/paymentgateway/'))) {
|
||||
r2(U . "codecanyon", 'e', 'Folder system/paymentgateway/ is not writable');
|
||||
if (!is_writeable($PAYMENTGATEWAY_PATH)) {
|
||||
r2(U . "codecanyon", 'e', 'Folder paymentgateway/ is not writable');
|
||||
}
|
||||
set_time_limit(-1);
|
||||
$item_id = $routes['2'];
|
||||
@ -42,7 +42,7 @@ switch ($action) {
|
||||
if (!isset($json['download_url'])) {
|
||||
r2(U . 'codecanyon', 'e', 'Failed to get download url. ' . $json['description']);
|
||||
}
|
||||
$file = File::pathFixer('system/cache/codecanyon/');
|
||||
$file = File::pathFixer($CACHE_PATH . '/codecanyon/');
|
||||
if (!file_exists($file)) {
|
||||
mkdir($file);
|
||||
}
|
||||
@ -62,16 +62,16 @@ switch ($action) {
|
||||
curl_close($ch);
|
||||
fclose($fp);
|
||||
//extract
|
||||
$target = File::pathFixer('system/cache/codecanyon/' . $item_id . '/');
|
||||
$target = File::pathFixer($CACHE_PATH . '/codecanyon/' . $item_id . '/');
|
||||
$zip = new ZipArchive();
|
||||
$zip->open($file);
|
||||
$zip->extractTo($target);
|
||||
$zip->close();
|
||||
//moving
|
||||
if (file_exists($target . 'plugin')) {
|
||||
File::copyFolder($target . 'plugin', File::pathFixer('system/plugin/'));
|
||||
File::copyFolder($target . 'plugin', $PLUGIN_PATH . DIRECTORY_SEPARATOR);
|
||||
} else if (file_exists($target . 'paymentgateway')) {
|
||||
File::copyFolder($target . 'paymentgateway', File::pathFixer('system/paymentgateway/'));
|
||||
File::copyFolder($target . 'paymentgateway', $PAYMENTGATEWAY_PATH . DIRECTORY_SEPARATOR);
|
||||
} else if (file_exists($target . 'theme')) {
|
||||
File::copyFolder($target . 'theme', File::pathFixer('ui/themes/'));
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ $ui->assign('_title', 'Community');
|
||||
$ui->assign('_system_menu', 'community');
|
||||
|
||||
$action = $routes['1'];
|
||||
$admin = Admin::_info();
|
||||
$ui->assign('_admin', $admin);
|
||||
|
||||
$ui->display('community.tpl');
|
@ -10,9 +10,11 @@ $ui->assign('_title', Lang::T('Customer'));
|
||||
$ui->assign('_system_menu', 'customers');
|
||||
|
||||
$action = $routes['1'];
|
||||
$admin = Admin::_info();
|
||||
$ui->assign('_admin', $admin);
|
||||
|
||||
if (empty($action)) {
|
||||
$action = 'list';
|
||||
}
|
||||
|
||||
switch ($action) {
|
||||
case 'list':
|
||||
@ -46,7 +48,7 @@ switch ($action) {
|
||||
|
||||
case 'csv':
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) {
|
||||
r2(U . "dashboard", 'e', Lang::T('You do not have permission to access this page'));
|
||||
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
|
||||
}
|
||||
$cs = ORM::for_table('tbl_customers')
|
||||
->select('tbl_customers.id', 'id')
|
||||
@ -84,28 +86,63 @@ switch ($action) {
|
||||
}
|
||||
break;
|
||||
case 'add':
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin', 'Agent', 'Sales'])) {
|
||||
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
|
||||
}
|
||||
run_hook('view_add_customer'); #HOOK
|
||||
$ui->display('customers-add.tpl');
|
||||
break;
|
||||
case 'recharge':
|
||||
$id_customer = $routes['2'];
|
||||
$b = ORM::for_table('tbl_user_recharges')->where('customer_id', $id_customer)->find_one();
|
||||
if ($b) {
|
||||
if (Package::rechargeUser($id_customer, $b['routers'], $b['plan_id'], "Recharge", $admin['fullname'])) {
|
||||
r2(U . 'customers/view/' . $id_customer, 's', 'Success Recharge Customer');
|
||||
} else {
|
||||
r2(U . 'customers/view/' . $id_customer, 'e', 'Customer plan is inactive');
|
||||
}
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin', 'Agent', 'Sales'])) {
|
||||
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
|
||||
}
|
||||
r2(U . 'customers/view/' . $id_customer, 'e', 'Cannot find active plan');
|
||||
$id_customer = $routes['2'];
|
||||
$plan_id = $routes['3'];
|
||||
$b = ORM::for_table('tbl_user_recharges')->where('customer_id', $id_customer)->where('plan_id', $plan_id)->find_one();
|
||||
if ($b) {
|
||||
$gateway = 'Recharge';
|
||||
$channel = $admin['fullname'];
|
||||
$cust = User::_info($id_customer);
|
||||
$plan = ORM::for_table('tbl_plans')->find_one($b['plan_id']);
|
||||
list($bills, $add_cost) = User::getBills($id_customer);
|
||||
if ($using == 'balance' && $config['enable_balance'] == 'yes') {
|
||||
if (!$cust) {
|
||||
r2(U . 'plan/recharge', 'e', Lang::T('Customer not found'));
|
||||
}
|
||||
if (!$plan) {
|
||||
r2(U . 'plan/recharge', 'e', Lang::T('Plan not found'));
|
||||
}
|
||||
if ($cust['balance'] < ($plan['price'] + $add_cost)) {
|
||||
r2(U . 'plan/recharge', 'e', Lang::T('insufficient balance'));
|
||||
}
|
||||
$gateway = 'Recharge Balance';
|
||||
}
|
||||
if ($using == 'zero') {
|
||||
$zero = 1;
|
||||
$gateway = 'Recharge Zero';
|
||||
}
|
||||
$ui->assign('bills', $bills);
|
||||
$ui->assign('add_cost', $add_cost);
|
||||
$ui->assign('cust', $cust);
|
||||
$ui->assign('gateway', $gateway);
|
||||
$ui->assign('channel', $channel);
|
||||
$ui->assign('server', $b['routers']);
|
||||
$ui->assign('using', 'cash');
|
||||
$ui->assign('plan', $plan);
|
||||
$ui->display('recharge-confirm.tpl');
|
||||
}else{
|
||||
r2(U . 'customers/view/' . $id_customer, 'e', 'Cannot find active plan');
|
||||
}
|
||||
break;
|
||||
case 'deactivate':
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) {
|
||||
r2(U . "dashboard", 'e', Lang::T('You do not have permission to access this page'));
|
||||
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
|
||||
}
|
||||
$id_customer = $routes['2'];
|
||||
$b = ORM::for_table('tbl_user_recharges')->where('customer_id', $id_customer)->find_one();
|
||||
$plan_id = $routes['3'];
|
||||
$b = ORM::for_table('tbl_user_recharges')->where('customer_id', $id_customer)->where('plan_id', $plan_id)->find_one();
|
||||
if ($b) {
|
||||
$p = ORM::for_table('tbl_plans')->where('id', $b['plan_id'])->where('enabled', '1')->find_one();
|
||||
$p = ORM::for_table('tbl_plans')->where('id', $b['plan_id'])->find_one();
|
||||
if ($p) {
|
||||
if ($p['is_radius']) {
|
||||
Radius::customerDeactivate($b['username']);
|
||||
@ -133,27 +170,28 @@ switch ($action) {
|
||||
break;
|
||||
case 'sync':
|
||||
$id_customer = $routes['2'];
|
||||
$b = ORM::for_table('tbl_user_recharges')->where('customer_id', $id_customer)->where('status', 'on')->find_one();
|
||||
if ($b) {
|
||||
$c = ORM::for_table('tbl_customers')->find_one($id_customer);
|
||||
$p = ORM::for_table('tbl_plans')->where('id', $b['plan_id'])->where('enabled', '1')->find_one();
|
||||
if ($p) {
|
||||
if ($p['is_radius']) {
|
||||
Radius::customerAddPlan($c, $p, $p['expiration'] . ' ' . $p['time']);
|
||||
r2(U . 'customers/view/' . $id_customer, 's', 'Success sync customer to Radius');
|
||||
} else {
|
||||
$mikrotik = Mikrotik::info($b['routers']);
|
||||
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
||||
if ($b['type'] == 'Hotspot') {
|
||||
Mikrotik::addHotspotUser($client, $p, $c);
|
||||
} else if ($b['type'] == 'PPPOE') {
|
||||
Mikrotik::addPpoeUser($client, $p, $c);
|
||||
$bs = ORM::for_table('tbl_user_recharges')->where('customer_id', $id_customer)->where('status', 'on')->findMany();
|
||||
if ($bs) {
|
||||
$routers = [];
|
||||
foreach ($bs as $b) {
|
||||
$c = ORM::for_table('tbl_customers')->find_one($id_customer);
|
||||
$p = ORM::for_table('tbl_plans')->where('id', $b['plan_id'])->where('enabled', '1')->find_one();
|
||||
if ($p) {
|
||||
$routers[] = $b['routers'];
|
||||
if ($p['is_radius']) {
|
||||
Radius::customerAddPlan($c, $p, $p['expiration'] . ' ' . $p['time']);
|
||||
} else {
|
||||
$mikrotik = Mikrotik::info($b['routers']);
|
||||
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
||||
if ($b['type'] == 'Hotspot') {
|
||||
Mikrotik::addHotspotUser($client, $p, $c);
|
||||
} else if ($b['type'] == 'PPPOE') {
|
||||
Mikrotik::addPpoeUser($client, $p, $c);
|
||||
}
|
||||
}
|
||||
r2(U . 'customers/view/' . $id_customer, 's', 'Success sync customer to Mikrotik');
|
||||
}
|
||||
} else {
|
||||
r2(U . 'customers/view/' . $id_customer, 'e', 'Customer plan is inactive');
|
||||
}
|
||||
r2(U . 'customers/view/' . $id_customer, 's', 'Sync success to '.implode(", ",$routers));
|
||||
}
|
||||
r2(U . 'customers/view/' . $id_customer, 'e', 'Cannot find active plan');
|
||||
break;
|
||||
@ -174,7 +212,10 @@ switch ($action) {
|
||||
->find_many();
|
||||
|
||||
$v = $routes['3'];
|
||||
if (empty($v) || $v == 'order') {
|
||||
if(empty($v)){
|
||||
$v = 'activation';
|
||||
}
|
||||
if ($v == 'order') {
|
||||
$v = 'order';
|
||||
$paginator = Paginator::build(ORM::for_table('tbl_payment_gateway'), ['username' => $customer['username']]);
|
||||
$order = ORM::for_table('tbl_payment_gateway')
|
||||
@ -196,8 +237,7 @@ switch ($action) {
|
||||
$ui->assign('paginator', $paginator);
|
||||
$ui->assign('activation', $activation);
|
||||
}
|
||||
$package = ORM::for_table('tbl_user_recharges')->where('username', $customer['username'])->find_one();
|
||||
$ui->assign('package', $package);
|
||||
$ui->assign('packages', User::_billing($customer['id']));
|
||||
$ui->assign('v', $v);
|
||||
$ui->assign('d', $customer);
|
||||
$ui->assign('customFields', $customFields);
|
||||
@ -207,6 +247,9 @@ switch ($action) {
|
||||
}
|
||||
break;
|
||||
case 'edit':
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin', 'Agent'])) {
|
||||
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
|
||||
}
|
||||
$id = $routes['2'];
|
||||
run_hook('edit_customer'); #HOOK
|
||||
$d = ORM::for_table('tbl_customers')->find_one($id);
|
||||
@ -225,7 +268,7 @@ switch ($action) {
|
||||
|
||||
case 'delete':
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) {
|
||||
r2(U . "dashboard", 'e', Lang::T('You do not have permission to access this page'));
|
||||
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
|
||||
}
|
||||
$id = $routes['2'];
|
||||
run_hook('delete_customer'); #HOOK
|
||||
@ -266,7 +309,7 @@ switch ($action) {
|
||||
} catch (Throwable $e) {
|
||||
}
|
||||
try {
|
||||
$c->delete();
|
||||
if ($c) $c->delete();
|
||||
} catch (Exception $e) {
|
||||
} catch (Throwable $e) {
|
||||
}
|
||||
@ -454,6 +497,7 @@ switch ($action) {
|
||||
// Delete the Customers Attributes with the given field name
|
||||
ORM::for_table('tbl_customers_fields')
|
||||
->where('field_name', $fieldName)
|
||||
->where('customer_id', $id)
|
||||
->delete_many();
|
||||
}
|
||||
}
|
||||
@ -487,7 +531,7 @@ switch ($action) {
|
||||
}
|
||||
}
|
||||
}
|
||||
r2(U . 'customers/list', 's', 'User Updated Successfully');
|
||||
r2(U . 'customers/view/' . $id, 's', 'User Updated Successfully');
|
||||
} else {
|
||||
r2(U . 'customers/edit/' . $id, 'e', $msg);
|
||||
}
|
||||
|
@ -7,7 +7,6 @@
|
||||
|
||||
_admin();
|
||||
$ui->assign('_title', Lang::T('Dashboard'));
|
||||
$admin = Admin::_info();
|
||||
$ui->assign('_admin', $admin);
|
||||
|
||||
$fdate = date('Y-m-01');
|
||||
@ -17,13 +16,18 @@ $first_day_month = date('Y-m-01');
|
||||
$mdate = date('Y-m-d');
|
||||
$month_n = date('n');
|
||||
|
||||
$iday = ORM::for_table('tbl_transactions')->where('recharged_on', $mdate)->sum('price');
|
||||
$iday = ORM::for_table('tbl_transactions')
|
||||
->where('recharged_on', $mdate)
|
||||
->where_not_equal('method', 'Customer - Balance')
|
||||
->where_not_equal('method', 'Recharge Balance - Administrator')
|
||||
->sum('price');
|
||||
|
||||
if ($iday == '') {
|
||||
$iday = '0.00';
|
||||
}
|
||||
$ui->assign('iday', $iday);
|
||||
|
||||
$imonth = ORM::for_table('tbl_transactions')->where_gte('recharged_on', $first_day_month)->where_lte('recharged_on', $mdate)->sum('price');
|
||||
$imonth = ORM::for_table('tbl_transactions')->where_not_equal('method', 'Customer - Balance')->where_not_equal('method', 'Recharge Balance - Administrator')->where_gte('recharged_on', $first_day_month)->where_lte('recharged_on', $mdate)->sum('price');
|
||||
if ($imonth == '') {
|
||||
$imonth = '0.00';
|
||||
}
|
||||
@ -48,7 +52,7 @@ if (empty($c_all)) {
|
||||
}
|
||||
$ui->assign('c_all', $c_all);
|
||||
|
||||
if($config['hide_uet'] != 'yes'){
|
||||
if ($config['hide_uet'] != 'yes') {
|
||||
//user expire
|
||||
$paginator = Paginator::build(ORM::for_table('tbl_user_recharges'));
|
||||
$expire = ORM::for_table('tbl_user_recharges')
|
||||
@ -78,14 +82,14 @@ $log = ORM::for_table('tbl_logs')->count();
|
||||
$ui->assign('log', $log);
|
||||
|
||||
|
||||
if($config['hide_vs'] != 'yes'){
|
||||
$cacheStocksfile = File::pathFixer('system/cache/VoucherStocks.temp');
|
||||
$cachePlanfile = File::pathFixer('system/cache/VoucherPlans.temp');
|
||||
if ($config['hide_vs'] != 'yes') {
|
||||
$cacheStocksfile = $CACHE_PATH . File::pathFixer('/VoucherStocks.temp');
|
||||
$cachePlanfile = $CACHE_PATH . File::pathFixer('/VoucherPlans.temp');
|
||||
//Cache for 5 minutes
|
||||
if(file_exists($cacheStocksfile) && time()- filemtime($cacheStocksfile) < 600){
|
||||
if (file_exists($cacheStocksfile) && time() - filemtime($cacheStocksfile) < 600) {
|
||||
$stocks = json_decode(file_get_contents($cacheStocksfile), true);
|
||||
$plans = json_decode(file_get_contents($cachePlanfile), true);
|
||||
}else{
|
||||
} else {
|
||||
// Count stock
|
||||
$tmp = $v = ORM::for_table('tbl_plans')->select('id')->select('name_plan')->find_many();
|
||||
$plans = array();
|
||||
@ -112,11 +116,11 @@ if($config['hide_vs'] != 'yes'){
|
||||
}
|
||||
}
|
||||
|
||||
$cacheMRfile = File::pathFixer('system/cache/monthlyRegistered.temp');
|
||||
$cacheMRfile = File::pathFixer('/monthlyRegistered.temp');
|
||||
//Cache for 1 hour
|
||||
if(file_exists($cacheMRfile) && time()- filemtime($cacheMRfile) < 3600){
|
||||
if (file_exists($cacheMRfile) && time() - filemtime($cacheMRfile) < 3600) {
|
||||
$monthlyRegistered = json_decode(file_get_contents($cacheMRfile), true);
|
||||
}else{
|
||||
} else {
|
||||
//Monthly Registered Customers
|
||||
$result = ORM::for_table('tbl_customers')
|
||||
->select_expr('MONTH(created_at)', 'month')
|
||||
@ -135,16 +139,18 @@ if(file_exists($cacheMRfile) && time()- filemtime($cacheMRfile) < 3600){
|
||||
file_put_contents($cacheMRfile, json_encode($monthlyRegistered));
|
||||
}
|
||||
|
||||
$cacheMSfile = File::pathFixer('system/cache/monthlySales.temp');
|
||||
$cacheMSfile = $CACHE_PATH . File::pathFixer('/monthlySales.temp');
|
||||
//Cache for 12 hours
|
||||
if(file_exists($cacheMSfile) && time()- filemtime($cacheMSfile) < 43200){
|
||||
if (file_exists($cacheMSfile) && time() - filemtime($cacheMSfile) < 43200) {
|
||||
$monthlySales = json_decode(file_get_contents($cacheMSfile), true);
|
||||
}else{
|
||||
} else {
|
||||
// Query to retrieve monthly data
|
||||
$results = ORM::for_table('tbl_transactions')
|
||||
->select_expr('MONTH(recharged_on)', 'month')
|
||||
->select_expr('SUM(price)', 'total')
|
||||
->where_raw("YEAR(recharged_on) = YEAR(CURRENT_DATE())") // Filter by the current year
|
||||
->where_not_equal('method', 'Customer - Balance')
|
||||
->where_not_equal('method', 'Recharge Balance - Administrator')
|
||||
->group_by_expr('MONTH(recharged_on)')
|
||||
->find_many();
|
||||
|
||||
|
@ -4,5 +4,10 @@
|
||||
* by https://t.me/ibnux
|
||||
**/
|
||||
|
||||
|
||||
r2(APP_URL.'/index.php?_route=dashboard');
|
||||
if(Admin::getID()){
|
||||
r2(U.'dashboard');
|
||||
}if(User::getID()){
|
||||
r2(U.'home');
|
||||
}else{
|
||||
r2(U.'login');
|
||||
}
|
||||
|
@ -10,7 +10,6 @@ $ui->assign('_title', Lang::T('Reports'));
|
||||
$ui->assign('_sysfrm_menu', 'reports');
|
||||
|
||||
$action = $routes['1'];
|
||||
$admin = Admin::_info();
|
||||
$ui->assign('_admin', $admin);
|
||||
|
||||
$mdate = date('Y-m-d');
|
||||
@ -63,10 +62,11 @@ switch ($action) {
|
||||
$title = ' Reports [' . $mdate . ']';
|
||||
$title = str_replace('-', ' ', $title);
|
||||
|
||||
if(file_exists('system/uploads/logo.png')){
|
||||
$logo = 'system/uploads/logo.png';
|
||||
}else{
|
||||
$logo = 'system/uploads/logo.default.png';
|
||||
$UPLOAD_URL_PATH = str_replace($root_path, '', $UPLOAD_PATH);
|
||||
if (file_exists($UPLOAD_PATH . '/logo.png')) {
|
||||
$logo = $UPLOAD_URL_PATH . '/logo.png';
|
||||
} else {
|
||||
$logo = $UPLOAD_URL_PATH . '/logo.default.png';
|
||||
}
|
||||
|
||||
if ($x) {
|
||||
@ -77,7 +77,7 @@ switch ($action) {
|
||||
' . $config['address'] . '<br>
|
||||
' . Lang::T('Phone Number') . ': ' . $config['phone'] . '<br>
|
||||
</div>
|
||||
<div id="logo"><img id="image" src="'.$logo.'" alt="logo" /></div>
|
||||
<div id="logo"><img id="image" src="' . $logo . '" alt="logo" /></div>
|
||||
</div>
|
||||
<div id="header">' . Lang::T('All Transactions at Date') . ': ' . date($config['date_format'], strtotime($mdate)) . '</div>
|
||||
<table id="customers">
|
||||
@ -170,7 +170,7 @@ $style
|
||||
$html
|
||||
EOF;
|
||||
$mpdf->WriteHTML($nhtml);
|
||||
$mpdf->Output(date('Y-m-d') . Package::_raid(4) . '.pdf', 'D');
|
||||
$mpdf->Output(date('Ymd_His') . '.pdf', 'D');
|
||||
} else {
|
||||
echo 'No Data';
|
||||
}
|
||||
@ -235,10 +235,12 @@ EOF;
|
||||
|
||||
$title = ' Reports [' . $mdate . ']';
|
||||
$title = str_replace('-', ' ', $title);
|
||||
if(file_exists('system/uploads/logo.png')){
|
||||
$logo = 'system/uploads/logo.png';
|
||||
}else{
|
||||
$logo = 'system/uploads/logo.default.png';
|
||||
|
||||
$UPLOAD_URL_PATH = str_replace($root_path, '', $UPLOAD_PATH);
|
||||
if (file_exists($UPLOAD_PATH . '/logo.png')) {
|
||||
$logo = $UPLOAD_URL_PATH . '/logo.png';
|
||||
} else {
|
||||
$logo = $UPLOAD_URL_PATH . '/logo.default.png';
|
||||
}
|
||||
|
||||
if ($x) {
|
||||
@ -249,7 +251,7 @@ EOF;
|
||||
' . $config['address'] . '<br>
|
||||
' . Lang::T('Phone Number') . ': ' . $config['phone'] . '<br>
|
||||
</div>
|
||||
<div id="logo"><img id="image" src="'.$logo.'" alt="logo" /></div>
|
||||
<div id="logo"><img id="image" src="' . $logo . '" alt="logo" /></div>
|
||||
</div>
|
||||
<div id="header">' . Lang::T('All Transactions at Date') . ': ' . date($config['date_format'], strtotime($fdate)) . ' - ' . date($config['date_format'], strtotime($tdate)) . '</div>
|
||||
<table id="customers">
|
||||
@ -342,7 +344,7 @@ $style
|
||||
$html
|
||||
EOF;
|
||||
$mpdf->WriteHTML($nhtml);
|
||||
$mpdf->Output(date('Y-m-d') . Package::_raid(4) . '.pdf', 'D');
|
||||
$mpdf->Output(date('Ymd_His') . '.pdf', 'D');
|
||||
} else {
|
||||
echo 'No Data';
|
||||
}
|
||||
|
@ -99,9 +99,6 @@ if (isset($_GET['recharge']) && !empty($_GET['recharge'])) {
|
||||
if(!$plan['enabled']){
|
||||
r2(U . "home", 'e', 'Plan is not exists');
|
||||
}
|
||||
if($plan['allow_purchase'] != 'yes'){
|
||||
r2(U . "home", 'e', 'Cannot recharge this plan');
|
||||
}
|
||||
if ($user['balance'] > $plan['price']) {
|
||||
r2(U . "order/pay/$router[id]/$bill[plan_id]", 'e', 'Order Plan');
|
||||
} else {
|
||||
|
@ -5,6 +5,10 @@
|
||||
* by https://t.me/ibnux
|
||||
**/
|
||||
|
||||
if(User::getID()){
|
||||
r2(U.'home');
|
||||
}
|
||||
|
||||
if (isset($routes['1'])) {
|
||||
$do = $routes['1'];
|
||||
} else {
|
||||
@ -26,7 +30,7 @@ switch ($do) {
|
||||
$d->last_login = date('Y-m-d H:i:s');
|
||||
$d->save();
|
||||
_log($username . ' ' . Lang::T('Login Successful'), 'User', $d['id']);
|
||||
r2(U . 'home');
|
||||
_alert(Lang::T('Login Successful'),'success', "home");
|
||||
} else {
|
||||
_msglog('e', Lang::T('Invalid Username or Password'));
|
||||
_log($username . ' ' . Lang::T('Failed Login'), 'User');
|
||||
@ -64,6 +68,7 @@ switch ($do) {
|
||||
r2(U . 'login', 'e', Lang::T('Voucher activation failed'));
|
||||
}
|
||||
} else {
|
||||
_alert(Lang::T('Login Successful'),'success', "dashboard");
|
||||
r2(U . 'login', 'e', Lang::T('Voucher activation failed') . '.');
|
||||
}
|
||||
}
|
||||
|
@ -9,4 +9,4 @@ if (session_status() == PHP_SESSION_NONE) session_start();
|
||||
Admin::removeCookie();
|
||||
User::removeCookie();
|
||||
session_destroy();
|
||||
header('location: index.php');
|
||||
_alert(Lang::T('Logout Successful'),'warning', "login");
|
@ -10,11 +10,10 @@ $ui->assign('_title', 'PHPNuxBill Logs');
|
||||
$ui->assign('_system_menu', 'logs');
|
||||
|
||||
$action = $routes['1'];
|
||||
$admin = Admin::_info();
|
||||
$ui->assign('_admin', $admin);
|
||||
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) {
|
||||
r2(U . "dashboard", 'e', Lang::T('You do not have permission to access this page'));
|
||||
_alert(Lang::T('You do not have permission to access this page'),'danger', "dashboard");
|
||||
}
|
||||
|
||||
|
||||
|
212
system/controllers/message.php
Normal file
212
system/controllers/message.php
Normal file
@ -0,0 +1,212 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
|
||||
* by https://t.me/ibnux
|
||||
**/
|
||||
|
||||
_admin();
|
||||
$ui->assign('_title', Lang::T('Send Message'));
|
||||
$ui->assign('_system_menu', 'message');
|
||||
|
||||
$action = $routes['1'];
|
||||
$ui->assign('_admin', $admin);
|
||||
|
||||
if (empty($action)) {
|
||||
$action = 'send';
|
||||
}
|
||||
|
||||
switch ($action) {
|
||||
case 'send':
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin', 'Agent', 'Sales'])) {
|
||||
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
|
||||
}
|
||||
|
||||
$select2_customer = <<<EOT
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function(event) {
|
||||
$('#personSelect').select2({
|
||||
theme: "bootstrap",
|
||||
ajax: {
|
||||
url: function(params) {
|
||||
if(params.term != undefined){
|
||||
return './index.php?_route=autoload/customer_select2&s='+params.term;
|
||||
}else{
|
||||
return './index.php?_route=autoload/customer_select2';
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
EOT;
|
||||
$c = ORM::for_table('tbl_customers')->find_many();
|
||||
$ui->assign('c', $c);
|
||||
$ui->assign('xfooter', $select2_customer);
|
||||
$ui->display('message.tpl');
|
||||
break;
|
||||
|
||||
case 'send-post':
|
||||
// Check user permissions
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin', 'Agent', 'Sales'])) {
|
||||
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
|
||||
}
|
||||
|
||||
// Get form data
|
||||
$id_customer = $_POST['id_customer'];
|
||||
$message = $_POST['message'];
|
||||
$via = $_POST['via'];
|
||||
|
||||
// Check if fields are empty
|
||||
if ($id_customer == '' or $message == '' or $via == '') {
|
||||
r2(U . 'message/send', 'e', Lang::T('All field is required'));
|
||||
} else {
|
||||
// Get customer details from the database
|
||||
$c = ORM::for_table('tbl_customers')->find_one($id_customer);
|
||||
|
||||
// Replace placeholders in the message with actual values
|
||||
$message = str_replace('[[name]]', $c['fullname'], $message);
|
||||
$message = str_replace('[[user_name]]', $c['username'], $message);
|
||||
$message = str_replace('[[phone]]', $c['phonenumber'], $message);
|
||||
$message = str_replace('[[company_name]]', $config['CompanyName'], $message);
|
||||
|
||||
|
||||
//Send the message
|
||||
if ($via == 'sms' || $via == 'both') {
|
||||
$smsSent = Message::sendSMS($c['phonenumber'], $message);
|
||||
}
|
||||
|
||||
if ($via == 'wa' || $via == 'both') {
|
||||
$waSent = Message::sendWhatsapp($c['phonenumber'], $message);
|
||||
}
|
||||
|
||||
if (isset($smsSent) || isset($waSent)) {
|
||||
r2(U . 'message/send', 's', Lang::T('Message Sent Successfully'));
|
||||
} else {
|
||||
r2(U . 'message/send', 'e', Lang::T('Failed to send message'));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'send_bulk':
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin', 'Agent', 'Sales'])) {
|
||||
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
|
||||
}
|
||||
$ui->display('message-bulk.tpl');
|
||||
break;
|
||||
case 'send_bulk-post':
|
||||
// Check user permissions
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin', 'Agent', 'Sales'])) {
|
||||
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
|
||||
}
|
||||
|
||||
// Get form data
|
||||
$group = $_POST['group'];
|
||||
$message = $_POST['message'];
|
||||
$via = $_POST['via'];
|
||||
|
||||
// Initialize counters
|
||||
$successCount = 0;
|
||||
$failCount = 0;
|
||||
$successMessages = [];
|
||||
$failMessages = [];
|
||||
|
||||
// Check if fields are empty
|
||||
if ($group == '' or $message == '' or $via == '') {
|
||||
r2(U . 'message/send_bulk', 'e', Lang::T('All fields are required'));
|
||||
} else {
|
||||
// Get customer details from the database based on the selected group
|
||||
if ($group == 'all') {
|
||||
$customers = ORM::for_table('tbl_customers')->find_many();
|
||||
} elseif ($group == 'new') {
|
||||
// Get customers created just a month ago
|
||||
$customers = ORM::for_table('tbl_customers')->where_raw("DATE(created_at) >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH)")->find_many();
|
||||
} elseif ($group == 'expired') {
|
||||
// Get expired user recharges where status is 'off'
|
||||
$expired = ORM::for_table('tbl_user_recharges')->where('status', 'off')->find_many();
|
||||
$customer_ids = [];
|
||||
foreach ($expired as $recharge) {
|
||||
$customer_ids[] = $recharge->customer_id;
|
||||
}
|
||||
$customers = ORM::for_table('tbl_customers')->where_in('id', $customer_ids)->find_many();
|
||||
} elseif ($group == 'active') {
|
||||
// Get active user recharges where status is 'on'
|
||||
$active = ORM::for_table('tbl_user_recharges')->where('status', 'on')->find_many();
|
||||
$customer_ids = [];
|
||||
foreach ($active as $recharge) {
|
||||
$customer_ids[] = $recharge->customer_id;
|
||||
}
|
||||
$customers = ORM::for_table('tbl_customers')->where_in('id', $customer_ids)->find_many();
|
||||
}
|
||||
|
||||
// Loop through customers and send messages
|
||||
foreach ($customers as $customer) {
|
||||
// Replace placeholders in the message with actual values for each customer
|
||||
$message = str_replace('[[name]]', $customer['fullname'], $message);
|
||||
$message = str_replace('[[user_name]]', $customer['username'], $message);
|
||||
$message = str_replace('[[phone]]', $customer['phonenumber'], $message);
|
||||
$message = str_replace('[[company_name]]', $config['CompanyName'], $message);
|
||||
|
||||
// Send the message based on the selected method
|
||||
if ($via == 'sms' || $via == 'both') {
|
||||
$smsSent = Message::sendSMS($customer['phonenumber'], $message);
|
||||
if ($smsSent) {
|
||||
$successCount++;
|
||||
$successMessages[] = "SMS sent to {$customer['fullname']}: {$customer['phonenumber']}";
|
||||
} else {
|
||||
$failCount++;
|
||||
$failMessages[] = "Failed to send SMS to {$customer['fullname']}: {$customer['phonenumber']}";
|
||||
}
|
||||
// Introduce a delay of 5 seconds between each SMS
|
||||
sleep(5);
|
||||
}
|
||||
|
||||
if ($via == 'wa' || $via == 'both') {
|
||||
$waSent = Message::sendWhatsapp($customer['phonenumber'], $message);
|
||||
if ($waSent) {
|
||||
$successCount++;
|
||||
$successMessages[] = "WhatsApp message sent to {$customer['fullname']}: {$customer['phonenumber']}";
|
||||
} else {
|
||||
$failCount++;
|
||||
$failMessages[] = "Failed to send WhatsApp message to {$customer['fullname']}: {$customer['phonenumber']}";
|
||||
}
|
||||
// Introduce a delay of 5 seconds between each WhatsApp message
|
||||
sleep(5);
|
||||
}
|
||||
}
|
||||
|
||||
$responseMessage = '';
|
||||
|
||||
if ($successCount > 0) {
|
||||
$responseMessage .= "Messages Sent Successfully: {$successCount}<br>";
|
||||
$responseMessage .= "<ul>";
|
||||
foreach ($successMessages as $successMessage) {
|
||||
$responseMessage .= "<li>{$successMessage}</li>";
|
||||
}
|
||||
$responseMessage .= "</ul>";
|
||||
}
|
||||
|
||||
if ($failCount > 0) {
|
||||
$responseMessage .= "Failed to send messages: {$failCount}<br>";
|
||||
$responseMessage .= "<ul>";
|
||||
foreach ($failMessages as $failMessage) {
|
||||
$responseMessage .= "<li>{$failMessage}</li>";
|
||||
}
|
||||
$responseMessage .= "</ul>";
|
||||
}
|
||||
|
||||
if ($responseMessage != '') {
|
||||
r2(U . 'message/send_bulk', 's', $responseMessage);
|
||||
} else {
|
||||
r2(U . 'message/send_bulk', 'e', Lang::T('No messages sent'));
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
||||
|
||||
|
||||
default:
|
||||
r2(U . 'message/send_sms', 'e', 'action not defined');
|
||||
}
|
@ -19,7 +19,7 @@ switch ($action) {
|
||||
break;
|
||||
case 'history':
|
||||
$ui->assign('_system_menu', 'history');
|
||||
$paginator = Paginator::build(ORM::for_table('tbl_payment_gateway'),['username'=>$user['username']]);
|
||||
$paginator = Paginator::build(ORM::for_table('tbl_payment_gateway'), ['username' => $user['username']]);
|
||||
$d = ORM::for_table('tbl_payment_gateway')
|
||||
->where('username', $user['username'])
|
||||
->order_by_desc('id')
|
||||
@ -31,51 +31,51 @@ switch ($action) {
|
||||
run_hook('customer_view_order_history'); #HOOK
|
||||
$ui->display('user-orderHistory.tpl');
|
||||
break;
|
||||
case 'balance':
|
||||
if (strpos($user['email'], '@') === false) {
|
||||
r2(U . 'accounts/profile', 'e', Lang::T("Please enter your email address"));
|
||||
}
|
||||
$ui->assign('_title', 'Top Up');
|
||||
$ui->assign('_system_menu', 'balance');
|
||||
$plans_balance = ORM::for_table('tbl_plans')->where('enabled', '1')->where('type', 'Balance')->where('allow_purchase', 'yes')->find_many();
|
||||
$ui->assign('plans_balance', $plans_balance);
|
||||
$ui->display('user-orderBalance.tpl');
|
||||
break;
|
||||
case 'package':
|
||||
if (strpos($user['email'], '@') === false) {
|
||||
r2(U . 'accounts/profile', 'e', Lang::T("Please enter your email address"));
|
||||
}
|
||||
$ui->assign('_title', 'Order Plan');
|
||||
$ui->assign('_system_menu', 'package');
|
||||
if (!empty($_SESSION['nux-router'])) {
|
||||
if ($_SESSION['nux-router'] == 'radius') {
|
||||
$radius_pppoe = ORM::for_table('tbl_plans')->where('enabled', '1')->where('is_radius', 1)->where('type', 'PPPOE')->where('allow_purchase', 'yes')->find_many();
|
||||
$radius_hotspot = ORM::for_table('tbl_plans')->where('enabled', '1')->where('is_radius', 1)->where('type', 'Hotspot')->where('allow_purchase', 'yes')->find_many();
|
||||
} else {
|
||||
$routers = ORM::for_table('tbl_routers')->where('id', $_SESSION['nux-router'])->find_many();
|
||||
$rs = [];
|
||||
foreach ($routers as $r) {
|
||||
$rs[] = $r['name'];
|
||||
}
|
||||
$plans_pppoe = ORM::for_table('tbl_plans')->where('enabled', '1')->where_in('routers', $rs)->where('is_radius', 0)->where('type', 'PPPOE')->where('allow_purchase', 'yes')->find_many();
|
||||
$plans_hotspot = ORM::for_table('tbl_plans')->where('enabled', '1')->where_in('routers', $rs)->where('is_radius', 0)->where('type', 'Hotspot')->where('allow_purchase', 'yes')->find_many();
|
||||
}
|
||||
case 'balance':
|
||||
if (strpos($user['email'], '@') === false) {
|
||||
r2(U . 'accounts/profile', 'e', Lang::T("Please enter your email address"));
|
||||
}
|
||||
$ui->assign('_title', 'Top Up');
|
||||
$ui->assign('_system_menu', 'balance');
|
||||
$plans_balance = ORM::for_table('tbl_plans')->where('enabled', '1')->where('type', 'Balance')->where('prepaid', 'yes')->find_many();
|
||||
$ui->assign('plans_balance', $plans_balance);
|
||||
$ui->display('user-orderBalance.tpl');
|
||||
break;
|
||||
case 'package':
|
||||
if (strpos($user['email'], '@') === false) {
|
||||
r2(U . 'accounts/profile', 'e', Lang::T("Please enter your email address"));
|
||||
}
|
||||
$ui->assign('_title', 'Order Plan');
|
||||
$ui->assign('_system_menu', 'package');
|
||||
if (!empty($_SESSION['nux-router'])) {
|
||||
if ($_SESSION['nux-router'] == 'radius') {
|
||||
$radius_pppoe = ORM::for_table('tbl_plans')->where('enabled', '1')->where('is_radius', 1)->where('type', 'PPPOE')->where('prepaid', 'yes')->find_many();
|
||||
$radius_hotspot = ORM::for_table('tbl_plans')->where('enabled', '1')->where('is_radius', 1)->where('type', 'Hotspot')->where('prepaid', 'yes')->find_many();
|
||||
} else {
|
||||
$radius_pppoe = ORM::for_table('tbl_plans')->where('enabled', '1')->where('is_radius', 1)->where('type', 'PPPOE')->where('allow_purchase', 'yes')->find_many();
|
||||
$radius_hotspot = ORM::for_table('tbl_plans')->where('enabled', '1')->where('is_radius', 1)->where('type', 'Hotspot')->where('allow_purchase', 'yes')->find_many();
|
||||
|
||||
$routers = ORM::for_table('tbl_routers')->find_many();
|
||||
$plans_pppoe = ORM::for_table('tbl_plans')->where('enabled', '1')->where('is_radius', 0)->where('type', 'PPPOE')->where('allow_purchase', 'yes')->find_many();
|
||||
$plans_hotspot = ORM::for_table('tbl_plans')->where('enabled', '1')->where('is_radius', 0)->where('type', 'Hotspot')->where('allow_purchase', 'yes')->find_many();
|
||||
$routers = ORM::for_table('tbl_routers')->where('id', $_SESSION['nux-router'])->find_many();
|
||||
$rs = [];
|
||||
foreach ($routers as $r) {
|
||||
$rs[] = $r['name'];
|
||||
}
|
||||
$plans_pppoe = ORM::for_table('tbl_plans')->where('enabled', '1')->where_in('routers', $rs)->where('is_radius', 0)->where('type', 'PPPOE')->where('prepaid', 'yes')->find_many();
|
||||
$plans_hotspot = ORM::for_table('tbl_plans')->where('enabled', '1')->where_in('routers', $rs)->where('is_radius', 0)->where('type', 'Hotspot')->where('prepaid', 'yes')->find_many();
|
||||
}
|
||||
$ui->assign('routers', $routers);
|
||||
$ui->assign('radius_pppoe', $radius_pppoe);
|
||||
$ui->assign('radius_hotspot', $radius_hotspot);
|
||||
$ui->assign('plans_pppoe', $plans_pppoe);
|
||||
$ui->assign('plans_hotspot', $plans_hotspot);
|
||||
run_hook('customer_view_order_plan'); #HOOK
|
||||
$ui->display('user-orderPlan.tpl');
|
||||
break;
|
||||
} else {
|
||||
$radius_pppoe = ORM::for_table('tbl_plans')->where('enabled', '1')->where('is_radius', 1)->where('type', 'PPPOE')->where('prepaid', 'yes')->find_many();
|
||||
$radius_hotspot = ORM::for_table('tbl_plans')->where('enabled', '1')->where('is_radius', 1)->where('type', 'Hotspot')->where('prepaid', 'yes')->find_many();
|
||||
|
||||
$routers = ORM::for_table('tbl_routers')->find_many();
|
||||
$plans_pppoe = ORM::for_table('tbl_plans')->where('enabled', '1')->where('is_radius', 0)->where('type', 'PPPOE')->where('prepaid', 'yes')->find_many();
|
||||
$plans_hotspot = ORM::for_table('tbl_plans')->where('enabled', '1')->where('is_radius', 0)->where('type', 'Hotspot')->where('prepaid', 'yes')->find_many();
|
||||
}
|
||||
$ui->assign('routers', $routers);
|
||||
$ui->assign('radius_pppoe', $radius_pppoe);
|
||||
$ui->assign('radius_hotspot', $radius_hotspot);
|
||||
$ui->assign('plans_pppoe', $plans_pppoe);
|
||||
$ui->assign('plans_hotspot', $plans_hotspot);
|
||||
run_hook('customer_view_order_plan'); #HOOK
|
||||
$ui->display('user-orderPlan.tpl');
|
||||
break;
|
||||
case 'unpaid':
|
||||
$d = ORM::for_table('tbl_payment_gateway')
|
||||
->where('username', $user['username'])
|
||||
@ -108,13 +108,13 @@ switch ($action) {
|
||||
r2(U . "order/buy/" . (($trx['routers_id'] == 0) ? $trx['routers'] : $trx['routers_id']) . '/' . $trx['plan_id'], 'w', Lang::T("Checking payment"));
|
||||
}
|
||||
if ($routes['3'] == 'check') {
|
||||
if (!file_exists('system/paymentgateway/' . $trx['gateway'] . '.php')) {
|
||||
if (!file_exists($PAYMENTGATEWAY_PATH . DIRECTORY_SEPARATOR . $trx['gateway'] . '.php')) {
|
||||
r2(U . 'order/view/' . $trxid, 'e', Lang::T("No Payment Gateway Available"));
|
||||
}
|
||||
run_hook('customer_check_payment_status'); #HOOK
|
||||
include 'system/paymentgateway/' . $trx['gateway'] . '.php';
|
||||
include $PAYMENTGATEWAY_PATH . DIRECTORY_SEPARATOR . $trx['gateway'] . '.php';
|
||||
call_user_func($trx['gateway'] . '_validate_config');
|
||||
call_user_func($config['payment_gateway'] . '_get_status', $trx, $user);
|
||||
call_user_func($trx['gateway'] . '_get_status', $trx, $user);
|
||||
} else if ($routes['3'] == 'cancel') {
|
||||
run_hook('customer_cancel_payment'); #HOOK
|
||||
$trx->pg_paid_response = '{}';
|
||||
@ -124,16 +124,16 @@ switch ($action) {
|
||||
$trx = ORM::for_table('tbl_payment_gateway')
|
||||
->where('username', $user['username'])
|
||||
->find_one($trxid);
|
||||
if ('midtrans' == $trx['gateway']) {
|
||||
//Hapus invoice link
|
||||
}
|
||||
}
|
||||
if (empty($trx)) {
|
||||
r2(U . "order/package", 'e', Lang::T("Transaction Not found"));
|
||||
}
|
||||
$router = ORM::for_table('tbl_routers')->find_one($trx['routers_id']);
|
||||
$router = Mikrotik::info($trx['routers']);
|
||||
$plan = ORM::for_table('tbl_plans')->find_one($trx['plan_id']);
|
||||
$bandw = ORM::for_table('tbl_bandwidth')->find_one($plan['id_bw']);
|
||||
list($bills, $add_cost) = User::getBills($id_customer);
|
||||
$ui->assign('bills', $bills);
|
||||
$ui->assign('add_cost', $add_cost);
|
||||
$ui->assign('trx', $trx);
|
||||
$ui->assign('router', $router);
|
||||
$ui->assign('plan', $plan);
|
||||
@ -142,29 +142,27 @@ switch ($action) {
|
||||
$ui->display('user-orderView.tpl');
|
||||
break;
|
||||
case 'pay':
|
||||
if ($_c['enable_balance'] != 'yes' && $config['allow_balance_transfer'] != 'yes') {
|
||||
if ($config['enable_balance'] != 'yes') {
|
||||
r2(U . "order/package", 'e', Lang::T("Balance not enabled"));
|
||||
}
|
||||
$plan = ORM::for_table('tbl_plans')->where('enabled', '1')->find_one($routes['3']);
|
||||
if (empty($plan)) {
|
||||
r2(U . "order/package", 'e', Lang::T("Plan Not found"));
|
||||
}
|
||||
if(!$plan['enabled']){
|
||||
if (!$plan['enabled']) {
|
||||
r2(U . "home", 'e', 'Plan is not exists');
|
||||
}
|
||||
if($plan['allow_purchase'] != 'yes'){
|
||||
r2(U . "home", 'e', 'Cannot recharge this plan');
|
||||
}
|
||||
if ($routes['2'] == 'radius') {
|
||||
$router_name = 'radius';
|
||||
} else {
|
||||
$router_name = $plan['routers'];
|
||||
}
|
||||
list($bills, $add_cost) = User::getBills($id_customer);
|
||||
if ($plan && $plan['enabled'] && $user['balance'] >= $plan['price']) {
|
||||
if (Package::rechargeUser($user['id'], $router_name, $plan['id'], 'Customer', 'Balance')) {
|
||||
// if success, then get the balance
|
||||
Balance::min($user['id'], $plan['price']);
|
||||
r2(U . "home", 's', Lang::T("Success to buy package"));
|
||||
Balance::min($user['id'], $plan['price'] + $add_cost);
|
||||
r2(U . "voucher/invoice/", 's', Lang::T("Success to buy package"));
|
||||
} else {
|
||||
r2(U . "order/package", 'e', Lang::T("Failed to buy package"));
|
||||
Message::sendTelegram("Buy Package with Balance Failed\n\n#u$c[username] #buy \n" . $plan['name_plan'] .
|
||||
@ -176,7 +174,7 @@ switch ($action) {
|
||||
}
|
||||
break;
|
||||
case 'send':
|
||||
if ($_c['enable_balance'] != 'yes') {
|
||||
if ($config['enable_balance'] != 'yes') {
|
||||
r2(U . "order/package", 'e', Lang::T("Balance not enabled"));
|
||||
}
|
||||
$ui->assign('_title', Lang::T('Buy for friend'));
|
||||
@ -185,12 +183,9 @@ switch ($action) {
|
||||
if (empty($plan)) {
|
||||
r2(U . "order/package", 'e', Lang::T("Plan Not found"));
|
||||
}
|
||||
if(!$plan['enabled']){
|
||||
if (!$plan['enabled']) {
|
||||
r2(U . "home", 'e', 'Plan is not exists');
|
||||
}
|
||||
if($plan['allow_purchase'] != 'yes'){
|
||||
r2(U . "home", 'e', 'Cannot recharge this plan');
|
||||
}
|
||||
if ($routes['2'] == 'radius') {
|
||||
$router_name = 'radius';
|
||||
} else {
|
||||
@ -198,6 +193,12 @@ switch ($action) {
|
||||
}
|
||||
if (isset($_POST['send']) && $_POST['send'] == 'plan') {
|
||||
$target = ORM::for_table('tbl_customers')->where('username', _post('username'))->find_one();
|
||||
list($bills, $add_cost) = User::getBills($target['id']);
|
||||
if (!empty($add_cost)) {
|
||||
$ui->assign('bills', $bills);
|
||||
$ui->assign('add_cost', $add_cost);
|
||||
$plan['price'] += $add_cost;
|
||||
}
|
||||
if (!$target) {
|
||||
r2(U . 'home', 'd', Lang::T('Username not found'));
|
||||
}
|
||||
@ -266,19 +267,49 @@ switch ($action) {
|
||||
$ui->assign('plan', $plan);
|
||||
$ui->display('user-sendPlan.tpl');
|
||||
break;
|
||||
case 'buy':
|
||||
case 'gateway':
|
||||
$ui->assign('_title', Lang::T('Select Payment Gateway'));
|
||||
$ui->assign('_system_menu', 'package');
|
||||
if (strpos($user['email'], '@') === false) {
|
||||
r2(U . 'accounts/profile', 'e', Lang::T("Please enter your email address"));
|
||||
}
|
||||
if ($config['payment_gateway'] == 'none') {
|
||||
r2(U . 'home', 'e', Lang::T("No Payment Gateway Available"));
|
||||
$pgs = array_values(explode(',', $config['payment_gateway']));
|
||||
if (count($pgs) == 0) {
|
||||
sendTelegram("Payment Gateway not set, please set it in Settings");
|
||||
_log(Lang::T("Payment Gateway not set, please set it in Settings"));
|
||||
r2(U . "home", 'e', Lang::T("Failed to create Transaction.."));
|
||||
}
|
||||
if (!file_exists('system/paymentgateway/' . $config['payment_gateway'] . '.php')) {
|
||||
r2(U . 'home', 'e', Lang::T("No Payment Gateway Available"));
|
||||
if (count($pgs) > 1) {
|
||||
$ui->assign('pgs', $pgs);
|
||||
//$ui->assign('pgs', $pgs);
|
||||
$ui->assign('route2', $routes[2]);
|
||||
$ui->assign('route3', $routes[3]);
|
||||
|
||||
//$ui->assign('plan', $plan);
|
||||
$ui->display('user-selectGateway.tpl');
|
||||
break;
|
||||
} else {
|
||||
if (empty($pgs[0])) {
|
||||
sendTelegram("Payment Gateway not set, please set it in Settings");
|
||||
_log(Lang::T("Payment Gateway not set, please set it in Settings"));
|
||||
r2(U . "home", 'e', Lang::T("Failed to create Transaction.."));
|
||||
} else {
|
||||
$_POST['gateway'] = $pgs[0];
|
||||
}
|
||||
}
|
||||
case 'buy':
|
||||
$gateway = _post('gateway');
|
||||
if (empty($gateway) && !empty($_SESSION['gateway'])) {
|
||||
$gateway = $_SESSION['gateway'];
|
||||
} else if (!empty($gateway)) {
|
||||
$_SESSION['gateway'] = $gateway;
|
||||
}
|
||||
if (empty($gateway)) {
|
||||
r2(U . 'order/gateway/' . $routes[2] . '/' . $routes[3], 'w', Lang::T("Please select Payment Gateway"));
|
||||
}
|
||||
run_hook('customer_buy_plan'); #HOOK
|
||||
include 'system/paymentgateway/' . $config['payment_gateway'] . '.php';
|
||||
call_user_func($config['payment_gateway'] . '_validate_config');
|
||||
include $PAYMENTGATEWAY_PATH . DIRECTORY_SEPARATOR . $gateway . '.php';
|
||||
call_user_func($gateway . '_validate_config');
|
||||
|
||||
if ($routes['2'] == 'radius') {
|
||||
$router['id'] = 0;
|
||||
@ -289,7 +320,7 @@ switch ($action) {
|
||||
$router['id'] = 0;
|
||||
$router['name'] = 'balance';
|
||||
}
|
||||
$plan = ORM::for_table('tbl_plans')->where('enabled', '1')->where('allow_purchase', 'yes')->find_one($routes['3']);
|
||||
$plan = ORM::for_table('tbl_plans')->where('enabled', '1')->find_one($routes['3']);
|
||||
if (empty($router) || empty($plan)) {
|
||||
r2(U . "order/package", 'e', Lang::T("Plan Not found"));
|
||||
}
|
||||
@ -301,7 +332,7 @@ switch ($action) {
|
||||
if ($d['pg_url_payment']) {
|
||||
r2(U . "order/view/" . $d['id'], 'w', Lang::T("You already have unpaid transaction, cancel it or pay it."));
|
||||
} else {
|
||||
if ($config['payment_gateway'] == $d['gateway']) {
|
||||
if ($gateway == $d['gateway']) {
|
||||
$id = $d['id'];
|
||||
} else {
|
||||
$d->status = 4;
|
||||
@ -309,27 +340,53 @@ switch ($action) {
|
||||
}
|
||||
}
|
||||
}
|
||||
$add_cost = 0;
|
||||
if ($router['name'] != 'balance') {
|
||||
list($bills, $add_cost) = User::getBills($id_customer);
|
||||
}
|
||||
if (empty($id)) {
|
||||
$d = ORM::for_table('tbl_payment_gateway')->create();
|
||||
$d->username = $user['username'];
|
||||
$d->gateway = $config['payment_gateway'];
|
||||
$d->gateway = $gateway;
|
||||
$d->plan_id = $plan['id'];
|
||||
$d->plan_name = $plan['name_plan'];
|
||||
$d->routers_id = $router['id'];
|
||||
$d->routers = $router['name'];
|
||||
$d->price = $plan['price'];
|
||||
if ($plan['validity_unit'] == 'Period') {
|
||||
// Postpaid price from field
|
||||
$add_inv = User::getAttribute("Invoice", $id_customer);
|
||||
if (empty ($add_inv) or $add_inv == 0) {
|
||||
$d->price = ($plan['price'] + $add_cost);
|
||||
} else {
|
||||
$d->price = ($add_inv + $add_cost);
|
||||
}
|
||||
} else {
|
||||
$d->price = ($plan['price'] + $add_cost);
|
||||
}
|
||||
//$d->price = ($plan['price'] + $add_cost);
|
||||
$d->created_date = date('Y-m-d H:i:s');
|
||||
$d->status = 1;
|
||||
$d->save();
|
||||
$id = $d->id();
|
||||
} else {
|
||||
$d->username = $user['username'];
|
||||
$d->gateway = $config['payment_gateway'];
|
||||
$d->gateway = $gateway;
|
||||
$d->plan_id = $plan['id'];
|
||||
$d->plan_name = $plan['name_plan'];
|
||||
$d->routers_id = $router['id'];
|
||||
$d->routers = $router['name'];
|
||||
$d->price = $plan['price'];
|
||||
if ($plan['validity_unit'] == 'Period') {
|
||||
// Postpaid price from field
|
||||
$add_inv = User::getAttribute("Invoice", $id_customer);
|
||||
if (empty ($add_inv) or $add_inv == 0) {
|
||||
$d->price = ($plan['price'] + $add_cost);
|
||||
} else {
|
||||
$d->price = ($add_inv + $add_cost);
|
||||
}
|
||||
} else {
|
||||
$d->price = ($plan['price'] + $add_cost);
|
||||
}
|
||||
//$d->price = ($plan['price'] + $add_cost);
|
||||
$d->created_date = date('Y-m-d H:i:s');
|
||||
$d->status = 1;
|
||||
$d->save();
|
||||
@ -337,7 +394,7 @@ switch ($action) {
|
||||
if (!$id) {
|
||||
r2(U . "order/package/" . $d['id'], 'e', Lang::T("Failed to create Transaction.."));
|
||||
} else {
|
||||
call_user_func($config['payment_gateway'] . '_create_transaction', $d, $user);
|
||||
call_user_func($gateway . '_create_transaction', $d, $user);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -9,10 +9,12 @@ $ui->assign('_title', 'Pages');
|
||||
$ui->assign('_system_menu', 'pages');
|
||||
|
||||
$action = $routes['1'];
|
||||
$admin = Admin::_info();
|
||||
$ui->assign('_admin', $admin);
|
||||
|
||||
if(strpos($action,"-reset")!==false){
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) {
|
||||
_alert(Lang::T('You do not have permission to access this page'),'danger', "dashboard");
|
||||
}
|
||||
$action = str_replace("-reset","",$action);
|
||||
$path = "pages/".str_replace(".","",$action).".html";
|
||||
$temp = "pages_template/".str_replace(".","",$action).".html";
|
||||
@ -25,6 +27,9 @@ if(strpos($action,"-reset")!==false){
|
||||
}
|
||||
r2(U . 'pages/'.$action);
|
||||
}else if(strpos($action,"-post")===false){
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) {
|
||||
_alert(Lang::T('You do not have permission to access this page'),'danger', "dashboard");
|
||||
}
|
||||
$path = "pages/".str_replace(".","",$action).".html";
|
||||
//echo $path;
|
||||
run_hook('view_edit_pages'); #HOOK
|
||||
@ -48,6 +53,9 @@ if(strpos($action,"-reset")!==false){
|
||||
}else
|
||||
$ui->display('a404.tpl');
|
||||
}else{
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) {
|
||||
_alert(Lang::T('You do not have permission to access this page'),'danger', "dashboard");
|
||||
}
|
||||
$action = str_replace("-post","",$action);
|
||||
$path = "pages/".str_replace(".","",$action).".html";
|
||||
if(file_exists($path)){
|
||||
|
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
|
||||
* by https://t.me/ibnux
|
||||
@ -7,51 +8,76 @@
|
||||
_admin();
|
||||
$ui->assign('_system_menu', 'paymentgateway');
|
||||
|
||||
$action = alphanumeric($routes['1']);
|
||||
$admin = Admin::_info();
|
||||
$action = alphanumeric($routes[1]);
|
||||
$ui->assign('_admin', $admin);
|
||||
|
||||
if(file_exists('system/paymentgateway/'.$action.'.php')){
|
||||
include 'system/paymentgateway/'.$action.'.php';
|
||||
if ($action == 'delete') {
|
||||
$pg = alphanumeric($routes[2]);
|
||||
if (file_exists($PAYMENTGATEWAY_PATH . DIRECTORY_SEPARATOR . $pg . '.php')) {
|
||||
deleteFile($PAYMENTGATEWAY_PATH . DIRECTORY_SEPARATOR, $pg);
|
||||
}
|
||||
r2(U . 'paymentgateway', 's', Lang::T('Payment Gateway Deleted'));
|
||||
}
|
||||
|
||||
if (_post('save') == 'actives') {
|
||||
$pgs = '';
|
||||
if(is_array($_POST['pgs'])){
|
||||
$pgs = implode(',', $_POST['pgs']);
|
||||
}
|
||||
$d = ORM::for_table('tbl_appconfig')->where('setting', 'payment_gateway')->find_one();
|
||||
if ($d) {
|
||||
$d->value = $pgs;
|
||||
$d->save();
|
||||
} else {
|
||||
$d = ORM::for_table('tbl_appconfig')->create();
|
||||
$d->setting = 'payment_gateway';
|
||||
$d->value = $pgs;
|
||||
$d->save();
|
||||
}
|
||||
r2(U . 'paymentgateway', 's', Lang::T('Payment Gateway saved successfully'));
|
||||
}
|
||||
|
||||
if (file_exists($PAYMENTGATEWAY_PATH . DIRECTORY_SEPARATOR . $action . '.php')) {
|
||||
include $PAYMENTGATEWAY_PATH . DIRECTORY_SEPARATOR . $action . '.php';
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if(function_exists($action.'_save_config')){
|
||||
call_user_func($action.'_save_config');
|
||||
}else{
|
||||
if (function_exists($action . '_save_config')) {
|
||||
call_user_func($action . '_save_config');
|
||||
} else {
|
||||
$ui->display('a404.tpl');
|
||||
}
|
||||
}else{
|
||||
if(function_exists($action.'_show_config')){
|
||||
call_user_func($action.'_show_config');
|
||||
}else{
|
||||
} else {
|
||||
if (function_exists($action . '_show_config')) {
|
||||
call_user_func($action . '_show_config');
|
||||
} else {
|
||||
$ui->display('a404.tpl');
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if(!empty($action)){
|
||||
} else {
|
||||
if (!empty($action)) {
|
||||
r2(U . 'paymentgateway', 'w', Lang::T('Payment Gateway Not Found'));
|
||||
}else{
|
||||
$files = scandir('system/paymentgateway/');
|
||||
foreach($files as $file){
|
||||
if(pathinfo($file, PATHINFO_EXTENSION)=='php'){
|
||||
$pgs[] = str_replace('.php','',$file);
|
||||
} else {
|
||||
$files = scandir($PAYMENTGATEWAY_PATH);
|
||||
foreach ($files as $file) {
|
||||
if (pathinfo($file, PATHINFO_EXTENSION) == 'php') {
|
||||
$pgs[] = str_replace('.php', '', $file);
|
||||
}
|
||||
}
|
||||
if(isset($_POST['payment_gateway'])){
|
||||
$payment_gateway = _post('payment_gateway');
|
||||
$d = ORM::for_table('tbl_appconfig')->where('setting', 'payment_gateway')->find_one();
|
||||
if($d){
|
||||
$d->value = $payment_gateway;
|
||||
$d->save();
|
||||
}else{
|
||||
$d = ORM::for_table('tbl_appconfig')->create();
|
||||
$d->setting = 'payment_gateway';
|
||||
$d->value = $payment_gateway;
|
||||
$d->save();
|
||||
}
|
||||
r2(U . 'paymentgateway', 's', Lang::T('Payment Gateway saved successfully'));
|
||||
}
|
||||
$ui->assign('_title', 'Payment Gateway Settings');
|
||||
$ui->assign('pgs', $pgs);
|
||||
$ui->assign('actives', explode(',', $config['payment_gateway']));
|
||||
$ui->display('paymentgateway.tpl');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function deleteFile($path, $name)
|
||||
{
|
||||
$files = scandir($path);
|
||||
foreach ($files as $file) {
|
||||
if (is_file($path . $file) && strpos($file, $name) !== false) {
|
||||
unlink($path . $file);
|
||||
} else if (is_dir($path . $file) && !in_array($file, ['.', '..'])) {
|
||||
deleteFile($path . $file . DIRECTORY_SEPARATOR, $name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
|
||||
* by https://t.me/ibnux
|
||||
@ -11,19 +12,18 @@ $ui->assign('_system_menu', 'settings');
|
||||
$plugin_repository = 'https://hotspotbilling.github.io/Plugin-Repository/repository.json';
|
||||
|
||||
$action = $routes['1'];
|
||||
$admin = Admin::_info();
|
||||
$ui->assign('_admin', $admin);
|
||||
|
||||
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) {
|
||||
r2(U . "dashboard", 'e', Lang::T('You do not have permission to access this page'));
|
||||
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
|
||||
}
|
||||
|
||||
$cache = File::pathFixer('system/cache/plugin_repository.json');
|
||||
$cache = $CACHE_PATH . File::pathFixer('/plugin_repository.json');
|
||||
if (file_exists($cache) && time() - filemtime($cache) < (24 * 60 * 60)) {
|
||||
$txt = file_get_contents($cache);
|
||||
$json = json_decode($txt, true);
|
||||
if(empty($json['plugins']) && empty($json['payment_gateway'])){
|
||||
if (empty($json['plugins']) && empty($json['payment_gateway'])) {
|
||||
unlink($cache);
|
||||
r2(U . 'dashboard', 'd', $txt);
|
||||
}
|
||||
@ -32,26 +32,24 @@ if (file_exists($cache) && time() - filemtime($cache) < (24 * 60 * 60)) {
|
||||
file_put_contents($cache, $data);
|
||||
$json = json_decode($data, true);
|
||||
}
|
||||
|
||||
switch ($action) {
|
||||
|
||||
case 'install':
|
||||
if(!is_writeable(File::pathFixer('system/cache/'))){
|
||||
r2(U . "pluginmanager", 'e', 'Folder system/cache/ is not writable');
|
||||
case 'delete':
|
||||
if (!is_writeable($CACHE_PATH)) {
|
||||
r2(U . "pluginmanager", 'e', 'Folder cache/ is not writable');
|
||||
}
|
||||
if(!is_writeable(File::pathFixer('system/plugin/'))){
|
||||
r2(U . "pluginmanager", 'e', 'Folder system/plugin/ is not writable');
|
||||
if (!is_writeable($PLUGIN_PATH)) {
|
||||
r2(U . "pluginmanager", 'e', 'Folder plugin/ is not writable');
|
||||
}
|
||||
set_time_limit(-1);
|
||||
$tipe = $routes['2'];
|
||||
$plugin = $routes['3'];
|
||||
$file = File::pathFixer('system/cache/') . $plugin . '.zip';
|
||||
$file = $CACHE_PATH . DIRECTORY_SEPARATOR . $plugin . '.zip';
|
||||
if (file_exists($file)) unlink($file);
|
||||
if ($tipe == 'plugin') {
|
||||
foreach ($json['plugins'] as $plg) {
|
||||
if ($plg['id'] == $plugin) {
|
||||
$fp = fopen($file, 'w+');
|
||||
$ch = curl_init($plg['github'].'/archive/refs/heads/master.zip');
|
||||
$ch = curl_init($plg['github'] . '/archive/refs/heads/master.zip');
|
||||
curl_setopt($ch, CURLOPT_POST, 0);
|
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
|
||||
@ -64,19 +62,67 @@ switch ($action) {
|
||||
|
||||
$zip = new ZipArchive();
|
||||
$zip->open($file);
|
||||
$zip->extractTo(File::pathFixer('system/cache/'));
|
||||
$zip->extractTo($CACHE_PATH);
|
||||
$zip->close();
|
||||
$folder = File::pathFixer('system/cache/' . $plugin.'-main/');
|
||||
if(!file_exists($folder)){
|
||||
$folder = File::pathFixer('system/cache/' . $plugin.'-master/');
|
||||
$folder = $CACHE_PATH . File::pathFixer('/' . $plugin . '-main/');
|
||||
if (!file_exists($folder)) {
|
||||
$folder = $CACHE_PATH . File::pathFixer('/' . $plugin . '-master/');
|
||||
}
|
||||
if(!file_exists($folder)){
|
||||
if (!file_exists($folder)) {
|
||||
r2(U . "pluginmanager", 'e', 'Extracted Folder is unknown');
|
||||
}
|
||||
File::copyFolder($folder, File::pathFixer('system/plugin/'), ['README.md','LICENSE']);
|
||||
scanAndRemovePath($folder, $PLUGIN_PATH . DIRECTORY_SEPARATOR);
|
||||
File::deleteFolder($folder);
|
||||
unlink($file);
|
||||
r2(U . "pluginmanager", 's', 'Plugin '.$plugin.' has been installed');
|
||||
r2(U . "pluginmanager", 's', 'Plugin ' . $plugin . ' has been deleted');
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'install':
|
||||
if (!is_writeable($CACHE_PATH)) {
|
||||
r2(U . "pluginmanager", 'e', 'Folder cache/ is not writable');
|
||||
}
|
||||
if (!is_writeable($PLUGIN_PATH)) {
|
||||
r2(U . "pluginmanager", 'e', 'Folder plugin/ is not writable');
|
||||
}
|
||||
set_time_limit(-1);
|
||||
$tipe = $routes['2'];
|
||||
$plugin = $routes['3'];
|
||||
$file = $CACHE_PATH . DIRECTORY_SEPARATOR . $plugin . '.zip';
|
||||
if (file_exists($file)) unlink($file);
|
||||
if ($tipe == 'plugin') {
|
||||
foreach ($json['plugins'] as $plg) {
|
||||
if ($plg['id'] == $plugin) {
|
||||
$fp = fopen($file, 'w+');
|
||||
$ch = curl_init($plg['github'] . '/archive/refs/heads/master.zip');
|
||||
curl_setopt($ch, CURLOPT_POST, 0);
|
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
||||
curl_setopt($ch, CURLOPT_FILE, $fp);
|
||||
curl_exec($ch);
|
||||
curl_close($ch);
|
||||
fclose($fp);
|
||||
|
||||
$zip = new ZipArchive();
|
||||
$zip->open($file);
|
||||
$zip->extractTo($CACHE_PATH);
|
||||
$zip->close();
|
||||
$folder = $CACHE_PATH . File::pathFixer('/' . $plugin . '-main/');
|
||||
if (!file_exists($folder)) {
|
||||
$folder = $CACHE_PATH . File::pathFixer('/' . $plugin . '-master/');
|
||||
}
|
||||
if (!file_exists($folder)) {
|
||||
r2(U . "pluginmanager", 'e', 'Extracted Folder is unknown');
|
||||
}
|
||||
File::copyFolder($folder, $PLUGIN_PATH . DIRECTORY_SEPARATOR, ['README.md', 'LICENSE']);
|
||||
File::deleteFolder($folder);
|
||||
unlink($file);
|
||||
r2(U . "pluginmanager", 's', 'Plugin ' . $plugin . ' has been installed');
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -85,7 +131,7 @@ switch ($action) {
|
||||
foreach ($json['payment_gateway'] as $plg) {
|
||||
if ($plg['id'] == $plugin) {
|
||||
$fp = fopen($file, 'w+');
|
||||
$ch = curl_init($plg['github'].'/archive/refs/heads/master.zip');
|
||||
$ch = curl_init($plg['github'] . '/archive/refs/heads/master.zip');
|
||||
curl_setopt($ch, CURLOPT_POST, 0);
|
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
|
||||
@ -98,19 +144,19 @@ switch ($action) {
|
||||
|
||||
$zip = new ZipArchive();
|
||||
$zip->open($file);
|
||||
$zip->extractTo(File::pathFixer('system/cache/'));
|
||||
$zip->extractTo($CACHE_PATH);
|
||||
$zip->close();
|
||||
$folder = File::pathFixer('system/cache/' . $plugin.'-main/');
|
||||
if(!file_exists($folder)){
|
||||
$folder = File::pathFixer('system/cache/' . $plugin.'-master/');
|
||||
$folder = $CACHE_PATH . File::pathFixer('/' . $plugin . '-main/');
|
||||
if (!file_exists($folder)) {
|
||||
$folder = $CACHE_PATH . File::pathFixer('/' . $plugin . '-master/');
|
||||
}
|
||||
if(!file_exists($folder)){
|
||||
if (!file_exists($folder)) {
|
||||
r2(U . "pluginmanager", 'e', 'Extracted Folder is unknown');
|
||||
}
|
||||
File::copyFolder($folder, File::pathFixer('system/paymentgateway/'), ['README.md','LICENSE']);
|
||||
File::copyFolder($folder, $PAYMENTGATEWAY_PATH . DIRECTORY_SEPARATOR, ['README.md', 'LICENSE']);
|
||||
File::deleteFolder($folder);
|
||||
unlink($file);
|
||||
r2(U . "paymentgateway", 's', 'Payment Gateway '.$plugin.' has been installed');
|
||||
r2(U . "paymentgateway", 's', 'Payment Gateway ' . $plugin . ' has been installed');
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -127,3 +173,24 @@ switch ($action) {
|
||||
$ui->assign('pgs', $json['payment_gateway']);
|
||||
$ui->display('plugin-manager.tpl');
|
||||
}
|
||||
|
||||
|
||||
function scanAndRemovePath($source, $target)
|
||||
{
|
||||
$files = scandir($source);
|
||||
foreach ($files as $file) {
|
||||
if (is_file($source . $file)) {
|
||||
if(file_exists($target.$file)){
|
||||
unlink($target . $file);
|
||||
}
|
||||
} else if (is_dir($source . $file) && !in_array($file, ['.', '..'])) {
|
||||
scanAndRemovePath($source. $file. DIRECTORY_SEPARATOR, $target. $file. DIRECTORY_SEPARATOR);
|
||||
if(file_exists($target.$file)){
|
||||
rmdir($target . $file);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(file_exists($target)){
|
||||
rmdir($target);
|
||||
}
|
||||
}
|
@ -10,11 +10,10 @@ $ui->assign('_title', Lang::T('Network'));
|
||||
$ui->assign('_system_menu', 'network');
|
||||
|
||||
$action = $routes['1'];
|
||||
$admin = Admin::_info();
|
||||
$ui->assign('_admin', $admin);
|
||||
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) {
|
||||
r2(U . "dashboard", 'e', Lang::T('You do not have permission to access this page'));
|
||||
_alert(Lang::T('You do not have permission to access this page'),'danger', "dashboard");
|
||||
}
|
||||
|
||||
|
||||
|
@ -8,12 +8,11 @@ $ui->assign('_title', $_L['Plugin Manager']);
|
||||
$ui->assign('_system_menu', 'settings');
|
||||
|
||||
$action = $routes['1'];
|
||||
$admin = Admin::_info();
|
||||
$ui->assign('_admin', $admin);
|
||||
|
||||
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) {
|
||||
r2(U . "dashboard", 'e', Lang::T('You do not have permission to access this page'));
|
||||
_alert(Lang::T('You do not have permission to access this page'),'danger', "dashboard");
|
||||
}
|
||||
|
||||
switch ($action) {
|
||||
|
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
|
||||
* by https://t.me/ibnux
|
||||
@ -10,21 +11,21 @@ if (isset($routes['1'])) {
|
||||
$do = 'register-display';
|
||||
}
|
||||
|
||||
$otpPath = 'system/cache/sms/';
|
||||
$otpPath = $CACHE_PATH . File::pathFixer('/sms/');
|
||||
|
||||
switch ($do) {
|
||||
case 'post':
|
||||
$otp_code = _post('otp_code');
|
||||
$username = alphanumeric(_post('username'),"+_.");
|
||||
$username = alphanumeric(_post('username'), "+_.");
|
||||
$email = _post('email');
|
||||
$fullname = _post('fullname');
|
||||
$password = _post('password');
|
||||
$cpassword = _post('cpassword');
|
||||
$address = _post('address');
|
||||
if(!empty($config['sms_url'])){
|
||||
if (!empty($config['sms_url'])) {
|
||||
$phonenumber = Lang::phoneFormat($username);
|
||||
$username = $phonenumber;
|
||||
}else if(strlen($username)<21){
|
||||
} else if (strlen($username) < 21) {
|
||||
$phonenumber = $username;
|
||||
}
|
||||
$msg = '';
|
||||
@ -44,16 +45,16 @@ switch ($do) {
|
||||
$msg .= Lang::T('Passwords does not match') . '<br>';
|
||||
}
|
||||
|
||||
if(!empty($config['sms_url'])){
|
||||
$otpPath .= sha1($username.$db_password).".txt";
|
||||
if (!empty($config['sms_url'])) {
|
||||
$otpPath .= sha1($username . $db_password) . ".txt";
|
||||
run_hook('validate_otp'); #HOOK
|
||||
//expired 10 minutes
|
||||
if(file_exists($otpPath) && time()-filemtime($otpPath)>1200){
|
||||
if (file_exists($otpPath) && time() - filemtime($otpPath) > 1200) {
|
||||
unlink($otpPath);
|
||||
r2(U . 'register', 's', 'Verification code expired');
|
||||
}else if(file_exists($otpPath)){
|
||||
} else if (file_exists($otpPath)) {
|
||||
$code = file_get_contents($otpPath);
|
||||
if($code!=$otp_code){
|
||||
if ($code != $otp_code) {
|
||||
$ui->assign('username', $username);
|
||||
$ui->assign('fullname', $fullname);
|
||||
$ui->assign('address', $address);
|
||||
@ -63,10 +64,10 @@ switch ($do) {
|
||||
$ui->assign('notify_t', 'd');
|
||||
$ui->display('register-otp.tpl');
|
||||
exit();
|
||||
}else{
|
||||
} else {
|
||||
unlink($otpPath);
|
||||
}
|
||||
}else{
|
||||
} else {
|
||||
r2(U . 'register', 's', 'No Verification code');
|
||||
}
|
||||
}
|
||||
@ -77,7 +78,7 @@ switch ($do) {
|
||||
if ($msg == '') {
|
||||
run_hook('register_user'); #HOOK
|
||||
$d = ORM::for_table('tbl_customers')->create();
|
||||
$d->username = alphanumeric($username,"+_.");
|
||||
$d->username = alphanumeric($username, "+_.");
|
||||
$d->password = $password;
|
||||
$d->fullname = $fullname;
|
||||
$d->address = $address;
|
||||
@ -110,38 +111,38 @@ switch ($do) {
|
||||
break;
|
||||
|
||||
default:
|
||||
if(!empty($config['sms_url'])){
|
||||
if (!empty($config['sms_url'])) {
|
||||
$username = _post('username');
|
||||
if(!empty($username)){
|
||||
if (!empty($username)) {
|
||||
$d = ORM::for_table('tbl_customers')->where('username', $username)->find_one();
|
||||
if ($d) {
|
||||
r2(U . 'register', 's', Lang::T('Account already axist'));
|
||||
}
|
||||
if(!file_exists($otpPath)){
|
||||
if (!file_exists($otpPath)) {
|
||||
mkdir($otpPath);
|
||||
touch($otpPath.'index.html');
|
||||
touch($otpPath . 'index.html');
|
||||
}
|
||||
$otpPath .= sha1($username.$db_password).".txt";
|
||||
$otpPath .= sha1($username . $db_password) . ".txt";
|
||||
//expired 10 minutes
|
||||
if(file_exists($otpPath) && time()-filemtime($otpPath)<1200){
|
||||
if (file_exists($otpPath) && time() - filemtime($otpPath) < 1200) {
|
||||
$ui->assign('username', $username);
|
||||
$ui->assign('notify', 'Please wait '.(1200-(time()-filemtime($otpPath))).' seconds before sending another SMS');
|
||||
$ui->assign('notify', 'Please wait ' . (1200 - (time() - filemtime($otpPath))) . ' seconds before sending another SMS');
|
||||
$ui->assign('notify_t', 'd');
|
||||
$ui->display('register-otp.tpl');
|
||||
}else{
|
||||
$otp = rand(100000,999999);
|
||||
} else {
|
||||
$otp = rand(100000, 999999);
|
||||
file_put_contents($otpPath, $otp);
|
||||
Message::sendSMS($username,$config['CompanyName']."\nYour Verification code are: $otp");
|
||||
Message::sendSMS($username, $config['CompanyName'] . "\nYour Verification code are: $otp");
|
||||
$ui->assign('username', $username);
|
||||
$ui->assign('notify', 'Verification code has been sent to your phone');
|
||||
$ui->assign('notify_t', 's');
|
||||
$ui->display('register-otp.tpl');
|
||||
}
|
||||
}else{
|
||||
} else {
|
||||
run_hook('view_otp_register'); #HOOK
|
||||
$ui->display('register-rotp.tpl');
|
||||
}
|
||||
}else{
|
||||
} else {
|
||||
$ui->assign('username', "");
|
||||
$ui->assign('fullname', "");
|
||||
$ui->assign('address', "");
|
||||
|
@ -10,7 +10,6 @@ $ui->assign('_title', Lang::T('Reports'));
|
||||
$ui->assign('_system_menu', 'reports');
|
||||
|
||||
$action = $routes['1'];
|
||||
$admin = Admin::_info();
|
||||
$ui->assign('_admin', $admin);
|
||||
|
||||
$mdate = date('Y-m-d');
|
||||
|
@ -10,7 +10,6 @@ $ui->assign('_title', Lang::T('Network'));
|
||||
$ui->assign('_system_menu', 'network');
|
||||
|
||||
$action = $routes['1'];
|
||||
$admin = Admin::_info();
|
||||
$ui->assign('_admin', $admin);
|
||||
|
||||
use PEAR2\Net\RouterOS;
|
||||
@ -18,7 +17,7 @@ use PEAR2\Net\RouterOS;
|
||||
require_once 'system/autoload/PEAR2/Autoload.php';
|
||||
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) {
|
||||
r2(U . "dashboard", 'e', Lang::T('You do not have permission to access this page'));
|
||||
_alert(Lang::T('You do not have permission to access this page'),'danger', "dashboard");
|
||||
}
|
||||
|
||||
switch ($action) {
|
||||
|
@ -9,11 +9,10 @@ $ui->assign('_title', Lang::T('Hotspot Plans'));
|
||||
$ui->assign('_system_menu', 'services');
|
||||
|
||||
$action = $routes['1'];
|
||||
$admin = Admin::_info();
|
||||
$ui->assign('_admin', $admin);
|
||||
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) {
|
||||
r2(U . "dashboard", 'e', Lang::T('You do not have permission to access this page'));
|
||||
_alert(Lang::T('You do not have permission to access this page'),'danger', "dashboard");
|
||||
}
|
||||
|
||||
use PEAR2\Net\RouterOS;
|
||||
@ -173,7 +172,7 @@ switch ($action) {
|
||||
Mikrotik::removeHotspotPlan($client, $d['name_plan']);
|
||||
} catch (Exception $e) {
|
||||
//ignore exception, it means router has already deleted
|
||||
} catch(Throwable $e){
|
||||
} catch (Throwable $e) {
|
||||
//ignore exception, it means router has already deleted
|
||||
}
|
||||
}
|
||||
@ -200,8 +199,9 @@ switch ($action) {
|
||||
$validity_unit = _post('validity_unit');
|
||||
$routers = _post('routers');
|
||||
$pool_expired = _post('pool_expired');
|
||||
$list_expired = _post('list_expired');
|
||||
$enabled = _post('enabled');
|
||||
$allow_purchase = _post('allow_purchase');
|
||||
$prepaid = _post('prepaid');
|
||||
|
||||
$msg = '';
|
||||
if (Validator::UnsignedNumber($validity) == false) {
|
||||
@ -243,6 +243,7 @@ switch ($action) {
|
||||
}
|
||||
$rate = $b['rate_up'] . $unitup . "/" . $b['rate_down'] . $unitdown;
|
||||
$radiusRate = $b['rate_up'] . $radup . '/' . $b['rate_down'] . $raddown;
|
||||
$rate = trim($rate . " " . $b['burst']);
|
||||
|
||||
$d = ORM::for_table('tbl_plans')->create();
|
||||
$d->name_plan = $name;
|
||||
@ -264,10 +265,11 @@ switch ($action) {
|
||||
} else {
|
||||
$d->is_radius = 0;
|
||||
$d->routers = $routers;
|
||||
$d->pool_expired = $pool_expired;
|
||||
}
|
||||
$d->pool_expired = $pool_expired;
|
||||
$d->list_expired = $list_expired;
|
||||
$d->enabled = $enabled;
|
||||
$d->allow_purchase = $allow_purchase;
|
||||
$d->prepaid = $prepaid;
|
||||
$d->save();
|
||||
$plan_id = $d->id();
|
||||
|
||||
@ -305,8 +307,9 @@ switch ($action) {
|
||||
$validity = _post('validity');
|
||||
$validity_unit = _post('validity_unit');
|
||||
$pool_expired = _post('pool_expired');
|
||||
$list_expired = _post('list_expired');
|
||||
$enabled = _post('enabled');
|
||||
$allow_purchase = _post('allow_purchase');
|
||||
$prepaid = _post('prepaid');
|
||||
$routers = _post('routers');
|
||||
$msg = '';
|
||||
if (Validator::UnsignedNumber($validity) == false) {
|
||||
@ -343,6 +346,8 @@ switch ($action) {
|
||||
$rate = $b['rate_up'] . $unitup . "/" . $b['rate_down'] . $unitdown;
|
||||
$radiusRate = $b['rate_up'] . $radup . '/' . $b['rate_down'] . $raddown;
|
||||
|
||||
$rate = trim($rate . " " . $b['burst']);
|
||||
|
||||
if ($d['is_radius']) {
|
||||
Radius::planUpSert($id, $radiusRate);
|
||||
} else {
|
||||
@ -367,8 +372,9 @@ switch ($action) {
|
||||
$d->validity_unit = $validity_unit;
|
||||
$d->shared_users = $sharedusers;
|
||||
$d->pool_expired = $pool_expired;
|
||||
$d->list_expired = $list_expired;
|
||||
$d->enabled = $enabled;
|
||||
$d->allow_purchase = $allow_purchase;
|
||||
$d->prepaid = $prepaid;
|
||||
$d->save();
|
||||
|
||||
r2(U . 'services/hotspot', 's', Lang::T('Data Updated Successfully'));
|
||||
@ -443,7 +449,7 @@ switch ($action) {
|
||||
Mikrotik::removePpoePlan($client, $d['name_plan']);
|
||||
} catch (Exception $e) {
|
||||
//ignore exception, it means router has already deleted
|
||||
} catch(Throwable $e){
|
||||
} catch (Throwable $e) {
|
||||
//ignore exception, it means router has already deleted
|
||||
}
|
||||
}
|
||||
@ -463,8 +469,9 @@ switch ($action) {
|
||||
$routers = _post('routers');
|
||||
$pool = _post('pool_name');
|
||||
$pool_expired = _post('pool_expired');
|
||||
$list_expired = _post('list_expired');
|
||||
$enabled = _post('enabled');
|
||||
$allow_purchase = _post('allow_purchase');
|
||||
$prepaid = _post('prepaid');
|
||||
|
||||
|
||||
$msg = '';
|
||||
@ -506,6 +513,7 @@ switch ($action) {
|
||||
}
|
||||
$rate = $b['rate_up'] . $unitup . "/" . $b['rate_down'] . $unitdown;
|
||||
$radiusRate = $b['rate_up'] . $radup . '/' . $b['rate_down'] . $raddown;
|
||||
$rate = trim($rate . " " . $b['burst']);
|
||||
|
||||
$d = ORM::for_table('tbl_plans')->create();
|
||||
$d->type = 'PPPOE';
|
||||
@ -521,10 +529,11 @@ switch ($action) {
|
||||
} else {
|
||||
$d->is_radius = 0;
|
||||
$d->routers = $routers;
|
||||
$d->pool_expired = $pool_expired;
|
||||
}
|
||||
$d->pool_expired = $pool_expired;
|
||||
$d->list_expired = $list_expired;
|
||||
$d->enabled = $enabled;
|
||||
$d->allow_purchase = $allow_purchase;
|
||||
$d->prepaid = $prepaid;
|
||||
$d->save();
|
||||
$plan_id = $d->id();
|
||||
|
||||
@ -555,8 +564,9 @@ switch ($action) {
|
||||
$routers = _post('routers');
|
||||
$pool = _post('pool_name');
|
||||
$pool_expired = _post('pool_expired');
|
||||
$list_expired = _post('list_expired');
|
||||
$enabled = _post('enabled');
|
||||
$allow_purchase = _post('allow_purchase');
|
||||
$prepaid = _post('prepaid');
|
||||
|
||||
$msg = '';
|
||||
if (Validator::UnsignedNumber($validity) == false) {
|
||||
@ -593,6 +603,7 @@ switch ($action) {
|
||||
}
|
||||
$rate = $b['rate_up'] . $unitup . "/" . $b['rate_down'] . $unitdown;
|
||||
$radiusRate = $b['rate_up'] . $radup . '/' . $b['rate_down'] . $raddown;
|
||||
$rate = trim($rate . " " . $b['burst']);
|
||||
|
||||
if ($d['is_radius']) {
|
||||
Radius::planUpSert($id, $radiusRate, $pool);
|
||||
@ -613,8 +624,9 @@ switch ($action) {
|
||||
$d->routers = $routers;
|
||||
$d->pool = $pool;
|
||||
$d->pool_expired = $pool_expired;
|
||||
$d->list_expired = $list_expired;
|
||||
$d->enabled = $enabled;
|
||||
$d->allow_purchase = $allow_purchase;
|
||||
$d->prepaid = $prepaid;
|
||||
$d->save();
|
||||
|
||||
r2(U . 'services/pppoe', 's', Lang::T('Data Updated Successfully'));
|
||||
@ -666,7 +678,7 @@ switch ($action) {
|
||||
$name = _post('name');
|
||||
$price = _post('price');
|
||||
$enabled = _post('enabled');
|
||||
$allow_purchase = _post('allow_purchase');
|
||||
$prepaid = _post('prepaid');
|
||||
|
||||
$msg = '';
|
||||
if (Validator::UnsignedNumber($price) == false) {
|
||||
@ -686,7 +698,7 @@ switch ($action) {
|
||||
$d->name_plan = $name;
|
||||
$d->price = $price;
|
||||
$d->enabled = $enabled;
|
||||
$d->allow_purchase = $allow_purchase;
|
||||
$d->prepaid = 'yes';
|
||||
$d->save();
|
||||
|
||||
r2(U . 'services/balance', 's', Lang::T('Data Updated Successfully'));
|
||||
@ -698,7 +710,6 @@ switch ($action) {
|
||||
$name = _post('name');
|
||||
$price = _post('price');
|
||||
$enabled = _post('enabled');
|
||||
$allow_purchase = _post('allow_purchase');
|
||||
|
||||
$msg = '';
|
||||
if (Validator::UnsignedNumber($price) == false) {
|
||||
@ -724,7 +735,7 @@ switch ($action) {
|
||||
$d->routers = '';
|
||||
$d->pool = '';
|
||||
$d->enabled = $enabled;
|
||||
$d->allow_purchase = $allow_purchase;
|
||||
$d->prepaid = 'yes';
|
||||
$d->save();
|
||||
|
||||
r2(U . 'services/balance', 's', Lang::T('Data Created Successfully'));
|
||||
|
@ -9,13 +9,12 @@ $ui->assign('_title', Lang::T('Settings'));
|
||||
$ui->assign('_system_menu', 'settings');
|
||||
|
||||
$action = $routes['1'];
|
||||
$admin = Admin::_info();
|
||||
$ui->assign('_admin', $admin);
|
||||
|
||||
switch ($action) {
|
||||
case 'app':
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) {
|
||||
r2(U . "dashboard", 'e', Lang::T('You do not have permission to access this page'));
|
||||
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
|
||||
}
|
||||
|
||||
if (!empty(_get('testWa'))) {
|
||||
@ -31,15 +30,16 @@ switch ($action) {
|
||||
r2(U . "settings/app", 's', 'Test Telegram has been send<br>Result: ' . $result);
|
||||
}
|
||||
|
||||
if (file_exists('system/uploads/logo.png')) {
|
||||
$logo = 'system/uploads/logo.png?' . time();
|
||||
$UPLOAD_URL_PATH = str_replace($root_path,'', $UPLOAD_PATH);
|
||||
if (file_exists($UPLOAD_PATH . DIRECTORY_SEPARATOR . 'logo.png')) {
|
||||
$logo = $UPLOAD_URL_PATH . DIRECTORY_SEPARATOR . 'logo.png?' . time();
|
||||
} else {
|
||||
$logo = 'system/uploads/logo.default.png';
|
||||
$logo = $UPLOAD_URL_PATH . DIRECTORY_SEPARATOR . 'logo.default.png';
|
||||
}
|
||||
$ui->assign('logo', $logo);
|
||||
if ($_c['radius_enable'] && empty($_c['radius_client'])) {
|
||||
if ($config['radius_enable'] && empty($config['radius_client'])) {
|
||||
try {
|
||||
$_c['radius_client'] = Radius::getClient();
|
||||
$config['radius_client'] = Radius::getClient();
|
||||
$ui->assign('_c', $_c);
|
||||
} catch (Exception $e) {
|
||||
//ignore
|
||||
@ -84,14 +84,17 @@ switch ($action) {
|
||||
break;
|
||||
|
||||
case 'app-post':
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) {
|
||||
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
|
||||
}
|
||||
$company = _post('CompanyName');
|
||||
run_hook('save_settings'); #HOOK
|
||||
|
||||
|
||||
if (!empty($_FILES['logo']['name'])) {
|
||||
if (function_exists('imagecreatetruecolor')) {
|
||||
if (file_exists('system/uploads/logo.png')) unlink('system/uploads/logo.png');
|
||||
File::resizeCropImage($_FILES['logo']['tmp_name'], 'system/uploads/logo.png', 1078, 200, 100);
|
||||
if (file_exists($UPLOAD_PATH . DIRECTORY_SEPARATOR . 'logo.png')) unlink($UPLOAD_PATH . DIRECTORY_SEPARATOR . 'logo.png');
|
||||
File::resizeCropImage($_FILES['logo']['tmp_name'], $UPLOAD_PATH . DIRECTORY_SEPARATOR . 'logo.png', 1078, 200, 100);
|
||||
if (file_exists($_FILES['logo']['tmp_name'])) unlink($_FILES['logo']['tmp_name']);
|
||||
} else {
|
||||
r2(U . 'settings/app', 'e', 'PHP GD is not installed');
|
||||
@ -151,7 +154,7 @@ switch ($action) {
|
||||
|
||||
case 'localisation':
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) {
|
||||
r2(U . "dashboard", 'e', Lang::T('You do not have permission to access this page'));
|
||||
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
|
||||
}
|
||||
$folders = [];
|
||||
$files = scandir('system/lan/');
|
||||
@ -177,6 +180,9 @@ switch ($action) {
|
||||
break;
|
||||
|
||||
case 'localisation-post':
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) {
|
||||
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
|
||||
}
|
||||
$tzone = _post('tzone');
|
||||
$date_format = _post('date_format');
|
||||
$country_code_phone = _post('country_code_phone');
|
||||
@ -265,7 +271,7 @@ switch ($action) {
|
||||
|
||||
case 'users':
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin', 'Agent'])) {
|
||||
r2(U . "dashboard", 'e', Lang::T('You do not have permission to access this page'));
|
||||
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
|
||||
}
|
||||
$search = _req('search');
|
||||
if ($search != '') {
|
||||
@ -280,14 +286,16 @@ switch ($action) {
|
||||
'username' => '%' . $search . '%',
|
||||
['user_type' => 'Report'],
|
||||
['user_type' => 'Agent'],
|
||||
['user_type' => 'Sales']
|
||||
['user_type' => 'Sales'],
|
||||
['id' => $admin['id']]
|
||||
], $search);
|
||||
$d = ORM::for_table('tbl_users')
|
||||
->where_like('username', '%' . $search . '%')
|
||||
->where_any_is([
|
||||
['user_type' => 'Report'],
|
||||
['user_type' => 'Agent'],
|
||||
['user_type' => 'Sales']
|
||||
['user_type' => 'Sales'],
|
||||
['id' => $admin['id']]
|
||||
])
|
||||
->offset($paginator['startpoint'])
|
||||
->limit($paginator['limit'])->order_by_asc('id')->findArray();
|
||||
@ -311,7 +319,8 @@ switch ($action) {
|
||||
$d = ORM::for_table('tbl_users')->where_any_is([
|
||||
['user_type' => 'Report'],
|
||||
['user_type' => 'Agent'],
|
||||
['user_type' => 'Sales']
|
||||
['user_type' => 'Sales'],
|
||||
['id' => $admin['id']]
|
||||
])->offset($paginator['startpoint'])->limit($paginator['limit'])->order_by_asc('id')->findArray();
|
||||
} else {
|
||||
$paginator = Paginator::build(ORM::for_table('tbl_users'));
|
||||
@ -352,7 +361,7 @@ switch ($action) {
|
||||
|
||||
case 'users-add':
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin', 'Agent'])) {
|
||||
r2(U . "dashboard", 'e', Lang::T('You do not have permission to access this page'));
|
||||
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
|
||||
}
|
||||
$ui->assign('_title', Lang::T('Add User'));
|
||||
$ui->assign('agents', ORM::for_table('tbl_users')->where('user_type', 'Agent')->find_many());
|
||||
@ -384,7 +393,7 @@ switch ($action) {
|
||||
if ($isApi) {
|
||||
unset($d['password']);
|
||||
$agent = $ui->get('agent');
|
||||
if($agent) unset($agent['password']);
|
||||
if ($agent) unset($agent['password']);
|
||||
showResult(true, $action, [
|
||||
'admin' => $d,
|
||||
'agent' => $agent
|
||||
@ -399,7 +408,7 @@ switch ($action) {
|
||||
break;
|
||||
case 'users-edit':
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin', 'Agent'])) {
|
||||
r2(U . "dashboard", 'e', Lang::T('You do not have permission to access this page'));
|
||||
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
|
||||
}
|
||||
$ui->assign('_title', Lang::T('Edit User'));
|
||||
$id = $routes['2'];
|
||||
@ -437,7 +446,7 @@ switch ($action) {
|
||||
|
||||
case 'users-delete':
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) {
|
||||
r2(U . "dashboard", 'e', Lang::T('You do not have permission to access this page'));
|
||||
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
|
||||
}
|
||||
|
||||
$id = $routes['2'];
|
||||
@ -455,6 +464,9 @@ switch ($action) {
|
||||
break;
|
||||
|
||||
case 'users-post':
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin', 'Agent'])) {
|
||||
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
|
||||
}
|
||||
$username = _post('username');
|
||||
$fullname = _post('fullname');
|
||||
$password = _post('password');
|
||||
@ -484,11 +496,11 @@ switch ($action) {
|
||||
$date_now = date("Y-m-d H:i:s");
|
||||
run_hook('add_admin'); #HOOK
|
||||
if ($msg == '') {
|
||||
$password = Password::_crypt($password);
|
||||
$passwordC = Password::_crypt($password);
|
||||
$d = ORM::for_table('tbl_users')->create();
|
||||
$d->username = $username;
|
||||
$d->fullname = $fullname;
|
||||
$d->password = $password;
|
||||
$d->password = $passwordC;
|
||||
$d->user_type = $user_type;
|
||||
$d->phone = $phone;
|
||||
$d->email = $email;
|
||||
@ -591,7 +603,9 @@ switch ($action) {
|
||||
$d->city = $city;
|
||||
$d->subdistrict = $subdistrict;
|
||||
$d->ward = $ward;
|
||||
$d->status = $status;
|
||||
if (isset($_POST['status'])) {
|
||||
$d->status = $status;
|
||||
}
|
||||
|
||||
if ($admin['user_type'] == 'Agent') {
|
||||
// Prevent hacking from form
|
||||
@ -652,24 +666,27 @@ switch ($action) {
|
||||
|
||||
case 'notifications':
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) {
|
||||
r2(U . "dashboard", 'e', Lang::T('You do not have permission to access this page'));
|
||||
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
|
||||
}
|
||||
run_hook('view_notifications'); #HOOK
|
||||
if (file_exists("system/uploads/notifications.json")) {
|
||||
$ui->assign('_json', json_decode(file_get_contents('system/uploads/notifications.json'), true));
|
||||
if (file_exists($UPLOAD_PATH . DIRECTORY_SEPARATOR . "notifications.json")) {
|
||||
$ui->assign('_json', json_decode(file_get_contents($UPLOAD_PATH . DIRECTORY_SEPARATOR . 'notifications.json'), true));
|
||||
} else {
|
||||
$ui->assign('_json', json_decode(file_get_contents('system/uploads/notifications.default.json'), true));
|
||||
$ui->assign('_json', json_decode(file_get_contents($UPLOAD_PATH . DIRECTORY_SEPARATOR . 'notifications.default.json'), true));
|
||||
}
|
||||
$ui->assign('_default', json_decode(file_get_contents('system/uploads/notifications.default.json'), true));
|
||||
$ui->assign('_default', json_decode(file_get_contents($UPLOAD_PATH . DIRECTORY_SEPARATOR . 'notifications.default.json'), true));
|
||||
$ui->display('app-notifications.tpl');
|
||||
break;
|
||||
case 'notifications-post':
|
||||
file_put_contents("system/uploads/notifications.json", json_encode($_POST));
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) {
|
||||
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
|
||||
}
|
||||
file_put_contents($UPLOAD_PATH . "/notifications.json", json_encode($_POST));
|
||||
r2(U . 'settings/notifications', 's', Lang::T('Settings Saved Successfully'));
|
||||
break;
|
||||
case 'dbstatus':
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) {
|
||||
r2(U . "dashboard", 'e', Lang::T('You do not have permission to access this page'));
|
||||
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
|
||||
}
|
||||
|
||||
$dbc = new mysqli($db_host, $db_user, $db_password, $db_name);
|
||||
@ -686,8 +703,8 @@ switch ($action) {
|
||||
break;
|
||||
|
||||
case 'dbbackup':
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) {
|
||||
r2(U . "dashboard", 'e', Lang::T('You do not have permission to access this page'));
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin'])) {
|
||||
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
|
||||
}
|
||||
$tables = $_POST['tables'];
|
||||
set_time_limit(-1);
|
||||
@ -706,8 +723,8 @@ switch ($action) {
|
||||
echo json_encode($array);
|
||||
break;
|
||||
case 'dbrestore':
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) {
|
||||
r2(U . "dashboard", 'e', Lang::T('You do not have permission to access this page'));
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin'])) {
|
||||
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
|
||||
}
|
||||
if (file_exists($_FILES['json']['tmp_name'])) {
|
||||
$suc = 0;
|
||||
@ -737,7 +754,7 @@ switch ($action) {
|
||||
break;
|
||||
case 'language':
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) {
|
||||
r2(U . "dashboard", 'e', Lang::T('You do not have permission to access this page'));
|
||||
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
|
||||
}
|
||||
run_hook('view_add_language'); #HOOK
|
||||
if (file_exists($lan_file)) {
|
||||
|
@ -49,7 +49,19 @@ switch ($action) {
|
||||
$ui->display('user-activation-list.tpl');
|
||||
|
||||
break;
|
||||
|
||||
case 'invoice':
|
||||
$id = $routes[2];
|
||||
if(empty($id)){
|
||||
$in = ORM::for_table('tbl_transactions')->where('username', $user['username'])->order_by_desc('id')->find_one();
|
||||
}else{
|
||||
$in = ORM::for_table('tbl_transactions')->where('username', $user['username'])->where('id', $id)->find_one();
|
||||
}
|
||||
if($in){
|
||||
Package::createInvoice($in);
|
||||
$ui->display('invoice-customer.tpl');
|
||||
}else{
|
||||
r2(U . 'voucher/list-activated', 'e', Lang::T('Not Found'));
|
||||
}
|
||||
default:
|
||||
$ui->display('a404.tpl');
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ echo "Found " . count($d) . " user(s)\n";
|
||||
run_hook('cronjob'); #HOOK
|
||||
|
||||
foreach ($d as $ds) {
|
||||
if ($ds['type'] == 'Hotspot') {
|
||||
if ($ds['type'] == 'Hotspot') { # HOTSPOT
|
||||
$date_now = strtotime(date("Y-m-d H:i:s"));
|
||||
$expiration = strtotime($ds['expiration'] . ' ' . $ds['time']);
|
||||
echo $ds['expiration'] . " : " . (($isCli) ? $ds['username'] : Lang::maskText($ds['username']));
|
||||
@ -46,19 +46,28 @@ foreach ($d as $ds) {
|
||||
$client = Mikrotik::getClient($m['ip_address'], $m['username'], $m['password']);
|
||||
if (!empty($p['pool_expired'])) {
|
||||
Mikrotik::setHotspotUserPackage($client, $c['username'], 'EXPIRED NUXBILL ' . $p['pool_expired']);
|
||||
// }if (!empty($p['list_expired'])) {
|
||||
// $ip = Mikrotik::getIpHotspotUser($client, $ds['username']);
|
||||
// Mikrotik::addIpToAddressList($client, $ip, $p['list_expired'], $c['username']);
|
||||
} else {
|
||||
Mikrotik::removeHotspotUser($client, $c['username']);
|
||||
}
|
||||
Mikrotik::removeHotspotActiveUser($client, $c['username']);
|
||||
}
|
||||
echo Message::sendPackageNotification($c['phonenumber'], $c['fullname'], $u['namebp'], $price, $textExpired, $config['user_notification_expired'])."\n";
|
||||
echo Message::sendPackageNotification($c, $u['namebp'], $price, $textExpired, $config['user_notification_expired']) . "\n";
|
||||
//update database user dengan status off
|
||||
$u->status = 'off';
|
||||
$u->save();
|
||||
|
||||
// autorenewal from deposit
|
||||
if ($config['enable_balance'] == 'yes' && $c['auto_renewal']) {
|
||||
if ($p && $p['enabled'] && $c['balance'] >= $p['price'] && $p['allow_purchase'] == 'yes') {
|
||||
list($bills, $add_cost) = User::getBills($ds['customer_id']);
|
||||
if ($add_cost > 0) {
|
||||
if (!empty($add_cost)) {
|
||||
$p['price'] += $add_cost;
|
||||
}
|
||||
}
|
||||
if ($p && $p['enabled'] && $c['balance'] >= $p['price']) {
|
||||
if (Package::rechargeUser($ds['customer_id'], $p['routers'], $p['id'], 'Customer', 'Balance')) {
|
||||
// if success, then get the balance
|
||||
Balance::min($ds['customer_id'], $p['price']);
|
||||
@ -79,7 +88,7 @@ foreach ($d as $ds) {
|
||||
}
|
||||
} else
|
||||
echo " : ACTIVE \r\n";
|
||||
} else {
|
||||
} else { # PPPOE
|
||||
$date_now = strtotime(date("Y-m-d H:i:s"));
|
||||
$expiration = strtotime($ds['expiration'] . ' ' . $ds['time']);
|
||||
echo $ds['expiration'] . " : " . (($isCli) ? $ds['username'] : Lang::maskText($ds['username']));
|
||||
@ -106,14 +115,20 @@ foreach ($d as $ds) {
|
||||
}
|
||||
Mikrotik::removePpoeActive($client, $c['username']);
|
||||
}
|
||||
echo Message::sendPackageNotification($c['phonenumber'], $c['fullname'], $u['namebp'], $price, $textExpired, $config['user_notification_expired'])."\n";
|
||||
echo Message::sendPackageNotification($c, $u['namebp'], $price, $textExpired, $config['user_notification_expired']) . "\n";
|
||||
|
||||
$u->status = 'off';
|
||||
$u->save();
|
||||
|
||||
// autorenewal from deposit
|
||||
if ($config['enable_balance'] == 'yes' && $c['auto_renewal']) {
|
||||
if ($p && $p['enabled'] && $c['balance'] >= $p['price'] && $p['allow_purchase'] == 'yes') {
|
||||
list($bills, $add_cost) = User::getBills($ds['customer_id']);
|
||||
if ($add_cost > 0) {
|
||||
if (!empty($add_cost)) {
|
||||
$p['price'] += $add_cost;
|
||||
}
|
||||
}
|
||||
if ($p && $p['enabled'] && $c['balance'] >= $p['price']) {
|
||||
if (Package::rechargeUser($ds['customer_id'], $p['routers'], $p['id'], 'Customer', 'Balance')) {
|
||||
// if success, then get the balance
|
||||
Balance::min($ds['customer_id'], $p['price']);
|
||||
|
@ -38,13 +38,30 @@ foreach ($d as $ds) {
|
||||
$u = ORM::for_table('tbl_user_recharges')->where('id', $ds['id'])->find_one();
|
||||
$p = ORM::for_table('tbl_plans')->where('id', $u['plan_id'])->find_one();
|
||||
$c = ORM::for_table('tbl_customers')->where('id', $ds['customer_id'])->find_one();
|
||||
$price = Lang::moneyFormat($p['price']);
|
||||
list($bills, $add_cost) = User::getBills($ds['customer_id']);
|
||||
if ($add_cost > 0) {
|
||||
if (!empty($add_cost)) {
|
||||
$p['price'] += $add_cost;
|
||||
}
|
||||
}
|
||||
if ($p['validity_unit'] == 'Period') {
|
||||
// Postpaid price from field
|
||||
$add_inv = User::getAttribute("Invoice", $ds['customer_id']);
|
||||
if (empty ($add_inv) or $add_inv == 0) {
|
||||
$price = Lang::moneyFormat($p['price']);
|
||||
} else {
|
||||
$price = Lang::moneyFormat($add_inv);
|
||||
}
|
||||
} else {
|
||||
$price = Lang::moneyFormat($p['price']);
|
||||
}
|
||||
//$price = Lang::moneyFormat($p['price']);
|
||||
if ($ds['expiration'] == $day7) {
|
||||
echo Message::sendPackageNotification($c['phonenumber'], $c['fullname'], $p['name_plan'], $price, Lang::getNotifText('reminder_7_day'), $config['user_notification_reminder']) . "\n";
|
||||
echo Message::sendPackageNotification($c, $p['name_plan'], $price, Lang::getNotifText('reminder_7_day'), $config['user_notification_reminder']) . "\n";
|
||||
} else if ($ds['expiration'] == $day3) {
|
||||
echo Message::sendPackageNotification($c['phonenumber'], $c['fullname'], $p['name_plan'], $price, Lang::getNotifText('reminder_3_day'), $config['user_notification_reminder']) . "\n";
|
||||
echo Message::sendPackageNotification($c, $p['name_plan'], $price, Lang::getNotifText('reminder_3_day'), $config['user_notification_reminder']) . "\n";
|
||||
} else if ($ds['expiration'] == $day1) {
|
||||
echo Message::sendPackageNotification($c['phonenumber'], $c['fullname'], $p['name_plan'], $price, Lang::getNotifText('reminder_1_day'), $config['user_notification_reminder']) . "\n";
|
||||
echo Message::sendPackageNotification($c, $p['name_plan'], $price, Lang::getNotifText('reminder_1_day'), $config['user_notification_reminder']) . "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -100,9 +100,6 @@
|
||||
"Add_Pool": "Add Pool",
|
||||
"Edit_Pool": "Edit Pool",
|
||||
"Pool_Name_Already_Exist": "Pool Name Already Exist",
|
||||
"Prepaid": "Prepaid",
|
||||
"Prepaid_Users": "Prepaid Users",
|
||||
"Prepaid_Vouchers": "Prepaid Vouchers",
|
||||
"Refill_Account": "Refill Account",
|
||||
"Recharge_Account": "Recharge Account",
|
||||
"Select_Account": "Select Account",
|
||||
@ -384,7 +381,6 @@
|
||||
"After_Customer_activate_voucher_or_login__customer_will_be_redirected_to_this_url": "After Customer activate voucher or login, customer will be redirected to this url",
|
||||
"Voucher_Prefix": "Voucher Prefix",
|
||||
"Voucher_activation_success__now_you_can_login": "Voucher activation success, now you can login",
|
||||
"Client_Can_Purchase": "Client Can Purchase",
|
||||
"Buy_this__your_active_package_will_be_overwritten": "Buy this? your active package will be overwritten",
|
||||
"Pay_this_with_Balance__your_active_package_will_be_overwritten": "Pay this with Balance? your active package will be overwritten",
|
||||
"Buy_this__your_active_package_will_be_overwrite": "Buy this? your active package will be overwrite",
|
||||
@ -413,5 +409,108 @@
|
||||
"Ward": "Ward",
|
||||
"Credentials": "Credentials",
|
||||
"Agent": "Agent",
|
||||
"This_Token_will_act_as_SuperAdmin_Admin": "This Token will act as SuperAdmin\/Admin"
|
||||
"This_Token_will_act_as_SuperAdmin_Admin": "This Token will act as SuperAdmin\/Admin",
|
||||
"Login": "Login",
|
||||
"Expired_Action": "Expired Action",
|
||||
"Expired_Address_List_Name": "Expired Address List Name",
|
||||
"Address_List": "Address List",
|
||||
"Optional": "Optional",
|
||||
"Generated_By": "Generated By",
|
||||
"Admin": "Admin",
|
||||
"Password_should_be_minimum_6_characters": "Password should be minimum 6 characters",
|
||||
"Add_User": "Add User",
|
||||
"Send_Notification": "Send Notification",
|
||||
"Code": "Code",
|
||||
"Send_To_Customer": "Send To Customer",
|
||||
"Prev": "Prev",
|
||||
"Voucher_Not_Found": "Voucher Not Found",
|
||||
"Miscellaneous": "Miscellaneous",
|
||||
"OTP_Required": "OTP Required",
|
||||
"Change": "Change",
|
||||
"Change_Phone_Number": "Change Phone Number",
|
||||
"Current_Number": "Current Number",
|
||||
"New_Number": "New Number",
|
||||
"Input_your_phone_number": "Input your phone number",
|
||||
"OTP": "OTP",
|
||||
"Enter_OTP_that_was_sent_to_your_phone": "Enter OTP that was sent to your phone",
|
||||
"Update": "Update",
|
||||
"OTP_is_required_when_user_want_to_change_phone_number": "OTP is required when user want to change phone number",
|
||||
"Rate": "Rate",
|
||||
"Burst": "Burst",
|
||||
"Editing_Bandwidth_will_not_automatically_update_the_plan__you_need_to_edit_the_plan_then_save_again": "Editing Bandwidth will not automatically update the plan, you need to edit the plan then save again",
|
||||
"OTP_Method": "OTP Method",
|
||||
"SMS": "SMS",
|
||||
"WhatsApp": "WhatsApp",
|
||||
"SMS_and_WhatsApp": "SMS and WhatsApp",
|
||||
"The_method_which_OTP_will_be_sent_to_user": "The method which OTP will be sent to user",
|
||||
"Report_Viewer": "Report Viewer",
|
||||
"Super_Administrator": "Super Administrator",
|
||||
"Send_To": "Send To",
|
||||
"Resend": "Resend",
|
||||
"Alert": "Alert",
|
||||
"success": "success",
|
||||
"Click_Here": "Click Here",
|
||||
"danger": "danger",
|
||||
"Logout_Successful": "Logout Successful",
|
||||
"warning": "warning",
|
||||
"Users_Announcement": "Users Announcement",
|
||||
"Customer_Announcement": "Customer Announcement",
|
||||
"1_Period___1_Month__Expires_the_20th_of_each_month": "1 Period = 1 Month, Expires the 20th of each month",
|
||||
"Period": "Period",
|
||||
"Add": "Add",
|
||||
"Select_Payment_Gateway": "Select Payment Gateway",
|
||||
"Available_Payment_Gateway": "Available Payment Gateway",
|
||||
"Pay_Now": "Pay Now",
|
||||
"Please_select_Payment_Gateway": "Please select Payment Gateway",
|
||||
"Payment_Gateway_Deleted": "Payment Gateway Deleted",
|
||||
"Payment_Gateway_not_set__please_set_it_in_Settings": "Payment Gateway not set, please set it in Settings",
|
||||
"Failed_to_create_Transaction__": "Failed to create Transaction..",
|
||||
"Show_To_Customer": "Type",
|
||||
"Using": "Using",
|
||||
"Default": "Default",
|
||||
"Customer_Balance": "Customer Balance",
|
||||
"Vouchers": "Vouchers",
|
||||
"Refill_Customer": "Refill Customer",
|
||||
"Recharge_Customer": "Recharge Customer",
|
||||
"Plans": "Plans",
|
||||
"PPPOE": "PPPOE",
|
||||
"Bandwidth": "Bandwidth",
|
||||
"Customers": "Customers",
|
||||
"Actives": "Actives",
|
||||
"Name": "Name",
|
||||
"Confirm": "Confirm",
|
||||
"Plan": "Plan",
|
||||
"Total": "Total",
|
||||
"Current_Cycle": "Current Cycle",
|
||||
"Additional_Cost": "Additional Cost",
|
||||
"Remaining": "Remaining",
|
||||
"": "",
|
||||
"Not_Found": "Not Found",
|
||||
"Cash": "Cash",
|
||||
"Payment_not_found": "Payment not found",
|
||||
"If_your_friend_have_Additional_Cost__you_will_pay_for_that_too": "If your friend have Additional Cost, you will pay for that too",
|
||||
"Cache_cleared_successfully_": "Cache cleared successfully!",
|
||||
"Paid": "Paid",
|
||||
"Send_Message": "Send Message",
|
||||
"Send_SMS_WA_Message": "Send SMS\/WA Message",
|
||||
"Send_Bulk_SMS_WA_Message": "Send Bulk SMS\/WA Message",
|
||||
"Send_Personal_Message": "Send Personal Message",
|
||||
"Send_Via": "Send Via",
|
||||
"Compose_your_message___": "Compose your message...",
|
||||
"Use_placeholders_": "Use placeholders:",
|
||||
"__name__": "[[name]]",
|
||||
"Customer_Name": "Customer Name",
|
||||
"__user_name__": "[[user_name]]",
|
||||
"Customer_Username": "Customer Username",
|
||||
"__phone__": "[[phone]]",
|
||||
"Customer_Phone": "Customer Phone",
|
||||
"__company_name__": "[[company_name]]",
|
||||
"Your_Company_Name": "Your Company Name",
|
||||
"Message_Sent_Successfully": "Message Sent Successfully",
|
||||
"Send_Bulk_Message": "Send Bulk Message",
|
||||
"Group": "Group",
|
||||
"All_Customers": "All Customers",
|
||||
"New_Customers": "New Customers",
|
||||
"Expired_Customers": "Expired Customers",
|
||||
"Active_Customers": "Active Customers"
|
||||
}
|
@ -100,9 +100,6 @@
|
||||
"Add_Pool": "Tambahkan Pool",
|
||||
"Edit_Pool": "Sunting Pool",
|
||||
"Pool_Name_Already_Exist": "Nama Pool Sudah Ada",
|
||||
"Prepaid": "Prabayar",
|
||||
"Prepaid_Users": "Pengguna Prabayar",
|
||||
"Prepaid_Vouchers": "Voucher Prabayar",
|
||||
"Refill_Account": "Isi Ulang Akun",
|
||||
"Recharge_Account": "Isi Ulang Akun",
|
||||
"Select_Account": "Pilih Akun",
|
||||
|
@ -100,9 +100,6 @@
|
||||
"Add_Pool": "Agregar Pool",
|
||||
"Edit_Pool": "Editar Pool",
|
||||
"Pool_Name_Already_Exist": "Nombre del Pool ya existe",
|
||||
"Prepaid": "Prepago",
|
||||
"Prepaid_Users": "Usuarios prepago",
|
||||
"Prepaid_Vouchers": "Fichas prepago",
|
||||
"Refill_Account": "Recargar Ficha",
|
||||
"Recharge_Account": "Recargar Cuenta",
|
||||
"Select_Account": "Seleccionar cuenta",
|
||||
|
@ -96,9 +96,6 @@
|
||||
"Add_Pool": "Havuz ekle",
|
||||
"Edit_Pool": "Havuzu D\u00fczenle",
|
||||
"Pool_Name_Already_Exist": "Havuz Ad\u0131 \u200b\u200bZaten Var",
|
||||
"Prepaid": "\u00d6n \u00d6demeli",
|
||||
"Prepaid_Users": "\u00d6n \u00d6demeli Kullan\u0131c\u0131lar",
|
||||
"Prepaid_Vouchers": "\u00d6n \u00d6demeli Kuponlar",
|
||||
"Refill_Account": "Hesab\u0131 Yenile",
|
||||
"Recharge_Account": "Hesab\u0131 Yeniden \u015earj Et",
|
||||
"Select_Account": "Hesap Se\u00e7",
|
||||
|
@ -58,5 +58,25 @@
|
||||
],
|
||||
"2024.2.19": [
|
||||
"CREATE TABLE `tbl_customers_fields` (`id` INT PRIMARY KEY AUTO_INCREMENT, `customer_id` INT NOT NULL, `field_name` VARCHAR(255) NOT NULL, `field_value` VARCHAR(255) NOT NULL, FOREIGN KEY (customer_id) REFERENCES tbl_customers(id));"
|
||||
],
|
||||
"2024.2.20" : [
|
||||
"ALTER TABLE `tbl_plans` ADD `list_expired` VARCHAR(32) NOT NULL DEFAULT '' COMMENT 'address list' AFTER `pool_expired`;",
|
||||
"ALTER TABLE `tbl_bandwidth` ADD `burst` VARCHAR(128) NOT NULL DEFAULT '' AFTER `rate_up_unit`;"
|
||||
],
|
||||
"2024.2.20.1" : [
|
||||
"DROP TABLE IF EXISTS `tbl_customers_meta`;"
|
||||
],
|
||||
"2024.2.23" : [
|
||||
"ALTER TABLE `tbl_transactions` ADD `admin_id` INT NOT NULL DEFAULT '1' AFTER `type`;",
|
||||
"ALTER TABLE `tbl_user_recharges` ADD `admin_id` INT NOT NULL DEFAULT '1' AFTER `type`;"
|
||||
],
|
||||
"2024.3.3" : [
|
||||
"ALTER TABLE `tbl_plans` CHANGE `validity_unit` `validity_unit` ENUM('Mins','Hrs','Days','Months','Period') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL;"
|
||||
],
|
||||
"2024.3.12" : [
|
||||
"ALTER TABLE `tbl_plans` CHANGE `allow_purchase` `prepaid` ENUM('yes','no') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT 'yes' COMMENT 'is prepaid';"
|
||||
],
|
||||
"2024.3.14" : [
|
||||
"ALTER TABLE `tbl_transactions` ADD `note` VARCHAR(256) NOT NULL DEFAULT '' COMMENT 'for note' AFTER `type`;"
|
||||
]
|
||||
}
|
53
system/vendor/mpdf/mpdf/.github/CONTRIBUTING.md
vendored
53
system/vendor/mpdf/mpdf/.github/CONTRIBUTING.md
vendored
@ -1,53 +0,0 @@
|
||||
Contributing
|
||||
============
|
||||
|
||||
Issue tracker
|
||||
-------------
|
||||
|
||||
The Issue tracker serves mainly as a place to report bugs and request new features.
|
||||
Please do not abuse it as a general questions or troubleshooting location.
|
||||
|
||||
General troubleshooting
|
||||
-------------
|
||||
|
||||
For these questions please use [Discussions](https://github.com/mpdf/mpdf/discussions). Add your enquiry
|
||||
to appropriate category and as always, include a reproducible code example when applicable (see code example guidelines below).
|
||||
|
||||
You can also use the [mpdf tag](https://stackoverflow.com/questions/tagged/mpdf)
|
||||
at [Stack Overflow](https://stackoverflow.com/)
|
||||
as the StackOverflow user base is more likely to answer you in a timely manner.
|
||||
When doing so, make sure you comply to StackOverflow question guidelines.
|
||||
|
||||
Bug reports
|
||||
-------------
|
||||
|
||||
* Bug reports **MUST** contain a small example in php/html that reproduces the bug.
|
||||
* The code example **MUST** be reproducible by copy&paste assuming composer dependencies are installed. That means:
|
||||
* No calling unrelated funcions,
|
||||
* an actual final HTML code has to be present, pasting a template file is not enough,
|
||||
* if the bug considers import or fonts, example source PDF/TTF/etc files have to be included.
|
||||
* Failing to provide necessary information or not using the issue template will cause the issue to be closed until required information is provided.
|
||||
* Please report one feature or one bug per issue.
|
||||
|
||||
Feature requests
|
||||
-------------
|
||||
|
||||
Feature requests have to be labeled as such and have to include reasoning for the change in question.
|
||||
|
||||
|
||||
Pull requests
|
||||
-------------
|
||||
|
||||
Pull requests should be always based on the default [development](https://github.com/mpdf/mpdf/tree/development)
|
||||
branch except for backports to older versions.
|
||||
|
||||
Guidelines:
|
||||
|
||||
* Use an aptly named feature branch for the Pull request.
|
||||
* Only files and lines affecting the scope of the Pull request must be affected.
|
||||
* Make small, *atomic* commits that keep the smallest possible related code changes together.
|
||||
* Code must be accompanied by a unit test testing expected behaviour whenever possible.
|
||||
* To be incorporated, the PR should contain a change in the CHANGELOG.md file describing itself
|
||||
|
||||
When updating a PR, do not create a new one, just `git push --force` to your former feature branch, the PR will
|
||||
update itself.
|
1
system/vendor/mpdf/mpdf/.github/FUNDING.yml
vendored
1
system/vendor/mpdf/mpdf/.github/FUNDING.yml
vendored
@ -1 +0,0 @@
|
||||
custom: https://www.paypal.me/mpdf
|
@ -1,35 +0,0 @@
|
||||
name: Bug report 🐛
|
||||
description: The library does not work as expected
|
||||
body:
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Guidelines
|
||||
description: Please confirm this is a bug report and not general troubleshooting.
|
||||
options:
|
||||
- label: I understand that [if I fail to provide all required details, this issue may be closed without review](https://github.com/mpdf/mpdf/blob/development/.github/CONTRIBUTING.md).
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Description of the bug
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: mPDF version
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: PHP Version and environment (server type, cli provider etc., enclosing libraries and their respective versions)
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Reproducible PHP+CSS+HTML snippet suffering by the error
|
||||
validations:
|
||||
required: true
|
@ -1,8 +0,0 @@
|
||||
name: Feature request 🚀
|
||||
description: I would like to have a new functionality added
|
||||
body:
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Please describe the new functionality as best as you can.
|
||||
validations:
|
||||
required: true
|
@ -1,8 +0,0 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: General questions and troubleshooting ❓
|
||||
url: https://github.com/mpdf/mpdf/discussions
|
||||
about: You can use Github Discussions for general questions and troubleshooting. Please note that asking at Stack Overflow will probably be more successful.
|
||||
- name: QA at Stack Overflow ❓
|
||||
url: https://stackoverflow.com/questions/tagged/mpdf
|
||||
about: Ask at Stack Overflow for a greater chance of a quick and correct answer to your questions. Make sure to comply to SO rules, terms and conditions.
|
6
system/vendor/mpdf/mpdf/.github/SECURITY.md
vendored
6
system/vendor/mpdf/mpdf/.github/SECURITY.md
vendored
@ -1,6 +0,0 @@
|
||||
How to disclose potential security issues
|
||||
============
|
||||
|
||||
As mPDF does not have a domain or a dedicated contact apart from its Github repository, to prevent
|
||||
disclosing maintainers' contacts publicly, please create an Issue about the security issue with means to contact you.
|
||||
We will reach out to you as soon as possible.
|
@ -1,42 +0,0 @@
|
||||
# https://help.github.com/en/categories/automating-your-workflow-with-github-actions
|
||||
|
||||
name: "Code coverage"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "development"
|
||||
- "coverage"
|
||||
|
||||
jobs:
|
||||
|
||||
coverage:
|
||||
|
||||
name: "Code coverage"
|
||||
|
||||
runs-on: ${{ matrix.operating-system }}
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
php-version:
|
||||
- "7.4"
|
||||
|
||||
operating-system: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- name: "Checkout"
|
||||
uses: "actions/checkout@v3"
|
||||
|
||||
- name: "Install PHP"
|
||||
uses: "shivammathur/setup-php@v2"
|
||||
with:
|
||||
coverage: "xdebug"
|
||||
php-version: "${{ matrix.php-version }}"
|
||||
extensions: "mbstring, gd, bcmath, bz2"
|
||||
tools: composer:v2
|
||||
|
||||
- name: "Install dependencies"
|
||||
run: "composer install --no-interaction --no-progress"
|
||||
|
||||
- name: "Code coverage"
|
||||
run: composer coverage
|
43
system/vendor/mpdf/mpdf/.github/workflows/cs.yml
vendored
43
system/vendor/mpdf/mpdf/.github/workflows/cs.yml
vendored
@ -1,43 +0,0 @@
|
||||
# https://help.github.com/en/categories/automating-your-workflow-with-github-actions
|
||||
|
||||
name: "Coding standard check"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- "development"
|
||||
- "test"
|
||||
|
||||
jobs:
|
||||
|
||||
cs:
|
||||
|
||||
name: "Coding standard"
|
||||
|
||||
runs-on: ${{ matrix.operating-system }}
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
php-version:
|
||||
- "7.4"
|
||||
|
||||
operating-system: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- name: "Checkout"
|
||||
uses: "actions/checkout@v3"
|
||||
|
||||
- name: "Install PHP"
|
||||
uses: "shivammathur/setup-php@v2"
|
||||
with:
|
||||
coverage: "none"
|
||||
php-version: "${{ matrix.php-version }}"
|
||||
extensions: "mbstring"
|
||||
tools: composer:v2
|
||||
|
||||
- name: "Install dependencies"
|
||||
run: "composer install --no-interaction --no-progress"
|
||||
|
||||
- name: "CS"
|
||||
run: composer cs
|
@ -1,53 +0,0 @@
|
||||
# https://help.github.com/en/categories/automating-your-workflow-with-github-actions
|
||||
|
||||
name: "CI"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
- "development"
|
||||
- "test"
|
||||
|
||||
jobs:
|
||||
|
||||
tests:
|
||||
|
||||
name: "Tests"
|
||||
|
||||
runs-on: ${{ matrix.operating-system }}
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
php-version:
|
||||
- "5.6"
|
||||
- "7.0"
|
||||
- "7.1"
|
||||
- "7.2"
|
||||
- "7.3"
|
||||
- "7.4"
|
||||
- "8.0"
|
||||
- "8.1"
|
||||
- "8.2"
|
||||
operating-system: [ubuntu-latest, windows-latest]
|
||||
|
||||
steps:
|
||||
- name: "Checkout"
|
||||
uses: "actions/checkout@v3"
|
||||
|
||||
- name: "Install PHP"
|
||||
uses: "shivammathur/setup-php@v2"
|
||||
with:
|
||||
coverage: "none"
|
||||
php-version: "${{ matrix.php-version }}"
|
||||
extensions: "mbstring, gd, bcmath, bz2"
|
||||
tools: composer:v2
|
||||
ini-values: error_reporting=-1
|
||||
|
||||
- name: "Install dependencies"
|
||||
run: "composer install --no-interaction --no-progress"
|
||||
|
||||
- name: "Tests"
|
||||
run: composer test
|
2
system/vendor/mpdf/mpdf/.gitignore
vendored
2
system/vendor/mpdf/mpdf/.gitignore
vendored
@ -1,2 +0,0 @@
|
||||
vendor/*
|
||||
composer.lock
|
786
system/vendor/mpdf/mpdf/CHANGELOG.md
vendored
786
system/vendor/mpdf/mpdf/CHANGELOG.md
vendored
@ -1,786 +0,0 @@
|
||||
mPDF 8.1.x
|
||||
===========================
|
||||
|
||||
New features
|
||||
------------
|
||||
|
||||
* Service container for internal services
|
||||
* Set /Lang entry for better accessibility when document language is available (@cuongmits, #1418)
|
||||
* More verbose helper methods for `Output`: `OutputBinaryData`, `OutputHttpInline`, `OutputHttpDownload`, `OutputFile` (since v8.1.2)
|
||||
* Set font-size to `auto` in textarea and input in active forms to resize the font-size (@ChrisB9, #1721)
|
||||
* PHP 8.2 support in mPDF 8.1.3
|
||||
* Added support for `psr/log` v3 without dropping v2. (@markdorison, @apotek, @greg-1-anderson, #1857)
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
* Better exception message about fonts with MarkGlyphSets (Fix for #1408)
|
||||
* Updated Garuda font with fixed "k" character (Fix for #1440)
|
||||
* Testing and suppressing PNG file conversion errors
|
||||
* Prevent hyphenation of urls starting with https and e-mail addresses (@HKandulla, #1634)
|
||||
* Colorspace restrictor reads mode from Mpdf and works again (Fix for #1094)
|
||||
* Prevent exception when multiple columns wrap to next page
|
||||
* Update default `curlUserAgent` configuration variable from Firefox 13 to 108
|
||||
|
||||
mPDF 8.0.x
|
||||
===========================
|
||||
|
||||
* Ability to customize User-Agent header in the HTTP requests sent by cURL (@samuelecat, #1229)
|
||||
* Add Page Number Myanmar Language Support (@MinKyawNyunt, #1201)
|
||||
* new `Mpdf\Exception\FontException` extending base `MpdfException` was introduced and is thrown on Font manipulation
|
||||
* A bit cleaner exception messages for font-related errors
|
||||
* Use atomic cache writing. (@PATROMO, #1186)
|
||||
* Fix: "Undefined index: group" when calling MultiCell when using font without OTL data (@Kekos, #1213, #941)
|
||||
* Add C128RAW barcode type to create any barcode (ex: subtype change in middle of barcode) (#1124)
|
||||
* Add proxy support to curl
|
||||
* Fixed date and time format in the informations dictionary (#1083, @peterdevpl)
|
||||
* Checking allowed stream wrappers in CssManager
|
||||
* PHP 7.4 support (until final 7.4 release with composer --ignore-platform-reqs)
|
||||
* Improve debugging of remote content issues (@ribeirobreno)
|
||||
* Added `exposeVersion` configuration variable allowing to hide mPDF version from Producer tag and HTTP headers
|
||||
* Added the check for JPEG SOF header 0xFF 0xC1 (extended) (@jamiejones85)
|
||||
* Allows setting `none` as zoom mode in `SetDisplayMode` method, so that OpenAction is not written (#602)
|
||||
* Allowed image stream whitelist to be customised (#1005, thanks @jakejackson)
|
||||
* Fixed parsing of top-left-bottom-right CSS rules with !important (#1009)
|
||||
* Fixed skipping ordered list numbering with page-break-inside: avoid (#339)
|
||||
* Compound classes selector support, like `.one.two` or `div.message.special` (#538, @peterdevpl)
|
||||
* Fixed CMYK colors in text-shadow (#1115, @lexilya)
|
||||
* Skip non supported wrappers when resolving paths (#1204, @MarkVaughn)
|
||||
* Fixed SVGs using a style tag, has styles ignored ( Requires ext-dom ) (#450, @antman3351)
|
||||
* Allows `{nb}`, `{nbpg}`, `{PAGENO}` and `{DATE ...}` substitution in body (#172 and #267, @Dasc3er)
|
||||
* Cache now creates a dedicated subdirectory `/mpdf`.
|
||||
* It is possible to disable automatic cache cleanup with `cacheCleanupInterval` config variable
|
||||
* PHP 8.0 is supported since 8.0.10 (#1263)
|
||||
* Fix: First header of named page is added twice (@antman3351, #1320)
|
||||
* Added `curlExecutionTimeout` configuration variable allowing to `CURLOPT_TIMEOUT` when fetching remote content
|
||||
* Fix: Not all combinations were generated for more than three compound classes (@JeppeKnockaert)
|
||||
* Added `quiet_zone_left` and `quiet_zone_right` to barcodes which support quiet zones in order to customize its width
|
||||
* Updated `CssManager` to use the `RemoteContentFetcher` class instead of `curl` natively (@greew)
|
||||
* Added optional `continue2pages` parameter to `SetDocTemplate` method, allowing a template to continue the last 2 pages alternately (@bmg-ruudv)
|
||||
* Ensure that all digits of a string are hexadecimal before decoding in ColorConverter (@derklaro)
|
||||
* Fix: Using mpdf in phar package leads to weird errors (#1504, @sandreas)
|
||||
* WEBP images support (#1525)
|
||||
|
||||
|
||||
mPDF 8.0.0
|
||||
===========================
|
||||
|
||||
### 15/03/2019
|
||||
|
||||
* Updated FPDI dependency to version 2 (thanks a lot, @JanSlabon)
|
||||
- removed `SetImportUse` method
|
||||
- case of `ImportPage` method changed to `importPage`
|
||||
- similarly, case of `setSourceFile` and `useTemplate` was changed to a lowercase first letter.
|
||||
- signature of `importPage` changed
|
||||
- returned value of `useTemplate` changed
|
||||
* Moved QRCode generating code portions to external package _mpdf/qrcode_
|
||||
- This reduced package size considerably (ca 6MB)
|
||||
* Fraction sizes without leading zeros allowed for font sizes (#973, thanks @peterdevpl)
|
||||
* WriteHTML is now strict about used `$mode` parameter (#915, thanks, @tomtomau)
|
||||
* Fixed regression in nested tables (#860, thanks, @machour)
|
||||
* Scientific notation handling in CSS font sizes (#753, thanks, @peterdevpl)
|
||||
|
||||
|
||||
mPDF 7.1.x
|
||||
===========================
|
||||
|
||||
* PHAR security issue fixed (thanks, @jakejackson)
|
||||
* Font temporary data saved as JSON instead of generating PHP files (thanks, @jakejackson)
|
||||
* cURL handling enhancements (thanks, @jakejackson)
|
||||
* SVG parsing fixes (thanks, @achretien)
|
||||
* Write PDF content with *Writer service classes
|
||||
* PHP 7.3 is supported
|
||||
* Added myclabs/deepcopy dependency, fixed TOC page numbering (thanks, @jakejackson)
|
||||
* Custom color for QR codes
|
||||
* Added support for orientation config key
|
||||
* Code and tests cleanups and enhancements
|
||||
- PHPUnit dedicated assertions (thanks, @carusogabriel)
|
||||
- WriteHTML part constants (thanks, @tomtomau)
|
||||
- Various notice fixes (kudos to all respective authors)
|
||||
|
||||
mPDF 7.0.x
|
||||
===========================
|
||||
|
||||
* Allow passing file content or file path to `SetAssociatedFiles` (#558)
|
||||
* Allowed ^1.4 and ^2.0 of paragon/random_compat to allow wider usage
|
||||
* Fix of undefined _getImage function (#539)
|
||||
* Code cleanup
|
||||
* Better writable rights for temp dir validation (#534)
|
||||
* Fix displaying dollar character in footer with core fonts (#520)
|
||||
* Fixed missed code2utf call (#531)
|
||||
* Refactored and cleaned-up classes and subnamespaces
|
||||
|
||||
|
||||
mPDF 7.0.0
|
||||
===========================
|
||||
|
||||
### 19/10/2017
|
||||
|
||||
Backward incompatible changes
|
||||
-----------------------------
|
||||
|
||||
- PHP `^5.6 || ~7.0.0 || ~7.1.0 || ~7.2.0` is required.
|
||||
- Entire project moved under `Mpdf` namespace
|
||||
- Practically all classes renamed to use `PascalCase` and named to be more verbose
|
||||
- Changed directory structure to comply to `PSR-4`
|
||||
- Removed explicit require calls, replaced with Composer autoloading
|
||||
- Removed configuration files
|
||||
- All configuration now done via `__construct` parameter (see below)
|
||||
- Changed `\Mpdf\Mpdf` constructor signature
|
||||
- Class now accepts only single array `$config` parameter
|
||||
- Array keys are former `config.php` and `config_fonts.php` properties
|
||||
- Additionally, former constructor parameters can be used as keys
|
||||
- `tempDir` directory now must be writable, otherwise an exception is thrown
|
||||
- ICC profile is loaded as entire path to file (to prevent a need to write inside vendor directory)
|
||||
- Moved examples to separate repository
|
||||
- Moved `TextVars` constants to separate class
|
||||
- Moved border constants to separate class
|
||||
- `scriptToLang` and `langToFont` in separate interfaced class methods
|
||||
- Will now throw an exception when `mbstring.func_overload` is set
|
||||
- Moved Glyph operator `GF_` constants in separate `\Mpdf\Fonts\GlyphOperator` class
|
||||
- All methods in Barcode class renamed to camelCase including public `dec_to_hex` and `hex_to_dec`
|
||||
- Decimal conversion methods (to roman, cjk, etc.) were moved to classes in `\Mpdf\Conversion` namespace
|
||||
- Images in PHP variables (`<img src="var:smileyface">`) were moved from direct Mpdf properties to `Mpdf::$imageVars` public property array
|
||||
- Removed global `_SVG_AUTOFONT` and `_SVG_CLASSES` constants in favor of `svgAutoFont` and `svgClasses` configuration keys
|
||||
- Moved global `_testIntersect`, `_testIntersectCircle` and `calc_bezier_bbox` fucntions inside `Svg` class as private methods.
|
||||
- Changed names to camelCase without underscores and to `computeBezierBoundingBox`
|
||||
- Security: Embedded files via `<annotation>` custom tag must be explicitly allowed via `allowAnnotationFiles` configuration key
|
||||
- `fontDir` property of Mpdf class is private and must be accessed via configuration variable with array of paths or `AddFontDirectory` method
|
||||
- QR code `<barcode>` element now treats `\r\n` and `\n` as actual line breaks
|
||||
- cURL is prefered over socket when downloading images.
|
||||
- Removed globally defined functions from `functions.php` in favor of `\Mpdf\Utils` classes `PdfDate` and `UtfString`.
|
||||
- Unused global functions were removed entirely.
|
||||
|
||||
|
||||
Removed features
|
||||
----------------
|
||||
|
||||
- Progressbar support
|
||||
- JpGraph support
|
||||
- `error_reporting` changes
|
||||
- Timezone changes
|
||||
- `compress.php` utility
|
||||
- `_MPDF_PATH` and `_MPDF_URI` constants
|
||||
- `_MPDF_TEMP_PATH` constant in favor of `tempDir` configuration variable
|
||||
- `_MPDF_TTFONTDATAPATH` in favor of `tempDir` configuration variable
|
||||
- `_MPDFK` constant in favor of `\Mpdf\Mpdf::SCALE` class constant
|
||||
- `FONT_DESCRIPTOR` constant in favor of `fontDescriptor` configuration variable
|
||||
- `_MPDF_SYSTEM_TTFONTS` constant in favor of `fontDir` configuration variable with array of paths or `AddFontDirectory` method
|
||||
- HTML output of error messages and debugs
|
||||
- Formerly deprecated methods
|
||||
|
||||
|
||||
Fixes and code enhancements
|
||||
----------------------------
|
||||
|
||||
- Fixed joining arab letters
|
||||
- Fixed redeclared `unicode_hex` function
|
||||
- Converted arrays to short syntax
|
||||
- Refactored and tested color handling with potential conversion fixes in `hsl*()` color definitions
|
||||
- Refactored `Barcode` class with separate class in `Mpdf\Barcode` namespace for each barcode type
|
||||
- Fixed colsum calculation for different locales (by @flow-control in #491)
|
||||
- Image type guessing from content separated to its own class
|
||||
|
||||
|
||||
New features
|
||||
------------
|
||||
|
||||
- Refactored caching (custom `Cache` and `FontCache` classes)
|
||||
- Implemented `Psr\Log\LoggerAware` interface
|
||||
- All debug and additional messages are now sent to the logger
|
||||
- Messages can be filtered based on `\Mpdf\Log\Context` class constants
|
||||
- `FontFileFinder` class allowing to specify multiple paths to search for fonts
|
||||
- `MpdfException` now extends `ErrorException` to allow specifying place in code where error occured
|
||||
- Generating font metrics moved to separate class
|
||||
- Added `\Mpdf\Output\Destination` class with verbose output destination constants
|
||||
- Availability to set custom default CSS file
|
||||
- Availability to set custom hyphenation dictionary file
|
||||
- Refactored code portions to new "separate" classes:
|
||||
- `Mpdf\Color\*` classes
|
||||
- `ColorConvertor`
|
||||
- `ColorModeConvertor`
|
||||
- `ColorSpaceRestrictor`
|
||||
- `Mpdf\SizeConvertor`
|
||||
- `Mpdf\Hyphenator`
|
||||
- `Mpdf\Image\ImageProcessor`
|
||||
- `Mpdf\Image\ImageTypeGuesser`
|
||||
- `Mpdf\Conversion\*` classes
|
||||
- Custom watermark angle with `watermarkAngle` configuration variable
|
||||
- Custom document properties (idea by @zarubik in #142)
|
||||
- PDF/A-3 associated files + additional xmp rdf (by @chab in #130)
|
||||
- Additional font directories can be added via `addFontDir` method
|
||||
- Introduced `cleanup` method which restores original `mb_` encoding settings (see #421)
|
||||
- QR code `<barcode>` element now treats `\r\n` and `\n` as actual line breaks
|
||||
- Customizable following of 3xx HTTP redirects, validation of SSL certificates, cURL timeout.
|
||||
- `curlFollowLocation`
|
||||
- `curlAllowUnsafeSslRequests`
|
||||
- `curlTimeout`
|
||||
- QR codes can be generated without a border using `disableborder="1"` HTML attribute in `<barcode>` tag
|
||||
|
||||
|
||||
Git repository enhancements
|
||||
---------------------------
|
||||
|
||||
- Added contributing guidelines
|
||||
- Added Issue template
|
||||
|
||||
|
||||
mPDF 6.1.0
|
||||
===========================
|
||||
|
||||
### 26/04/2016
|
||||
|
||||
- Composer updates
|
||||
- First release officially supporting Composer
|
||||
- Updated license in composer.json
|
||||
- Chmod 777 on dirs `ttfontdata`, `tmp`, `graph_cache` after composer install
|
||||
- Requiring PHP 5.4.0+ with Composer
|
||||
- Code style
|
||||
- Reformated (almost) all PHP files to keep basic code style
|
||||
- Removed trailing whitespaces
|
||||
- Converted all txt, php, css, and htm files to utf8
|
||||
- Removed closing PHP tags
|
||||
- Change all else if calls to elseif
|
||||
- Added base PHPUnit tests
|
||||
- Added Travis CI integration with unit tests
|
||||
- Changed all `mPDF::Error` and `die()` calls to throwing `MpdfException`
|
||||
- PDF Import changes
|
||||
- FPDI updated to 1.6.0 to fix incompatible licenses
|
||||
- FPDI loaded from Composer or manually only
|
||||
- Removed iccprofiles/CMYK directory
|
||||
- Renamed example files: change spaces to underscores to make scripting easier
|
||||
- Fixed `LEDGER` and `TABLOID` paper sizes
|
||||
- Implemented static cache for mpdf function `ConvertColor`.
|
||||
- Removed PHP4 style constructors
|
||||
- Work with HTML tags separated to `Tag` class
|
||||
- Fixed most Strict standards PHP errors
|
||||
- Add config constant so we can define custom font data
|
||||
- HTML
|
||||
- fax & tel support in href attribute
|
||||
- Check $html in `$mpdf->WriteHTML()` to see if it is an integer, float, string, boolean or
|
||||
a class with `__toString()` and cast to a string, otherwise throw exception.
|
||||
- PHP 7
|
||||
- Fix getting image from internal variable in PHP7 (4dcc2b4)
|
||||
- Fix PHP7 Fatal error: `'break' not in the 'loop' or 'switch' context` (002bb8a)
|
||||
- Fixed output file name for `D` and `I` output modes (issue #105, f297546)
|
||||
|
||||
mPDF 6.0
|
||||
===========================
|
||||
|
||||
### 20/12/2014
|
||||
|
||||
New features / Improvements
|
||||
---------------------------
|
||||
- Support for OpenTypeLayout tables / features for complex scripts and Advances Typography.
|
||||
- Improved bidirectional text handling.
|
||||
- Improved line-breaking, including for complex scripts e.g. Lao, Thai and Khmer.
|
||||
- Updated page-breaking options.
|
||||
- Automatic language mark-up and font selection using autoScriptToLang and autoLangToFont.
|
||||
- Kashida for text-justification in arabic scripts.
|
||||
- Index collation for non-ASCII characters.
|
||||
- Index mark-up allowing control over layout using CSS.
|
||||
- `{PAGENO}` and `{nbpg}` can use any of the number types as in list-style e.g. set in `<pagebreak>` using pagenumstyle.
|
||||
- CSS support for lists.
|
||||
- Default stylesheet - `mpdf.css` - updated.
|
||||
|
||||
Added CSS support
|
||||
-----------------
|
||||
- lang attribute selector e.g. :lang(fr), [lang="fr"]
|
||||
- font-variant-position
|
||||
- font-variant-caps
|
||||
- font-variant-ligatures
|
||||
- font-variant-numeric
|
||||
- font-variant-alternates - Only [normal | historical-forms] supported (i.e. most are NOT supported)
|
||||
- font-variant - as above, and except for: east-asian-variant-values, east-asian-width-values, ruby
|
||||
- font-language-override
|
||||
- font-feature-settings
|
||||
- text-outline is now supported on TD/TH tags
|
||||
- hebrew, khmer, cambodian, lao, and cjk-decimal recognised as values for "list-style-type" in numbered lists and page numbering.
|
||||
- list-style-image and list-style-position
|
||||
- transform (on `<img>` only)
|
||||
- text-decoration:overline
|
||||
- image-rendering
|
||||
- unicode-bidi (also `<bdi>` tag)
|
||||
- vertical-align can use lengths e.g. 0.5em
|
||||
- line-stacking-strategy
|
||||
- line-stacking-shift
|
||||
|
||||
mPDF 5.7.4
|
||||
================
|
||||
|
||||
### 15/12/2014
|
||||
|
||||
Bug Fixes & Minor Additions
|
||||
---------------------------
|
||||
- SVG images now support embedded images e.g. `<image xlink:href="image.png" width="100px" height="100px" />`
|
||||
- SVG images now supports `<tspan>` element e.g. `<tspan x,y,dx,dy,text-anchor >`, and also `<tref>`
|
||||
- SVG images now can use Autofont (see top of `classes/svg.php` file)
|
||||
- SVG images now has limited support for CSS classes (see top of `classes/svg.php` file)
|
||||
- SVG images - style inheritance improved
|
||||
- SVG images - improved handling of comments and other extraneous code
|
||||
- SVG images - fix to ensure opacity is reset before another element
|
||||
- SVG images - font-size not resetting after a `<text>` element
|
||||
- SVG radial gradients bug (if the focus [fx,fy] lies outside circle defined by [cx,cy] and r) cf. pservers-grad-15-b.svg
|
||||
- SVG allows spaces in attribute definitions in `<use>` or `<defs>` e.g. `<use x = "0" y = "0" xlink:href = "#s3" />`
|
||||
- SVG text which contains a `<` sign, it will break the text - now processed as `<` (despite the fact that this does not conform to XML spec)
|
||||
- SVG images - support automatic font selection and (minimal) use of CSS classes - cf. the defined constants at top of svg.php file
|
||||
- SVG images - text-anchor now supported as a CSS style, as well as an HTML attribute
|
||||
- CSS support for :nth-child() selector improved to fully support the draft CSS3 spec - http://www.w3.org/TR/selectors/#nth-child-pseudo
|
||||
[NB only works on table columns or rows]
|
||||
- text-indent when set as "em" - incorrectly calculated if last text in line in different font size than for block
|
||||
- CSS not applying cascaded styles on `<A>` elements - [changed MergeCSS() type to INLINE for 'A', LEGEND, METER and PROGRESS]
|
||||
- fix for underline/strikethrough/overline so that line position(s) are based correctly on font-size/font in nested situations
|
||||
- Error: Strict warning: Only variables should be passed by reference - in PHP5.5.9
|
||||
- bug accessing images from some servers (HTTP 403 Forbidden whn accessed using fopen etc.)
|
||||
- Setting page format incorrectly set default twice and missed some options
|
||||
- bug fixed in Overwrite() when specifying replacement as a string
|
||||
- barcode C93 - updated C93 code from TCPDF because of bug - incorrect checksum character for "153-2-4"
|
||||
- Tables - bug when using colspan across columns which may have a cell width specified
|
||||
cf. http://www.mpdf1.com/forum/discussion/2221/colspan-bug
|
||||
- Tables - cell height (when specified) is not resized when table is shrunk
|
||||
- Tables - if table width specified, but narrower than minimum cell wdith, and less than page width - table will expand to
|
||||
minimum cell width(s) as long as $keep_table_proportions = true
|
||||
- Tables - if using packTableData, and borders-collapse, wider border is overwriting content of adjacent cell
|
||||
Test case:
|
||||
```
|
||||
<table style="border-collapse: collapse;">
|
||||
<tr><td style="border-bottom: 42px solid #0FF; "> Hallo world </td></tr>
|
||||
<tr><td style="border-top: 14px solid #0F0; "> Hallo world </td></tr>
|
||||
</table>
|
||||
```
|
||||
- Images - image height is reset proportional to original if width is set to maximum e.g. `<img width="100%" height="20mm">`
|
||||
- URL handling changed to work with special characters in path fragments; affects `<a>` links, `<img>` images and
|
||||
CSS url() e.g background-image
|
||||
- also to ignore `../` included as a query value
|
||||
- Barcodes with bottom numerals e.g. EAN-13 - incorrect numeral size when using core fonts
|
||||
|
||||
--------------------------------
|
||||
|
||||
NB Spec. for embedded SVG images:
|
||||
as per http://www.w3.org/TR/2003/REC-SVG11-20030114/struct.html#ImageElement
|
||||
Attributes supported:
|
||||
- x
|
||||
- y
|
||||
- xlink:href (required) - can be jpeg, png or gif image - not vector (SVG or WMF) image
|
||||
- width (required)
|
||||
- height (required)
|
||||
- preserveAspectRatio
|
||||
|
||||
Note: all attribute names and values are case-sensitive
|
||||
width and height cannot be assigned by CSS - must be attributes
|
||||
|
||||
mPDF 5.7.3
|
||||
================
|
||||
|
||||
### 24/8/2014
|
||||
|
||||
Bug Fixes & Minor Additions
|
||||
---------------------------
|
||||
|
||||
- Tables - cellSpacing and cellPadding taking preference over CSS stylesheet
|
||||
- Tables - background images in table inside HTML Footer incorrectly positioned
|
||||
- Tables - cell in a nested table with a specified width, should determine width of parent table cell
|
||||
(cf. http://www.mpdf1.com/forum/discussion/1648/nested-table-bug-)
|
||||
- Tables - colspan (on a row after first row) exceeds number of columns in table
|
||||
- Gradients in Imported documents (mPDFI) causing error in some browsers
|
||||
- Fatal error after page-break-after:always on root level block element
|
||||
- Support for 'https/SSL' if file_get_contents_by_socket required (e.g. getting images with allow_url_fopen turned off)
|
||||
- Improved support for specified ports when getting external CSS stylesheets e.g. www.domain.com:80
|
||||
- error accessing local .css files with dummy queries (cache-busting) e.g. mpdfstyleA4.css?v=2.0.18.9
|
||||
- start of end tag in PRE incorrectly changed to <
|
||||
- error thrown when open.basedir restriction in effect (deleting temporary files)
|
||||
- image which forces pagebreak incorrectly positioned at top of page
|
||||
- [changes to avoid warning notices by checking if (isset(x)) before referencing it]
|
||||
- text with letter-spacing set inside table which needs to be resixed (shrunk) - letter-spacing was not adjusted
|
||||
- nested table incorrectly calculating width and unnecessarily wrapping text
|
||||
- vertical-align:super|sub can be nested using `<span>` elements
|
||||
- inline elements can be nested e.g. text `<sup>text<sup>13</sup>text</sup>` text
|
||||
- CSS vertical-align:0.5em (or %) now supported
|
||||
- underline and strikethrough now use the parent inline block baseline/fontsize/color for child inline elements *** change in behaviour
|
||||
(Adjusts line height to take account of superscript and subscript except in tables)
|
||||
- nested table incorrectly calculating width and unnecessarily wrapping text
|
||||
- tables - font size carrying over from one nested table to the next nested table
|
||||
- tables - border set as attribute on `<TABLE>` overrides border set as CSS on `<TD>`
|
||||
- tables - if table width set to 100% and one cell/column is empty with no padding/border, sizing incorrectly
|
||||
(http://www.mpdf1.com/forum/discussion/1886/td-fontsize-in-nested-table-bug-#Item_5)
|
||||
- `<main>` added as recognised tag
|
||||
- CSS style transform supported on `<img>` element (only)
|
||||
All transform functions are supported except matrix() i.e. translate(), translateX(), translateY(), skew(), skewX(), skewY(),
|
||||
scale(), scaleX(), scaleY(), rotate()
|
||||
NB When using Columns or Keep-with-table (use_kwt), cannot use transform
|
||||
- CSS background-color now supported on `<img>` element
|
||||
- @page :first not recognised unless @page {} has styles set
|
||||
- left/right margins not allowed on @page :first
|
||||
|
||||
mPDF 5.7.2
|
||||
================
|
||||
|
||||
### 28/12/2013
|
||||
|
||||
Bug Fixes
|
||||
---------
|
||||
|
||||
- `<tfoot>` not printing at all (since v5.7)
|
||||
- list-style incorrectly overriding list-style-type in cascading CSS
|
||||
- page-break-after:avoid not taking into account bottom padding and margin when estimating if next line can fit on page
|
||||
- images not displayed when using "https://" if images are referenced by src="//domain.com/image"
|
||||
- +aCJK incorrectly parsed when instantiating class e.g. new mpDF('ja+aCJK')
|
||||
- line-breaking - zero-width object at end of line (e.g. index entry) causing a space left untrimmed at end of line
|
||||
- ToC since v5.7 incorrectly handling non-ascii characters, entities or tags
|
||||
- cell height miscalculated when using hard-hyphenate
|
||||
- border colors set with transparency not working
|
||||
- transparency settings for stroke and fill interfering with one another
|
||||
- 'float' inside a HTML header/footer - not clearing the float before first line of text
|
||||
- error if script run across date change at midnight
|
||||
- temporary file name collisions (e.g. when processing images) if numerous users
|
||||
- `<watermarkimage>` position attribute not working
|
||||
- `<` (less-than sign) inside a PRE element, and NOT start of a valid tag, was incorrectly removed
|
||||
- file attachments not opening in Reader XI
|
||||
- JPG images not recognised if not containing JFIF or Exif markers
|
||||
- instance of preg_replace with /e modifier causing error in PHP 5.5
|
||||
- correctly handle CSS URLs with no scheme
|
||||
- Index entries causing errors when repeat entries are used within page-break-inside:avoid, rotated tables etc.
|
||||
- table with fixed width column and long word in cell set to colspan across this column (adding spare width to all columns)
|
||||
- incorrect hyphenation if multiple soft-hyphens on line before break
|
||||
- SVG images - objects contained in `<defs>` being displayed
|
||||
- SVG images - multiple, or quoted fonts e.g. style="font-family:'lucida grande', verdana" not recognised
|
||||
- SVG images - line with opacity=0 still visible (only in some PDF viewers/browsers)
|
||||
- text in an SVG image displaying with incorrect font in some PDF viewers/browsers
|
||||
- SVG images - fill:RGB(0,0,0) not recognised when uppercase
|
||||
- background images using data:image\/(jpeg|gif|png);base64 format - error when reading in stylesheet
|
||||
|
||||
New CSS support
|
||||
---------------
|
||||
|
||||
- added support for style="opacity:0.6;" in SVG images - previously only supported style="fill-opacity:0.6; stroke-opacity: 0.6;"
|
||||
- improved PNG image handling for some cases of alpha channel transparency
|
||||
- khmer, cambodian and lao recognised as list-style-type for numbered lists
|
||||
|
||||
SVG Images
|
||||
----------
|
||||
|
||||
- Limited support for `<use>` and `<defs>`
|
||||
|
||||
mPDF 5.7.1
|
||||
================
|
||||
## 01/09/2013
|
||||
|
||||
1) FILES: mpdf.php
|
||||
|
||||
Bug fix; Dollar sign enclosed by `<pre>` tag causing error.
|
||||
Test e.g.: `<pre>Test $1.00 Test</pre> <pre>Test $2.00 Test</pre> <pre>Test $3.00 Test</pre> <pre>Test $4.00 Test</pre>`
|
||||
|
||||
-----------------------------
|
||||
|
||||
2) FILES: includes/functions.php AND mpdf.php
|
||||
|
||||
Changes to `preg_replace` with `/e` modifier to use `preg_replace_callback`
|
||||
(/e depracated from PHP 5.5)
|
||||
|
||||
-----------------------------
|
||||
|
||||
3) FILES: classes/barcode.php
|
||||
|
||||
Small change to function `barcode_c128()` which allows ASCII 0 - 31 to be used in C128A e.g. chr(13) in:
|
||||
`<barcode code="5432
1068" type="C128A" />`
|
||||
|
||||
-----------------------------
|
||||
|
||||
4) FILES: mpdf.php
|
||||
|
||||
Using $use_kwt ("keep-[heading]-with-table") if `<h4></h4>` before table is on 2 lines and pagebreak occurs after first line
|
||||
the first line is displayed at the bottom of the 2nd page.
|
||||
Edited so that $use_kwt only works if the HEADING is only one line. Else ignores (but prints correctly)
|
||||
|
||||
-----------------------------
|
||||
|
||||
5) FILES: mpdf.php
|
||||
|
||||
Clearing old temporary files from `_MPDF_TEMP_PATH` will now ignore "hidden" files e.g. starting with a "`.`" `.htaccess`, `.gitignore` etc.
|
||||
and also leave `dummy.txt` alone
|
||||
|
||||
|
||||
mPDF 5.7
|
||||
===========================
|
||||
|
||||
### 14/07/2013
|
||||
|
||||
Files changed
|
||||
-------------
|
||||
- config.php
|
||||
- mpdf.php
|
||||
- classes/tocontents.php
|
||||
- classes/cssmgr.php
|
||||
- classes/svg.php
|
||||
- includes/functions.php
|
||||
- includes/out.php
|
||||
- examples/formsubmit.php [Important - Security update]
|
||||
|
||||
Updated Example Files in /examples/
|
||||
-----------------------------------
|
||||
|
||||
- All example files
|
||||
- mpdfstyleA4.css
|
||||
|
||||
config.php
|
||||
----------
|
||||
|
||||
Removed:
|
||||
- $this->hyphenateTables
|
||||
- $this->hyphenate
|
||||
- $this->orphansAllowed
|
||||
Edited:
|
||||
- "hyphens: manual" - Added to $this->defaultCSS
|
||||
- $this->allowedCSStags now includes '|TEXTCIRCLE|DOTTAB'
|
||||
New:
|
||||
- $this->decimal_align = array('DP'=>'.', 'DC'=>',', 'DM'=>"\xc2\xb7", 'DA'=>"\xd9\xab", 'DD'=>'-');
|
||||
- $this->h2toc = array('H1'=>0, 'H2'=>1, 'H3'=>2);
|
||||
- $this->h2bookmarks = array('H1'=>0, 'H2'=>1, 'H3'=>2);
|
||||
- $this->CJKforceend = false; // Forces overflowng punctuation to hang outside right margin (used with CJK script)
|
||||
|
||||
|
||||
Backwards compatability
|
||||
-----------------------
|
||||
|
||||
Changes in mPDF 5.7 may cause some changes to the way your documents appear. There are two main differences:
|
||||
1) Hyphenation. To retain appearance compatible with earlier versions, set the CSS property "hyphens: auto" whenever
|
||||
you previously used $mpdf->hyphenate=true;
|
||||
2) Table of Contents - appearance can now be controlled with CSS styles. By default, in mPDF 5.7, no styling is applied so you will get:
|
||||
- No indent (previous default of 5mm) - ($tocindent is ignored)
|
||||
- Any font, font-size set ($tocfont or $tocfontsize) will not work
|
||||
- HyperLinks will appear with your default appearance - usually blue and underlined
|
||||
- line spacing will be narrower (can use line-height or margin-top in CSS)
|
||||
|
||||
New features / Improvements
|
||||
---------------------------
|
||||
- Layout of Table of Content ToC now controlled using CSS styles
|
||||
- Text alignment on decimal mark inside tables
|
||||
- Automatically generated bookmarks and/or ToC entries from H1 - H6 tags
|
||||
- Support for unit of "rem" as size e.g. font-size: 1rem;
|
||||
- Origin and clipping for background images and gradients controlled by CSS i.e. background-origin, background-size, background-clip
|
||||
- Text-outline controlled by CSS (compatible with CSS3 spec.)
|
||||
- Use of `<dottab>` enhanced by custom CSS "outdent" property
|
||||
- Image HTML attributes `<img>` added: max-height, max-width, min-height and min-width
|
||||
- Spotcolor can now be defined as it is used e.g. color: spot(PANTONE 534 EC, 100%, 85, 65, 47, 9);
|
||||
- Lists - added support for "start" attribute in `<ol>` e.g. `<ol start="5">`
|
||||
- Hyphenation controlled using CSS, consistent with CSS3 spec.
|
||||
- Line breaking improved to avoid breaks within words where HTML tags are used e.g. H<sub>2<sub>0
|
||||
- Line breaking in CJK scripts improved (and ability to force hanging punctuation)
|
||||
- Numerals in a CJK script are kept together
|
||||
- RTL improved support for phrases containing numerals and \ and /
|
||||
- Bidi override codes supported - Right-to-Left Embedding [RLE] U+202B, Left-to-Right Embedding [LRE] U+202A,
|
||||
U+202C POP DIRECTIONAL FORMATTING (PDF)
|
||||
- Support for `<base href="">` in HTML - uses it to SetBasePath for relative URLs.
|
||||
- HTML tag - added support for `<wbr>` or `<wbr />` - converted to a soft-hyphen
|
||||
- CSS now takes precedence over HTML attribute e.g. `<table bgcolor="black" style="background-color:yellow">`
|
||||
|
||||
Added CSS support
|
||||
-----------------
|
||||
- max-height, max-width, min-height and min-width for images `<img>`
|
||||
- "hyphens: none|manual|auto" as per CSS3 spec.
|
||||
- Decimal mark alignment e.g. text-align: "." center;
|
||||
- "rem" accepted as a valid (font)size in CSS e.g. font-size: 1.5rem
|
||||
- text-outline, text-outline-width and text-outline-color supported everywhere except in tables (blur not supported)
|
||||
- background-origin, background-size, background-clip are now supported everywhere except in tables
|
||||
- "visibility: hidden|visible|printonly|screenonly" for inline elements e.g. `<span>`
|
||||
- Colors: device-cmyk(c,m,y,k) as per CSS3 spec. For consistency, device-cmyka also supported (not CSS3 spec)
|
||||
- "z-index" can be used to utilise layers in the PDF document
|
||||
- Custom CSS property added: "outdent" - opposite of indent
|
||||
|
||||
The HTML elements `<dottab>` and `<textcircle>` can now have CSS properties applied to them.
|
||||
|
||||
Bug fixes
|
||||
---------
|
||||
- SVG images - path including e.g. 1.234E-15 incorrectly parsed (not recognising capital E)
|
||||
- Tables - if a table starts when the Y position on page is below bottom margin caused endless loop
|
||||
- Float-ing DIVs - starting a float at bottom of page and it causes page break before anything output, second new page is forced
|
||||
- Tables - Warning notice now given in Table footer or header if `<tfoot>` placed after `<tbody>` and table spans page
|
||||
- Columns - block with border-width wider than the length of the border line, line overflows
|
||||
- Columns - block with no padding containing a block with borders but no backgound colour, borders not printed
|
||||
- Table in Columns - when background color set by surrounding block element - colour missing for height of half bottom border.
|
||||
- TOCpagebreakByArray() when called by function was not adding the pagebreak
|
||||
- Border around block element - dashed not showing correctly (not resetting linewidth between different edges)
|
||||
- Double border in table - when background colour set in surrounding block element - shows as black line between the 2 bits of double
|
||||
- Borders around DIVs - "double" border problem if not all 4 sides equally - fixed
|
||||
- Borders around DIVs - solid (and double) borders overlap as in tables - now fixed so mitred joins as in browser
|
||||
[Inadvertently improves borders in Columns because of change in LineCap]
|
||||
- Page numbering - $mpdf->pagenumSuffix etc not suppressed in HTML headers/footers if number suppressed
|
||||
- Page numbering - Page number total {nbpg} incorrect - e.g. showing decreasing numbers through document, when ToC present
|
||||
- RTL numerals - incorrectly reversing a number followed by a comma
|
||||
- Transform to uppercase/lowercase not working for chars > ASCII 128 when using core fonts
|
||||
- TOCpagebreak - Not setting TOC-FOOTER
|
||||
- TOCpagebreak - toc-even-header-name etc. not working
|
||||
- Parsing some relative URLs incorrectly
|
||||
- Textcircle - when moved to next page by "page-break-inside: avoid"
|
||||
- Bookmarks will now work if jump more than one level e.g. 0,2,1 Inserts a new blank entry at level 1
|
||||
- Paths to img or stylesheets - incorrectly reading "//www.domain.com" i.e. when starting with two /
|
||||
- data:image as background url() - incorrectly adjusting path on server if MPDF_PATH not specified (included in release mPDF 5.6.1)
|
||||
- Image problem if spaces or commas in path using http:// URL (included in release mPDF 5.6.1)
|
||||
- Image URL parsing rewritten to handle both urlencoded URLs and not urlencoded (included in release mPDF 5.6.1)
|
||||
- `<dottab>` fixed to allow color, font-size and font-family to be correctly used, avoid dots being moved to new page, and to work in RTL
|
||||
- Table {colsum} summed figures in table header
|
||||
- list-style-type (custom) colour not working
|
||||
- `<tocpagebreak>` toc-preHTML and toc-postHTML can now contain quotes
|
||||
|
||||
mPDF 5.6
|
||||
===========================
|
||||
|
||||
### 20/01/2013
|
||||
|
||||
Files changed
|
||||
-------------
|
||||
- mpdf.php
|
||||
- config.php
|
||||
- includes/functions.php
|
||||
- classes/meter.php
|
||||
- classes/directw.php
|
||||
|
||||
|
||||
config.php changes
|
||||
------------------
|
||||
|
||||
- $this->allowedCSStags - added HTML5 tags + textcircle AND
|
||||
- $this->outerblocktags - added HTML5 tags
|
||||
- $this->defaultCSS - added default CSS properties
|
||||
|
||||
New features / Improvements
|
||||
---------------------------
|
||||
CSS support added for for min-height, min-width, max-height and max-width in `<img>`
|
||||
|
||||
Images embedded in CSS
|
||||
- `<img src="data:image/gif;base64,....">` improved to make it more robust, and background: `url(data:image...` now added to work
|
||||
|
||||
HTML5 tags supported
|
||||
- as generic block elements: `<article><aside><details><figure><figcaption><footer><header><hgroup><nav><section><summary>`
|
||||
- as in-line elements: `<mark><time><meter><progress>`
|
||||
- `<mark>` has a default CSS set in config.php to yellow highlight
|
||||
- `<meter>` and `<progress>` support attributes as for HTML5
|
||||
- custom appearances for `<meter>` and `<progress>` can be made by editing `classes/meter.php` file
|
||||
- `<meter>` and `<progress>` suppress text inside the tags
|
||||
|
||||
Textcircle/Circular
|
||||
- font: "auto" added: automatically sizes text to fill semicircle (if both set) or full circle (if only one set)
|
||||
NB for this AND ALL CSS on `<textcircle>`: does not inherit CSS styles
|
||||
- attribute: divider="[characters including HTML entities]" added
|
||||
- `<textcircle r="30mm" top-text="Text Circular Text Circular" bottom-text="Text Circular Text Circular"
|
||||
divider=" • " style="font-size: auto" />`
|
||||
|
||||
» ’ ‚ „ are now included in "orphan"-management at the end of lines
|
||||
|
||||
Improved CJK line wrapping (if CJK character at end of line, breaks there rather than previous wordspace)
|
||||
|
||||
NB mPDF 5.5 added support for `<fieldset>` and `<legend>` (omitted from ChangeLog)
|
||||
|
||||
Bug fixes
|
||||
---------
|
||||
|
||||
- embedded fonts: Panose string incorrectly output as decimals - changed to hexadecimal
|
||||
Only a problem in limited circumstances.
|
||||
*****Need to delete all ttfontdata/ files in order for fix to have effect.
|
||||
- `<textCircle>` background white even when set to none/transparent
|
||||
- border="0" causing mPDF to add border to table CELLS as well as table
|
||||
- iteration counter in THEAD crashed in some circumstances
|
||||
- CSS color now supports spaces in the rgb() format e.g. border: 1px solid rgb(170, 170, 170);
|
||||
- CJK not working in table following changes made in v5.4
|
||||
- images fixed to work with Google Chart API (now mPDF does not urldecode the query part of the src)
|
||||
- CSS `<style>` within HTML page crashed if CSS is too large (? > 32Kb)
|
||||
- SVG image nested int eht HTML failed to show if code too large (? > 32Kb)
|
||||
- cyrillic character p р at end of table cell caused cell height to be incorrectly calculated
|
||||
|
||||
mPDF 5.5
|
||||
===========================
|
||||
|
||||
### 02/03/2012
|
||||
|
||||
Files changed
|
||||
-------------
|
||||
|
||||
- mpdf.php
|
||||
- classes/ttfontsuni.php
|
||||
- classes/svg.php
|
||||
- classes/tocontents.php
|
||||
- config.php
|
||||
- config_fonts.php
|
||||
- utils/font_collections.php
|
||||
- utils/font_coverage.php
|
||||
- utils/font_dump.php
|
||||
|
||||
Files added
|
||||
-----------
|
||||
|
||||
classes/ttfontsuni_analysis.php
|
||||
|
||||
config.php changes
|
||||
------------------
|
||||
|
||||
To avoid just the border/background-color of the (empty) end of a block being moved on to next page (`</div></div>`)
|
||||
|
||||
`$this->margBuffer = 0; // Allow an (empty) end of block to extend beyond the bottom margin by this amount (mm)`
|
||||
|
||||
config_fonts.php changes
|
||||
------------------------
|
||||
|
||||
Added to (arabic) fonts to allow "use non-mapped Arabic Glyphs" e.g. for Pashto
|
||||
'unAGlyphs' => true,
|
||||
|
||||
Arabic text
|
||||
-----------
|
||||
|
||||
Arabic text (RTL) rewritten with improved support for Pashto/Sindhi/Urdu/Kurdish
|
||||
Presentation forms added:
|
||||
U+0649, U+0681, U+0682, U+0685, U+069A-U+069E, U+06A0, U+06A2, U+06A3, U+06A5, U+06AB-U+06AE,
|
||||
U+06B0-U+06B4, U+06B5-U+06B9, U+06BB, U+06BC, U+06BE, U+06BF, U+06C0, U+06CD, U+06CE, U+06D1, U+06D3, U+0678
|
||||
Joining improved:
|
||||
U+0672, U+0675, U+0676, U+0677, U+0679-U+067D, U+067F, U+0680, U+0683, U+0684, U+0687, U+0687, U+0688-U+0692,
|
||||
U+0694, U+0695, U+0697, U+0699, U+068F, U+06A1, U+06A4, U+06A6, U+06A7, U+06A8, U+06AA, U+06BA, U+06C2-U+06CB, U+06CF
|
||||
|
||||
Note - Some characters in Pashto/Sindhi/Urdu/Kurdish do not have Unicode values for the final/initial/medial forms of the characters.
|
||||
However, some fonts include these characters "un-mapped" to Unicode (including XB Zar and XB Riyaz, which are bundled with mPDF).
|
||||
`'unAGlyphs' => true`, added to the config_fonts.php file for appropriate fonts will
|
||||
|
||||
This requires the font file to include a Format 2.0 POST table which references the glyphs as e.g. uni067C.med or uni067C.medi:
|
||||
e.g. XB Riyaz, XB Zar, Arabic Typesetting (MS), Arial (MS)
|
||||
|
||||
NB If you want to know if a font file is suitable, you can open a .ttf file in a text editor and search for "uni067C.med" - if it exists, it may work!
|
||||
Using "unAGlyphs" forces subsetting of fonts, and will not work with SIP/SMP fonts (using characters beyond the Unicode BMP Plane).
|
||||
|
||||
mPDF maps these characters to part of the Private Use Area allocated by Unicode U+F500-F7FF. This could interfere with correct use
|
||||
if the font already utilises these codes (unlikely).
|
||||
|
||||
mPDF now deletes U+200C,U+200D,U+200E,U+200F zero-widthjoiner/non-joiner, LTR and RTL marks so they will not appear
|
||||
even though some fonts contain glyphs for these characters.
|
||||
|
||||
|
||||
Other New features / Improvements
|
||||
---------------------------------
|
||||
Avoid just the border/background-color of the (empty) end of a block being moved on to next page (`</div></div>`)
|
||||
using configurable variable: `$this->margBuffer`;
|
||||
|
||||
|
||||
The TTFontsUni class contained a long function (extractcoreinfo) which is not used routinely in mPDF
|
||||
|
||||
This has been moved to a new file: classes/ttfontsuni_analysis.php.
|
||||
|
||||
The 3 utility scripts have been updated to use the new extended class:
|
||||
|
||||
- utils/font_collections.php
|
||||
- utils/font_coverage.php
|
||||
- utils/font_dump.php
|
||||
|
||||
|
||||
Bug fixes
|
||||
---------
|
||||
- Border & background when closing 2 blocks (e.g. `</div></div>`) incorrectly being moved to next page because incorrectly
|
||||
calculating how much space required
|
||||
- Fixed/Absolute-positioned elements not inheriting letter-spacing style
|
||||
- Rotated cell - error if text-rotate set on a table cell, but no text content in cell
|
||||
- SVG images, text-anchor not working
|
||||
- Nested table - not resetting cell style (font, color etc) after nested table, if text follows immediately
|
||||
- Nested table - font-size 70% set in extenal style sheet; if repeated nested tables, sets 70% of 70% etc etc
|
||||
- SVG setting font-size as percent on successive `<text>` elements gives progressively smaller text
|
||||
- mPDF will check if magic_quotes_runtime set ON even >= PHP 5.3 (will now cause an error message)
|
||||
- not resetting after 2 nested tags of same type e.g. `<b><b>bold</b></b>` still bold
|
||||
- When using charset_in other than utf-8, HTML Footers using tags e.g. `<htmlpageheader>` do not decode correctly
|
||||
- ToC if nested > 3 levels, line spacing reduces and starts to overlap
|
||||
|
||||
Older changes can be seen [on the documentation site](https://mpdf.github.io/about-mpdf/changelog.html).
|
91
system/vendor/mpdf/mpdf/CREDITS.txt
vendored
91
system/vendor/mpdf/mpdf/CREDITS.txt
vendored
@ -1,91 +0,0 @@
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Software: FPDF *
|
||||
* Version: 1.53 *
|
||||
* Date: 2004-12-31 *
|
||||
* Author: Olivier PLATHEY *
|
||||
* License: Freeware *
|
||||
* *
|
||||
* You may use and modify this software as you wish. *
|
||||
*******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* HTML2FPDF is a php script to read a HTML text and generate a PDF file. *
|
||||
* Copyright (C) 2004-2005 Renato Coelho *
|
||||
* *
|
||||
* html2fpdf.php, htmltoolkit.php *
|
||||
*******************************************************************************/
|
||||
|
||||
CREDITS From HTML2FPDF:
|
||||
|
||||
-Olivier Plathey for the fpdf.php class [http://www.fpdf.org]
|
||||
-Damon Kohler for the Flowing Block script [mailto:damonkohler@yahoo.com]
|
||||
-Clément Lavoillotte for HTML-oriented FPDF idea
|
||||
-Yamasoft for the gif.php class [http://www.yamasoft.com/]
|
||||
-Jérôme Fenal for the _parsegif() function
|
||||
-"VIETCOM" for the PDFTable code [http://www.freepgs.com/vietcom/tool/pdftable/] [mailto:vncommando@yahoo.com]
|
||||
-Yukihiro O. for the SetDash() function [mailto:yukihiro_o@infoseek.jp]
|
||||
-Ron Korving for the WordWrap() function
|
||||
-Michel Poulain for the DisplayPreferences() function
|
||||
-Patrick Benny for the MultiCellBlt() function idea [no longer in use]
|
||||
-Seb for the _SetTextRendering() and SetTextOutline() functions [mailto:captainseb@wanadoo.fr]
|
||||
-MorphSoft for the colornames list idea
|
||||
-W3SCHOOLS for HTML-related reference info [http://www.w3schools.com/]
|
||||
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* Software: FPDF_Protection *
|
||||
* Version: 1.02 *
|
||||
* Date: 2005/05/08 *
|
||||
* Author: Klemen VODOPIVEC *
|
||||
* License: Freeware *
|
||||
* *
|
||||
* You may use and modify this software as you wish as stated in original *
|
||||
* FPDF package. *
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
// FPDI - Version 1.2
|
||||
//
|
||||
// Copyright 2004-2007 Setasign - Jan Slabon
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* @copyright Khaled Al-Shamaa 2008
|
||||
* @link http://www.ar-php.org
|
||||
* @author Khaled Al-Shamaa <khaled@ar-php.org>
|
||||
* @desc Set of PHP5 / UTF-8 Classes developed to enhance Arabic web
|
||||
* applications by providing set of tools includes stem-based searching,
|
||||
* translitiration, soundex, Hijri calendar, charset detection and
|
||||
* converter, spell numbers, keyboard language, Muslim prayer time,
|
||||
* auto-summarization, and more...
|
||||
* @package Arabic
|
||||
*
|
||||
* @version 1.8 released in Feb 15, 2009
|
||||
*
|
||||
* @license LGPL
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation;
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
[http://www.opensource.org/licenses/lgpl-license.php]
|
280
system/vendor/mpdf/mpdf/LICENSE.txt
vendored
280
system/vendor/mpdf/mpdf/LICENSE.txt
vendored
@ -1,280 +0,0 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
147
system/vendor/mpdf/mpdf/README.md
vendored
147
system/vendor/mpdf/mpdf/README.md
vendored
@ -1,147 +0,0 @@
|
||||
mPDF is a PHP library which generates PDF files from UTF-8 encoded HTML.
|
||||
|
||||
It is based on [FPDF](http://www.fpdf.org/) and [HTML2FPDF](http://html2fpdf.sourceforge.net/)
|
||||
(see [CREDITS](CREDITS.txt)), with a number of enhancements. mPDF was written by Ian Back and is released
|
||||
under the [GNU GPL v2 licence](LICENSE.txt).
|
||||
|
||||
[](https://packagist.org/packages/mpdf/mpdf)
|
||||
[](https://packagist.org/packages/mpdf/mpdf)
|
||||
[](https://packagist.org/packages/mpdf/mpdf)
|
||||
|
||||
|
||||
> ⚠ If you are viewing this file on mPDF GitHub repository homepage or on Packagist, please note that
|
||||
> the default repository branch is `development` which can differ from the last stable release.
|
||||
|
||||
Requirements
|
||||
============
|
||||
|
||||
PHP versions and extensions
|
||||
---------------------------
|
||||
|
||||
- `PHP >=5.6 <7.3.0` is supported for `mPDF >= 7.0`
|
||||
- `PHP 7.3` is supported since `mPDF v7.1.7`
|
||||
- `PHP 7.4` is supported since `mPDF v8.0.4`
|
||||
- `PHP 8.0` is supported since `mPDF v8.0.10`
|
||||
- `PHP 8.1` is supported as of `mPDF v8.0.13`
|
||||
- `PHP 8.2` is supported as of `mPDF v8.1.3`
|
||||
|
||||
PHP `mbstring` and `gd` extensions have to be loaded.
|
||||
|
||||
Additional extensions may be required for some advanced features such as `zlib` for compression of output and
|
||||
embedded resources such as fonts, `bcmath` for generating barcodes or `xml` for character set conversion
|
||||
and SVG handling.
|
||||
|
||||
Known server caveats
|
||||
--------------------
|
||||
|
||||
mPDF has some problems with fetching external HTTP resources with single threaded servers such as `php -S`. A proper
|
||||
server such as nginx (php-fpm) or Apache is recommended.
|
||||
|
||||
Support us
|
||||
==========
|
||||
|
||||
Consider supporting development of mPDF with a donation of any value. [Donation button][1] can be found on the
|
||||
[main page of the documentation][1].
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
Official installation method is via composer and its packagist package [mpdf/mpdf](https://packagist.org/packages/mpdf/mpdf).
|
||||
|
||||
```
|
||||
$ composer require mpdf/mpdf
|
||||
```
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
The simplest usage (since version 7.0) of the library would be as follows:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
$mpdf = new \Mpdf\Mpdf();
|
||||
$mpdf->WriteHTML('<h1>Hello world!</h1>');
|
||||
$mpdf->Output();
|
||||
|
||||
```
|
||||
|
||||
This will output the PDF inline to the browser as `application/pdf` Content-type.
|
||||
|
||||
Setup & Configuration
|
||||
=====================
|
||||
|
||||
All [configuration directives](https://mpdf.github.io/reference/mpdf-variables/overview.html) can
|
||||
be set by the `$config` parameter of the constructor.
|
||||
|
||||
It is recommended to set one's own temporary directory via `tempDir` configuration variable.
|
||||
The directory must have write permissions (mode `775` is recommended) for users using mPDF
|
||||
(typically `cli`, `webserver`, `fpm`).
|
||||
|
||||
**Warning:** mPDF will clean up old temporary files in the temporary directory. Choose a path dedicated to mPDF only.
|
||||
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
$mpdf = new \Mpdf\Mpdf(['tempDir' => __DIR__ . '/tmp']);
|
||||
|
||||
```
|
||||
|
||||
By default, the temporary directory will be inside vendor directory and will have write permissions from
|
||||
`post_install` composer script.
|
||||
|
||||
For more information about custom temporary directory see the note on
|
||||
[Folder for temporary files](https://mpdf.github.io/installation-setup/folders-for-temporary-files.html)
|
||||
in the section on Installation & Setup in the [manual][1].
|
||||
|
||||
If you have problems, please read the section on
|
||||
[troubleshooting](https://mpdf.github.io/troubleshooting/known-issues.html) in the manual.
|
||||
|
||||
About CSS support and development state
|
||||
=======================================
|
||||
|
||||
mPDF as a whole is a quite dated software. Nowadays, better alternatives are available, albeit not written in PHP.
|
||||
|
||||
Use mPDF if you cannot use non-PHP approach to generate PDF files or if you want to leverage some of the benefits of mPDF
|
||||
over browser approach – color handling, pre-print, barcodes support, headers and footers, page numbering, TOCs, etc.
|
||||
But beware that a HTML/CSS template tailored for mPDF might be necessary.
|
||||
|
||||
If you are looking for state of the art CSS support, mirroring existing HTML pages to PDF, use headless Chrome.
|
||||
|
||||
mPDF will still be updated to enhance some internal capabilities and to support newer versions of PHP,
|
||||
but better and/or newer CSS support will most likely not be implemented.
|
||||
|
||||
Online manual
|
||||
=============
|
||||
|
||||
Online manual is available at https://mpdf.github.io/.
|
||||
|
||||
General troubleshooting
|
||||
=============
|
||||
|
||||
For general questions or troubleshooting please use [Discussions](https://github.com/mpdf/mpdf/discussions).
|
||||
|
||||
You can also use the [mpdf tag](https://stackoverflow.com/questions/tagged/mpdf) at Stack Overflow as the StackOverflow user base is more likely to answer you in a timely manner.
|
||||
|
||||
Contributing
|
||||
============
|
||||
|
||||
Before submitting issues and pull requests please read the [CONTRIBUTING.md](https://github.com/mpdf/mpdf/blob/development/.github/CONTRIBUTING.md) file.
|
||||
|
||||
Unit Testing
|
||||
============
|
||||
|
||||
Unit testing for mPDF is done using [PHPUnit](https://phpunit.de/).
|
||||
|
||||
To get started, run `composer install` from the command line while in the mPDF root directory
|
||||
(you'll need [composer installed first](https://getcomposer.org/download/)).
|
||||
|
||||
To execute tests, run `composer test` from the command line while in the mPDF root directory.
|
||||
|
||||
Any assistance writing unit tests for mPDF is greatly appreciated. If you'd like to help, please
|
||||
note that any PHP file located in the `/tests/` directory will be autoloaded when unit testing.
|
||||
|
||||
[1]: https://mpdf.github.io
|
70
system/vendor/mpdf/mpdf/composer.json
vendored
70
system/vendor/mpdf/mpdf/composer.json
vendored
@ -1,70 +0,0 @@
|
||||
{
|
||||
"name": "mpdf/mpdf",
|
||||
"type": "library",
|
||||
"description": "PHP library generating PDF files from UTF-8 encoded HTML",
|
||||
"keywords": ["php", "pdf", "utf-8"],
|
||||
"homepage": "https://mpdf.github.io",
|
||||
"license": ["GPL-2.0-only"],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Matěj Humpál",
|
||||
"role": "Developer, maintainer"
|
||||
},
|
||||
{
|
||||
"name": "Ian Back",
|
||||
"role": "Developer (retired)"
|
||||
}
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/mpdf/mpdf/issues",
|
||||
"source": "https://github.com/mpdf/mpdf",
|
||||
"docs": "http://mpdf.github.io"
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.6 || ^7.0 || ~8.0.0 || ~8.1.0 || ~8.2.0",
|
||||
"ext-gd": "*",
|
||||
"ext-mbstring": "*",
|
||||
"mpdf/psr-log-aware-trait": "^2.0 || ^3.0",
|
||||
"myclabs/deep-copy": "^1.7",
|
||||
"paragonie/random_compat": "^1.4|^2.0|^9.99.99",
|
||||
"psr/http-message": "^1.0",
|
||||
"psr/log": "^1.0 || ^2.0 || ^3.0",
|
||||
"setasign/fpdi": "^2.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "^1.3.0",
|
||||
"mpdf/qrcode": "^1.1.0",
|
||||
"squizlabs/php_codesniffer": "^3.5.0",
|
||||
"tracy/tracy": "~2.5",
|
||||
"yoast/phpunit-polyfills": "^1.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-bcmath": "Needed for generation of some types of barcodes",
|
||||
"ext-zlib": "Needed for compression of embedded resources, such as fonts",
|
||||
"ext-xml": "Needed mainly for SVG manipulation"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Mpdf\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Mpdf\\": "tests/Mpdf"
|
||||
},
|
||||
"files": [
|
||||
"src/functions-dev.php"
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"post-install-cmd": [
|
||||
"php -r \"chmod('./tmp', 0777);\""
|
||||
],
|
||||
"cs": "@php vendor/bin/phpcs -v --report-width=160 --standard=ruleset.xml --severity=1 --warning-severity=0 --extensions=php src utils tests",
|
||||
"test": "@php vendor/bin/phpunit",
|
||||
"coverage": "@php vendor/bin/phpunit --coverage-text"
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true
|
||||
}
|
||||
}
|
23
system/vendor/mpdf/mpdf/phpunit.xml
vendored
23
system/vendor/mpdf/mpdf/phpunit.xml
vendored
@ -1,23 +0,0 @@
|
||||
<phpunit
|
||||
bootstrap="tests/bootstrap.php"
|
||||
colors="true"
|
||||
backupGlobals="false"
|
||||
beStrictAboutTestsThatDoNotTestAnything="false">
|
||||
|
||||
<testsuites>
|
||||
<testsuite name="Tests">
|
||||
<directory suffix="Test.php">./tests</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<coverage processUncoveredFiles="true">
|
||||
<include>
|
||||
<directory suffix=".php">src</directory>
|
||||
</include>
|
||||
<report>
|
||||
<html outputDirectory="build/coverage"/>
|
||||
<text outputFile="php://stdout" showOnlySummary="true"/>
|
||||
</report>
|
||||
</coverage>
|
||||
|
||||
</phpunit>
|
43
system/vendor/mpdf/mpdf/ruleset.xml
vendored
43
system/vendor/mpdf/mpdf/ruleset.xml
vendored
@ -1,43 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<ruleset name="PSR2Tabs">
|
||||
<description>PSR2 with tabs instead of spaces.</description>
|
||||
<arg name="tab-width" value="4" />
|
||||
<rule ref="PSR2">
|
||||
|
||||
<exclude name="Generic.Commenting.DocComment" />
|
||||
<exclude name="Generic.Files.LineLength.TooLong" />
|
||||
<exclude name="Generic.Files.LineLength.MaxExceeded" />
|
||||
<exclude name="Generic.NamingConventions.UpperCaseConstantName.ClassConstantNotUpperCase)" />
|
||||
<exclude name="Generic.WhiteSpace.DisallowTabIndent" />
|
||||
|
||||
<exclude name="PSR1.Files.SideEffects.FoundWithSymbols" />
|
||||
<exclude name="PSR1.Methods.CamelCapsMethodName.NotCamelCaps" />
|
||||
|
||||
<exclude name="PSR2.Classes.ClassDeclaration.CloseBraceAfterBody" />
|
||||
<exclude name="PSR2.Classes.PropertyDeclaration.ScopeMissing" />
|
||||
<exclude name="PSR2.Classes.PropertyDeclaration.Underscore" />
|
||||
<exclude name="PSR2.Classes.PropertyDeclaration.VarUsed" />
|
||||
<exclude name="PSR2.ControlStructures.SwitchDeclaration.BodyOnNextLineCASE" />
|
||||
<exclude name="PSR2.Methods.MethodDeclaration.Underscore" />
|
||||
|
||||
<exclude name="Squiz.ControlStructures.ControlSignature.SpaceAfterCloseBrace" />
|
||||
<exclude name="Squiz.Scope.MethodScope.Missing" />
|
||||
<exclude name="Squiz.WhiteSpace.ControlStructureSpacing.SpacingAfterOpen" />
|
||||
<exclude name="Squiz.WhiteSpace.ControlStructureSpacing.SpacingBeforeClose" />
|
||||
|
||||
</rule>
|
||||
|
||||
<rule ref="Generic.Formatting.SpaceAfterCast">
|
||||
<properties>
|
||||
<property name="spacing" value="1" />
|
||||
</properties>
|
||||
</rule>
|
||||
|
||||
<rule ref="Generic.WhiteSpace.DisallowSpaceIndent" />
|
||||
<rule ref="Generic.WhiteSpace.ScopeIndent">
|
||||
<properties>
|
||||
<property name="indent" value="4" />
|
||||
<property name="tabIndent" value="true" />
|
||||
</properties>
|
||||
</rule>
|
||||
</ruleset>
|
Binary file not shown.
BIN
system/vendor/mpdf/mpdf/ttfonts/Abyssinica_SIL.ttf
vendored
BIN
system/vendor/mpdf/mpdf/ttfonts/Abyssinica_SIL.ttf
vendored
Binary file not shown.
BIN
system/vendor/mpdf/mpdf/ttfonts/Aegean.otf
vendored
BIN
system/vendor/mpdf/mpdf/ttfonts/Aegean.otf
vendored
Binary file not shown.
BIN
system/vendor/mpdf/mpdf/ttfonts/Aegyptus.otf
vendored
BIN
system/vendor/mpdf/mpdf/ttfonts/Aegyptus.otf
vendored
Binary file not shown.
BIN
system/vendor/mpdf/mpdf/ttfonts/Akkadian.otf
vendored
BIN
system/vendor/mpdf/mpdf/ttfonts/Akkadian.otf
vendored
Binary file not shown.
BIN
system/vendor/mpdf/mpdf/ttfonts/DBSILBR.ttf
vendored
BIN
system/vendor/mpdf/mpdf/ttfonts/DBSILBR.ttf
vendored
Binary file not shown.
BIN
system/vendor/mpdf/mpdf/ttfonts/DejaVuSans-Bold.ttf
vendored
BIN
system/vendor/mpdf/mpdf/ttfonts/DejaVuSans-Bold.ttf
vendored
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
system/vendor/mpdf/mpdf/ttfonts/DejaVuSans.ttf
vendored
BIN
system/vendor/mpdf/mpdf/ttfonts/DejaVuSans.ttf
vendored
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
system/vendor/mpdf/mpdf/ttfonts/DejaVuSansMono.ttf
vendored
BIN
system/vendor/mpdf/mpdf/ttfonts/DejaVuSansMono.ttf
vendored
Binary file not shown.
BIN
system/vendor/mpdf/mpdf/ttfonts/DejaVuSerif-Bold.ttf
vendored
BIN
system/vendor/mpdf/mpdf/ttfonts/DejaVuSerif-Bold.ttf
vendored
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
system/vendor/mpdf/mpdf/ttfonts/DejaVuSerif.ttf
vendored
BIN
system/vendor/mpdf/mpdf/ttfonts/DejaVuSerif.ttf
vendored
Binary file not shown.
Binary file not shown.
Binary file not shown.
99
system/vendor/mpdf/mpdf/ttfonts/DejaVuinfo.txt
vendored
99
system/vendor/mpdf/mpdf/ttfonts/DejaVuinfo.txt
vendored
@ -1,99 +0,0 @@
|
||||
Fonts are (c) Bitstream (see below). DejaVu changes are in public domain.
|
||||
Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below)
|
||||
|
||||
Bitstream Vera Fonts Copyright
|
||||
------------------------------
|
||||
|
||||
Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is
|
||||
a trademark of Bitstream, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of the fonts accompanying this license ("Fonts") and associated
|
||||
documentation files (the "Font Software"), to reproduce and distribute the
|
||||
Font Software, including without limitation the rights to use, copy, merge,
|
||||
publish, distribute, and/or sell copies of the Font Software, and to permit
|
||||
persons to whom the Font Software is furnished to do so, subject to the
|
||||
following conditions:
|
||||
|
||||
The above copyright and trademark notices and this permission notice shall
|
||||
be included in all copies of one or more of the Font Software typefaces.
|
||||
|
||||
The Font Software may be modified, altered, or added to, and in particular
|
||||
the designs of glyphs or characters in the Fonts may be modified and
|
||||
additional glyphs or characters may be added to the Fonts, only if the fonts
|
||||
are renamed to names not containing either the words "Bitstream" or the word
|
||||
"Vera".
|
||||
|
||||
This License becomes null and void to the extent applicable to Fonts or Font
|
||||
Software that has been modified and is distributed under the "Bitstream
|
||||
Vera" names.
|
||||
|
||||
The Font Software may be sold as part of a larger software package but no
|
||||
copy of one or more of the Font Software typefaces may be sold by itself.
|
||||
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT,
|
||||
TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME
|
||||
FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING
|
||||
ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
|
||||
THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE
|
||||
FONT SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the names of Gnome, the Gnome
|
||||
Foundation, and Bitstream Inc., shall not be used in advertising or
|
||||
otherwise to promote the sale, use or other dealings in this Font Software
|
||||
without prior written authorization from the Gnome Foundation or Bitstream
|
||||
Inc., respectively. For further information, contact: fonts at gnome dot
|
||||
org.
|
||||
|
||||
Arev Fonts Copyright
|
||||
------------------------------
|
||||
|
||||
Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the fonts accompanying this license ("Fonts") and
|
||||
associated documentation files (the "Font Software"), to reproduce
|
||||
and distribute the modifications to the Bitstream Vera Font Software,
|
||||
including without limitation the rights to use, copy, merge, publish,
|
||||
distribute, and/or sell copies of the Font Software, and to permit
|
||||
persons to whom the Font Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright and trademark notices and this permission notice
|
||||
shall be included in all copies of one or more of the Font Software
|
||||
typefaces.
|
||||
|
||||
The Font Software may be modified, altered, or added to, and in
|
||||
particular the designs of glyphs or characters in the Fonts may be
|
||||
modified and additional glyphs or characters may be added to the
|
||||
Fonts, only if the fonts are renamed to names not containing either
|
||||
the words "Tavmjong Bah" or the word "Arev".
|
||||
|
||||
This License becomes null and void to the extent applicable to Fonts
|
||||
or Font Software that has been modified and is distributed under the
|
||||
"Tavmjong Bah Arev" names.
|
||||
|
||||
The Font Software may be sold as part of a larger software package but
|
||||
no copy of one or more of the Font Software typefaces may be sold by
|
||||
itself.
|
||||
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL
|
||||
TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of Tavmjong Bah shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other
|
||||
dealings in this Font Software without prior written authorization
|
||||
from Tavmjong Bah. For further information, contact: tavmjong @ free
|
||||
. fr.
|
||||
|
||||
$Id: LICENSE 2133 2007-11-28 02:46:28Z lechimp $
|
BIN
system/vendor/mpdf/mpdf/ttfonts/Dhyana-Bold.ttf
vendored
BIN
system/vendor/mpdf/mpdf/ttfonts/Dhyana-Bold.ttf
vendored
Binary file not shown.
BIN
system/vendor/mpdf/mpdf/ttfonts/Dhyana-Regular.ttf
vendored
BIN
system/vendor/mpdf/mpdf/ttfonts/Dhyana-Regular.ttf
vendored
Binary file not shown.
94
system/vendor/mpdf/mpdf/ttfonts/DhyanaOFL.txt
vendored
94
system/vendor/mpdf/mpdf/ttfonts/DhyanaOFL.txt
vendored
@ -1,94 +0,0 @@
|
||||
Copyright (c) 2010, Vernon Adams (vern@newtypography.co.uk),
|
||||
with Reserved Font Names "Dhyana".
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
http://scripts.sil.org/OFL
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
BIN
system/vendor/mpdf/mpdf/ttfonts/FreeMono.ttf
vendored
BIN
system/vendor/mpdf/mpdf/ttfonts/FreeMono.ttf
vendored
Binary file not shown.
BIN
system/vendor/mpdf/mpdf/ttfonts/FreeMonoBold.ttf
vendored
BIN
system/vendor/mpdf/mpdf/ttfonts/FreeMonoBold.ttf
vendored
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user